diff options
Diffstat (limited to '3rdparty/assimp/code')
247 files changed, 0 insertions, 90898 deletions
diff --git a/3rdparty/assimp/code/3DSConverter.cpp b/3rdparty/assimp/code/3DSConverter.cpp deleted file mode 100644 index 351d0cca..00000000 --- a/3rdparty/assimp/code/3DSConverter.cpp +++ /dev/null @@ -1,844 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 3ds importer class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER - -// internal headers -#include "3DSLoader.h" -#include "TargetAnimation.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Setup final material indices, generae a default material if necessary -void Discreet3DSImporter::ReplaceDefaultMaterial() -{ - - // Try to find an existing material that matches the - // typical default material setting: - // - no textures - // - diffuse color (in grey!) - // NOTE: This is here to workaround the fact that some - // exporters are writing a default material, too. - unsigned int idx = 0xcdcdcdcd; - for (unsigned int i = 0; i < mScene->mMaterials.size();++i) - { - std::string s = mScene->mMaterials[i].mName; - for (std::string::iterator it = s.begin(); it != s.end(); ++it) - *it = ::tolower(*it); - - if (std::string::npos == s.find("default"))continue; - - if (mScene->mMaterials[i].mDiffuse.r != - mScene->mMaterials[i].mDiffuse.g || - mScene->mMaterials[i].mDiffuse.r != - mScene->mMaterials[i].mDiffuse.b)continue; - - if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 || - mScene->mMaterials[i].sTexBump.mMapName.length() != 0 || - mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 || - mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 || - mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 || - mScene->mMaterials[i].sTexShininess.mMapName.length() != 0 ) - { - continue; - } - idx = i; - } - if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size(); - - // now iterate through all meshes and through all faces and - // find all faces that are using the default material - unsigned int cnt = 0; - for (std::vector<D3DS::Mesh>::iterator - i = mScene->mMeshes.begin(); - i != mScene->mMeshes.end();++i) - { - for (std::vector<unsigned int>::iterator - a = (*i).mFaceMaterials.begin(); - a != (*i).mFaceMaterials.end();++a) - { - // NOTE: The additional check seems to be necessary, - // some exporters seem to generate invalid data here - if (0xcdcdcdcd == (*a)) - { - (*a) = idx; - ++cnt; - } - else if ( (*a) >= mScene->mMaterials.size()) - { - (*a) = idx; - DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material"); - ++cnt; - } - } - } - if (cnt && idx == mScene->mMaterials.size()) - { - // We need to create our own default material - D3DS::Material sMat; - sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f); - sMat.mName = "%%%DEFAULT"; - mScene->mMaterials.push_back(sMat); - - DefaultLogger::get()->info("3DS: Generating default material"); - } -} - -// ------------------------------------------------------------------------------------------------ -// Check whether all indices are valid. Otherwise we'd crash before the validation step is reached -void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh) -{ - for (std::vector< D3DS::Face >::iterator i = sMesh.mFaces.begin(); i != sMesh.mFaces.end();++i) - { - // check whether all indices are in range - for (unsigned int a = 0; a < 3;++a) - { - if ((*i).mIndices[a] >= sMesh.mPositions.size()) - { - DefaultLogger::get()->warn("3DS: Vertex index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1; - } - if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) - { - DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Generate out unique verbose format representation -void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh) -{ - // TODO: really necessary? I don't think. Just a waste of memory and time - // to do it now in a separate buffer. - - // Allocate output storage - std::vector<aiVector3D> vNew (sMesh.mFaces.size() * 3); - std::vector<aiVector3D> vNew2; - if (sMesh.mTexCoords.size()) - vNew2.resize(sMesh.mFaces.size() * 3); - - for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i) - { - D3DS::Face& face = sMesh.mFaces[i]; - - // Positions - for (unsigned int a = 0; a < 3;++a,++base) - { - vNew[base] = sMesh.mPositions[face.mIndices[a]]; - if (sMesh.mTexCoords.size()) - vNew2[base] = sMesh.mTexCoords[face.mIndices[a]]; - - face.mIndices[a] = base; - } - } - sMesh.mPositions = vNew; - sMesh.mTexCoords = vNew2; -} - -// ------------------------------------------------------------------------------------------------ -// Convert a 3DS texture to texture keys in an aiMaterial -void CopyTexture(MaterialHelper& mat, D3DS::Texture& texture, aiTextureType type) -{ - // Setup the texture name - aiString tex; - tex.Set( texture.mMapName); - mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0)); - - // Setup the texture blend factor - if (is_not_qnan(texture.mTextureBlend)) - mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); - - // Setup the texture mapping mode - mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0)); - mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0)); - - // Mirroring - double the scaling values - // FIXME: this is not really correct ... - if (texture.mMapMode == aiTextureMapMode_Mirror) - { - texture.mScaleU *= 2.f; - texture.mScaleV *= 2.f; - texture.mOffsetU /= 2.f; - texture.mOffsetV /= 2.f; - } - - // Setup texture UV transformations - mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Convert a 3DS material to an aiMaterial -void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat, - MaterialHelper& mat) -{ - // NOTE: Pass the background image to the viewer by bypassing the - // material system. This is an evil hack, never do it again! - if (0 != mBackgroundImage.length() && bHasBG) - { - aiString tex; - tex.Set( mBackgroundImage); - mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE); - - // Be sure this is only done for the first material - mBackgroundImage = std::string(""); - } - - // At first add the base ambient color of the scene to the material - oldMat.mAmbient.r += mClrAmbient.r; - oldMat.mAmbient.g += mClrAmbient.g; - oldMat.mAmbient.b += mClrAmbient.b; - - aiString name; - name.Set( oldMat.mName); - mat.AddProperty( &name, AI_MATKEY_NAME); - - // Material colors - mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); - mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); - - // Phong shininess and shininess strength - if (D3DS::Discreet3DS::Phong == oldMat.mShading || - D3DS::Discreet3DS::Metal == oldMat.mShading) - { - if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength) - { - oldMat.mShading = D3DS::Discreet3DS::Gouraud; - } - else - { - mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); - } - } - - // Opacity - mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY); - - // Bump height scaling - mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING); - - // Two sided rendering? - if (oldMat.mTwoSided) - { - int i = 1; - mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED); - } - - // Shading mode - aiShadingMode eShading = aiShadingMode_NoShading; - switch (oldMat.mShading) - { - case D3DS::Discreet3DS::Flat: - eShading = aiShadingMode_Flat; break; - - // I don't know what "Wire" shading should be, - // assume it is simple lambertian diffuse shading - case D3DS::Discreet3DS::Wire: - { - // Set the wireframe flag - unsigned int iWire = 1; - mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); - } - - case D3DS::Discreet3DS::Gouraud: - eShading = aiShadingMode_Gouraud; break; - - // assume cook-torrance shading for metals. - case D3DS::Discreet3DS::Phong : - eShading = aiShadingMode_Phong; break; - - case D3DS::Discreet3DS::Metal : - eShading = aiShadingMode_CookTorrance; break; - - // FIX to workaround a warning with GCC 4 who complained - // about a missing case Blinn: here - Blinn isn't a valid - // value in the 3DS Loader, it is just needed for ASE - case D3DS::Discreet3DS::Blinn : - eShading = aiShadingMode_Blinn; break; - } - mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); - - // DIFFUSE texture - if ( oldMat.sTexDiffuse.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE); - - // SPECULAR texture - if ( oldMat.sTexSpecular.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR); - - // OPACITY texture - if ( oldMat.sTexOpacity.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY); - - // EMISSIVE texture - if ( oldMat.sTexEmissive.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE); - - // BUMP texture - if ( oldMat.sTexBump.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT); - - // SHININESS texture - if ( oldMat.sTexShininess.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS); - - // REFLECTION texture - if ( oldMat.sTexReflective.mMapName.length() > 0) - CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION); - - // Store the name of the material itself, too - if ( oldMat.mName.length()) { - aiString tex; - tex.Set( oldMat.mName); - mat.AddProperty( &tex, AI_MATKEY_NAME); - } -} - -// ------------------------------------------------------------------------------------------------ -// Split meshes by their materials and generate output aiMesh'es -void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut) -{ - std::vector<aiMesh*> avOutMeshes; - avOutMeshes.reserve(mScene->mMeshes.size() * 2); - - unsigned int iFaceCnt = 0,num = 0; - aiString name; - - // we need to split all meshes by their materials - for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i) { - boost::scoped_array< std::vector<unsigned int> > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]); - - name.length = ASSIMP_itoa10(name.data,num++); - - unsigned int iNum = 0; - for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin(); - a != (*i).mFaceMaterials.end();++a,++iNum) - { - aiSplit[*a].push_back(iNum); - } - // now generate submeshes - for (unsigned int p = 0; p < mScene->mMaterials.size();++p) - { - if (aiSplit[p].empty()) { - continue; - } - aiMesh* meshOut = new aiMesh(); - - std::string name_parts((*i).mName); - name_parts.append("::"); - name_parts.append(mScene->mMaterials.at(p).mName); - meshOut->mName.Set(name_parts); - - meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // be sure to setup the correct material index - meshOut->mMaterialIndex = p; - - // use the color data as temporary storage - meshOut->mColors[0] = (aiColor4D*)(&*i); - avOutMeshes.push_back(meshOut); - - // convert vertices - meshOut->mNumFaces = (unsigned int)aiSplit[p].size(); - meshOut->mNumVertices = meshOut->mNumFaces*3; - - // allocate enough storage for faces - meshOut->mFaces = new aiFace[meshOut->mNumFaces]; - iFaceCnt += meshOut->mNumFaces; - - meshOut->mVertices = new aiVector3D[meshOut->mNumVertices]; - meshOut->mNormals = new aiVector3D[meshOut->mNumVertices]; - if ((*i).mTexCoords.size()) - { - meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices]; - } - for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q) - { - register unsigned int index = aiSplit[p][q]; - aiFace& face = meshOut->mFaces[q]; - - face.mIndices = new unsigned int[3]; - face.mNumIndices = 3; - - for (unsigned int a = 0; a < 3;++a,++base) - { - unsigned int idx = (*i).mFaces[index].mIndices[a]; - meshOut->mVertices[base] = (*i).mPositions[idx]; - meshOut->mNormals [base] = (*i).mNormals[idx]; - - if ((*i).mTexCoords.size()) - meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx]; - - face.mIndices[a] = base; - } - } - } - } - - // Copy them to the output array - pcOut->mNumMeshes = (unsigned int)avOutMeshes.size(); - pcOut->mMeshes = new aiMesh*[pcOut->mNumMeshes](); - for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) { - pcOut->mMeshes[a] = avOutMeshes[a]; - } - - // We should have at least one face here - if (!iFaceCnt) { - throw DeadlyImportError("No faces loaded. The mesh is empty"); - } -} - -// ------------------------------------------------------------------------------------------------ -// Add a node to the scenegraph and setup its final transformation -void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut, - D3DS::Node* pcIn, aiMatrix4x4& absTrafo) -{ - std::vector<unsigned int> iArray; - iArray.reserve(3); - - aiMatrix4x4 abs; - - // Find all meshes with the same name as the node - for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a) - { - const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0]; - ai_assert(NULL != pcMesh); - - if (pcIn->mName == pcMesh->mName) - iArray.push_back(a); - } - if (!iArray.empty()) - { - // The matrix should be identical for all meshes with the - // same name. It HAS to be identical for all meshes ..... - D3DS::Mesh* imesh = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0]); - - // Compute the inverse of the transformation matrix to move the - // vertices back to their relative and local space - aiMatrix4x4 mInv = imesh->mMat, mInvTransposed = imesh->mMat; - mInv.Inverse();mInvTransposed.Transpose(); - aiVector3D pivot = pcIn->vPivot; - - pcOut->mNumMeshes = (unsigned int)iArray.size(); - pcOut->mMeshes = new unsigned int[iArray.size()]; - for (unsigned int i = 0;i < iArray.size();++i) { - const unsigned int iIndex = iArray[i]; - aiMesh* const mesh = pcSOut->mMeshes[iIndex]; - - // Transform the vertices back into their local space - // fixme: consider computing normals after this, so we don't need to transform them - const aiVector3D* const pvEnd = mesh->mVertices+mesh->mNumVertices; - aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals; - - for (;pvCurrent != pvEnd;++pvCurrent,++t2) { - *pvCurrent = mInv * (*pvCurrent); - *t2 = mInvTransposed * (*t2); - } - - // Handle negative transformation matrix determinant -> invert vertex x - if (imesh->mMat.Determinant() < 0.0f) - { - /* we *must* have normals */ - for (pvCurrent = mesh->mVertices,t2 = mesh->mNormals;pvCurrent != pvEnd;++pvCurrent,++t2) { - pvCurrent->x *= -1.f; - t2->x *= -1.f; - } - DefaultLogger::get()->info("3DS: Flipping mesh X-Axis"); - } - - // Handle pivot point - if (pivot.x || pivot.y || pivot.z) - { - for (pvCurrent = mesh->mVertices;pvCurrent != pvEnd;++pvCurrent) { - *pvCurrent -= pivot; - } - } - - // Setup the mesh index - pcOut->mMeshes[i] = iIndex; - } - } - - // Setup the name of the node - pcOut->mName.Set(pcIn->mName); - - // Now build the transformation matrix of the node - // ROTATION - if (pcIn->aRotationKeys.size()){ - - // FIX to get to Assimp's quaternion conventions - for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) { - (*it).mValue.w *= -1.f; - } - - pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() ); - } - else if (pcIn->aCameraRollKeys.size()) - { - aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue), - pcOut->mTransformation); - } - - // SCALING - aiMatrix4x4& m = pcOut->mTransformation; - if (pcIn->aScalingKeys.size()) - { - const aiVector3D& v = pcIn->aScalingKeys[0].mValue; - m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x; - m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y; - m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z; - } - - // TRANSLATION - if (pcIn->aPositionKeys.size()) - { - const aiVector3D& v = pcIn->aPositionKeys[0].mValue; - m.a4 += v.x; - m.b4 += v.y; - m.c4 += v.z; - } - - // Generate animation channels for the node - if (pcIn->aPositionKeys.size() > 1 || pcIn->aRotationKeys.size() > 1 || - pcIn->aScalingKeys.size() > 1 || pcIn->aCameraRollKeys.size() > 1 || - pcIn->aTargetPositionKeys.size() > 1) - { - aiAnimation* anim = pcSOut->mAnimations[0]; - ai_assert(NULL != anim); - - if (pcIn->aCameraRollKeys.size() > 1) - { - DefaultLogger::get()->debug("3DS: Converting camera roll track ..."); - - // Camera roll keys - in fact they're just rotations - // around the camera's z axis. The angles are given - // in degrees (and they're clockwise). - pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size()); - for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i) - { - aiQuatKey& q = pcIn->aRotationKeys[i]; - aiFloatKey& f = pcIn->aCameraRollKeys[i]; - - q.mTime = f.mTime; - - // FIX to get to Assimp quaternion conventions - q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD( /*-*/ f.mValue)); - } - } -#if 0 - if (pcIn->aTargetPositionKeys.size() > 1) - { - DefaultLogger::get()->debug("3DS: Converting target track ..."); - - // Camera or spot light - need to convert the separate - // target position channel to our representation - TargetAnimationHelper helper; - - if (pcIn->aPositionKeys.empty()) - { - // We can just pass zero here ... - helper.SetFixedMainAnimationChannel(aiVector3D()); - } - else helper.SetMainAnimationChannel(&pcIn->aPositionKeys); - helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys); - - // Do the conversion - std::vector<aiVectorKey> distanceTrack; - helper.Process(&distanceTrack); - - // Now add a new node as child, name it <ourName>.Target - // and assign the distance track to it. This is that the - // information where the target is and how it moves is - // not lost - D3DS::Node* nd = new D3DS::Node(); - pcIn->push_back(nd); - - nd->mName = pcIn->mName + ".Target"; - - aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); - nda->mNodeName.Set(nd->mName); - - nda->mNumPositionKeys = (unsigned int)distanceTrack.size(); - nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; - ::memcpy(nda->mPositionKeys,&distanceTrack[0], - sizeof(aiVectorKey)*nda->mNumPositionKeys); - } -#endif - - // Cameras or lights define their transformation in their parent node and in the - // corresponding light or camera chunks. However, we read and process the latter - // to to be able to return valid cameras/lights even if no scenegraph is given. - for (unsigned int n = 0; n < pcSOut->mNumCameras;++n) { - if (pcSOut->mCameras[n]->mName == pcOut->mName) { - pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f); - } - } - for (unsigned int n = 0; n < pcSOut->mNumLights;++n) { - if (pcSOut->mLights[n]->mName == pcOut->mName) { - pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f); - } - } - - // Allocate a new node anim and setup its name - aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); - nda->mNodeName.Set(pcIn->mName); - - // POSITION keys - if (pcIn->aPositionKeys.size() > 0) - { - nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size(); - nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys]; - ::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0], - sizeof(aiVectorKey)*nda->mNumPositionKeys); - } - - // ROTATION keys - if (pcIn->aRotationKeys.size() > 0) - { - nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size(); - nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys]; - - // Rotations are quaternion offsets - aiQuaternion abs; - for (unsigned int n = 0; n < nda->mNumRotationKeys;++n) - { - const aiQuatKey& q = pcIn->aRotationKeys[n]; - - abs = (n ? abs * q.mValue : q.mValue); - nda->mRotationKeys[n].mTime = q.mTime; - nda->mRotationKeys[n].mValue = abs.Normalize(); - } - } - - // SCALING keys - if (pcIn->aScalingKeys.size() > 0) - { - nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size(); - nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys]; - ::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0], - sizeof(aiVectorKey)*nda->mNumScalingKeys); - } - } - - // Allocate storage for children - pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size(); - pcOut->mChildren = new aiNode*[pcIn->mChildren.size()]; - - // Recursively process all children - const unsigned int size = pcIn->mChildren.size(); - for (unsigned int i = 0; i < size;++i) - { - pcOut->mChildren[i] = new aiNode(); - pcOut->mChildren[i]->mParent = pcOut; - AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs); - } -} - -// ------------------------------------------------------------------------------------------------ -// Find out how many node animation channels we'll have finally -void CountTracks(D3DS::Node* node, unsigned int& cnt) -{ - ////////////////////////////////////////////////////////////////////////////// - // We will never generate more than one channel for a node, so - // this is rather easy here. - - if (node->aPositionKeys.size() > 1 || node->aRotationKeys.size() > 1 || - node->aScalingKeys.size() > 1 || node->aCameraRollKeys.size() > 1 || - node->aTargetPositionKeys.size() > 1) - { - ++cnt; - - // account for the additional channel for the camera/spotlight target position - if (node->aTargetPositionKeys.size() > 1)++cnt; - } - - // Recursively process all children - for (unsigned int i = 0; i < node->mChildren.size();++i) - CountTracks(node->mChildren[i],cnt); -} - -// ------------------------------------------------------------------------------------------------ -// Generate the output node graph -void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut) -{ - pcOut->mRootNode = new aiNode(); - if (0 == mRootNode->mChildren.size()) - { - ////////////////////////////////////////////////////////////////////////////// - // It seems the file is so fucked up that it has not even a hierarchy. - // generate a flat hiearachy which looks like this: - // - // ROOT_NODE - // | - // ---------------------------------------- - // | | | | | - // MESH_0 MESH_1 MESH_2 ... MESH_N CAMERA_0 .... - // - DefaultLogger::get()->warn("No hierarchy information has been found in the file. "); - - pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes + - mScene->mCameras.size() + mScene->mLights.size(); - - pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ]; - pcOut->mRootNode->mName.Set("<3DSDummyRoot>"); - - // Build dummy nodes for all meshes - unsigned int a = 0; - for (unsigned int i = 0; i < pcOut->mNumMeshes;++i,++a) - { - aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); - pcNode->mParent = pcOut->mRootNode; - pcNode->mMeshes = new unsigned int[1]; - pcNode->mMeshes[0] = i; - pcNode->mNumMeshes = 1; - - // Build a name for the node - pcNode->mName.length = sprintf(pcNode->mName.data,"3DSMesh_%i",i); - } - - // Build dummy nodes for all cameras - for (unsigned int i = 0; i < (unsigned int )mScene->mCameras.size();++i,++a) - { - aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); - pcNode->mParent = pcOut->mRootNode; - - // Build a name for the node - pcNode->mName = mScene->mCameras[i]->mName; - } - - // Build dummy nodes for all lights - for (unsigned int i = 0; i < (unsigned int )mScene->mLights.size();++i,++a) - { - aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode(); - pcNode->mParent = pcOut->mRootNode; - - // Build a name for the node - pcNode->mName = mScene->mLights[i]->mName; - } - } - else - { - // First of all: find out how many scaling, rotation and translation - // animation tracks we'll have afterwards - unsigned int numChannel = 0; - CountTracks(mRootNode,numChannel); - - if (numChannel) - { - // Allocate a primary animation channel - pcOut->mNumAnimations = 1; - pcOut->mAnimations = new aiAnimation*[1]; - aiAnimation* anim = pcOut->mAnimations[0] = new aiAnimation(); - - anim->mName.Set("3DSMasterAnim"); - - // Allocate enough storage for all node animation channels, - // but don't set the mNumChannels member - we'll use it to - // index into the array - anim->mChannels = new aiNodeAnim*[numChannel]; - } - - aiMatrix4x4 m; - AddNodeToGraph(pcOut, pcOut->mRootNode, mRootNode,m); - } - - // We used the first vertex color set to store some emporary values so we need to cleanup here - for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) - pcOut->mMeshes[a]->mColors[0] = NULL; - - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pcOut->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation; - - // If the root node is unnamed name it "<3DSRoot>" - if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) || - (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') ) - { - pcOut->mRootNode->mName.Set("<3DSRoot>"); - } -} - -// ------------------------------------------------------------------------------------------------ -// Convert all meshes in the scene and generate the final output scene. -void Discreet3DSImporter::ConvertScene(aiScene* pcOut) -{ - // Allocate enough storage for all output materials - pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size(); - pcOut->mMaterials = new aiMaterial*[pcOut->mNumMaterials]; - - // ... and convert the 3DS materials to aiMaterial's - for (unsigned int i = 0; i < pcOut->mNumMaterials;++i) - { - MaterialHelper* pcNew = new MaterialHelper(); - ConvertMaterial(mScene->mMaterials[i],*pcNew); - pcOut->mMaterials[i] = pcNew; - } - - // Generate the output mesh list - ConvertMeshes(pcOut); - - // Now copy all light sources to the output scene - pcOut->mNumLights = (unsigned int)mScene->mLights.size(); - if (pcOut->mNumLights) - { - pcOut->mLights = new aiLight*[pcOut->mNumLights]; - ::memcpy(pcOut->mLights,&mScene->mLights[0],sizeof(void*)*pcOut->mNumLights); - } - - // Now copy all cameras to the output scene - pcOut->mNumCameras = (unsigned int)mScene->mCameras.size(); - if (pcOut->mNumCameras) - { - pcOut->mCameras = new aiCamera*[pcOut->mNumCameras]; - ::memcpy(pcOut->mCameras,&mScene->mCameras[0],sizeof(void*)*pcOut->mNumCameras); - } -} - -#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/3rdparty/assimp/code/3DSHelper.h b/3rdparty/assimp/code/3DSHelper.h deleted file mode 100644 index 90da85c6..00000000 --- a/3rdparty/assimp/code/3DSHelper.h +++ /dev/null @@ -1,577 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines helper data structures for the import of 3DS files */ - -#ifndef AI_3DSFILEHELPER_H_INC -#define AI_3DSFILEHELPER_H_INC - - -#include "SpatialSort.h" -#include "SmoothingGroups.h" - -namespace Assimp { -namespace D3DS { - -#include "./../include/Compiler/pushpack1.h" - -// --------------------------------------------------------------------------- -/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks -* and data structures. -*/ -class Discreet3DS -{ -private: - inline Discreet3DS() {} - -public: - - //! data structure for a single chunk in a .3ds file - struct Chunk - { - uint16_t Flag; - uint32_t Size; - } PACK_STRUCT; - - - //! Used for shading field in material3ds structure - //! From AutoDesk 3ds SDK - typedef enum - { - // translated to gouraud shading with wireframe active - Wire = 0x0, - - // if this material is set, no vertex normals will - // be calculated for the model. Face normals + gouraud - Flat = 0x1, - - // standard gouraud shading - Gouraud = 0x2, - - // phong shading - Phong = 0x3, - - // cooktorrance or anistropic phong shading ... - // the exact meaning is unknown, if you know it - // feel free to tell me ;-) - Metal = 0x4, - - // required by the ASE loader - Blinn = 0x5 - } shadetype3ds; - - // Flags for animated keys - enum - { - KEY_USE_TENS = 0x1, - KEY_USE_CONT = 0x2, - KEY_USE_BIAS = 0x4, - KEY_USE_EASE_TO = 0x8, - KEY_USE_EASE_FROM = 0x10 - } ; - - enum - { - - // ******************************************************************** - // Basic chunks which can be found everywhere in the file - CHUNK_VERSION = 0x0002, - CHUNK_RGBF = 0x0010, // float4 R; float4 G; float4 B - CHUNK_RGBB = 0x0011, // int1 R; int1 G; int B - - // Linear color values (gamma = 2.2?) - CHUNK_LINRGBF = 0x0013, // float4 R; float4 G; float4 B - CHUNK_LINRGBB = 0x0012, // int1 R; int1 G; int B - - CHUNK_PERCENTW = 0x0030, // int2 percentage - CHUNK_PERCENTF = 0x0031, // float4 percentage - // ******************************************************************** - - // Prj master chunk - CHUNK_PRJ = 0xC23D, - - // MDLI master chunk - CHUNK_MLI = 0x3DAA, - - // Primary main chunk of the .3ds file - CHUNK_MAIN = 0x4D4D, - - // Mesh main chunk - CHUNK_OBJMESH = 0x3D3D, - - // Specifies the background color of the .3ds file - // This is passed through the material system for - // viewing purposes. - CHUNK_BKGCOLOR = 0x1200, - - // Specifies the ambient base color of the scene. - // This is added to all materials in the file - CHUNK_AMBCOLOR = 0x2100, - - // Specifies the background image for the whole scene - // This value is passed through the material system - // to the viewer - CHUNK_BIT_MAP = 0x1100, - CHUNK_BIT_MAP_EXISTS = 0x1101, - - // ******************************************************************** - // Viewport related stuff. Ignored - CHUNK_DEFAULT_VIEW = 0x3000, - CHUNK_VIEW_TOP = 0x3010, - CHUNK_VIEW_BOTTOM = 0x3020, - CHUNK_VIEW_LEFT = 0x3030, - CHUNK_VIEW_RIGHT = 0x3040, - CHUNK_VIEW_FRONT = 0x3050, - CHUNK_VIEW_BACK = 0x3060, - CHUNK_VIEW_USER = 0x3070, - CHUNK_VIEW_CAMERA = 0x3080, - // ******************************************************************** - - // Mesh chunks - CHUNK_OBJBLOCK = 0x4000, - CHUNK_TRIMESH = 0x4100, - CHUNK_VERTLIST = 0x4110, - CHUNK_VERTFLAGS = 0x4111, - CHUNK_FACELIST = 0x4120, - CHUNK_FACEMAT = 0x4130, - CHUNK_MAPLIST = 0x4140, - CHUNK_SMOOLIST = 0x4150, - CHUNK_TRMATRIX = 0x4160, - CHUNK_MESHCOLOR = 0x4165, - CHUNK_TXTINFO = 0x4170, - CHUNK_LIGHT = 0x4600, - CHUNK_CAMERA = 0x4700, - CHUNK_HIERARCHY = 0x4F00, - - // Specifies the global scaling factor. This is applied - // to the root node's transformation matrix - CHUNK_MASTER_SCALE = 0x0100, - - // ******************************************************************** - // Material chunks - CHUNK_MAT_MATERIAL = 0xAFFF, - - // asciiz containing the name of the material - CHUNK_MAT_MATNAME = 0xA000, - CHUNK_MAT_AMBIENT = 0xA010, // followed by color chunk - CHUNK_MAT_DIFFUSE = 0xA020, // followed by color chunk - CHUNK_MAT_SPECULAR = 0xA030, // followed by color chunk - - // Specifies the shininess of the material - // followed by percentage chunk - CHUNK_MAT_SHININESS = 0xA040, - CHUNK_MAT_SHININESS_PERCENT = 0xA041 , - - // Specifies the shading mode to be used - // followed by a short - CHUNK_MAT_SHADING = 0xA100, - - // NOTE: Emissive color (self illumination) seems not - // to be a color but a single value, type is unknown. - // Make the parser accept both of them. - // followed by percentage chunk (?) - CHUNK_MAT_SELF_ILLUM = 0xA080, - - // Always followed by percentage chunk (?) - CHUNK_MAT_SELF_ILPCT = 0xA084, - - // Always followed by percentage chunk - CHUNK_MAT_TRANSPARENCY = 0xA050, - - // Diffuse texture channel 0 - CHUNK_MAT_TEXTURE = 0xA200, - - // Contains opacity information for each texel - CHUNK_MAT_OPACMAP = 0xA210, - - // Contains a reflection map to be used to reflect - // the environment. This is partially supported. - CHUNK_MAT_REFLMAP = 0xA220, - - // Self Illumination map (emissive colors) - CHUNK_MAT_SELFIMAP = 0xA33d, - - // Bumpmap. Not specified whether it is a heightmap - // or a normal map. Assme it is a heightmap since - // artist normally prefer this format. - CHUNK_MAT_BUMPMAP = 0xA230, - - // Specular map. Seems to influence the specular color - CHUNK_MAT_SPECMAP = 0xA204, - - // Holds shininess data. - CHUNK_MAT_MAT_SHINMAP = 0xA33C, - - // Scaling in U/V direction. - // (need to gen separate UV coordinate set - // and do this by hand) - CHUNK_MAT_MAP_USCALE = 0xA354, - CHUNK_MAT_MAP_VSCALE = 0xA356, - - // Translation in U/V direction. - // (need to gen separate UV coordinate set - // and do this by hand) - CHUNK_MAT_MAP_UOFFSET = 0xA358, - CHUNK_MAT_MAP_VOFFSET = 0xA35a, - - // UV-coordinates rotation around the z-axis - // Assumed to be in radians. - CHUNK_MAT_MAP_ANG = 0xA35C, - - // Tiling flags for 3DS files - CHUNK_MAT_MAP_TILING = 0xa351, - - // Specifies the file name of a texture - CHUNK_MAPFILE = 0xA300, - - // Specifies whether a materail requires two-sided rendering - CHUNK_MAT_TWO_SIDE = 0xA081, - // ******************************************************************** - - // Main keyframer chunk. Contains translation/rotation/scaling data - CHUNK_KEYFRAMER = 0xB000, - - // Supported sub chunks - CHUNK_TRACKINFO = 0xB002, - CHUNK_TRACKOBJNAME = 0xB010, - CHUNK_TRACKDUMMYOBJNAME = 0xB011, - CHUNK_TRACKPIVOT = 0xB013, - CHUNK_TRACKPOS = 0xB020, - CHUNK_TRACKROTATE = 0xB021, - CHUNK_TRACKSCALE = 0xB022, - - // ******************************************************************** - // Keyframes for various other stuff in the file - // Partially ignored - CHUNK_AMBIENTKEY = 0xB001, - CHUNK_TRACKMORPH = 0xB026, - CHUNK_TRACKHIDE = 0xB029, - CHUNK_OBJNUMBER = 0xB030, - CHUNK_TRACKCAMERA = 0xB003, - CHUNK_TRACKFOV = 0xB023, - CHUNK_TRACKROLL = 0xB024, - CHUNK_TRACKCAMTGT = 0xB004, - CHUNK_TRACKLIGHT = 0xB005, - CHUNK_TRACKLIGTGT = 0xB006, - CHUNK_TRACKSPOTL = 0xB007, - CHUNK_FRAMES = 0xB008, - // ******************************************************************** - - // light sub-chunks - CHUNK_DL_OFF = 0x4620, - CHUNK_DL_OUTER_RANGE = 0x465A, - CHUNK_DL_INNER_RANGE = 0x4659, - CHUNK_DL_MULTIPLIER = 0x465B, - CHUNK_DL_EXCLUDE = 0x4654, - CHUNK_DL_ATTENUATE = 0x4625, - CHUNK_DL_SPOTLIGHT = 0x4610, - - // camera sub-chunks - CHUNK_CAM_RANGES = 0x4720 - }; -}; - -// --------------------------------------------------------------------------- -/** Helper structure representing a 3ds mesh face */ -struct Face : public FaceWithSmoothingGroup -{ -}; - -// --------------------------------------------------------------------------- -/** Helper structure representing a texture */ -struct Texture -{ - //! Default constructor - Texture() - : mOffsetU (0.0f) - , mOffsetV (0.0f) - , mScaleU (1.0f) - , mScaleV (1.0f) - , mRotation (0.0f) - , mMapMode (aiTextureMapMode_Wrap) - , iUVSrc (0) - { - mTextureBlend = get_qnan(); - } - - //! Specifies the blend factor for the texture - float mTextureBlend; - - //! Specifies the filename of the texture - std::string mMapName; - - //! Specifies texture coordinate offsets/scaling/rotations - float mOffsetU; - float mOffsetV; - float mScaleU; - float mScaleV; - float mRotation; - - //! Specifies the mapping mode to be used for the texture - aiTextureMapMode mMapMode; - - //! Used internally - bool bPrivate; - int iUVSrc; -}; - -#include "./../include/Compiler/poppack1.h" - -// --------------------------------------------------------------------------- -/** Helper structure representing a 3ds material */ -struct Material -{ - //! Default constructor. Builds a default name for the material - Material() - : - mDiffuse (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black - mSpecularExponent (0.0f), - mShininessStrength (1.0f), - mShading(Discreet3DS::Gouraud), - mTransparency (1.0f), - mBumpHeight (1.0f), - mTwoSided (false) - { - static int iCnt = 0; - - char szTemp[128]; - sprintf(szTemp,"UNNAMED_%i",iCnt++); - mName = szTemp; - } - - //! Name of the material - std::string mName; - //! Diffuse color of the material - aiColor3D mDiffuse; - //! Specular exponent - float mSpecularExponent; - //! Shininess strength, in percent - float mShininessStrength; - //! Specular color of the material - aiColor3D mSpecular; - //! Ambient color of the material - aiColor3D mAmbient; - //! Shading type to be used - Discreet3DS::shadetype3ds mShading; - //! Opacity of the material - float mTransparency; - //! Diffuse texture channel - Texture sTexDiffuse; - //! Opacity texture channel - Texture sTexOpacity; - //! Specular texture channel - Texture sTexSpecular; - //! Reflective texture channel - Texture sTexReflective; - //! Bump texture channel - Texture sTexBump; - //! Emissive texture channel - Texture sTexEmissive; - //! Shininess texture channel - Texture sTexShininess; - //! Scaling factor for the bump values - float mBumpHeight; - //! Emissive color - aiColor3D mEmissive; - //! Ambient texture channel - //! (used by the ASE format) - Texture sTexAmbient; - //! True if the material must be rendered from two sides - bool mTwoSided; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent a 3ds file mesh */ -struct Mesh : public MeshWithSmoothingGroups<D3DS::Face> -{ - //! Default constructor - Mesh() - { - static int iCnt = 0; - - // Generate a default name for the mesh - char szTemp[128]; - ::sprintf(szTemp,"UNNAMED_%i",iCnt++); - mName = szTemp; - } - - //! Name of the mesh - std::string mName; - - //! Texture coordinates - std::vector<aiVector3D> mTexCoords; - - //! Face materials - std::vector<unsigned int> mFaceMaterials; - - //! Local transformation matrix - aiMatrix4x4 mMat; -}; - -// --------------------------------------------------------------------------- -/** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the - C-API, so it would be difficult to make them a template. */ -struct aiFloatKey -{ - double mTime; ///< The time of this key - float mValue; ///< The value of this key - -#ifdef __cplusplus - - // time is not compared - bool operator == (const aiFloatKey& o) const - {return o.mValue == this->mValue;} - - bool operator != (const aiFloatKey& o) const - {return o.mValue != this->mValue;} - - // Only time is compared. This operator is defined - // for use with std::sort - bool operator < (const aiFloatKey& o) const - {return mTime < o.mTime;} - - bool operator > (const aiFloatKey& o) const - {return mTime < o.mTime;} - -#endif -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent a 3ds file node */ -struct Node -{ - Node() - - : mHierarchyPos (0) - , mHierarchyIndex (0) - - { - static int iCnt = 0; - - // Generate a default name for the node - char szTemp[128]; - ::sprintf(szTemp,"UNNAMED_%i",iCnt++); - mName = szTemp; - - aRotationKeys.reserve (20); - aPositionKeys.reserve (20); - aScalingKeys.reserve (20); - } - - ~Node() - { - for (unsigned int i = 0; i < mChildren.size();++i) - delete mChildren[i]; - } - - //! Pointer to the parent node - Node* mParent; - - //! Holds all child nodes - std::vector<Node*> mChildren; - - //! Name of the node - std::string mName; - - //! Dummy nodes: real name to be combined with the $$$DUMMY - std::string mDummyName; - - //! Position of the node in the hierarchy (tree depth) - int16_t mHierarchyPos; - - //! Index of the node - int16_t mHierarchyIndex; - - //! Rotation keys loaded from the file - std::vector<aiQuatKey> aRotationKeys; - - //! Position keys loaded from the file - std::vector<aiVectorKey> aPositionKeys; - - //! Scaling keys loaded from the file - std::vector<aiVectorKey> aScalingKeys; - - - // For target lights (spot lights and directional lights): - // The position of the target - std::vector< aiVectorKey > aTargetPositionKeys; - - // For cameras: the camera roll angle - std::vector< aiFloatKey > aCameraRollKeys; - - //! Pivot position loaded from the file - aiVector3D vPivot; - - //! Add a child node, setup the right parent node for it - //! \param pc Node to be 'adopted' - inline Node& push_back(Node* pc) - { - mChildren.push_back(pc); - pc->mParent = this; - return *this; - } -}; -// --------------------------------------------------------------------------- -/** Helper structure analogue to aiScene */ -struct Scene -{ - //! List of all materials loaded - //! NOTE: 3ds references materials globally - std::vector<Material> mMaterials; - - //! List of all meshes loaded - std::vector<Mesh> mMeshes; - - //! List of all cameras loaded - std::vector<aiCamera*> mCameras; - - //! List of all lights loaded - std::vector<aiLight*> mLights; - - //! Pointer to the root node of the scene - // --- moved to main class - // Node* pcRootNode; -}; - - -} // end of namespace D3DS -} // end of namespace Assimp - -#endif // AI_XFILEHELPER_H_INC diff --git a/3rdparty/assimp/code/3DSLoader.cpp b/3rdparty/assimp/code/3DSLoader.cpp deleted file mode 100644 index 169256b2..00000000 --- a/3rdparty/assimp/code/3DSLoader.cpp +++ /dev/null @@ -1,1378 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 3DSLoader.cpp - * @brief Implementation of the 3ds importer class - * - * http://www.the-labs.com/Blender/3DS-details.html - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER - -// internal headers -#include "3DSLoader.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Begins a new parsing block -// - Reads the current chunk and validates it -// - computes its length -#define ASSIMP_3DS_BEGIN_CHUNK() \ - while (true) { \ - if (stream->GetRemainingSizeToLimit() < sizeof(Discreet3DS::Chunk)){ \ - return; \ - } \ - Discreet3DS::Chunk chunk; \ - ReadChunk(&chunk); \ - int chunkSize = chunk.Size-sizeof(Discreet3DS::Chunk); \ - const int oldReadLimit = stream->GetReadLimit(); \ - stream->SetReadLimit(stream->GetCurrentPos() + chunkSize); \ - - -// ------------------------------------------------------------------------------------------------ -// End a parsing block -// Must follow at the end of each parsing block, reset chunk end marker to previous value -#define ASSIMP_3DS_END_CHUNK() \ - stream->SkipToReadLimit(); \ - stream->SetReadLimit(oldReadLimit); \ - if (stream->GetRemainingSizeToLimit() == 0) \ - return; \ - } - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -Discreet3DSImporter::Discreet3DSImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -Discreet3DSImporter::~Discreet3DSImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - std::string extension = GetExtension(pFile); - if (extension == "3ds" || extension == "prj" ) { - return true; - } - if (!extension.length() || checkSig) { - uint16_t token[3]; - token[0] = 0x4d4d; - token[1] = 0x3dc2; - //token[2] = 0x3daa; - return CheckMagicToken(pIOHandler,pFile,token,2,0,2); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get list of all extension supported by this loader -void Discreet3DSImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("3ds"); - extensions.insert("prj"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void Discreet3DSImporter::SetupProperties(const Importer* pImp) -{ - // nothing to be done for the moment -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void Discreet3DSImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); - this->stream = &stream; - - // We should have at least one chunk - if (stream.GetRemainingSize() < 16) { - throw DeadlyImportError("3DS file is either empty or corrupt: " + pFile); - } - - // Allocate our temporary 3DS representation - mScene = new D3DS::Scene(); - - // Initialize members - mLastNodeIndex = -1; - mCurrentNode = new D3DS::Node(); - mRootNode = mCurrentNode; - mRootNode->mHierarchyPos = -1; - mRootNode->mHierarchyIndex = -1; - mRootNode->mParent = NULL; - mMasterScale = 1.0f; - mBackgroundImage = ""; - bHasBG = false; - bIsPrj = false; - - // Parse the file - ParseMainChunk(); - - // Process all meshes in the file. First check whether all - // face indices haev valid values. The generate our - // internal verbose representation. Finally compute normal - // vectors from the smoothing groups we read from the - // file. - for (std::vector<D3DS::Mesh>::iterator i = mScene->mMeshes.begin(), - end = mScene->mMeshes.end(); i != end;++i) { - CheckIndices(*i); - MakeUnique (*i); - ComputeNormalsWithSmoothingsGroups<D3DS::Face>(*i); - } - - // Replace all occurences of the default material with a - // valid material. Generate it if no material containing - // DEFAULT in its name has been found in the file - ReplaceDefaultMaterial(); - - // Convert the scene from our internal representation to an - // aiScene object. This involves copying all meshes, lights - // and cameras to the scene - ConvertScene(pScene); - - // Generate the node graph for the scene. This is a little bit - // tricky since we'll need to split some meshes into submeshes - GenerateNodeGraph(pScene); - - // Now apply the master scaling factor to the scene - ApplyMasterScale(pScene); - - // Delete our internal scene representation and the root - // node, so the whole hierarchy will follow - delete mRootNode; - delete mScene; - - AI_DEBUG_INVALIDATE_PTR(mRootNode); - AI_DEBUG_INVALIDATE_PTR(mScene); - AI_DEBUG_INVALIDATE_PTR(this->stream); -} - -// ------------------------------------------------------------------------------------------------ -// Applies a master-scaling factor to the imported scene -void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) -{ - // There are some 3DS files with a zero scaling factor - if (!mMasterScale)mMasterScale = 1.0f; - else mMasterScale = 1.0f / mMasterScale; - - // Construct an uniform scaling matrix and multiply with it - pScene->mRootNode->mTransformation *= aiMatrix4x4( - mMasterScale,0.0f, 0.0f, 0.0f, - 0.0f, mMasterScale,0.0f, 0.0f, - 0.0f, 0.0f, mMasterScale,0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); - - // Check whether a scaling track is assigned to the root node. -} - -// ------------------------------------------------------------------------------------------------ -// Reads a new chunk from the file -void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut) -{ - ai_assert(pcOut != NULL); - - pcOut->Flag = stream->GetI2(); - pcOut->Size = stream->GetI4(); - - if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize()) - throw DeadlyImportError("Chunk is too large"); - - if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) - DefaultLogger::get()->error("3DS: Chunk overflow"); -} - -// ------------------------------------------------------------------------------------------------ -// Skip a chunk -void Discreet3DSImporter::SkipChunk() -{ - Discreet3DS::Chunk psChunk; - ReadChunk(&psChunk); - - stream->IncPtr(psChunk.Size-sizeof(Discreet3DS::Chunk)); - return; -} - -// ------------------------------------------------------------------------------------------------ -// Process the primary chunk of the file -void Discreet3DSImporter::ParseMainChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // get chunk type - switch (chunk.Flag) - { - - case Discreet3DS::CHUNK_PRJ: - bIsPrj = true; - case Discreet3DS::CHUNK_MAIN: - ParseEditorChunk(); - break; - }; - - ASSIMP_3DS_END_CHUNK(); - // recursively continue processing this hierarchy level - return ParseMainChunk(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseEditorChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_OBJMESH: - - ParseObjectChunk(); - break; - - // NOTE: In several documentations in the internet this - // chunk appears at different locations - case Discreet3DS::CHUNK_KEYFRAMER: - - ParseKeyframeChunk(); - break; - - case Discreet3DS::CHUNK_VERSION: - { - // print the version number - char buff[10]; - ASSIMP_itoa10(buff,stream->GetI2()); - DefaultLogger::get()->info(std::string("3DS file format version: ") + buff); - } - break; - }; - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseObjectChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_OBJBLOCK: - { - unsigned int cnt = 0; - const char* sz = (const char*)stream->GetPtr(); - - // Get the name of the geometry object - while (stream->GetI1())++cnt; - ParseChunk(sz,cnt); - } - break; - - case Discreet3DS::CHUNK_MAT_MATERIAL: - - // Add a new material to the list - mScene->mMaterials.push_back(D3DS::Material()); - ParseMaterialChunk(); - break; - - case Discreet3DS::CHUNK_AMBCOLOR: - - // This is the ambient base color of the scene. - // We add it to the ambient color of all materials - ParseColorChunk(&mClrAmbient,true); - if (is_qnan(mClrAmbient.r)) - { - // We failed to read the ambient base color. - DefaultLogger::get()->error("3DS: Failed to read ambient base color"); - mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f; - } - break; - - case Discreet3DS::CHUNK_BIT_MAP: - { - // Specifies the background image. The string should already be - // properly 0 terminated but we need to be sure - unsigned int cnt = 0; - const char* sz = (const char*)stream->GetPtr(); - while (stream->GetI1())++cnt; - mBackgroundImage = std::string(sz,cnt); - } - break; - - case Discreet3DS::CHUNK_BIT_MAP_EXISTS: - bHasBG = true; - break; - - case Discreet3DS::CHUNK_MASTER_SCALE: - // Scene master scaling factor - mMasterScale = stream->GetF4(); - break; - }; - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num) -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // IMPLEMENTATION NOTE; - // Cameras or lights define their transformation in their parent node and in the - // corresponding light or camera chunks. However, we read and process the latter - // to to be able to return valid cameras/lights even if no scenegraph is given. - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_TRIMESH: - { - // this starts a new triangle mesh - mScene->mMeshes.push_back(D3DS::Mesh()); - D3DS::Mesh& m = mScene->mMeshes.back(); - - // Setup the name of the mesh - m.mName = std::string(name, num); - - // Read mesh chunks - ParseMeshChunk(); - } - break; - - case Discreet3DS::CHUNK_LIGHT: - { - // This starts a new light - aiLight* light = new aiLight(); - mScene->mLights.push_back(light); - - light->mName.Set(std::string(name, num)); - - // First read the position of the light - light->mPosition.x = stream->GetF4(); - light->mPosition.y = stream->GetF4(); - light->mPosition.z = stream->GetF4(); - - light->mColorDiffuse = aiColor3D(1.f,1.f,1.f); - - // Now check for further subchunks - if (!bIsPrj) /* fixme */ - ParseLightChunk(); - - // The specular light color is identical the the diffuse light color. The ambient light color - // is equal to the ambient base color of the whole scene. - light->mColorSpecular = light->mColorDiffuse; - light->mColorAmbient = mClrAmbient; - - if (light->mType == aiLightSource_UNDEFINED) - { - // It must be a point light - light->mType = aiLightSource_POINT; - }} - break; - - case Discreet3DS::CHUNK_CAMERA: - { - // This starts a new camera - aiCamera* camera = new aiCamera(); - mScene->mCameras.push_back(camera); - camera->mName.Set(std::string(name, num)); - - // First read the position of the camera - camera->mPosition.x = stream->GetF4(); - camera->mPosition.y = stream->GetF4(); - camera->mPosition.z = stream->GetF4(); - - // Then the camera target - camera->mLookAt.x = stream->GetF4() - camera->mPosition.x; - camera->mLookAt.y = stream->GetF4() - camera->mPosition.y; - camera->mLookAt.z = stream->GetF4() - camera->mPosition.z; - float len = camera->mLookAt.Length(); - if (len < 1e-5f) { - - // There are some files with lookat == position. Don't know why or whether it's ok or not. - DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector"); - camera->mLookAt = aiVector3D(0.f,1.f,0.f); - - } - else camera->mLookAt /= len; - - // And finally - the camera rotation angle, in counter clockwise direction - const float angle = AI_DEG_TO_RAD( stream->GetF4() ); - aiQuaternion quat(camera->mLookAt,angle); - camera->mUp = quat.GetMatrix() * aiVector3D(0.f,1.f,0.f); - - // Read the lense angle - camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() ); - if (camera->mHorizontalFOV < 0.001f) { - camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f); - } - - // Now check for further subchunks - if (!bIsPrj) /* fixme */ { - ParseCameraChunk(); - }} - break; - }; - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseLightChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - aiLight* light = mScene->mLights.back(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_DL_SPOTLIGHT: - // Now we can be sure that the light is a spot light - light->mType = aiLightSource_SPOT; - - // We wouldn't need to normalize here, but we do it - light->mDirection.x = stream->GetF4() - light->mPosition.x; - light->mDirection.y = stream->GetF4() - light->mPosition.y; - light->mDirection.z = stream->GetF4() - light->mPosition.z; - light->mDirection.Normalize(); - - // Now the hotspot and falloff angles - in degrees - light->mAngleInnerCone = AI_DEG_TO_RAD( stream->GetF4() ); - - // FIX: the falloff angle is just an offset - light->mAngleOuterCone = light->mAngleInnerCone+AI_DEG_TO_RAD( stream->GetF4() ); - break; - - // intensity multiplier - case Discreet3DS::CHUNK_DL_MULTIPLIER: - light->mColorDiffuse = light->mColorDiffuse * stream->GetF4(); - break; - - // light color - case Discreet3DS::CHUNK_RGBF: - case Discreet3DS::CHUNK_LINRGBF: - light->mColorDiffuse.r *= stream->GetF4(); - light->mColorDiffuse.g *= stream->GetF4(); - light->mColorDiffuse.b *= stream->GetF4(); - break; - - // light attenuation - case Discreet3DS::CHUNK_DL_ATTENUATE: - light->mAttenuationLinear = stream->GetF4(); - break; - }; - - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseCameraChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - aiCamera* camera = mScene->mCameras.back(); - - // get chunk type - switch (chunk.Flag) - { - // near and far clip plane - case Discreet3DS::CHUNK_CAM_RANGES: - camera->mClipPlaneNear = stream->GetF4(); - camera->mClipPlaneFar = stream->GetF4(); - break; - } - - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseKeyframeChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_TRACKCAMTGT: - case Discreet3DS::CHUNK_TRACKSPOTL: - case Discreet3DS::CHUNK_TRACKCAMERA: - case Discreet3DS::CHUNK_TRACKINFO: - case Discreet3DS::CHUNK_TRACKLIGHT: - case Discreet3DS::CHUNK_TRACKLIGTGT: - - // this starts a new mesh hierarchy chunk - ParseHierarchyChunk(chunk.Flag); - break; - }; - - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -// Little helper function for ParseHierarchyChunk -void Discreet3DSImporter::InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent) -{ - if (!pcCurrent) { - mRootNode->push_back(pcNode); - return; - } - - if (pcCurrent->mHierarchyPos == pcNode->mHierarchyPos) { - if (pcCurrent->mParent) { - pcCurrent->mParent->push_back(pcNode); - } - else pcCurrent->push_back(pcNode); - return; - } - return InverseNodeSearch(pcNode,pcCurrent->mParent); -} - -// ------------------------------------------------------------------------------------------------ -// Find a node with a specific name in the import hierarchy -D3DS::Node* FindNode(D3DS::Node* root, const std::string& name) -{ - if (root->mName == name) - return root; - for (std::vector<D3DS::Node*>::iterator it = root->mChildren.begin();it != root->mChildren.end(); ++it) { - D3DS::Node* nd; - if (( nd = FindNode(*it,name))) - return nd; - } - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// Binary predicate for std::unique() -template <class T> -bool KeyUniqueCompare(const T& first, const T& second) -{ - return first.mTime == second.mTime; -} - -// ------------------------------------------------------------------------------------------------ -// Skip some additional import data. -void Discreet3DSImporter::SkipTCBInfo() -{ - unsigned int flags = stream->GetI2(); - - if (!flags) { - // Currently we can't do anything with these values. They occur - // quite rare, so it wouldn't be worth the effort implementing - // them. 3DS ist not really suitable for complex animations, - // so full support is not required. - DefaultLogger::get()->warn("3DS: Skipping TCB animation info"); - } - - if (flags & Discreet3DS::KEY_USE_TENS) { - stream->IncPtr(4); - } - if (flags & Discreet3DS::KEY_USE_BIAS) { - stream->IncPtr(4); - } - if (flags & Discreet3DS::KEY_USE_CONT) { - stream->IncPtr(4); - } - if (flags & Discreet3DS::KEY_USE_EASE_FROM) { - stream->IncPtr(4); - } - if (flags & Discreet3DS::KEY_USE_EASE_TO) { - stream->IncPtr(4); - } -} - -// ------------------------------------------------------------------------------------------------ -// Read hierarchy and keyframe info -void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent) -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_TRACKOBJNAME: - - // This is the name of the object to which the track applies. The chunk also - // defines the position of this object in the hierarchy. - { - - // First of all: get the name of the object - unsigned int cnt = 0; - const char* sz = (const char*)stream->GetPtr(); - - while (stream->GetI1())++cnt; - std::string name = std::string(sz,cnt); - - // Now find out whether we have this node already (target animation channels - // are stored with a separate object ID) - D3DS::Node* pcNode = FindNode(mRootNode,name); - if (pcNode) - { - // Make this node the current node - mCurrentNode = pcNode; - break; - } - pcNode = new D3DS::Node(); - pcNode->mName = name; - - // There are two unknown values which we can safely ignore - stream->IncPtr(4); - - // Now read the hierarchy position of the object - uint16_t hierarchy = stream->GetI2() + 1; - pcNode->mHierarchyPos = hierarchy; - pcNode->mHierarchyIndex = mLastNodeIndex; - - // And find a proper position in the graph for it - if (mCurrentNode && mCurrentNode->mHierarchyPos == hierarchy) { - - // add to the parent of the last touched node - mCurrentNode->mParent->push_back(pcNode); - mLastNodeIndex++; - } - else if (hierarchy >= mLastNodeIndex) { - - // place it at the current position in the hierarchy - mCurrentNode->push_back(pcNode); - mLastNodeIndex = hierarchy; - } - else { - // need to go back to the specified position in the hierarchy. - InverseNodeSearch(pcNode,mCurrentNode); - mLastNodeIndex++; - } - // Make this node the current node - mCurrentNode = pcNode; - } - break; - - case Discreet3DS::CHUNK_TRACKDUMMYOBJNAME: - - // This is the "real" name of a $$$DUMMY object - { - const char* sz = (const char*) stream->GetPtr(); - while (stream->GetI1()); - - // If object name is DUMMY, take this one instead - if (mCurrentNode->mName == "$$$DUMMY") { - //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object"); - mCurrentNode->mName = std::string(sz); - break; - } - } - break; - - case Discreet3DS::CHUNK_TRACKPIVOT: - - if ( Discreet3DS::CHUNK_TRACKINFO != parent) - { - DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object"); - break; - } - - // Pivot = origin of rotation and scaling - mCurrentNode->vPivot.x = stream->GetF4(); - mCurrentNode->vPivot.y = stream->GetF4(); - mCurrentNode->vPivot.z = stream->GetF4(); - break; - - - // //////////////////////////////////////////////////////////////////// - // POSITION KEYFRAME - case Discreet3DS::CHUNK_TRACKPOS: - { - stream->IncPtr(10); - const unsigned int numFrames = stream->GetI4(); - bool sortKeys = false; - - // This could also be meant as the target position for - // (targeted) lights and cameras - std::vector<aiVectorKey>* l; - if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent) { - l = & mCurrentNode->aTargetPositionKeys; - } - else l = & mCurrentNode->aPositionKeys; - - l->reserve(numFrames); - for (unsigned int i = 0; i < numFrames;++i) { - const unsigned int fidx = stream->GetI4(); - - // Setup a new position key - aiVectorKey v; - v.mTime = (double)fidx; - - SkipTCBInfo(); - v.mValue.x = stream->GetF4(); - v.mValue.y = stream->GetF4(); - v.mValue.z = stream->GetF4(); - - // check whether we'll need to sort the keys - if (!l->empty() && v.mTime <= l->back().mTime) - sortKeys = true; - - // Add the new keyframe to the list - l->push_back(v); - } - - // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() ); - }} - - break; - - // //////////////////////////////////////////////////////////////////// - // CAMERA ROLL KEYFRAME - case Discreet3DS::CHUNK_TRACKROLL: - { - // roll keys are accepted for cameras only - if (parent != Discreet3DS::CHUNK_TRACKCAMERA) { - DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object"); - break; - } - bool sortKeys = false; - std::vector<aiFloatKey>* l = &mCurrentNode->aCameraRollKeys; - - stream->IncPtr(10); - const unsigned int numFrames = stream->GetI4(); - l->reserve(numFrames); - for (unsigned int i = 0; i < numFrames;++i) { - const unsigned int fidx = stream->GetI4(); - - // Setup a new position key - aiFloatKey v; - v.mTime = (double)fidx; - - // This is just a single float - SkipTCBInfo(); - v.mValue = stream->GetF4(); - - // Check whether we'll need to sort the keys - if (!l->empty() && v.mTime <= l->back().mTime) - sortKeys = true; - - // Add the new keyframe to the list - l->push_back(v); - } - - // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiFloatKey>), l->end() ); - }} - break; - - - // //////////////////////////////////////////////////////////////////// - // CAMERA FOV KEYFRAME - case Discreet3DS::CHUNK_TRACKFOV: - { - DefaultLogger::get()->error("3DS: Skipping FOV animation track. " - "This is not supported"); - } - break; - - - // //////////////////////////////////////////////////////////////////// - // ROTATION KEYFRAME - case Discreet3DS::CHUNK_TRACKROTATE: - { - stream->IncPtr(10); - const unsigned int numFrames = stream->GetI4(); - - bool sortKeys = false; - std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys; - l->reserve(numFrames); - - for (unsigned int i = 0; i < numFrames;++i) { - const unsigned int fidx = stream->GetI4(); - SkipTCBInfo(); - - aiQuatKey v; - v.mTime = (double)fidx; - - // The rotation keyframe is given as an axis-angle pair - const float rad = stream->GetF4(); - aiVector3D axis; - axis.x = stream->GetF4(); - axis.y = stream->GetF4(); - axis.z = stream->GetF4(); - - if (!axis.x && !axis.y && !axis.z) - axis.y = 1.f; - - // Construct a rotation quaternion from the axis-angle pair - v.mValue = aiQuaternion(axis,rad); - - // Check whether we'll need to sort the keys - if (!l->empty() && v.mTime <= l->back().mTime) - sortKeys = true; - - // add the new keyframe to the list - l->push_back(v); - } - // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiQuatKey>), l->end() ); - }} - break; - - // //////////////////////////////////////////////////////////////////// - // SCALING KEYFRAME - case Discreet3DS::CHUNK_TRACKSCALE: - { - stream->IncPtr(10); - const unsigned int numFrames = stream->GetI2(); - stream->IncPtr(2); - - bool sortKeys = false; - std::vector<aiVectorKey>* l = &mCurrentNode->aScalingKeys; - l->reserve(numFrames); - - for (unsigned int i = 0; i < numFrames;++i) { - const unsigned int fidx = stream->GetI4(); - SkipTCBInfo(); - - // Setup a new key - aiVectorKey v; - v.mTime = (double)fidx; - - // ... and read its value - v.mValue.x = stream->GetF4(); - v.mValue.y = stream->GetF4(); - v.mValue.z = stream->GetF4(); - - // check whether we'll need to sort the keys - if (!l->empty() && v.mTime <= l->back().mTime) - sortKeys = true; - - // Remove zero-scalings on singular axes - they've been reported to be there erroneously in some strange files - if (!v.mValue.x) v.mValue.x = 1.f; - if (!v.mValue.y) v.mValue.y = 1.f; - if (!v.mValue.z) v.mValue.z = 1.f; - - l->push_back(v); - } - // Sort all keys with ascending time values and remove duplicates? - if (sortKeys) { - std::stable_sort(l->begin(),l->end()); - l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() ); - }} - break; - }; - - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -// Read a face chunk - it contains smoothing groups and material assignments -void Discreet3DSImporter::ParseFaceChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // Get the mesh we're currently working on - D3DS::Mesh& mMesh = mScene->mMeshes.back(); - - // Get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_SMOOLIST: - { - // This is the list of smoothing groups - a bitfield for every face. - // Up to 32 smoothing groups assigned to a single face. - unsigned int num = chunkSize/4, m = 0; - for (std::vector<D3DS::Face>::iterator i = mMesh.mFaces.begin(); m != num;++i, ++m) { - // nth bit is set for nth smoothing group - (*i).iSmoothGroup = stream->GetI4(); - }} - break; - - case Discreet3DS::CHUNK_FACEMAT: - { - // at fist an asciiz with the material name - const char* sz = (const char*)stream->GetPtr(); - while (stream->GetI1()); - - // find the index of the material - unsigned int idx = 0xcdcdcdcd, cnt = 0; - for (std::vector<D3DS::Material>::const_iterator i = mScene->mMaterials.begin();i != mScene->mMaterials.end();++i,++cnt) { - // use case independent comparisons. hopefully it will work. - if ((*i).mName.length() && !ASSIMP_stricmp(sz, (*i).mName.c_str())) { - idx = cnt; - break; - } - } - if (0xcdcdcdcd == idx) { - DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz); - } - - // Now continue and read all material indices - cnt = (uint16_t)stream->GetI2(); - for (unsigned int i = 0; i < cnt;++i) { - unsigned int fidx = (uint16_t)stream->GetI2(); - - // check range - if (fidx >= mMesh.mFaceMaterials.size()) { - DefaultLogger::get()->error("3DS: Invalid face index in face material list"); - } - else mMesh.mFaceMaterials[fidx] = idx; - }} - break; - }; - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -// Read a mesh chunk. Here's the actual mesh data -void Discreet3DSImporter::ParseMeshChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // Get the mesh we're currently working on - D3DS::Mesh& mMesh = mScene->mMeshes.back(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_VERTLIST: - { - // This is the list of all vertices in the current mesh - int num = (int)(uint16_t)stream->GetI2(); - mMesh.mPositions.reserve(num); - while (num-- > 0) { - aiVector3D v; - v.x = stream->GetF4(); - v.y = stream->GetF4(); - v.z = stream->GetF4(); - mMesh.mPositions.push_back(v); - }} - break; - case Discreet3DS::CHUNK_TRMATRIX: - { - // This is the RLEATIVE transformation matrix of the current mesh. Vertices are - // pretransformed by this matrix wonder. - mMesh.mMat.a1 = stream->GetF4(); - mMesh.mMat.b1 = stream->GetF4(); - mMesh.mMat.c1 = stream->GetF4(); - mMesh.mMat.a2 = stream->GetF4(); - mMesh.mMat.b2 = stream->GetF4(); - mMesh.mMat.c2 = stream->GetF4(); - mMesh.mMat.a3 = stream->GetF4(); - mMesh.mMat.b3 = stream->GetF4(); - mMesh.mMat.c3 = stream->GetF4(); - mMesh.mMat.a4 = stream->GetF4(); - mMesh.mMat.b4 = stream->GetF4(); - mMesh.mMat.c4 = stream->GetF4(); - } - break; - - case Discreet3DS::CHUNK_MAPLIST: - { - // This is the list of all UV coords in the current mesh - int num = (int)(uint16_t)stream->GetI2(); - mMesh.mTexCoords.reserve(num); - while (num-- > 0) { - aiVector3D v; - v.x = stream->GetF4(); - v.y = stream->GetF4(); - mMesh.mTexCoords.push_back(v); - }} - break; - - case Discreet3DS::CHUNK_FACELIST: - { - // This is the list of all faces in the current mesh - int num = (int)(uint16_t)stream->GetI2(); - mMesh.mFaces.reserve(num); - while (num-- > 0) { - // 3DS faces are ALWAYS triangles - mMesh.mFaces.push_back(D3DS::Face()); - D3DS::Face& sFace = mMesh.mFaces.back(); - - sFace.mIndices[0] = (uint16_t)stream->GetI2(); - sFace.mIndices[1] = (uint16_t)stream->GetI2(); - sFace.mIndices[2] = (uint16_t)stream->GetI2(); - - stream->IncPtr(2); // skip edge visibility flag - } - - // Resize the material array (0xcdcdcdcd marks the default material; so if a face is - // not referenced by a material, $$DEFAULT will be assigned to it) - mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd); - - // Larger 3DS files could have multiple FACE chunks here - chunkSize = stream->GetRemainingSizeToLimit(); - if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) ) - ParseFaceChunk(); - } - break; - }; - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -// Read a 3DS material chunk -void Discreet3DSImporter::ParseMaterialChunk() -{ - ASSIMP_3DS_BEGIN_CHUNK(); - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_MAT_MATNAME: - - { - // The material name string is already zero-terminated, but we need to be sure ... - const char* sz = (const char*)stream->GetPtr(); - unsigned int cnt = 0; - while (stream->GetI1()) - ++cnt; - - if (!cnt) { - // This may not be, we use the default name instead - DefaultLogger::get()->error("3DS: Empty material name"); - } - else mScene->mMaterials.back().mName = std::string(sz,cnt); - } - break; - - case Discreet3DS::CHUNK_MAT_DIFFUSE: - { - // This is the diffuse material color - aiColor3D* pc = &mScene->mMaterials.back().mDiffuse; - ParseColorChunk(pc); - if (is_qnan(pc->r)) { - // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk"); - pc->r = pc->g = pc->b = 1.0f; - }} - break; - - case Discreet3DS::CHUNK_MAT_SPECULAR: - { - // This is the specular material color - aiColor3D* pc = &mScene->mMaterials.back().mSpecular; - ParseColorChunk(pc); - if (is_qnan(pc->r)) { - // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk"); - pc->r = pc->g = pc->b = 1.0f; - }} - break; - - case Discreet3DS::CHUNK_MAT_AMBIENT: - { - // This is the ambient material color - aiColor3D* pc = &mScene->mMaterials.back().mAmbient; - ParseColorChunk(pc); - if (is_qnan(pc->r)) { - // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk"); - pc->r = pc->g = pc->b = 0.0f; - }} - break; - - case Discreet3DS::CHUNK_MAT_SELF_ILLUM: - { - // This is the emissive material color - aiColor3D* pc = &mScene->mMaterials.back().mEmissive; - ParseColorChunk(pc); - if (is_qnan(pc->r)) { - // color chunk is invalid. Simply ignore it - DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk"); - pc->r = pc->g = pc->b = 0.0f; - }} - break; - - case Discreet3DS::CHUNK_MAT_TRANSPARENCY: - { - // This is the material's transparency - float* pcf = &mScene->mMaterials.back().mTransparency; - *pcf = ParsePercentageChunk(); - - // NOTE: transparency, not opacity - if (is_qnan(*pcf)) - *pcf = 1.0f; - else *pcf = 1.0f - *pcf * (float)0xFFFF / 100.0f; - } - break; - - case Discreet3DS::CHUNK_MAT_SHADING: - // This is the material shading mode - mScene->mMaterials.back().mShading = (D3DS::Discreet3DS::shadetype3ds)stream->GetI2(); - break; - - case Discreet3DS::CHUNK_MAT_TWO_SIDE: - // This is the two-sided flag - mScene->mMaterials.back().mTwoSided = true; - break; - - case Discreet3DS::CHUNK_MAT_SHININESS: - { // This is the shininess of the material - float* pcf = &mScene->mMaterials.back().mSpecularExponent; - *pcf = ParsePercentageChunk(); - if (is_qnan(*pcf)) - *pcf = 0.0f; - else *pcf *= (float)0xFFFF; - } - break; - - case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT: - { // This is the shininess strength of the material - float* pcf = &mScene->mMaterials.back().mShininessStrength; - *pcf = ParsePercentageChunk(); - if (is_qnan(*pcf)) - *pcf = 0.0f; - else *pcf *= (float)0xffff / 100.0f; - } - break; - - case Discreet3DS::CHUNK_MAT_SELF_ILPCT: - { // This is the self illumination strength of the material - float f = ParsePercentageChunk(); - if (is_qnan(f)) - f = 0.0f; - else f *= (float)0xFFFF / 100.0f; - mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f); - } - break; - - // Parse texture chunks - case Discreet3DS::CHUNK_MAT_TEXTURE: - // Diffuse texture - ParseTextureChunk(&mScene->mMaterials.back().sTexDiffuse); - break; - case Discreet3DS::CHUNK_MAT_BUMPMAP: - // Height map - ParseTextureChunk(&mScene->mMaterials.back().sTexBump); - break; - case Discreet3DS::CHUNK_MAT_OPACMAP: - // Opacity texture - ParseTextureChunk(&mScene->mMaterials.back().sTexOpacity); - break; - case Discreet3DS::CHUNK_MAT_MAT_SHINMAP: - // Shininess map - ParseTextureChunk(&mScene->mMaterials.back().sTexShininess); - break; - case Discreet3DS::CHUNK_MAT_SPECMAP: - // Specular map - ParseTextureChunk(&mScene->mMaterials.back().sTexSpecular); - break; - case Discreet3DS::CHUNK_MAT_SELFIMAP: - // Self-illumination (emissive) map - ParseTextureChunk(&mScene->mMaterials.back().sTexEmissive); - break; - case Discreet3DS::CHUNK_MAT_REFLMAP: - // Reflection map - ParseTextureChunk(&mScene->mMaterials.back().sTexReflective); - break; - }; - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut) -{ - ASSIMP_3DS_BEGIN_CHUNK(); - - // get chunk type - switch (chunk.Flag) - { - case Discreet3DS::CHUNK_MAPFILE: - { - // The material name string is already zero-terminated, but we need to be sure ... - const char* sz = (const char*)stream->GetPtr(); - unsigned int cnt = 0; - while (stream->GetI1()) - ++cnt; - pcOut->mMapName = std::string(sz,cnt); - } - break; - - - case Discreet3DS::CHUNK_PERCENTF: - // Manually parse the blend factor - pcOut->mTextureBlend = stream->GetF4(); - break; - - case Discreet3DS::CHUNK_PERCENTW: - // Manually parse the blend factor - pcOut->mTextureBlend = (float)((uint16_t)stream->GetI2()) / 100.0f; - break; - - case Discreet3DS::CHUNK_MAT_MAP_USCALE: - // Texture coordinate scaling in the U direction - pcOut->mScaleU = stream->GetF4(); - if (0.0f == pcOut->mScaleU) - { - DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1."); - pcOut->mScaleU = 1.0f; - } - break; - case Discreet3DS::CHUNK_MAT_MAP_VSCALE: - // Texture coordinate scaling in the V direction - pcOut->mScaleV = stream->GetF4(); - if (0.0f == pcOut->mScaleV) - { - DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1."); - pcOut->mScaleV = 1.0f; - } - break; - - case Discreet3DS::CHUNK_MAT_MAP_UOFFSET: - // Texture coordinate offset in the U direction - pcOut->mOffsetU = -stream->GetF4(); - break; - - case Discreet3DS::CHUNK_MAT_MAP_VOFFSET: - // Texture coordinate offset in the V direction - pcOut->mOffsetV = stream->GetF4(); - break; - - case Discreet3DS::CHUNK_MAT_MAP_ANG: - // Texture coordinate rotation, CCW in DEGREES - pcOut->mRotation = -AI_DEG_TO_RAD( stream->GetF4() ); - break; - - case Discreet3DS::CHUNK_MAT_MAP_TILING: - { - const uint16_t iFlags = stream->GetI2(); - - // Get the mapping mode (for both axes) - if (iFlags & 0x2u) - pcOut->mMapMode = aiTextureMapMode_Mirror; - - else if (iFlags & 0x10u) - pcOut->mMapMode = aiTextureMapMode_Decal; - - // wrapping in all remaining cases - else pcOut->mMapMode = aiTextureMapMode_Wrap; - } - break; - }; - - ASSIMP_3DS_END_CHUNK(); -} - -// ------------------------------------------------------------------------------------------------ -// Read a percentage chunk -float Discreet3DSImporter::ParsePercentageChunk() -{ - Discreet3DS::Chunk chunk; - ReadChunk(&chunk); - - if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) - return stream->GetF4(); - else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) - return (float)((uint16_t)stream->GetI2()) / (float)0xFFFF; - return get_qnan(); -} - -// ------------------------------------------------------------------------------------------------ -// Read a color chunk. If a percentage chunk is found instead it is read as a grayscale color -void Discreet3DSImporter::ParseColorChunk(aiColor3D* out, - bool acceptPercent) -{ - ai_assert(out != NULL); - - // error return value - const float qnan = get_qnan(); - static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan); - - Discreet3DS::Chunk chunk; - ReadChunk(&chunk); - const unsigned int diff = chunk.Size - sizeof(Discreet3DS::Chunk); - - bool bGamma = false; - - // Get the type of the chunk - switch(chunk.Flag) - { - case Discreet3DS::CHUNK_LINRGBF: - bGamma = true; - - case Discreet3DS::CHUNK_RGBF: - if (sizeof(float) * 3 > diff) { - *out = clrError; - return; - } - out->r = stream->GetF4(); - out->g = stream->GetF4(); - out->b = stream->GetF4(); - break; - - case Discreet3DS::CHUNK_LINRGBB: - bGamma = true; - case Discreet3DS::CHUNK_RGBB: - if (sizeof(char) * 3 > diff) { - *out = clrError; - return; - } - out->r = (float)(uint8_t)stream->GetI1() / 255.0f; - out->g = (float)(uint8_t)stream->GetI1() / 255.0f; - out->b = (float)(uint8_t)stream->GetI1() / 255.0f; - break; - - // Percentage chunks are accepted, too. - case Discreet3DS::CHUNK_PERCENTF: - if (acceptPercent && 4 <= diff) { - out->g = out->b = out->r = stream->GetF4(); - break; - } - *out = clrError; - return; - - case Discreet3DS::CHUNK_PERCENTW: - if (acceptPercent && 1 <= diff) { - out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f; - break; - } - *out = clrError; - return; - - default: - stream->IncPtr(diff); - // Skip unknown chunks, hope this won't cause any problems. - return ParseColorChunk(out,acceptPercent); - }; -} - -#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/3rdparty/assimp/code/3DSLoader.h b/3rdparty/assimp/code/3DSLoader.h deleted file mode 100644 index 133a7c8e..00000000 --- a/3rdparty/assimp/code/3DSLoader.h +++ /dev/null @@ -1,280 +0,0 @@ - -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 3DSLoader.h - * @brief 3DS File format loader - */ -#ifndef AI_3DSIMPORTER_H_INC -#define AI_3DSIMPORTER_H_INC - -#include "BaseImporter.h" -#include "../include/aiTypes.h" - -struct aiNode; -#include "3DSHelper.h" - -namespace Assimp { -class MaterialHelper; - -using namespace D3DS; - -// --------------------------------------------------------------------------------- -/** Importer class for 3D Studio r3 and r4 3DS files - */ -class Discreet3DSImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - Discreet3DSImporter(); - - /** Destructor, private as well */ - ~Discreet3DSImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Converts a temporary material to the outer representation - */ - void ConvertMaterial(D3DS::Material& p_cMat, - MaterialHelper& p_pcOut); - - // ------------------------------------------------------------------- - /** Read a chunk - * - * @param pcOut Receives the current chunk - */ - void ReadChunk(Discreet3DS::Chunk* pcOut); - - // ------------------------------------------------------------------- - /** Parse a percentage chunk. mCurrent will point to the next - * chunk behind afterwards. If no percentage chunk is found - * QNAN is returned. - */ - float ParsePercentageChunk(); - - // ------------------------------------------------------------------- - /** Parse a color chunk. mCurrent will point to the next - * chunk behind afterwards. If no color chunk is found - * QNAN is returned in all members. - */ - void ParseColorChunk(aiColor3D* p_pcOut, - bool p_bAcceptPercent = true); - - - // ------------------------------------------------------------------- - /** Skip a chunk in the file - */ - void SkipChunk(); - - // ------------------------------------------------------------------- - /** Generate the nodegraph - */ - void GenerateNodeGraph(aiScene* pcOut); - - // ------------------------------------------------------------------- - /** Parse a main top-level chunk in the file - */ - void ParseMainChunk(); - - // ------------------------------------------------------------------- - /** Parse a top-level chunk in the file - */ - void ParseChunk(const char* name, unsigned int num); - - // ------------------------------------------------------------------- - /** Parse a top-level editor chunk in the file - */ - void ParseEditorChunk(); - - // ------------------------------------------------------------------- - /** Parse a top-level object chunk in the file - */ - void ParseObjectChunk(); - - // ------------------------------------------------------------------- - /** Parse a material chunk in the file - */ - void ParseMaterialChunk(); - - // ------------------------------------------------------------------- - /** Parse a mesh chunk in the file - */ - void ParseMeshChunk(); - - // ------------------------------------------------------------------- - /** Parse a light chunk in the file - */ - void ParseLightChunk(); - - // ------------------------------------------------------------------- - /** Parse a camera chunk in the file - */ - void ParseCameraChunk(); - - // ------------------------------------------------------------------- - /** Parse a face list chunk in the file - */ - void ParseFaceChunk(); - - // ------------------------------------------------------------------- - /** Parse a keyframe chunk in the file - */ - void ParseKeyframeChunk(); - - // ------------------------------------------------------------------- - /** Parse a hierarchy chunk in the file - */ - void ParseHierarchyChunk(uint16_t parent); - - // ------------------------------------------------------------------- - /** Parse a texture chunk in the file - */ - void ParseTextureChunk(D3DS::Texture* pcOut); - - // ------------------------------------------------------------------- - /** Convert the meshes in the file - */ - void ConvertMeshes(aiScene* pcOut); - - // ------------------------------------------------------------------- - /** Replace the default material in the scene - */ - void ReplaceDefaultMaterial(); - - // ------------------------------------------------------------------- - /** Convert the whole scene - */ - void ConvertScene(aiScene* pcOut); - - // ------------------------------------------------------------------- - /** generate unique vertices for a mesh - */ - void MakeUnique(D3DS::Mesh& sMesh); - - // ------------------------------------------------------------------- - /** Add a node to the node graph - */ - void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn, - aiMatrix4x4& absTrafo); - - // ------------------------------------------------------------------- - /** Search for a node in the graph. - * Called recursively - */ - void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent); - - // ------------------------------------------------------------------- - /** Apply the master scaling factor to the mesh - */ - void ApplyMasterScale(aiScene* pScene); - - // ------------------------------------------------------------------- - /** Clamp all indices in the file to a valid range - */ - void CheckIndices(D3DS::Mesh& sMesh); - - // ------------------------------------------------------------------- - /** Skip the TCB info in a track key - */ - void SkipTCBInfo(); - -protected: - - /** Stream to read from */ - StreamReaderLE* stream; - - /** Last touched node index */ - short mLastNodeIndex; - - /** Current node, root node */ - D3DS::Node* mCurrentNode, *mRootNode; - - /** Scene under construction */ - D3DS::Scene* mScene; - - /** Ambient base color of the scene */ - aiColor3D mClrAmbient; - - /** Master scaling factor of the scene */ - float mMasterScale; - - /** Path to the background image of the scene */ - std::string mBackgroundImage; - bool bHasBG; - - /** true if PRJ file */ - bool bIsPrj; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/ACLoader.cpp b/3rdparty/assimp/code/ACLoader.cpp deleted file mode 100644 index c0fd3178..00000000 --- a/3rdparty/assimp/code/ACLoader.cpp +++ /dev/null @@ -1,856 +0,0 @@ - -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 AC3D importer class */ - -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_AC_IMPORTER - -// internal headers -#include "ACLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" -#include "Subdivision.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -// skip to the next token -#define AI_AC_SKIP_TO_NEXT_TOKEN() \ - if (!SkipSpaces(&buffer)) \ - { \ - DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \ - continue; \ - } - -// ------------------------------------------------------------------------------------------------ -// read a string (may be enclosed in double quotation marks). buffer must point to " -#define AI_AC_GET_STRING(out) \ - ++buffer; \ - const char* sz = buffer; \ - while ('\"' != *buffer) \ - { \ - if (IsLineEnd( *buffer )) \ - { \ - DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \ - out = "ERROR"; \ - break; \ - } \ - ++buffer; \ - } \ - if (IsLineEnd( *buffer ))continue; \ - out = std::string(sz,(unsigned int)(buffer-sz)); \ - ++buffer; - - -// ------------------------------------------------------------------------------------------------ -// read 1 to n floats prefixed with an optional predefined identifier -#define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name,name_length,num,out) \ - AI_AC_SKIP_TO_NEXT_TOKEN(); \ - if (name_length) \ - { \ - if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \ - { \ - DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \ - continue; \ - } \ - buffer += name_length+1; \ - } \ - for (unsigned int i = 0; i < num;++i) \ - { \ - AI_AC_SKIP_TO_NEXT_TOKEN(); \ - buffer = fast_atof_move(buffer,((float*)out)[i]); \ - } - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -AC3DImporter::AC3DImporter() -{ - // nothing to be done here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -AC3DImporter::~AC3DImporter() -{ - // nothing to be done here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool AC3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - std::string extension = GetExtension(pFile); - - // fixme: are acc and ac3d *really* used? Some sources say they are - if (extension == "ac" || extension == "ac3d" || extension == "acc") { - return true; - } - if (!extension.length() || checkSig) { - uint32_t token = AI_MAKE_MAGIC("AC3D"); - return CheckMagicToken(pIOHandler,pFile,&token,1,0); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get list of file extensions handled by this loader -void AC3DImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("ac"); - extensions.insert("acc"); - extensions.insert("ac3d"); -} - -// ------------------------------------------------------------------------------------------------ -// Get a pointer to the next line from the file -bool AC3DImporter::GetNextLine( ) -{ - SkipLine(&buffer); - return SkipSpaces(&buffer); -} - -// ------------------------------------------------------------------------------------------------ -// Parse an object section in an AC file -void AC3DImporter::LoadObjectSection(std::vector<Object>& objects) -{ - if (!TokenMatch(buffer,"OBJECT",6)) - return; - - SkipSpaces(&buffer); - - ++mNumMeshes; - - objects.push_back(Object()); - Object& obj = objects.back(); - - aiLight* light = NULL; - if (!ASSIMP_strincmp(buffer,"light",5)) - { - // This is a light source. Add it to the list - mLights->push_back(light = new aiLight()); - - // Return a point light with no attenuation - light->mType = aiLightSource_POINT; - light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f); - light->mAttenuationConstant = 1.f; - - // Generate a default name for both the light source and the node - // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version. - light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",static_cast<unsigned int>(mLights->size())-1); - obj.name = std::string( light->mName.data ); - - DefaultLogger::get()->debug("AC3D: Light source encountered"); - obj.type = Object::Light; - } - else if (!ASSIMP_strincmp(buffer,"group",5)) - { - obj.type = Object::Group; - } - else if (!ASSIMP_strincmp(buffer,"world",5)) - { - obj.type = Object::World; - } - else obj.type = Object::Poly; - while (GetNextLine()) - { - if (TokenMatch(buffer,"kids",4)) - { - SkipSpaces(&buffer); - unsigned int num = strtol10(buffer,&buffer); - GetNextLine(); - if (num) - { - // load the children of this object recursively - obj.children.reserve(num); - for (unsigned int i = 0; i < num; ++i) - LoadObjectSection(obj.children); - } - return; - } - else if (TokenMatch(buffer,"name",4)) - { - SkipSpaces(&buffer); - AI_AC_GET_STRING(obj.name); - - // If this is a light source, we'll also need to store - // the name of the node in it. - if (light) - { - light->mName.Set(obj.name); - } - } - else if (TokenMatch(buffer,"texture",7)) - { - SkipSpaces(&buffer); - AI_AC_GET_STRING(obj.texture); - } - else if (TokenMatch(buffer,"texrep",6)) - { - SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat); - if (!obj.texRepeat.x || !obj.texRepeat.y) - obj.texRepeat = aiVector2D (1.f,1.f); - } - else if (TokenMatch(buffer,"texoff",6)) - { - SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texOffset); - } - else if (TokenMatch(buffer,"rot",3)) - { - SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation); - } - else if (TokenMatch(buffer,"loc",3)) - { - SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation); - } - else if (TokenMatch(buffer,"subdiv",6)) - { - SkipSpaces(&buffer); - obj.subDiv = strtol10(buffer,&buffer); - } - else if (TokenMatch(buffer,"crease",6)) - { - SkipSpaces(&buffer); - obj.crease = fast_atof(buffer); - } - else if (TokenMatch(buffer,"numvert",7)) - { - SkipSpaces(&buffer); - - unsigned int t = strtol10(buffer,&buffer); - obj.vertices.reserve(t); - for (unsigned int i = 0; i < t;++i) - { - if (!GetNextLine()) - { - DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet"); - break; - } - else if (!IsNumeric(*buffer)) - { - DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet"); - --buffer; // make sure the line is processed a second time - break; - } - obj.vertices.push_back(aiVector3D()); - aiVector3D& v = obj.vertices.back(); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x); - } - } - else if (TokenMatch(buffer,"numsurf",7)) - { - SkipSpaces(&buffer); - - bool Q3DWorkAround = false; - - const unsigned int t = strtol10(buffer,&buffer); - obj.surfaces.reserve(t); - for (unsigned int i = 0; i < t;++i) - { - GetNextLine(); - if (!TokenMatch(buffer,"SURF",4)) - { - // FIX: this can occur for some files - Quick 3D for - // example writes no surf chunks - if (!Q3DWorkAround) - { - DefaultLogger::get()->warn("AC3D: SURF token was expected"); - DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled"); - } - --buffer; // make sure the line is processed a second time - // break; --- see fix notes above - - Q3DWorkAround = true; - } - SkipSpaces(&buffer); - obj.surfaces.push_back(Surface()); - Surface& surf = obj.surfaces.back(); - surf.flags = strtol_cppstyle(buffer); - - while (1) - { - if (!GetNextLine()) - { - DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete"); - break; - } - if (TokenMatch(buffer,"mat",3)) - { - SkipSpaces(&buffer); - surf.mat = strtol10(buffer); - } - else if (TokenMatch(buffer,"refs",4)) - { - // --- see fix notes above - if (Q3DWorkAround) - { - if (!surf.entries.empty()) - { - buffer -= 6; - break; - } - } - - SkipSpaces(&buffer); - const unsigned int m = strtol10(buffer); - surf.entries.reserve(m); - - obj.numRefs += m; - - for (unsigned int k = 0; k < m; ++k) - { - if (!GetNextLine()) - { - DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete"); - break; - } - surf.entries.push_back(Surface::SurfaceEntry()); - Surface::SurfaceEntry& entry = surf.entries.back(); - - entry.first = strtol10(buffer,&buffer); - SkipSpaces(&buffer); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second); - } - } - else - { - - --buffer; // make sure the line is processed a second time - break; - } - } - } - } - } - DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected"); -} - -// ------------------------------------------------------------------------------------------------ -// Convert a material from AC3DImporter::Material to aiMaterial -void AC3DImporter::ConvertMaterial(const Object& object, - const Material& matSrc, - MaterialHelper& matDest) -{ - aiString s; - - if (matSrc.name.length()) - { - s.Set(matSrc.name); - matDest.AddProperty(&s,AI_MATKEY_NAME); - } - if (object.texture.length()) - { - s.Set(object.texture); - matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); - - // UV transformation - if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y || - object.texOffset.x || object.texOffset.y) - { - aiUVTransform transform; - transform.mScaling = object.texRepeat; - transform.mTranslation = object.texOffset; - matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0)); - } - } - - matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE); - matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT); - matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE); - matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR); - - int n; - if (matSrc.shin) - { - n = aiShadingMode_Phong; - matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS); - } - else n = aiShadingMode_Gouraud; - matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL); - - float f = 1.f - matSrc.trans; - matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY); -} - -// ------------------------------------------------------------------------------------------------ -// Converts the loaded data to the internal verbose representation -aiNode* AC3DImporter::ConvertObjectSection(Object& object, - std::vector<aiMesh*>& meshes, - std::vector<MaterialHelper*>& outMaterials, - const std::vector<Material>& materials, - aiNode* parent) -{ - aiNode* node = new aiNode(); - node->mParent = parent; - if (object.vertices.size()) - { - if (!object.surfaces.size() || !object.numRefs) - { - /* " An object with 7 vertices (no surfaces, no materials defined). - This is a good way of getting point data into AC3D. - The Vertex->create convex-surface/object can be used on these - vertices to 'wrap' a 3d shape around them " - (http://www.opencity.info/html/ac3dfileformat.html) - - therefore: if no surfaces are defined return point data only - */ - - DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, " - "a point list is returned"); - - meshes.push_back(new aiMesh()); - aiMesh* mesh = meshes.back(); - - mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size(); - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; - aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - - for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts) - { - *verts = object.vertices[i]; - faces->mNumIndices = 1; - faces->mIndices = new unsigned int[1]; - faces->mIndices[0] = i; - } - - // use the primary material in this case. this should be the - // default material if all objects of the file contain points - // and no faces. - mesh->mMaterialIndex = 0; - outMaterials.push_back(new MaterialHelper()); - ConvertMaterial(object, materials[0], *outMaterials.back()); - } - else - { - // need to generate one or more meshes for this object. - // find out how many different materials we have - typedef std::pair< unsigned int, unsigned int > IntPair; - typedef std::vector< IntPair > MatTable; - MatTable needMat(materials.size(),IntPair(0,0)); - - std::vector<Surface>::iterator it,end = object.surfaces.end(); - std::vector<Surface::SurfaceEntry>::iterator it2,end2; - - for (it = object.surfaces.begin(); it != end; ++it) - { - register unsigned int idx = (*it).mat; - if (idx >= needMat.size()) - { - DefaultLogger::get()->error("AC3D: material index is out of range"); - idx = 0; - } - if ((*it).entries.empty()) - { - DefaultLogger::get()->warn("AC3D: surface her zero vertex references"); - } - - // validate all vertex indices to make sure we won't crash here - for (it2 = (*it).entries.begin(), - end2 = (*it).entries.end(); it2 != end2; ++it2) - { - if ((*it2).first >= object.vertices.size()) - { - DefaultLogger::get()->warn("AC3D: Invalid vertex reference"); - (*it2).first = 0; - } - } - - if (!needMat[idx].first)++node->mNumMeshes; - - switch ((*it).flags & 0xf) - { - // closed line - case 0x1: - - needMat[idx].first += (unsigned int)(*it).entries.size(); - needMat[idx].second += (unsigned int)(*it).entries.size()<<1u; - break; - - // unclosed line - case 0x2: - - needMat[idx].first += (unsigned int)(*it).entries.size()-1; - needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u; - break; - - // 0 == polygon, else unknown - default: - - if ((*it).flags & 0xf) - { - DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown"); - (*it).flags &= ~(0xf); - } - - // the number of faces increments by one, the number - // of vertices by surface.numref. - needMat[idx].first++; - needMat[idx].second += (unsigned int)(*it).entries.size(); - }; - } - unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes]; - unsigned int mat = 0; - const size_t oldm = meshes.size(); - for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end(); - cit != cend; ++cit, ++mat) - { - if (!(*cit).first)continue; - - // allocate a new aiMesh object - *pip++ = (unsigned int)meshes.size(); - aiMesh* mesh = new aiMesh(); - meshes.push_back(mesh); - - mesh->mMaterialIndex = (unsigned int)outMaterials.size(); - outMaterials.push_back(new MaterialHelper()); - ConvertMaterial(object, materials[mat], *outMaterials.back()); - - // allocate storage for vertices and normals - mesh->mNumFaces = (*cit).first; - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces]; - - mesh->mNumVertices = (*cit).second; - aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - unsigned int cur = 0; - - // allocate UV coordinates, but only if the texture name for the - // surface is not empty - aiVector3D* uv = NULL; - if (object.texture.length()) - { - uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - mesh->mNumUVComponents[0] = 2; - } - - for (it = object.surfaces.begin(); it != end; ++it) - { - if (mat == (*it).mat) - { - const Surface& src = *it; - - // closed polygon - unsigned int type = (*it).flags & 0xf; - if (!type) - { - aiFace& face = *faces++; - if ((face.mNumIndices = (unsigned int)src.entries.size())) - { - face.mIndices = new unsigned int[face.mNumIndices]; - for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices) - { - const Surface::SurfaceEntry& entry = src.entries[i]; - face.mIndices[i] = cur++; - - // copy vertex positions - *vertices = object.vertices[entry.first] + object.translation; - - - // copy texture coordinates - if (uv) - { - uv->x = entry.second.x; - uv->y = entry.second.y; - ++uv; - } - } - } - } - else - { - - it2 = (*it).entries.begin(); - - // either a closed or an unclosed line - register unsigned int tmp = (unsigned int)(*it).entries.size(); - if (0x2 == type)--tmp; - for (unsigned int m = 0; m < tmp;++m) - { - aiFace& face = *faces++; - - face.mNumIndices = 2; - face.mIndices = new unsigned int[2]; - face.mIndices[0] = cur++; - face.mIndices[1] = cur++; - - // copy vertex positions - *vertices++ = object.vertices[(*it2).first]; - - // copy texture coordinates - if (uv) - { - uv->x = (*it2).second.x; - uv->y = (*it2).second.y; - ++uv; - } - - - if (0x1 == type && tmp-1 == m) - { - // if this is a closed line repeat its beginning now - it2 = (*it).entries.begin(); - } - else ++it2; - - // second point - *vertices++ = object.vertices[(*it2).first]; - - if (uv) - { - uv->x = (*it2).second.x; - uv->y = (*it2).second.y; - ++uv; - } - } - } - } - } - } - - // Now apply catmull clark subdivision if necessary. We split meshes into - // materials which is not done by AC3D during smoothing, so we need to - // collect all meshes using the same material group. - if (object.subDiv) { - if (configEvalSubdivision) { - boost::scoped_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); - DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name); - - std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL); - div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true); - std::copy(cpy.begin(),cpy.end(),meshes.begin()+oldm); - - // previous meshes are deleted vy Subdivide(). - } - else { - DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: " - +object.name); - } - } - } - } - - if (object.name.length()) - node->mName.Set(object.name); - else - { - // generate a name depending on the type of the node - switch (object.type) - { - case Object::Group: - node->mName.length = ::sprintf(node->mName.data,"ACGroup_%i",groups++); - break; - case Object::Poly: - node->mName.length = ::sprintf(node->mName.data,"ACPoly_%i",polys++); - break; - case Object::Light: - node->mName.length = ::sprintf(node->mName.data,"ACLight_%i",lights++); - break; - - // there shouldn't be more than one world, but we don't care - case Object::World: - node->mName.length = ::sprintf(node->mName.data,"ACWorld_%i",worlds++); - break; - } - } - - - // setup the local transformation matrix of the object - // compute the transformation offset to the parent node - node->mTransformation = aiMatrix4x4 ( object.rotation ); - - if (object.type == Object::Group || !object.numRefs) - { - node->mTransformation.a4 = object.translation.x; - node->mTransformation.b4 = object.translation.y; - node->mTransformation.c4 = object.translation.z; - } - - // add children to the object - if (object.children.size()) - { - node->mNumChildren = (unsigned int)object.children.size(); - node->mChildren = new aiNode*[node->mNumChildren]; - for (unsigned int i = 0; i < node->mNumChildren;++i) - { - node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials,node); - } - } - - return node; -} - -// ------------------------------------------------------------------------------------------------ -void AC3DImporter::SetupProperties(const Importer* pImp) -{ - configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false; - configEvalSubdivision = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION,1) ? true : false; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void AC3DImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open AC3D file " + pFile + "."); - - // allocate storage and copy the contents of the file to a memory buffer - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - - buffer = &mBuffer2[0]; - mNumMeshes = 0; - - lights = polys = worlds = groups = 0; - - if (::strncmp(buffer,"AC3D",4)) { - throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found"); - } - - // print the file format version to the console - unsigned int version = HexDigitToDecimal( buffer[4] ); - char msg[3]; - ASSIMP_itoa10(msg,3,version); - DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg); - - std::vector<Material> materials; - materials.reserve(5); - - std::vector<Object> rootObjects; - rootObjects.reserve(5); - - std::vector<aiLight*> lights; - mLights = & lights; - - while (GetNextLine()) - { - if (TokenMatch(buffer,"MATERIAL",8)) - { - materials.push_back(Material()); - Material& mat = materials.back(); - - // manually parse the material ... sscanf would use the buldin atof ... - // Format: (name) rgb %f %f %f amb %f %f %f emis %f %f %f spec %f %f %f shi %d trans %f - - AI_AC_SKIP_TO_NEXT_TOKEN(); - if ('\"' == *buffer) - { - AI_AC_GET_STRING(mat.name); - AI_AC_SKIP_TO_NEXT_TOKEN(); - } - - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin); - AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans); - } - LoadObjectSection(rootObjects); - } - - if (rootObjects.empty() || !mNumMeshes) - { - throw DeadlyImportError("AC3D: No meshes have been loaded"); - } - if (materials.empty()) - { - DefaultLogger::get()->warn("AC3D: No material has been found"); - materials.push_back(Material()); - } - - mNumMeshes += (mNumMeshes>>2u) + 1; - std::vector<aiMesh*> meshes; - meshes.reserve(mNumMeshes); - - std::vector<MaterialHelper*> omaterials; - materials.reserve(mNumMeshes); - - // generate a dummy root if there are multiple objects on the top layer - Object* root; - if (1 == rootObjects.size()) - root = &rootObjects[0]; - else - { - root = new Object(); - } - - // now convert the imported stuff to our output data structure - pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials); - if (1 != rootObjects.size())delete root; - - if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4)) - pScene->mRootNode->mName.Set("<AC3DWorld>"); - - // copy meshes - if (meshes.empty()) - { - throw DeadlyImportError("An unknown error occured during converting"); - } - pScene->mNumMeshes = (unsigned int)meshes.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*)); - - // copy materials - pScene->mNumMaterials = (unsigned int)omaterials.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*)); - - // copy lights - pScene->mNumLights = (unsigned int)lights.size(); - if (lights.size()) - { - pScene->mLights = new aiLight*[lights.size()]; - ::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*)); - } -} - -#endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER diff --git a/3rdparty/assimp/code/ACLoader.h b/3rdparty/assimp/code/ACLoader.h deleted file mode 100644 index f11d6b4a..00000000 --- a/3rdparty/assimp/code/ACLoader.h +++ /dev/null @@ -1,271 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ACLoader.h - * @brief Declaration of the .ac importer class. - */ -#ifndef AI_AC3DLOADER_H_INCLUDED -#define AI_AC3DLOADER_H_INCLUDED - -#include <vector> - -#include "BaseImporter.h" -#include "../include/aiTypes.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** AC3D (*.ac) importer class -*/ -class AC3DImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - AC3DImporter(); - - /** Destructor, private as well */ - ~AC3DImporter(); - - - // Represents an AC3D material - struct Material - { - Material() - : rgb (0.6f,0.6f,0.6f) - , spec (1.f,1.f,1.f) - , shin (0.f) - , trans (0.f) - {} - - // base color of the material - aiColor3D rgb; - - // ambient color of the material - aiColor3D amb; - - // emissive color of the material - aiColor3D emis; - - // specular color of the material - aiColor3D spec; - - // shininess exponent - float shin; - - // transparency. 0 == opaque - float trans; - - // name of the material. optional. - std::string name; - }; - - // Represents an AC3D surface - struct Surface - { - Surface() - : mat (0) - , flags (0) - {} - - unsigned int mat,flags; - - typedef std::pair<unsigned int, aiVector2D > SurfaceEntry; - std::vector< SurfaceEntry > entries; - }; - - // Represents an AC3D object - struct Object - { - Object() - : type (World) - , name( "" ) - , children() - , texture( "" ) - , texRepeat( 1.f, 1.f ) - , texOffset( 0.0f, 0.0f ) - , rotation() - , translation() - , vertices() - , surfaces() - , numRefs (0) - , subDiv (0) - {} - - // Type description - enum Type - { - World = 0x0, - Poly = 0x1, - Group = 0x2, - Light = 0x4 - } type; - - // name of the object - std::string name; - - // object children - std::vector<Object> children; - - // texture to be assigned to all surfaces of the object - std::string texture; - - // texture repat factors (scaling for all coordinates) - aiVector2D texRepeat, texOffset; - - // rotation matrix - aiMatrix3x3 rotation; - - // translation vector - aiVector3D translation; - - // vertices - std::vector<aiVector3D> vertices; - - // surfaces - std::vector<Surface> surfaces; - - // number of indices (= num verts in verbose format) - unsigned int numRefs; - - // number of subdivisions to be performed on the - // imported data - unsigned int subDiv; - - // max angle limit for smoothing - float crease; - }; - - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details*/ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list.*/ - void SetupProperties(const Importer* pImp); - -private: - - // ------------------------------------------------------------------- - /** Get the next line from the file. - * @return false if the end of the file was reached*/ - bool GetNextLine(); - - // ------------------------------------------------------------------- - /** Load the object section. This method is called recursively to - * load subobjects, the method returns after a 'kids 0' was - * encountered. - * @objects List of output objects*/ - void LoadObjectSection(std::vector<Object>& objects); - - // ------------------------------------------------------------------- - /** Convert all objects into meshes and nodes. - * @param object Current object to work on - * @param meshes Pointer to the list of output meshes - * @param outMaterials List of output materials - * @param materials Material list - * @param Scenegraph node for the object */ - aiNode* ConvertObjectSection(Object& object, - std::vector<aiMesh*>& meshes, - std::vector<MaterialHelper*>& outMaterials, - const std::vector<Material>& materials, - aiNode* parent = NULL); - - // ------------------------------------------------------------------- - /** Convert a material - * @param object Current object - * @param matSrc Source material description - * @param matDest Destination material to be filled */ - void ConvertMaterial(const Object& object, - const Material& matSrc, - MaterialHelper& matDest); - -private: - - - // points to the next data line - const char* buffer; - - // Configuration option: if enabled, up to two meshes - // are generated per material: those faces who have - // their bf cull flags set are separated. - bool configSplitBFCull; - - // Configuration switch: subdivision surfaces are only - // evaluated if the value is true. - bool configEvalSubdivision; - - // counts how many objects we have in the tree. - // basing on this information we can find a - // good estimate how many meshes we'll have in the final scene. - unsigned int mNumMeshes; - - // current list of light sources - std::vector<aiLight*>* mLights; - - // name counters - unsigned int lights, groups, polys, worlds; -}; - -} // end of namespace Assimp - -#endif // AI_AC3DIMPORTER_H_INC diff --git a/3rdparty/assimp/code/ASELoader.cpp b/3rdparty/assimp/code/ASELoader.cpp deleted file mode 100644 index fc3df8b9..00000000 --- a/3rdparty/assimp/code/ASELoader.cpp +++ /dev/null @@ -1,1302 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ASELoader.cpp - * @brief Implementation of the ASE importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER - -// internal headers -#include "ASELoader.h" -#include "MaterialSystem.h" -#include "StringComparison.h" -#include "SkeletonMeshBuilder.h" -#include "TargetAnimation.h" - -// utilities -#include "fast_atof.h" - -using namespace Assimp; -using namespace Assimp::ASE; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -ASEImporter::ASEImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ASEImporter::~ASEImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const -{ - // check file extension - const std::string extension = GetExtension(pFile); - - if ( extension == "ase" || extension == "ask") - return true; - - if ((!extension.length() || cs) && pIOHandler) { - const char* tokens[] = {"*3dsmax_asciiexport"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void ASEImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("ase"); - extensions.insert("ask"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration options -void ASEImporter::SetupProperties(const Importer* pImp) -{ - configRecomputeNormals = (pImp->GetPropertyInteger( - AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void ASEImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open ASE file " + pFile + "."); - } - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - - this->mBuffer = &mBuffer2[0]; - this->pcScene = pScene; - - // ------------------------------------------------------------------ - // Guess the file format by looking at the extension - // ASC is considered to be the older format 110, - // ASE is the actual version 200 (that is currently written by max) - // ------------------------------------------------------------------ - unsigned int defaultFormat; - std::string::size_type s = pFile.length()-1; - switch (pFile.c_str()[s]) { - - case 'C': - case 'c': - defaultFormat = AI_ASE_OLD_FILE_FORMAT; - break; - default: - defaultFormat = AI_ASE_NEW_FILE_FORMAT; - }; - - // Construct an ASE parser and parse the file - ASE::Parser parser(mBuffer,defaultFormat); - mParser = &parser; - mParser->Parse(); - - //------------------------------------------------------------------ - // Check whether we god at least one mesh. If we did - generate - // materials and copy meshes. - // ------------------------------------------------------------------ - if ( !mParser->m_vMeshes.empty()) { - - // If absolutely no material has been loaded from the file - // we need to generate a default material - GenerateDefaultMaterial(); - - // process all meshes - bool tookNormals = false; - std::vector<aiMesh*> avOutMeshes; - avOutMeshes.reserve(mParser->m_vMeshes.size()*2); - for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) { - if ((*i).bSkip) { - continue; - } - BuildUniqueRepresentation(*i); - - // Need to generate proper vertex normals if necessary - if (GenerateNormals(*i)) { - tookNormals = true; - } - - // Convert all meshes to aiMesh objects - ConvertMeshes(*i,avOutMeshes); - } - if (tookNormals) { - DefaultLogger::get()->debug("ASE: Taking normals from the file. Use " - "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you " - "experience problems"); - } - - // Now build the output mesh list. Remove dummies - pScene->mNumMeshes = (unsigned int)avOutMeshes.size(); - aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (std::vector<aiMesh*>::const_iterator i = avOutMeshes.begin();i != avOutMeshes.end();++i) { - if (!(*i)->mNumFaces) { - continue; - } - *pp++ = *i; - } - pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes); - - // Build final material indices (remove submaterials and setup - // the final list) - BuildMaterialIndices(); - } - - // ------------------------------------------------------------------ - // Copy all scene graph nodes - lights, cameras, dummies and meshes - // into one huge list. - //------------------------------------------------------------------ - std::vector<BaseNode*> nodes; - nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size() - + mParser->m_vCameras.size() + mParser->m_vDummies.size()); - - // Lights - for (std::vector<ASE::Light>::iterator it = mParser->m_vLights.begin(), - end = mParser->m_vLights.end();it != end; ++it)nodes.push_back(&(*it)); - // Cameras - for (std::vector<ASE::Camera>::iterator it = mParser->m_vCameras.begin(), - end = mParser->m_vCameras.end();it != end; ++it)nodes.push_back(&(*it)); - // Meshes - for (std::vector<ASE::Mesh>::iterator it = mParser->m_vMeshes.begin(), - end = mParser->m_vMeshes.end();it != end; ++it)nodes.push_back(&(*it)); - // Dummies - for (std::vector<ASE::Dummy>::iterator it = mParser->m_vDummies.begin(), - end = mParser->m_vDummies.end();it != end; ++it)nodes.push_back(&(*it)); - - // build the final node graph - BuildNodes(nodes); - - // build output animations - BuildAnimations(nodes); - - // build output cameras - BuildCameras(); - - // build output lights - BuildLights(); - - // ------------------------------------------------------------------ - // If we have no meshes use the SkeletonMeshBuilder helper class - // to build a mesh for the animation skeleton - // FIXME: very strange results - // ------------------------------------------------------------------ - if (!pScene->mNumMeshes) { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - SkeletonMeshBuilder skeleton(pScene); - } -} -// ------------------------------------------------------------------------------------------------ -void ASEImporter::GenerateDefaultMaterial() -{ - ai_assert(NULL != mParser); - - bool bHas = false; - for (std::vector<ASE::Mesh>::iterator i = mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) { - if ((*i).bSkip)continue; - if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex) { - (*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size(); - bHas = true; - } - } - if (bHas || mParser->m_vMaterials.empty()) { - // add a simple material without submaterials to the parser's list - mParser->m_vMaterials.push_back ( ASE::Material() ); - ASE::Material& mat = mParser->m_vMaterials.back(); - - mat.mDiffuse = aiColor3D(0.6f,0.6f,0.6f); - mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f); - mat.mAmbient = aiColor3D(0.05f,0.05f,0.05f); - mat.mShading = Discreet3DS::Gouraud; - mat.mName = AI_DEFAULT_MATERIAL_NAME; - } -} - -// ------------------------------------------------------------------------------------------------ -void ASEImporter::BuildAnimations(const std::vector<BaseNode*>& nodes) -{ - // check whether we have at least one mesh which has animations - std::vector<ASE::BaseNode*>::const_iterator i = nodes.begin(); - unsigned int iNum = 0; - for (;i != nodes.end();++i) { - - // TODO: Implement Bezier & TCB support - if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. " - "This is not supported."); - } - if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. " - "This is not supported."); - } - if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK) { - DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. " - "This is not supported."); - } - - // We compare against 1 here - firstly one key is not - // really an animation and secondly MAX writes dummies - // that represent the node transformation. - if ((*i)->mAnim.akeyPositions.size()>1 || (*i)->mAnim.akeyRotations.size()>1 || (*i)->mAnim.akeyScaling.size()>1){ - ++iNum; - } - if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( (*i)->mTargetPosition.x )) { - ++iNum; - } - } - if (iNum) { - // Generate a new animation channel and setup everything for it - pcScene->mNumAnimations = 1; - pcScene->mAnimations = new aiAnimation*[1]; - aiAnimation* pcAnim = pcScene->mAnimations[0] = new aiAnimation(); - pcAnim->mNumChannels = iNum; - pcAnim->mChannels = new aiNodeAnim*[iNum]; - pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame; - - iNum = 0; - - // Now iterate through all meshes and collect all data we can find - for (i = nodes.begin();i != nodes.end();++i) { - - ASE::BaseNode* me = *i; - if ( me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( me->mTargetPosition.x )) { - // Generate an extra channel for the camera/light target. - // BuildNodes() does also generate an extra node, named - // <baseName>.Target. - aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); - nd->mNodeName.Set(me->mName + ".Target"); - - // If there is no input position channel we will need - // to supply the default position from the node's - // local transformation matrix. - /*TargetAnimationHelper helper; - if (me->mAnim.akeyPositions.empty()) - { - aiMatrix4x4& mat = (*i)->mTransform; - helper.SetFixedMainAnimationChannel(aiVector3D( - mat.a4, mat.b4, mat.c4)); - } - else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions); - helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions); - - helper.Process(&me->mTargetAnim.akeyPositions);*/ - - // Allocate the key array and fill it - nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size(); - nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - - ::memcpy(nd->mPositionKeys,&me->mTargetAnim.akeyPositions[0], - nd->mNumPositionKeys * sizeof(aiVectorKey)); - } - - if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1) { - // Begin a new node animation channel for this node - aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim(); - nd->mNodeName.Set(me->mName); - - // copy position keys - if (me->mAnim.akeyPositions.size() > 1 ) - { - // Allocate the key array and fill it - nd->mNumPositionKeys = (unsigned int) me->mAnim.akeyPositions.size(); - nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - - ::memcpy(nd->mPositionKeys,&me->mAnim.akeyPositions[0], - nd->mNumPositionKeys * sizeof(aiVectorKey)); - } - // copy rotation keys - if (me->mAnim.akeyRotations.size() > 1 ) { - // Allocate the key array and fill it - nd->mNumRotationKeys = (unsigned int) me->mAnim.akeyRotations.size(); - nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys]; - - // -------------------------------------------------------------------- - // Rotation keys are offsets to the previous keys. - // We have the quaternion representations of all - // of them, so we just need to concatenate all - // (unit-length) quaternions to get the absolute - // rotations. - // Rotation keys are ABSOLUTE for older files - // -------------------------------------------------------------------- - - aiQuaternion cur; - for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) { - aiQuatKey q = me->mAnim.akeyRotations[a]; - - if (mParser->iFileFormat > 110) { - cur = (a ? cur*q.mValue : q.mValue); - q.mValue = cur.Normalize(); - } - nd->mRotationKeys[a] = q; - - // need this to get to Assimp quaternion conventions - nd->mRotationKeys[a].mValue.w *= -1.f; - } - } - // copy scaling keys - if (me->mAnim.akeyScaling.size() > 1 ) { - // Allocate the key array and fill it - nd->mNumScalingKeys = (unsigned int) me->mAnim.akeyScaling.size(); - nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys]; - - ::memcpy(nd->mScalingKeys,&me->mAnim.akeyScaling[0], - nd->mNumScalingKeys * sizeof(aiVectorKey)); - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Build output cameras -void ASEImporter::BuildCameras() -{ - if (!mParser->m_vCameras.empty()) { - pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size(); - pcScene->mCameras = new aiCamera*[pcScene->mNumCameras]; - - for (unsigned int i = 0; i < pcScene->mNumCameras;++i) { - aiCamera* out = pcScene->mCameras[i] = new aiCamera(); - ASE::Camera& in = mParser->m_vCameras[i]; - - // copy members - out->mClipPlaneFar = in.mFar; - out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f); - out->mHorizontalFOV = in.mFOV; - - out->mName.Set(in.mName); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Build output lights -void ASEImporter::BuildLights() -{ - if (!mParser->m_vLights.empty()) { - pcScene->mNumLights = (unsigned int)mParser->m_vLights.size(); - pcScene->mLights = new aiLight*[pcScene->mNumLights]; - - for (unsigned int i = 0; i < pcScene->mNumLights;++i) { - aiLight* out = pcScene->mLights[i] = new aiLight(); - ASE::Light& in = mParser->m_vLights[i]; - - // The direction is encoded in the transformation matrix of the node. - // In 3DS MAX the light source points into negative Z direction if - // the node transformation is the identity. - out->mDirection = aiVector3D(0.f,0.f,-1.f); - - out->mName.Set(in.mName); - switch (in.mLightType) - { - case ASE::Light::TARGET: - out->mType = aiLightSource_SPOT; - out->mAngleInnerCone = AI_DEG_TO_RAD(in.mAngle); - out->mAngleOuterCone = (in.mFalloff ? AI_DEG_TO_RAD(in.mFalloff) : out->mAngleInnerCone); - break; - - case ASE::Light::DIRECTIONAL: - out->mType = aiLightSource_DIRECTIONAL; - break; - - default: - //case ASE::Light::OMNI: - out->mType = aiLightSource_POINT; - break; - }; - out->mColorDiffuse = out->mColorSpecular = in.mColor * in.mIntensity; - } - } -} - -// ------------------------------------------------------------------------------------------------ -void ASEImporter::AddNodes(const std::vector<BaseNode*>& nodes, - aiNode* pcParent,const char* szName) -{ - aiMatrix4x4 m; - AddNodes(nodes,pcParent,szName,m); -} - -// ------------------------------------------------------------------------------------------------ -// Add meshes to a given node -void ASEImporter::AddMeshes(const ASE::BaseNode* snode,aiNode* node) -{ - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) { - // Get the name of the mesh (the mesh instance has been temporarily stored in the third vertex color) - const aiMesh* pcMesh = pcScene->mMeshes[i]; - const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2]; - - if (mesh == snode) { - ++node->mNumMeshes; - } - } - - if (node->mNumMeshes) { - node->mMeshes = new unsigned int[node->mNumMeshes]; - for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i) { - - const aiMesh* pcMesh = pcScene->mMeshes[i]; - const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2]; - if (mesh == snode) { - node->mMeshes[p++] = i; - - // Transform all vertices of the mesh back into their local space -> - // at the moment they are pretransformed - aiMatrix4x4 m = mesh->mTransform; - m.Inverse(); - - aiVector3D* pvCurPtr = pcMesh->mVertices; - const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices; - while (pvCurPtr != pvEndPtr) { - *pvCurPtr = m * (*pvCurPtr); - pvCurPtr++; - } - - // Do the same for the normal vectors, if we have them. - // As always, inverse transpose. - if (pcMesh->mNormals) { - aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform ); - m3.Transpose(); - - pvCurPtr = pcMesh->mNormals; - pvEndPtr = pvCurPtr + pcMesh->mNumVertices; - while (pvCurPtr != pvEndPtr) { - *pvCurPtr = m3 * (*pvCurPtr); - pvCurPtr++; - } - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Add child nodes to a given parent node -void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes, - aiNode* pcParent, const char* szName, - const aiMatrix4x4& mat) -{ - const size_t len = szName ? ::strlen(szName) : 0; - ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS); - - // Receives child nodes for the pcParent node - std::vector<aiNode*> apcNodes; - - // Now iterate through all nodes in the scene and search for one - // which has *us* as parent. - for (std::vector<BaseNode*>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) { - const BaseNode* snode = *it; - if (szName) { - if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str())) - continue; - } - else if (snode->mParent.length()) - continue; - - (*it)->mProcessed = true; - - // Allocate a new node and add it to the output data structure - apcNodes.push_back(new aiNode()); - aiNode* node = apcNodes.back(); - - node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node")); - node->mParent = pcParent; - - // Setup the transformation matrix of the node - aiMatrix4x4 mParentAdjust = mat; - mParentAdjust.Inverse(); - node->mTransformation = mParentAdjust*snode->mTransform; - - // Add sub nodes - prevent stack overflow due to recursive parenting - if (node->mName != node->mParent->mName) { - AddNodes(nodes,node,node->mName.data,snode->mTransform); - } - - // Further processing depends on the type of the node - if (snode->mType == ASE::BaseNode::Mesh) { - // If the type of this node is "Mesh" we need to search - // the list of output meshes in the data structure for - // all those that belonged to this node once. This is - // slightly inconvinient here and a better solution should - // be used when this code is refactored next. - AddMeshes(snode,node); - } - else if (is_not_qnan( snode->mTargetPosition.x )) { - // If this is a target camera or light we generate a small - // child node which marks the position of the camera - // target (the direction information is contained in *this* - // node's animation track but the exact target position - // would be lost otherwise) - if (!node->mNumChildren) { - node->mChildren = new aiNode*[1]; - } - - aiNode* nd = new aiNode(); - - nd->mName.Set ( snode->mName + ".Target" ); - - nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4; - nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4; - nd->mTransformation.c4 = snode->mTargetPosition.z - snode->mTransform.c4; - - nd->mParent = node; - - // The .Target node is always the first child node - for (unsigned int m = 0; m < node->mNumChildren;++m) - node->mChildren[m+1] = node->mChildren[m]; - - node->mChildren[0] = nd; - node->mNumChildren++; - - // What we did is so great, it is at least worth a debug message - DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")"); - } - } - - // Allocate enough space for the child nodes - // We allocate one slot more in case this is a target camera/light - pcParent->mNumChildren = (unsigned int)apcNodes.size(); - if (pcParent->mNumChildren) { - pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */]; - - // now build all nodes for our nice new children - for (unsigned int p = 0; p < apcNodes.size();++p) - pcParent->mChildren[p] = apcNodes[p]; - } - return; -} - -// ------------------------------------------------------------------------------------------------ -// Build the output node graph -void ASEImporter::BuildNodes(std::vector<BaseNode*>& nodes) { - ai_assert(NULL != pcScene); - - // allocate the one and only root node - aiNode* root = pcScene->mRootNode = new aiNode(); - root->mName.Set("<ASERoot>"); - - // Setup the coordinate system transformation - pcScene->mRootNode->mNumChildren = 1; - pcScene->mRootNode->mChildren = new aiNode*[1]; - aiNode* ch = pcScene->mRootNode->mChildren[0] = new aiNode(); - ch->mParent = root; - - // Change the transformation matrix of all nodes - for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) { - aiMatrix4x4& m = (*it)->mTransform; - m.Transpose(); // row-order vs column-order - } - - // add all nodes - AddNodes(nodes,ch,NULL); - - // now iterate through al nodes and find those that have not yet - // been added to the nodegraph (= their parent could not be recognized) - std::vector<const BaseNode*> aiList; - for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it) { - if ((*it)->mProcessed) { - continue; - } - - // check whether our parent is known - bool bKnowParent = false; - - // search the list another time, starting *here* and try to find out whether - // there is a node that references *us* as a parent - for (std::vector<BaseNode*>::const_iterator it2 = nodes.begin();it2 != end; ++it2) { - if (it2 == it) { - continue; - } - - if ((*it2)->mName == (*it)->mParent) { - bKnowParent = true; - break; - } - } - if (!bKnowParent) { - aiList.push_back(*it); - } - } - - // Are there ane orphaned nodes? - if (!aiList.empty()) { - std::vector<aiNode*> apcNodes; - apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren); - - for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren;++i) - apcNodes.push_back(pcScene->mRootNode->mChildren[i]); - - delete[] pcScene->mRootNode->mChildren; - for (std::vector<const BaseNode*>::/*const_*/iterator i = aiList.begin();i != aiList.end();++i) { - const ASE::BaseNode* src = *i; - - // The parent is not known, so we can assume that we must add - // this node to the root node of the whole scene - aiNode* pcNode = new aiNode(); - pcNode->mParent = pcScene->mRootNode; - pcNode->mName.Set(src->mName); - AddMeshes(src,pcNode); - AddNodes(nodes,pcNode,pcNode->mName.data); - apcNodes.push_back(pcNode); - } - - // Regenerate our output array - pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()]; - for (unsigned int i = 0; i < apcNodes.size();++i) - pcScene->mRootNode->mChildren[i] = apcNodes[i]; - - pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size(); - } - - // Reset the third color set to NULL - we used this field to store a temporary pointer - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - pcScene->mMeshes[i]->mColors[2] = NULL; - - // The root node should not have at least one child or the file is valid - if (!pcScene->mRootNode->mNumChildren) { - throw DeadlyImportError("ASE: No nodes loaded. The file is either empty or corrupt"); - } - - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); -} - -// ------------------------------------------------------------------------------------------------ -// Convert the imported data to the internal verbose representation -void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh) { - // allocate output storage - std::vector<aiVector3D> mPositions; - std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - std::vector<aiColor4D> mVertexColors; - std::vector<aiVector3D> mNormals; - std::vector<BoneVertex> mBoneVertices; - - unsigned int iSize = (unsigned int)mesh.mFaces.size() * 3; - mPositions.resize(iSize); - - // optional texture coordinates - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) { - if (!mesh.amTexCoords[i].empty()) { - amTexCoords[i].resize(iSize); - } - } - // optional vertex colors - if (!mesh.mVertexColors.empty()) { - mVertexColors.resize(iSize); - } - - // optional vertex normals (vertex normals can simply be copied) - if (!mesh.mNormals.empty()) { - mNormals.resize(iSize); - } - // bone vertices. There is no need to change the bone list - if (!mesh.mBoneVertices.empty()) { - mBoneVertices.resize(iSize); - } - - // iterate through all faces in the mesh - unsigned int iCurrent = 0, fi = 0; - for (std::vector<ASE::Face>::iterator i = mesh.mFaces.begin();i != mesh.mFaces.end();++i,++fi) { - for (unsigned int n = 0; n < 3;++n,++iCurrent) - { - mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]]; - - // add texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { - if (mesh.amTexCoords[c].empty())break; - amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]]; - } - // add vertex colors - if (!mesh.mVertexColors.empty()) { - mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]]; - } - // add normal vectors - if (!mesh.mNormals.empty()) { - mNormals[iCurrent] = mesh.mNormals[fi*3+n]; - mNormals[iCurrent].Normalize(); - } - - // handle bone vertices - if ((*i).mIndices[n] < mesh.mBoneVertices.size()) { - // (sometimes this will cause bone verts to be duplicated - // however, I' quite sure Schrompf' JoinVerticesStep - // will fix that again ...) - mBoneVertices[iCurrent] = mesh.mBoneVertices[(*i).mIndices[n]]; - } - (*i).mIndices[n] = iCurrent; - } - } - - // replace the old arrays - mesh.mNormals = mNormals; - mesh.mPositions = mPositions; - mesh.mVertexColors = mVertexColors; - - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - mesh.amTexCoords[c] = amTexCoords[c]; -} - -// ------------------------------------------------------------------------------------------------ -// Copy a texture from the ASE structs to the output material -void CopyASETexture(MaterialHelper& mat, ASE::Texture& texture, aiTextureType type) -{ - // Setup the texture name - aiString tex; - tex.Set( texture.mMapName); - mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0)); - - // Setup the texture blend factor - if (is_not_qnan(texture.mTextureBlend)) - mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0)); - - // Setup texture UV transformations - mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Convert from ASE material to output material -void ASEImporter::ConvertMaterial(ASE::Material& mat) -{ - // LARGE TODO: Much code her is copied from 3DS ... join them maybe? - - // Allocate the output material - mat.pcInstance = new MaterialHelper(); - - // At first add the base ambient color of the - // scene to the material - mat.mAmbient.r += mParser->m_clrAmbient.r; - mat.mAmbient.g += mParser->m_clrAmbient.g; - mat.mAmbient.b += mParser->m_clrAmbient.b; - - aiString name; - name.Set( mat.mName); - mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME); - - // material colors - mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT); - mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); - - // shininess - if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength) - { - mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH); - } - // If there is no shininess, we can disable phong lighting - else if (D3DS::Discreet3DS::Metal == mat.mShading || - D3DS::Discreet3DS::Phong == mat.mShading || - D3DS::Discreet3DS::Blinn == mat.mShading) - { - mat.mShading = D3DS::Discreet3DS::Gouraud; - } - - // opacity - mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY); - - // Two sided rendering? - if (mat.mTwoSided) - { - int i = 1; - mat.pcInstance->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED); - } - - // shading mode - aiShadingMode eShading = aiShadingMode_NoShading; - switch (mat.mShading) - { - case D3DS::Discreet3DS::Flat: - eShading = aiShadingMode_Flat; break; - case D3DS::Discreet3DS::Phong : - eShading = aiShadingMode_Phong; break; - case D3DS::Discreet3DS::Blinn : - eShading = aiShadingMode_Blinn; break; - - // I don't know what "Wire" shading should be, - // assume it is simple lambertian diffuse (L dot N) shading - case D3DS::Discreet3DS::Wire: - { - // set the wireframe flag - unsigned int iWire = 1; - mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME); - } - case D3DS::Discreet3DS::Gouraud: - eShading = aiShadingMode_Gouraud; break; - case D3DS::Discreet3DS::Metal : - eShading = aiShadingMode_CookTorrance; break; - } - mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL); - - // DIFFUSE texture - if ( mat.sTexDiffuse.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE); - - // SPECULAR texture - if ( mat.sTexSpecular.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR); - - // AMBIENT texture - if ( mat.sTexAmbient.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT); - - // OPACITY texture - if ( mat.sTexOpacity.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY); - - // EMISSIVE texture - if ( mat.sTexEmissive.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE); - - // BUMP texture - if ( mat.sTexBump.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT); - - // SHININESS texture - if ( mat.sTexShininess.mMapName.length() > 0) - CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS); - - // store the name of the material itself, too - if ( mat.mName.length() > 0) { - aiString tex;tex.Set( mat.mName); - mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -// Build output meshes -void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMeshes) -{ - // validate the material index of the mesh - if (mesh.iMaterialIndex >= mParser->m_vMaterials.size()) { - mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1; - DefaultLogger::get()->warn("Material index is out of range"); - } - - // If the material the mesh is assigned to is consisting of submeshes, split it - if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) { - std::vector<ASE::Material> vSubMaterials = mParser-> - m_vMaterials[mesh.iMaterialIndex].avSubMaterials; - - std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()]; - - // build a list of all faces per submaterial - for (unsigned int i = 0; i < mesh.mFaces.size();++i) { - // check range - if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) { - DefaultLogger::get()->warn("Submaterial index is out of range"); - - // use the last material instead - aiSplit[vSubMaterials.size()-1].push_back(i); - } - else aiSplit[mesh.mFaces[i].iMaterial].push_back(i); - } - - // now generate submeshes - for (unsigned int p = 0; p < vSubMaterials.size();++p) { - if (!aiSplit[p].empty()) { - - aiMesh* p_pcOut = new aiMesh(); - p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // let the sub material index - p_pcOut->mMaterialIndex = p; - - // we will need this material - mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true; - - // store the real index here ... color channel 3 - p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex; - - // store a pointer to the mesh in color channel 2 - p_pcOut->mColors[2] = (aiColor4D*) &mesh; - avOutMeshes.push_back(p_pcOut); - - // convert vertices - p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3; - p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size(); - - // receive output vertex weights - std::vector<std::pair<unsigned int, float> > *avOutputBones = NULL; - if (!mesh.mBones.empty()) { - avOutputBones = new std::vector<std::pair<unsigned int, float> >[mesh.mBones.size()]; - } - - // allocate enough storage for faces - p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; - - unsigned int iBase = 0,iIndex; - if (p_pcOut->mNumVertices) { - p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices]; - p_pcOut->mNormals = new aiVector3D[p_pcOut->mNumVertices]; - for (unsigned int q = 0; q < aiSplit[p].size();++q) { - - iIndex = aiSplit[p][q]; - - p_pcOut->mFaces[q].mIndices = new unsigned int[3]; - p_pcOut->mFaces[q].mNumIndices = 3; - - for (unsigned int t = 0; t < 3;++t, ++iBase) { - const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t]; - - p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2]; - p_pcOut->mNormals [iBase] = mesh.mNormals [iIndex2]; - - // convert bones, if existing - if (!mesh.mBones.empty()) { - // check whether there is a vertex weight for this vertex index - if (iIndex2 < mesh.mBoneVertices.size()) { - - for (std::vector<std::pair<int,float> >::const_iterator - blubb = mesh.mBoneVertices[iIndex2].mBoneWeights.begin(); - blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb) { - - // NOTE: illegal cases have already been filtered out - avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>( - iBase,(*blubb).second)); - } - } - } - p_pcOut->mFaces[q].mIndices[t] = iBase; - } - } - } - // convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported) - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { - if (!mesh.amTexCoords[c].empty()) - { - p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices]; - iBase = 0; - for (unsigned int q = 0; q < aiSplit[p].size();++q) { - iIndex = aiSplit[p][q]; - for (unsigned int t = 0; t < 3;++t) { - p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]]; - } - } - // Setup the number of valid vertex components - p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c]; - } - } - - // Convert vertex colors (only one set supported) - if (!mesh.mVertexColors.empty()){ - p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices]; - iBase = 0; - for (unsigned int q = 0; q < aiSplit[p].size();++q) { - iIndex = aiSplit[p][q]; - for (unsigned int t = 0; t < 3;++t) { - p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]]; - } - } - } - // Copy bones - if (!mesh.mBones.empty()) { - p_pcOut->mNumBones = 0; - for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock) - if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++; - - p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ]; - aiBone** pcBone = p_pcOut->mBones; - for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock) - { - if (!avOutputBones[mrspock].empty()) { - // we will need this bone. add it to the output mesh and - // add all per-vertex weights - aiBone* pc = *pcBone = new aiBone(); - pc->mName.Set(mesh.mBones[mrspock].mName); - - pc->mNumWeights = (unsigned int)avOutputBones[mrspock].size(); - pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - - for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk) - { - const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk]; - pc->mWeights[captainkirk].mVertexId = ref.first; - pc->mWeights[captainkirk].mWeight = ref.second; - } - ++pcBone; - } - } - // delete allocated storage - delete[] avOutputBones; - } - } - } - // delete storage - delete[] aiSplit; - } - else - { - // Otherwise we can simply copy the data to one output mesh - // This codepath needs less memory and uses fast memcpy()s - // to do the actual copying. So I think it is worth the - // effort here. - - aiMesh* p_pcOut = new aiMesh(); - p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // set an empty sub material index - p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX; - mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true; - - // store the real index here ... in color channel 3 - p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex; - - // store a pointer to the mesh in color channel 2 - p_pcOut->mColors[2] = (aiColor4D*) &mesh; - avOutMeshes.push_back(p_pcOut); - - // If the mesh hasn't faces or vertices, there are two cases - // possible: 1. the model is invalid. 2. This is a dummy - // helper object which we are going to remove later ... - if (mesh.mFaces.empty() || mesh.mPositions.empty()) { - return; - } - - // convert vertices - p_pcOut->mNumVertices = (unsigned int)mesh.mPositions.size(); - p_pcOut->mNumFaces = (unsigned int)mesh.mFaces.size(); - - // allocate enough storage for faces - p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces]; - - // copy vertices - p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()]; - memcpy(p_pcOut->mVertices,&mesh.mPositions[0], - mesh.mPositions.size() * sizeof(aiVector3D)); - - // copy normals - p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()]; - memcpy(p_pcOut->mNormals,&mesh.mNormals[0], - mesh.mNormals.size() * sizeof(aiVector3D)); - - // copy texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) { - if (!mesh.amTexCoords[c].empty()) { - p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()]; - memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0], - mesh.amTexCoords[c].size() * sizeof(aiVector3D)); - - // setup the number of valid vertex components - p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c]; - } - } - - // copy vertex colors - if (!mesh.mVertexColors.empty()) { - p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()]; - memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0], - mesh.mVertexColors.size() * sizeof(aiColor4D)); - } - - // copy faces - for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace) { - p_pcOut->mFaces[iFace].mNumIndices = 3; - p_pcOut->mFaces[iFace].mIndices = new unsigned int[3]; - - // copy indices - p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0]; - p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1]; - p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2]; - } - - // copy vertex bones - if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty()) { - std::vector<aiVertexWeight>* avBonesOut = new std::vector<aiVertexWeight>[mesh.mBones.size()]; - - // find all vertex weights for this bone - unsigned int quak = 0; - for (std::vector<BoneVertex>::const_iterator harrypotter = mesh.mBoneVertices.begin(); - harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak) { - - for (std::vector<std::pair<int,float> >::const_iterator - ronaldweasley = (*harrypotter).mBoneWeights.begin(); - ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley) - { - aiVertexWeight weight; - weight.mVertexId = quak; - weight.mWeight = (*ronaldweasley).second; - avBonesOut[(*ronaldweasley).first].push_back(weight); - } - } - - // now build a final bone list - p_pcOut->mNumBones = 0; - for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy) - if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++; - - p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones]; - aiBone** pcBone = p_pcOut->mBones; - for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy) { - if (!avBonesOut[jfkennedy].empty()) { - aiBone* pc = *pcBone = new aiBone(); - pc->mName.Set(mesh.mBones[jfkennedy].mName); - pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size(); - pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - ::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0], - sizeof(aiVertexWeight) * pc->mNumWeights); - ++pcBone; - } - } - - // delete allocated storage - delete[] avBonesOut; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Setup proper material indices and build output materials -void ASEImporter::BuildMaterialIndices() -{ - ai_assert(NULL != pcScene); - - // iterate through all materials and check whether we need them - for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) - { - ASE::Material& mat = mParser->m_vMaterials[iMat]; - if (mat.bNeed) { - // Convert it to the aiMaterial layout - ConvertMaterial(mat); - ++pcScene->mNumMaterials; - } - for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat) - { - ASE::Material& submat = mat.avSubMaterials[iSubMat]; - if (submat.bNeed) { - // Convert it to the aiMaterial layout - ConvertMaterial(submat); - ++pcScene->mNumMaterials; - } - } - } - - // allocate the output material array - pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials]; - D3DS::Material** pcIntMaterials = new D3DS::Material*[pcScene->mNumMaterials]; - - unsigned int iNum = 0; - for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) { - ASE::Material& mat = mParser->m_vMaterials[iMat]; - if (mat.bNeed) - { - ai_assert(NULL != mat.pcInstance); - pcScene->mMaterials[iNum] = mat.pcInstance; - - // Store the internal material, too - pcIntMaterials[iNum] = &mat; - - // Iterate through all meshes and search for one which is using - // this top-level material index - for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) - { - aiMesh* mesh = pcScene->mMeshes[iMesh]; - if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex && - iMat == (uintptr_t)mesh->mColors[3]) - { - mesh->mMaterialIndex = iNum; - mesh->mColors[3] = NULL; - } - } - iNum++; - } - for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat) { - ASE::Material& submat = mat.avSubMaterials[iSubMat]; - if (submat.bNeed) { - ai_assert(NULL != submat.pcInstance); - pcScene->mMaterials[iNum] = submat.pcInstance; - - // Store the internal material, too - pcIntMaterials[iNum] = &submat; - - // Iterate through all meshes and search for one which is using - // this sub-level material index - for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh) { - aiMesh* mesh = pcScene->mMeshes[iMesh]; - - if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3]) { - mesh->mMaterialIndex = iNum; - mesh->mColors[3] = NULL; - } - } - iNum++; - } - } - } - - // Dekete our temporary array - delete[] pcIntMaterials; -} - -// ------------------------------------------------------------------------------------------------ -// Generate normal vectors basing on smoothing groups -bool ASEImporter::GenerateNormals(ASE::Mesh& mesh) { - - if (!mesh.mNormals.empty() && !configRecomputeNormals) - { - // Check whether there are only uninitialized normals. If there are - // some, skip all normals from the file and compute them on our own - for (std::vector<aiVector3D>::const_iterator qq = mesh.mNormals.begin();qq != mesh.mNormals.end();++qq) { - if ((*qq).x || (*qq).y || (*qq).z) - { - return true; - } - } - } - // The array is reused. - ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh); - return false; -} - -#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER diff --git a/3rdparty/assimp/code/ASELoader.h b/3rdparty/assimp/code/ASELoader.h deleted file mode 100644 index 5a117ba2..00000000 --- a/3rdparty/assimp/code/ASELoader.h +++ /dev/null @@ -1,208 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ASELoader.h - * @brief Definition of the .ASE importer class. - */ -#ifndef AI_ASELOADER_H_INCLUDED -#define AI_ASELOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" - -struct aiNode; -#include "ASEParser.h" - -namespace Assimp { -class MaterialHelper; - -// -------------------------------------------------------------------------------- -/** Importer class for the 3DS ASE ASCII format. - * - */ -class ASEImporter : public BaseImporter { - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - ASEImporter(); - - /** Destructor, private as well */ - ~ASEImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - - -private: - - // ------------------------------------------------------------------- - /** Generate normal vectors basing on smoothing groups - * (in some cases the normal are already contained in the file) - * \param mesh Mesh to work on - * \return false if the normals have been recomputed - */ - bool GenerateNormals(ASE::Mesh& mesh); - - - // ------------------------------------------------------------------- - /** Create valid vertex/normal/UV/color/face lists. - * All elements are unique, faces have only one set of indices - * after this step occurs. - * \param mesh Mesh to work on - */ - void BuildUniqueRepresentation(ASE::Mesh& mesh); - - - /** Create one-material-per-mesh meshes ;-) - * \param mesh Mesh to work with - * \param Receives the list of all created meshes - */ - void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut); - - - // ------------------------------------------------------------------- - /** Convert a material to a MaterialHelper object - * \param mat Input material - */ - void ConvertMaterial(ASE::Material& mat); - - - // ------------------------------------------------------------------- - /** Setup the final material indices for each mesh - */ - void BuildMaterialIndices(); - - - // ------------------------------------------------------------------- - /** Build the node graph - */ - void BuildNodes(std::vector<ASE::BaseNode*>& nodes); - - - // ------------------------------------------------------------------- - /** Build output cameras - */ - void BuildCameras(); - - - // ------------------------------------------------------------------- - /** Build output lights - */ - void BuildLights(); - - - // ------------------------------------------------------------------- - /** Build output animations - */ - void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes); - - - // ------------------------------------------------------------------- - /** Add sub nodes to a node - * \param pcParent parent node to be filled - * \param szName Name of the parent node - * \param matrix Current transform - */ - void AddNodes(const std::vector<ASE::BaseNode*>& nodes, - aiNode* pcParent,const char* szName); - - void AddNodes(const std::vector<ASE::BaseNode*>& nodes, - aiNode* pcParent,const char* szName, - const aiMatrix4x4& matrix); - - void AddMeshes(const ASE::BaseNode* snode,aiNode* node); - - // ------------------------------------------------------------------- - /** Generate a default material and add it to the parser's list - * Called if no material has been found in the file (rare for ASE, - * but not impossible) - */ - void GenerateDefaultMaterial(); - -protected: - - /** Parser instance */ - ASE::Parser* mParser; - - /** Buffer to hold the loaded file */ - char* mBuffer; - - /** Scene to be filled */ - aiScene* pcScene; - - /** Config options: Recompute the normals in every case - WA - for 3DS Max broken ASE normal export */ - bool configRecomputeNormals; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/ASEParser.cpp b/3rdparty/assimp/code/ASEParser.cpp deleted file mode 100644 index a37fb869..00000000 --- a/3rdparty/assimp/code/ASEParser.cpp +++ /dev/null @@ -1,2150 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ASEParser.cpp - * @brief Implementation of the ASE parser class - */ - -#include "AssimpPCH.h" - -// internal headers -#include "TextureTransform.h" -#include "ASELoader.h" -#include "MaterialSystem.h" -#include "fast_atof.h" - -using namespace Assimp; -using namespace Assimp::ASE; - - -// ------------------------------------------------------------------------------------------------ -// Begin an ASE parsing function - -#define AI_ASE_PARSER_INIT() \ - int iDepth = 0; - -// ------------------------------------------------------------------------------------------------ -// Handle a "top-level" section in the file. EOF is no error in this case. - -#define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \ - else if ('{' == *filePtr)iDepth++; \ - else if ('}' == *filePtr) \ - { \ - if (0 == --iDepth) \ - { \ - ++filePtr; \ - SkipToNextToken(); \ - return; \ - } \ - } \ - else if ('\0' == *filePtr) \ - { \ - return; \ - } \ - if(IsLineEnd(*filePtr) && !bLastWasEndLine) \ - { \ - ++iLineNumber; \ - bLastWasEndLine = true; \ - } else bLastWasEndLine = false; \ - ++filePtr; - -// ------------------------------------------------------------------------------------------------ -// Handle a nested section in the file. EOF is an error in this case -// @param level "Depth" of the section -// @param msg Full name of the section (including the asterisk) - -#define AI_ASE_HANDLE_SECTION(level, msg) \ - if ('{' == *filePtr)iDepth++; \ - else if ('}' == *filePtr) \ - { \ - if (0 == --iDepth) \ - { \ - ++filePtr; \ - SkipToNextToken(); \ - return; \ - } \ - } \ - else if ('\0' == *filePtr) \ - { \ - LogError("Encountered unexpected EOL while parsing a " msg \ - " chunk (Level " level ")"); \ - } \ - if(IsLineEnd(*filePtr) && !bLastWasEndLine) \ - { \ - ++iLineNumber; \ - bLastWasEndLine = true; \ - } else bLastWasEndLine = false; \ - ++filePtr; - -// ------------------------------------------------------------------------------------------------ -Parser::Parser (const char* szFile, unsigned int fileFormatDefault) -{ - ai_assert(NULL != szFile); - filePtr = szFile; - iFileFormat = fileFormatDefault; - - // make sure that the color values are invalid - m_clrBackground.r = get_qnan(); - m_clrAmbient.r = get_qnan(); - - // setup some default values - iLineNumber = 0; - iFirstFrame = 0; - iLastFrame = 0; - iFrameSpeed = 30; // use 30 as default value for this property - iTicksPerFrame = 1; // use 1 as default value for this property - bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping -} - -// ------------------------------------------------------------------------------------------------ -void Parser::LogWarning(const char* szWarn) -{ - ai_assert(NULL != szWarn); - - char szTemp[1024]; -#if _MSC_VER >= 1400 - sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); -#else - snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); -#endif - - // output the warning to the logger ... - DefaultLogger::get()->warn(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -void Parser::LogInfo(const char* szWarn) -{ - ai_assert(NULL != szWarn); - - char szTemp[1024]; -#if _MSC_VER >= 1400 - sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); -#else - snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); -#endif - - // output the information to the logger ... - DefaultLogger::get()->info(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -void Parser::LogError(const char* szWarn) -{ - ai_assert(NULL != szWarn); - - char szTemp[1024]; -#if _MSC_VER >= 1400 - sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn); -#else - snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn); -#endif - - // throw an exception - throw DeadlyImportError(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -bool Parser::SkipToNextToken() -{ - while (true) - { - char me = *filePtr; - - // increase the line number counter if necessary - if (IsLineEnd(me) && !bLastWasEndLine) - { - ++iLineNumber; - bLastWasEndLine = true; - } - else bLastWasEndLine = false; - if ('*' == me || '}' == me || '{' == me)return true; - if ('\0' == me)return false; - - ++filePtr; - } -} - -// ------------------------------------------------------------------------------------------------ -bool Parser::SkipSection() -{ - // must handle subsections ... - int iCnt = 0; - while (true) - { - if ('}' == *filePtr) - { - --iCnt; - if (0 == iCnt) - { - // go to the next valid token ... - ++filePtr; - SkipToNextToken(); - return true; - } - } - else if ('{' == *filePtr) - { - ++iCnt; - } - else if ('\0' == *filePtr) - { - LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]"); - return false; - } - else if(IsLineEnd(*filePtr))++iLineNumber; - ++filePtr; - } -} - -// ------------------------------------------------------------------------------------------------ -void Parser::Parse() -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Version should be 200. Validate this ... - if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18)) - { - unsigned int fmt; - ParseLV4MeshLong(fmt); - - if (fmt > 200) - { - LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \ - be <= 200"); - } - // ************************************************************* - // - fmt will be 0 if we're unable to read the version number - // there are some faulty files without a version number ... - // in this case we'll guess the exact file format by looking - // at the file extension (ASE, ASK, ASC) - // ************************************************************* - - if (fmt)iFileFormat = fmt; - continue; - } - // main scene information - if (TokenMatch(filePtr,"SCENE",5)) - { - ParseLV1SceneBlock(); - continue; - } - // "group" - no implementation yet, in facte - // we're just ignoring them for the moment - if (TokenMatch(filePtr,"GROUP",5)) - { - Parse(); - continue; - } - // material list - if (TokenMatch(filePtr,"MATERIAL_LIST",13)) - { - ParseLV1MaterialListBlock(); - continue; - } - // geometric object (mesh) - if (TokenMatch(filePtr,"GEOMOBJECT",10)) - - { - m_vMeshes.push_back(Mesh()); - ParseLV1ObjectBlock(m_vMeshes.back()); - continue; - } - // helper object = dummy in the hierarchy - if (TokenMatch(filePtr,"HELPEROBJECT",12)) - - { - m_vDummies.push_back(Dummy()); - ParseLV1ObjectBlock(m_vDummies.back()); - continue; - } - // light object - if (TokenMatch(filePtr,"LIGHTOBJECT",11)) - - { - m_vLights.push_back(Light()); - ParseLV1ObjectBlock(m_vLights.back()); - continue; - } - // camera object - if (TokenMatch(filePtr,"CAMERAOBJECT",12)) - { - m_vCameras.push_back(Camera()); - ParseLV1ObjectBlock(m_vCameras.back()); - continue; - } - // comment - print it on the console - if (TokenMatch(filePtr,"COMMENT",7)) - { - std::string out = "<unknown>"; - ParseString(out,"*COMMENT"); - LogInfo(("Comment: " + out).c_str()); - continue; - } - // ASC bone weights - if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18)) - { - ParseLV1SoftSkinBlock(); - } - } - AI_ASE_HANDLE_TOP_LEVEL_SECTION(); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1SoftSkinBlock() -{ - // TODO: fix line counting here - - // ************************************************************** - // The soft skin block is formatted differently. There are no - // nested sections supported and the single elements aren't - // marked by keywords starting with an asterisk. - - /** - FORMAT BEGIN - - *MESH_SOFTSKINVERTS { - <nodename> - <number of vertices> - - [for <number of vertices> times:] - <number of weights> [for <number of weights> times:] <bone name> <weight> - } - - FORMAT END - */ - // ************************************************************** - while (true) - { - if (*filePtr == '}' ) {++filePtr;return;} - else if (*filePtr == '\0') return; - else if (*filePtr == '{' ) ++filePtr; - - else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr)) - { - ASE::Mesh* curMesh = NULL; - unsigned int numVerts = 0; - - const char* sz = filePtr; - while (!IsSpaceOrNewLine(*filePtr))++filePtr; - - const unsigned int diff = (unsigned int)(filePtr-sz); - if (diff) - { - std::string name = std::string(sz,diff); - for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin(); - it != m_vMeshes.end(); ++it) - { - if ((*it).mName == name) - { - curMesh = & (*it); - break; - } - } - if (!curMesh) - { - LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section"); - - // Skip the mesh data - until we find a new mesh - // or the end of the *MESH_SOFTSKINVERTS section - while (true) - { - SkipSpacesAndLineEnd(&filePtr); - if (*filePtr == '}') - {++filePtr;return;} - else if (!IsNumeric(*filePtr)) - break; - - SkipLine(&filePtr); - } - } - else - { - SkipSpacesAndLineEnd(&filePtr); - ParseLV4MeshLong(numVerts); - - // Reserve enough storage - curMesh->mBoneVertices.reserve(numVerts); - - for (unsigned int i = 0; i < numVerts;++i) - { - SkipSpacesAndLineEnd(&filePtr); - unsigned int numWeights; - ParseLV4MeshLong(numWeights); - - curMesh->mBoneVertices.push_back(ASE::BoneVertex()); - ASE::BoneVertex& vert = curMesh->mBoneVertices.back(); - - // Reserve enough storage - vert.mBoneWeights.reserve(numWeights); - - for (unsigned int w = 0; w < numWeights;++w) - { - std::string bone; - ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); - - // Find the bone in the mesh's list - std::pair<int,float> me; - me.first = -1; - - for (unsigned int n = 0; n < curMesh->mBones.size();++n) - { - if (curMesh->mBones[n].mName == bone) - { - me.first = n; - break; - } - } - if (-1 == me.first) - { - // We don't have this bone yet, so add it to the list - me.first = (int)curMesh->mBones.size(); - curMesh->mBones.push_back(ASE::Bone(bone)); - } - ParseLV4MeshFloat( me.second ); - - // Add the new bone weight to list - vert.mBoneWeights.push_back(me); - } - } - } - } - } - ++filePtr; - SkipSpacesAndLineEnd(&filePtr); - } -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1SceneBlock() -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23)) - - { - // parse a color triple and assume it is really the bg color - ParseLV4MeshFloatTriple( &m_clrBackground.r ); - continue; - } - if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20)) - - { - // parse a color triple and assume it is really the bg color - ParseLV4MeshFloatTriple( &m_clrAmbient.r ); - continue; - } - if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16)) - { - ParseLV4MeshLong(iFirstFrame); - continue; - } - if (TokenMatch(filePtr,"SCENE_LASTFRAME",15)) - { - ParseLV4MeshLong(iLastFrame); - continue; - } - if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16)) - { - ParseLV4MeshLong(iFrameSpeed); - continue; - } - if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19)) - { - ParseLV4MeshLong(iTicksPerFrame); - continue; - } - } - AI_ASE_HANDLE_TOP_LEVEL_SECTION(); - } -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1MaterialListBlock() -{ - AI_ASE_PARSER_INIT(); - - unsigned int iMaterialCount = 0; - unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - if (TokenMatch(filePtr,"MATERIAL_COUNT",14)) - { - ParseLV4MeshLong(iMaterialCount); - - // now allocate enough storage to hold all materials - m_vMaterials.resize(iOldMaterialCount+iMaterialCount); - continue; - } - if (TokenMatch(filePtr,"MATERIAL",8)) - { - unsigned int iIndex = 0; - ParseLV4MeshLong(iIndex); - - if (iIndex >= iMaterialCount) - { - LogWarning("Out of range: material index is too large"); - iIndex = iMaterialCount-1; - } - - // get a reference to the material - Material& sMat = m_vMaterials[iIndex+iOldMaterialCount]; - // parse the material block - ParseLV2MaterialBlock(sMat); - continue; - } - } - AI_ASE_HANDLE_TOP_LEVEL_SECTION(); - } -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2MaterialBlock(ASE::Material& mat) -{ - AI_ASE_PARSER_INIT(); - - unsigned int iNumSubMaterials = 0; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - if (TokenMatch(filePtr,"MATERIAL_NAME",13)) - { - if (!ParseString(mat.mName,"*MATERIAL_NAME")) - SkipToNextToken(); - continue; - } - // ambient material color - if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16)) - { - ParseLV4MeshFloatTriple(&mat.mAmbient.r); - continue; - } - // diffuse material color - if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) ) - { - ParseLV4MeshFloatTriple(&mat.mDiffuse.r); - continue; - } - // specular material color - if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17)) - { - ParseLV4MeshFloatTriple(&mat.mSpecular.r); - continue; - } - // material shading type - if (TokenMatch(filePtr,"MATERIAL_SHADING",16)) - { - if (TokenMatch(filePtr,"Blinn",5)) - { - mat.mShading = Discreet3DS::Blinn; - } - else if (TokenMatch(filePtr,"Phong",5)) - { - mat.mShading = Discreet3DS::Phong; - } - else if (TokenMatch(filePtr,"Flat",4)) - { - mat.mShading = Discreet3DS::Flat; - } - else if (TokenMatch(filePtr,"Wire",4)) - { - mat.mShading = Discreet3DS::Wire; - } - else - { - // assume gouraud shading - mat.mShading = Discreet3DS::Gouraud; - SkipToNextToken(); - } - continue; - } - // material transparency - if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21)) - { - ParseLV4MeshFloat(mat.mTransparency); - mat.mTransparency = 1.0f - mat.mTransparency;continue; - } - // material self illumination - if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18)) - { - float f = 0.0f; - ParseLV4MeshFloat(f); - - mat.mEmissive.r = f; - mat.mEmissive.g = f; - mat.mEmissive.b = f; - continue; - } - // material shininess - if (TokenMatch(filePtr,"MATERIAL_SHINE",14) ) - { - ParseLV4MeshFloat(mat.mSpecularExponent); - mat.mSpecularExponent *= 15; - continue; - } - // two-sided material - if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) ) - { - mat.mTwoSided = true; - continue; - } - // material shininess strength - if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22)) - { - ParseLV4MeshFloat(mat.mShininessStrength); - continue; - } - // diffuse color map - if (TokenMatch(filePtr,"MAP_DIFFUSE",11)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexDiffuse); - continue; - } - // ambient color map - if (TokenMatch(filePtr,"MAP_AMBIENT",11)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexAmbient); - continue; - } - // specular color map - if (TokenMatch(filePtr,"MAP_SPECULAR",12)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexSpecular); - continue; - } - // opacity map - if (TokenMatch(filePtr,"MAP_OPACITY",11)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexOpacity); - continue; - } - // emissive map - if (TokenMatch(filePtr,"MAP_SELFILLUM",13)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexEmissive); - continue; - } - // bump map - if (TokenMatch(filePtr,"MAP_BUMP",8)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexBump); - } - // specular/shininess map - if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17)) - { - // parse the texture block - ParseLV3MapBlock(mat.sTexShininess); - continue; - } - // number of submaterials - if (TokenMatch(filePtr,"NUMSUBMTLS",10)) - { - ParseLV4MeshLong(iNumSubMaterials); - - // allocate enough storage - mat.avSubMaterials.resize(iNumSubMaterials); - } - // submaterial chunks - if (TokenMatch(filePtr,"SUBMATERIAL",11)) - { - - unsigned int iIndex = 0; - ParseLV4MeshLong(iIndex); - - if (iIndex >= iNumSubMaterials) - { - LogWarning("Out of range: submaterial index is too large"); - iIndex = iNumSubMaterials-1; - } - - // get a reference to the material - Material& sMat = mat.avSubMaterials[iIndex]; - - // parse the material block - ParseLV2MaterialBlock(sMat); - continue; - } - } - AI_ASE_HANDLE_SECTION("2","*MATERIAL"); - } -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MapBlock(Texture& map) -{ - AI_ASE_PARSER_INIT(); - - // *********************************************************** - // *BITMAP should not be there if *MAP_CLASS is not BITMAP, - // but we need to expect that case ... if the path is - // empty the texture won't be used later. - // *********************************************************** - bool parsePath = true; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - // type of map - if (TokenMatch(filePtr,"MAP_CLASS" ,9)) - { - std::string temp; - if(!ParseString(temp,"*MAP_CLASS")) - SkipToNextToken(); - if (temp != "Bitmap") - { - DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp); - parsePath = false; - } - continue; - } - // path to the texture - if (parsePath && TokenMatch(filePtr,"BITMAP" ,6)) - { - if(!ParseString(map.mMapName,"*BITMAP")) - SkipToNextToken(); - - if (map.mMapName == "None") - { - // Files with 'None' as map name are produced by - // an Maja to ASE exporter which name I forgot .. - DefaultLogger::get()->warn("ASE: Skipping invalid map entry"); - map.mMapName = ""; - } - - continue; - } - // offset on the u axis - if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12)) - { - ParseLV4MeshFloat(map.mOffsetU); - continue; - } - // offset on the v axis - if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12)) - { - ParseLV4MeshFloat(map.mOffsetV); - continue; - } - // tiling on the u axis - if (TokenMatch(filePtr,"UVW_U_TILING" ,12)) - { - ParseLV4MeshFloat(map.mScaleU); - continue; - } - // tiling on the v axis - if (TokenMatch(filePtr,"UVW_V_TILING" ,12)) - { - ParseLV4MeshFloat(map.mScaleV); - continue; - } - // rotation around the z-axis - if (TokenMatch(filePtr,"UVW_ANGLE" ,9)) - { - ParseLV4MeshFloat(map.mRotation); - continue; - } - // map blending factor - if (TokenMatch(filePtr,"MAP_AMOUNT" ,10)) - { - ParseLV4MeshFloat(map.mTextureBlend); - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX"); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -bool Parser::ParseString(std::string& out,const char* szName) -{ - char szBuffer[1024]; - if (!SkipSpaces(&filePtr)) - { - - sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName); - LogWarning(szBuffer); - return false; - } - // there must be '"' - if ('\"' != *filePtr) - { - - sprintf(szBuffer,"Unable to parse %s block: Strings are expected " - "to be enclosed in double quotation marks",szName); - LogWarning(szBuffer); - return false; - } - ++filePtr; - const char* sz = filePtr; - while (true) - { - if ('\"' == *sz)break; - else if ('\0' == *sz) - { - sprintf(szBuffer,"Unable to parse %s block: Strings are expected to " - "be enclosed in double quotation marks but EOF was reached before " - "a closing quotation mark was encountered",szName); - LogWarning(szBuffer); - return false; - } - sz++; - } - out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr); - filePtr = sz+1; - return true; -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node) -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // first process common tokens such as node name and transform - // name of the mesh/node - if (TokenMatch(filePtr,"NODE_NAME" ,9)) - { - if(!ParseString(node.mName,"*NODE_NAME")) - SkipToNextToken(); - continue; - } - // name of the parent of the node - if (TokenMatch(filePtr,"NODE_PARENT" ,11) ) - { - if(!ParseString(node.mParent,"*NODE_PARENT")) - SkipToNextToken(); - continue; - } - // transformation matrix of the node - if (TokenMatch(filePtr,"NODE_TM" ,7)) - { - ParseLV2NodeTransformBlock(node); - continue; - } - // animation data of the node - if (TokenMatch(filePtr,"TM_ANIMATION" ,12)) - { - ParseLV2AnimationBlock(node); - continue; - } - - if (node.mType == BaseNode::Light) - { - // light settings - if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14)) - { - ParseLV2LightSettingsBlock((ASE::Light&)node); - continue; - } - // type of the light source - if (TokenMatch(filePtr,"LIGHT_TYPE" ,10)) - { - if (!ASSIMP_strincmp("omni",filePtr,4)) - { - ((ASE::Light&)node).mLightType = ASE::Light::OMNI; - } - else if (!ASSIMP_strincmp("target",filePtr,6)) - { - ((ASE::Light&)node).mLightType = ASE::Light::TARGET; - } - else if (!ASSIMP_strincmp("free",filePtr,4)) - { - ((ASE::Light&)node).mLightType = ASE::Light::FREE; - } - else if (!ASSIMP_strincmp("directional",filePtr,11)) - { - ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL; - } - else - { - LogWarning("Unknown kind of light source"); - } - continue; - } - } - else if (node.mType == BaseNode::Camera) - { - // Camera settings - if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15)) - { - ParseLV2CameraSettingsBlock((ASE::Camera&)node); - continue; - } - else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11)) - { - if (!ASSIMP_strincmp("target",filePtr,6)) - { - ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET; - } - else if (!ASSIMP_strincmp("free",filePtr,4)) - { - ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE; - } - else - { - LogWarning("Unknown kind of camera"); - } - continue; - } - } - else if (node.mType == BaseNode::Mesh) - { - // mesh data - // FIX: Older files use MESH_SOFTSKIN - if (TokenMatch(filePtr,"MESH" ,4) || - TokenMatch(filePtr,"MESH_SOFTSKIN",13)) - { - ParseLV2MeshBlock((ASE::Mesh&)node); - continue; - } - // mesh material index - if (TokenMatch(filePtr,"MATERIAL_REF" ,12)) - { - ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex); - continue; - } - } - } - AI_ASE_HANDLE_TOP_LEVEL_SECTION(); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera) -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - if (TokenMatch(filePtr,"CAMERA_NEAR" ,11)) - { - ParseLV4MeshFloat(camera.mNear); - continue; - } - if (TokenMatch(filePtr,"CAMERA_FAR" ,10)) - { - ParseLV4MeshFloat(camera.mFar); - continue; - } - if (TokenMatch(filePtr,"CAMERA_FOV" ,10)) - { - ParseLV4MeshFloat(camera.mFOV); - continue; - } - } - AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS"); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2LightSettingsBlock(ASE::Light& light) -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - if (TokenMatch(filePtr,"LIGHT_COLOR" ,11)) - { - ParseLV4MeshFloatTriple(&light.mColor.r); - continue; - } - if (TokenMatch(filePtr,"LIGHT_INTENS" ,12)) - { - ParseLV4MeshFloat(light.mIntensity); - continue; - } - if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13)) - { - ParseLV4MeshFloat(light.mAngle); - continue; - } - if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13)) - { - ParseLV4MeshFloat(light.mFalloff); - continue; - } - } - AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS"); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh) -{ - AI_ASE_PARSER_INIT(); - - ASE::Animation* anim = &mesh.mAnim; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - if (TokenMatch(filePtr,"NODE_NAME" ,9)) - { - std::string temp; - if(!ParseString(temp,"*NODE_NAME")) - SkipToNextToken(); - - // If the name of the node contains .target it - // represents an animated camera or spot light - // target. - if (std::string::npos != temp.find(".Target")) - { - if ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET) && - ( mesh.mType != BaseNode::Light || ((ASE::Light&)mesh).mLightType != ASE::Light::TARGET)) - { - - DefaultLogger::get()->error("ASE: Found target animation channel " - "but the node is neither a camera nor a spot light"); - anim = NULL; - } - else anim = &mesh.mTargetAnim; - } - continue; - } - - // position keyframes - if (TokenMatch(filePtr,"CONTROL_POS_TRACK" ,17) || - TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18) || - TokenMatch(filePtr,"CONTROL_POS_TCB" ,15)) - { - if (!anim)SkipSection(); - else ParseLV3PosAnimationBlock(*anim); - continue; - } - // scaling keyframes - if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK" ,19) || - TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) || - TokenMatch(filePtr,"CONTROL_SCALE_TCB" ,17)) - { - if (!anim || anim == &mesh.mTargetAnim) - { - // Target animation channels may have no rotation channels - DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation"); - SkipSection(); - } - else ParseLV3ScaleAnimationBlock(*anim); - continue; - } - // rotation keyframes - if (TokenMatch(filePtr,"CONTROL_ROT_TRACK" ,17) || - TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) || - TokenMatch(filePtr,"CONTROL_ROT_TCB" ,15)) - { - if (!anim || anim == &mesh.mTargetAnim) - { - // Target animation channels may have no rotation channels - DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation"); - SkipSection(); - } - else ParseLV3RotAnimationBlock(*anim); - continue; - } - } - AI_ASE_HANDLE_SECTION("2","TM_ANIMATION"); - } -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim) -{ - AI_ASE_PARSER_INIT(); - unsigned int iIndex; - - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - bool b = false; - - // For the moment we're just reading the three floats - - // we ignore the ádditional information for bezier's and TCBs - - // simple scaling keyframe - if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20)) - { - b = true; - anim.mScalingType = ASE::Animation::TRACK; - } - - // Bezier scaling keyframe - if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24)) - { - b = true; - anim.mScalingType = ASE::Animation::BEZIER; - } - // TCB scaling keyframe - if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21)) - { - b = true; - anim.mScalingType = ASE::Animation::TCB; - } - if (b) - { - anim.akeyScaling.push_back(aiVectorKey()); - aiVectorKey& key = anim.akeyScaling.back(); - ParseLV4MeshFloatTriple(&key.mValue.x,iIndex); - key.mTime = (double)iIndex; - } - } - AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK"); - } -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim) -{ - AI_ASE_PARSER_INIT(); - unsigned int iIndex; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - bool b = false; - - // For the moment we're just reading the three floats - - // we ignore the ádditional information for bezier's and TCBs - - // simple scaling keyframe - if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18)) - { - b = true; - anim.mPositionType = ASE::Animation::TRACK; - } - - // Bezier scaling keyframe - if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22)) - { - b = true; - anim.mPositionType = ASE::Animation::BEZIER; - } - // TCB scaling keyframe - if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19)) - { - b = true; - anim.mPositionType = ASE::Animation::TCB; - } - if (b) - { - anim.akeyPositions.push_back(aiVectorKey()); - aiVectorKey& key = anim.akeyPositions.back(); - ParseLV4MeshFloatTriple(&key.mValue.x,iIndex); - key.mTime = (double)iIndex; - } - } - AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK"); - } -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim) -{ - AI_ASE_PARSER_INIT(); - unsigned int iIndex; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - bool b = false; - - // For the moment we're just reading the floats - - // we ignore the ádditional information for bezier's and TCBs - - // simple scaling keyframe - if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18)) - { - b = true; - anim.mRotationType = ASE::Animation::TRACK; - } - - // Bezier scaling keyframe - if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22)) - { - b = true; - anim.mRotationType = ASE::Animation::BEZIER; - } - // TCB scaling keyframe - if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19)) - { - b = true; - anim.mRotationType = ASE::Animation::TCB; - } - if (b) - { - anim.akeyRotations.push_back(aiQuatKey()); - aiQuatKey& key = anim.akeyRotations.back(); - aiVector3D v;float f; - ParseLV4MeshFloatTriple(&v.x,iIndex); - ParseLV4MeshFloat(f); - key.mTime = (double)iIndex; - key.mValue = aiQuaternion(v,f); - } - } - AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK"); - } -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh) -{ - AI_ASE_PARSER_INIT(); - int mode = 0; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - // name of the node - if (TokenMatch(filePtr,"NODE_NAME" ,9)) - { - std::string temp; - if(!ParseString(temp,"*NODE_NAME")) - SkipToNextToken(); - - std::string::size_type s; - if (temp == mesh.mName) - { - mode = 1; - } - else if (std::string::npos != (s = temp.find(".Target")) && - mesh.mName == temp.substr(0,s)) - { - // This should be either a target light or a target camera - if ( (mesh.mType == BaseNode::Light && ((ASE::Light&)mesh) .mLightType == ASE::Light::TARGET) || - (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET)) - { - mode = 2; - } - else DefaultLogger::get()->error("ASE: Ignoring target transform, " - "this is no spot light or target camera"); - } - else - { - DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp); - // mode = 0 - } - continue; - } - if (mode) - { - // fourth row of the transformation matrix - and also the - // only information here that is interesting for targets - if (TokenMatch(filePtr,"TM_ROW3" ,7)) - { - ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x)); - continue; - } - if (mode == 1) - { - // first row of the transformation matrix - if (TokenMatch(filePtr,"TM_ROW0" ,7)) - { - ParseLV4MeshFloatTriple(mesh.mTransform[0]); - continue; - } - // second row of the transformation matrix - if (TokenMatch(filePtr,"TM_ROW1" ,7)) - { - ParseLV4MeshFloatTriple(mesh.mTransform[1]); - continue; - } - // third row of the transformation matrix - if (TokenMatch(filePtr,"TM_ROW2" ,7)) - { - ParseLV4MeshFloatTriple(mesh.mTransform[2]); - continue; - } - // inherited position axes - if (TokenMatch(filePtr,"INHERIT_POS" ,11)) - { - unsigned int aiVal[3]; - ParseLV4MeshLongTriple(aiVal); - - for (unsigned int i = 0; i < 3;++i) - mesh.inherit.abInheritPosition[i] = aiVal[i] != 0; - continue; - } - // inherited rotation axes - if (TokenMatch(filePtr,"INHERIT_ROT" ,11)) - { - unsigned int aiVal[3]; - ParseLV4MeshLongTriple(aiVal); - - for (unsigned int i = 0; i < 3;++i) - mesh.inherit.abInheritRotation[i] = aiVal[i] != 0; - continue; - } - // inherited scaling axes - if (TokenMatch(filePtr,"INHERIT_SCL" ,11)) - { - unsigned int aiVal[3]; - ParseLV4MeshLongTriple(aiVal); - - for (unsigned int i = 0; i < 3;++i) - mesh.inherit.abInheritScaling[i] = aiVal[i] != 0; - continue; - } - } - } - } - AI_ASE_HANDLE_SECTION("2","*NODE_TM"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - - unsigned int iNumVertices = 0; - unsigned int iNumFaces = 0; - unsigned int iNumTVertices = 0; - unsigned int iNumTFaces = 0; - unsigned int iNumCVertices = 0; - unsigned int iNumCFaces = 0; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - // Number of vertices in the mesh - if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14)) - { - ParseLV4MeshLong(iNumVertices); - continue; - } - // Number of texture coordinates in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15)) - { - ParseLV4MeshLong(iNumTVertices); - continue; - } - // Number of vertex colors in the mesh - if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15)) - { - ParseLV4MeshLong(iNumCVertices); - continue; - } - // Number of regular faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMFACES" ,13)) - { - ParseLV4MeshLong(iNumFaces); - continue; - } - // Number of UVWed faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15)) - { - ParseLV4MeshLong(iNumTFaces); - continue; - } - // Number of colored faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15)) - { - ParseLV4MeshLong(iNumCFaces); - continue; - } - // mesh vertex list block - if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16)) - { - ParseLV3MeshVertexListBlock(iNumVertices,mesh); - continue; - } - // mesh face list block - if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14)) - { - ParseLV3MeshFaceListBlock(iNumFaces,mesh); - continue; - } - // mesh texture vertex list block - if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14)) - { - ParseLV3MeshTListBlock(iNumTVertices,mesh); - continue; - } - // mesh texture face block - if (TokenMatch(filePtr,"MESH_TFACELIST" ,14)) - { - ParseLV3MeshTFaceListBlock(iNumTFaces,mesh); - continue; - } - // mesh color vertex list block - if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14)) - { - ParseLV3MeshCListBlock(iNumCVertices,mesh); - continue; - } - // mesh color face block - if (TokenMatch(filePtr,"MESH_CFACELIST" ,14)) - { - ParseLV3MeshCFaceListBlock(iNumCFaces,mesh); - continue; - } - // mesh normals - if (TokenMatch(filePtr,"MESH_NORMALS" ,12)) - { - ParseLV3MeshNormalListBlock(mesh); - continue; - } - // another mesh UV channel ... - if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19)) - { - - unsigned int iIndex = 0; - ParseLV4MeshLong(iIndex); - - if (iIndex < 2) - { - LogWarning("Mapping channel has an invalid index. Skipping UV channel"); - // skip it ... - SkipSection(); - } - if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS) - { - LogWarning("Too many UV channels specified. Skipping channel .."); - // skip it ... - SkipSection(); - } - else - { - // parse the mapping channel - ParseLV3MappingChannel(iIndex-1,mesh); - } - continue; - } - // mesh animation keyframe. Not supported - if (TokenMatch(filePtr,"MESH_ANIMATION" ,14)) - { - - LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. " - "Keyframe animation is not supported by Assimp, this element " - "will be ignored"); - //SkipSection(); - continue; - } - if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12)) - { - ParseLV3MeshWeightsBlock(mesh);continue; - } - } - AI_ASE_HANDLE_SECTION("2","*MESH"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - - unsigned int iNumVertices = 0, iNumBones = 0; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Number of bone vertices ... - if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14)) - { - ParseLV4MeshLong(iNumVertices); - continue; - } - // Number of bones - if (TokenMatch(filePtr,"MESH_NUMBONE" ,11)) - { - ParseLV4MeshLong(iNumBones); - continue; - } - // parse the list of bones - if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14)) - { - ParseLV4MeshBones(iNumBones,mesh); - continue; - } - // parse the list of bones vertices - if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) ) - { - ParseLV4MeshBonesVertices(iNumVertices,mesh); - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - mesh.mBones.resize(iNumBones); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Mesh bone with name ... - if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16)) - { - // parse an index ... - if(SkipSpaces(&filePtr)) - { - unsigned int iIndex = strtol10(filePtr,&filePtr); - if (iIndex >= iNumBones) - { - continue; - LogWarning("Bone index is out of bounds"); - } - if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME")) - SkipToNextToken(); - continue; - } - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST"); - } -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - mesh.mBoneVertices.resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Mesh bone vertex - if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16)) - { - // read the vertex index - unsigned int iIndex = strtol10(filePtr,&filePtr); - if (iIndex >= mesh.mPositions.size()) - { - iIndex = (unsigned int)mesh.mPositions.size()-1; - LogWarning("Bone vertex index is out of bounds. Using the largest valid " - "bone vertex index instead"); - } - - // --- ignored - float afVert[3]; - ParseLV4MeshFloatTriple(afVert); - - std::pair<int,float> pairOut; - while (true) - { - // first parse the bone index ... - if (!SkipSpaces(&filePtr))break; - pairOut.first = strtol10(filePtr,&filePtr); - - // then parse the vertex weight - if (!SkipSpaces(&filePtr))break; - filePtr = fast_atof_move(filePtr,pairOut.second); - - // -1 marks unused entries - if (-1 != pairOut.first) - { - mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut); - } - } - continue; - } - } - AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshVertexListBlock( - unsigned int iNumVertices, ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - - // allocate enough storage in the array - mesh.mPositions.resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Vertex entry - if (TokenMatch(filePtr,"MESH_VERTEX" ,11)) - { - - aiVector3D vTemp; - unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.x,iIndex); - - if (iIndex >= iNumVertices) - { - LogWarning("Invalid vertex index. It will be ignored"); - } - else mesh.mPositions[iIndex] = vTemp; - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - - // allocate enough storage in the face array - mesh.mFaces.resize(iNumFaces); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Face entry - if (TokenMatch(filePtr,"MESH_FACE" ,9)) - { - - ASE::Face mFace; - ParseLV4MeshFace(mFace); - - if (mFace.iFace >= iNumFaces) - { - LogWarning("Face has an invalid index. It will be ignored"); - } - else mesh.mFaces[mFace.iFace] = mFace; - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices, - ASE::Mesh& mesh, unsigned int iChannel) -{ - AI_ASE_PARSER_INIT(); - - // allocate enough storage in the array - mesh.amTexCoords[iChannel].resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Vertex entry - if (TokenMatch(filePtr,"MESH_TVERT" ,10)) - { - aiVector3D vTemp; - unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.x,iIndex); - - if (iIndex >= iNumVertices) - { - LogWarning("Tvertex has an invalid index. It will be ignored"); - } - else mesh.amTexCoords[iChannel][iIndex] = vTemp; - - if (0.0f != vTemp.z) - { - // we need 3 coordinate channels - mesh.mNumUVComponents[iChannel] = 3; - } - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces, - ASE::Mesh& mesh, unsigned int iChannel) -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Face entry - if (TokenMatch(filePtr,"MESH_TFACE" ,10)) - { - unsigned int aiValues[3]; - unsigned int iIndex = 0; - - ParseLV4MeshLongTriple(aiValues,iIndex); - if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) - { - LogWarning("UV-Face has an invalid index. It will be ignored"); - } - else - { - // copy UV indices - mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0]; - mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1]; - mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2]; - } - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - - unsigned int iNumTVertices = 0; - unsigned int iNumTFaces = 0; - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Number of texture coordinates in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15)) - { - ParseLV4MeshLong(iNumTVertices); - continue; - } - // Number of UVWed faces in the mesh - if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15)) - { - ParseLV4MeshLong(iNumTFaces); - continue; - } - // mesh texture vertex list block - if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14)) - { - ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel); - continue; - } - // mesh texture face block - if (TokenMatch(filePtr,"MESH_TFACELIST" ,14)) - { - ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel); - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - - // allocate enough storage in the array - mesh.mVertexColors.resize(iNumVertices); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Vertex entry - if (TokenMatch(filePtr,"MESH_VERTCOL" ,12)) - { - aiColor4D vTemp; - vTemp.a = 1.0f; - unsigned int iIndex; - ParseLV4MeshFloatTriple(&vTemp.r,iIndex); - - if (iIndex >= iNumVertices) - { - LogWarning("Vertex color has an invalid index. It will be ignored"); - } - else mesh.mVertexColors[iIndex] = vTemp; - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh) -{ - AI_ASE_PARSER_INIT(); - while (true) - { - if ('*' == *filePtr) - { - ++filePtr; - - // Face entry - if (TokenMatch(filePtr,"MESH_CFACE" ,11)) - { - unsigned int aiValues[3]; - unsigned int iIndex = 0; - - ParseLV4MeshLongTriple(aiValues,iIndex); - if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size()) - { - LogWarning("UV-Face has an invalid index. It will be ignored"); - } - else - { - // copy color indices - mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0]; - mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1]; - mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2]; - } - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh) -{ - AI_ASE_PARSER_INIT(); - - // Allocate enough storage for the normals - sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f )); - unsigned int index, faceIdx = 0xffffffff; - - // FIXME: rewrite this and find out how to interpret the normals - // correctly. This is crap. - - // Smooth the vertex and face normals together. The result - // will be edgy then, but otherwise everything would be soft ... - while (true) { - if ('*' == *filePtr) { - ++filePtr; - if (faceIdx != 0xffffffff && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17)) { - aiVector3D vNormal; - ParseLV4MeshFloatTriple(&vNormal.x,index); - if (faceIdx >= sMesh.mFaces.size()) - continue; - - // Make sure we assign it to the correct face - const ASE::Face& face = sMesh.mFaces[faceIdx]; - if (index == face.mIndices[0]) - index = 0; - else if (index == face.mIndices[1]) - index = 1; - else if (index == face.mIndices[2]) - index = 2; - else { - DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section"); - continue; - } - // We'll renormalize later - sMesh.mNormals[faceIdx*3+index] += vNormal; - continue; - } - if (TokenMatch(filePtr,"MESH_FACENORMAL",15)) { - aiVector3D vNormal; - ParseLV4MeshFloatTriple(&vNormal.x,faceIdx); - - if (faceIdx >= sMesh.mFaces.size()) { - DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section"); - continue; - } - - // We'll renormalize later - sMesh.mNormals[faceIdx*3] += vNormal; - sMesh.mNormals[faceIdx*3+1] += vNormal; - sMesh.mNormals[faceIdx*3+2] += vNormal; - continue; - } - } - AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS"); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFace(ASE::Face& out) -{ - // skip spaces and tabs - if(!SkipSpaces(&filePtr)) - { - LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]"); - SkipToNextToken(); - return; - } - - // parse the face index - out.iFace = strtol10(filePtr,&filePtr); - - // next character should be ':' - if(!SkipSpaces(&filePtr)) - { - // FIX: there are some ASE files which haven't got : here .... - LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]"); - SkipToNextToken(); - return; - } - // FIX: There are some ASE files which haven't got ':' here - if(':' == *filePtr)++filePtr; - - // Parse all mesh indices - for (unsigned int i = 0; i < 3;++i) - { - unsigned int iIndex = 0; - if(!SkipSpaces(&filePtr)) - { - LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL"); - SkipToNextToken(); - return; - } - switch (*filePtr) - { - case 'A': - case 'a': - break; - case 'B': - case 'b': - iIndex = 1; - break; - case 'C': - case 'c': - iIndex = 2; - break; - default: - LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " - "A,B or C expected [#3]"); - SkipToNextToken(); - return; - }; - ++filePtr; - - // next character should be ':' - if(!SkipSpaces(&filePtr) || ':' != *filePtr) - { - LogWarning("Unable to parse *MESH_FACE Element: " - "Unexpected EOL. \':\' expected [#2]"); - SkipToNextToken(); - return; - } - - ++filePtr; - if(!SkipSpaces(&filePtr)) - { - LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. " - "Vertex index ecpected [#4]"); - SkipToNextToken(); - return; - } - out.mIndices[iIndex] = strtol10(filePtr,&filePtr); - } - - // now we need to skip the AB, BC, CA blocks. - while (true) - { - if ('*' == *filePtr)break; - if (IsLineEnd(*filePtr)) - { - //iLineNumber++; - return; - } - filePtr++; - } - - // parse the smoothing group of the face - if (TokenMatch(filePtr,"*MESH_SMOOTHING",15)) - { - if(!SkipSpaces(&filePtr)) - { - LogWarning("Unable to parse *MESH_SMOOTHING Element: " - "Unexpected EOL. Smoothing group(s) expected [#5]"); - SkipToNextToken(); - return; - } - - // Parse smoothing groups until we don't anymore see commas - // FIX: There needn't always be a value, sad but true - while (true) - { - if (*filePtr < '9' && *filePtr >= '0') - { - out.iSmoothGroup |= (1 << strtol10(filePtr,&filePtr)); - } - SkipSpaces(&filePtr); - if (',' != *filePtr) - { - break; - } - ++filePtr; - SkipSpaces(&filePtr); - } - } - - // *MESH_MTLID is optional, too - while (true) - { - if ('*' == *filePtr)break; - if (IsLineEnd(*filePtr)) - { - return; - } - filePtr++; - } - - if (TokenMatch(filePtr,"*MESH_MTLID",11)) - { - if(!SkipSpaces(&filePtr)) - { - LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. " - "Material index expected [#6]"); - SkipToNextToken(); - return; - } - out.iMaterial = strtol10(filePtr,&filePtr); - } - return; -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshLongTriple(unsigned int* apOut) -{ - ai_assert(NULL != apOut); - - for (unsigned int i = 0; i < 3;++i) - ParseLV4MeshLong(apOut[i]); -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut) -{ - ai_assert(NULL != apOut); - - // parse the index - ParseLV4MeshLong(rIndexOut); - - // parse the three others - ParseLV4MeshLongTriple(apOut); -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut) -{ - ai_assert(NULL != apOut); - - // parse the index - ParseLV4MeshLong(rIndexOut); - - // parse the three others - ParseLV4MeshFloatTriple(apOut); -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloatTriple(float* apOut) -{ - ai_assert(NULL != apOut); - - for (unsigned int i = 0; i < 3;++i) - ParseLV4MeshFloat(apOut[i]); -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshFloat(float& fOut) -{ - // skip spaces and tabs - if(!SkipSpaces(&filePtr)) - { - // LOG - LogWarning("Unable to parse float: unexpected EOL [#1]"); - fOut = 0.0f; - ++iLineNumber; - return; - } - // parse the first float - filePtr = fast_atof_move(filePtr,fOut); -} -// ------------------------------------------------------------------------------------------------ -void Parser::ParseLV4MeshLong(unsigned int& iOut) -{ - // Skip spaces and tabs - if(!SkipSpaces(&filePtr)) - { - // LOG - LogWarning("Unable to parse long: unexpected EOL [#1]"); - iOut = 0; - ++iLineNumber; - return; - } - // parse the value - iOut = strtol10(filePtr,&filePtr); -} diff --git a/3rdparty/assimp/code/ASEParser.h b/3rdparty/assimp/code/ASEParser.h deleted file mode 100644 index 57fb6c55..00000000 --- a/3rdparty/assimp/code/ASEParser.h +++ /dev/null @@ -1,669 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the helper data structures for importing ASE files */ -#ifndef AI_ASEFILEHELPER_H_INC -#define AI_ASEFILEHELPER_H_INC - -// STL/CRT headers -#include <string> -#include <vector> -#include <list> - -// public ASSIMP headers -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include "../include/aiAnim.h" - -// for some helper routines like IsSpace() -#include "ParsingUtils.h" -#include "qnan.h" - -// ASE is quite similar to 3ds. We can reuse some structures -#include "3DSLoader.h" - -namespace Assimp { -namespace ASE { - -using namespace D3DS; - -// --------------------------------------------------------------------------- -/** Helper structure representing an ASE material */ -struct Material : public D3DS::Material -{ - //! Default constructor - Material() : pcInstance(NULL), bNeed (false) - {} - - //! Contains all sub materials of this material - std::vector<Material> avSubMaterials; - - //! MaterialHelper object - MaterialHelper* pcInstance; - - //! Can we remove this material? - bool bNeed; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE file face */ -struct Face : public FaceWithSmoothingGroup -{ - //! Default constructor. Initializes everything with 0 - Face() - { - mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0; - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - { - amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0; - } - - iMaterial = DEFAULT_MATINDEX; - iFace = 0; - } - - //! special value to indicate that no material index has - //! been assigned to a face. The default material index - //! will replace this value later. - static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF; - - - - //! Indices into each list of texture coordinates - unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3]; - - //! Index into the list of vertex colors - unsigned int mColorIndices[3]; - - //! (Sub)Material index to be assigned to this face - unsigned int iMaterial; - - //! Index of the face. It is not specified whether it is - //! a requirement of the file format that all faces are - //! written in sequential order, so we have to expect this case - unsigned int iFace; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE file bone */ -struct Bone -{ - //! Constructor - Bone() - { - static int iCnt = 0; - - // Generate a default name for the bone - char szTemp[128]; - ::sprintf(szTemp,"UNNAMED_%i",iCnt++); - mName = szTemp; - } - - //! Construction from an existing name - Bone( const std::string& name) - : mName (name) - {} - - //! Name of the bone - std::string mName; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE file bone vertex */ -struct BoneVertex -{ - //! Bone and corresponding vertex weight. - //! -1 for unrequired bones .... - std::vector<std::pair<int,float> > mBoneWeights; - - //! Position of the bone vertex. - //! MUST be identical to the vertex position - //aiVector3D mPosition; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE file animation */ -struct Animation -{ - enum Type - { - TRACK = 0x0, - BEZIER = 0x1, - TCB = 0x2 - } mRotationType, mScalingType, mPositionType; - - Animation() - : mRotationType (TRACK) - , mScalingType (TRACK) - , mPositionType (TRACK) - {} - - //! List of track rotation keyframes - std::vector< aiQuatKey > akeyRotations; - - //! List of track position keyframes - std::vector< aiVectorKey > akeyPositions; - - //! List of track scaling keyframes - std::vector< aiVectorKey > akeyScaling; - -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent the inheritance information of an ASE node */ -struct InheritanceInfo -{ - //! Default constructor - InheritanceInfo() - { - // set the inheritance flag for all axes by default to true - for (unsigned int i = 0; i < 3;++i) - abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true; - } - - //! Inherit the parent's position?, axis order is x,y,z - bool abInheritPosition[3]; - - //! Inherit the parent's rotation?, axis order is x,y,z - bool abInheritRotation[3]; - - //! Inherit the parent's scaling?, axis order is x,y,z - bool abInheritScaling[3]; -}; - -// --------------------------------------------------------------------------- -/** Represents an ASE file node. Base class for mesh, light and cameras */ -struct BaseNode -{ - enum Type {Light, Camera, Mesh, Dummy} mType; - - //! Constructor. Creates a default name for the node - BaseNode(Type _mType) - : mType (_mType) - , mProcessed (false) - { - // generate a default name for the node - static int iCnt = 0; - char szTemp[128]; // should be sufficiently large - ::sprintf(szTemp,"UNNAMED_%i",iCnt++); - mName = szTemp; - - // Set mTargetPosition to qnan - const float qnan = get_qnan(); - mTargetPosition.x = qnan; - } - - //! Name of the mesh - std::string mName; - - //! Name of the parent of the node - //! "" if there is no parent ... - std::string mParent; - - //! Transformation matrix of the node - aiMatrix4x4 mTransform; - - //! Target position (target lights and cameras) - aiVector3D mTargetPosition; - - //! Specifies which axes transformations a node inherits - //! from its parent ... - InheritanceInfo inherit; - - //! Animation channels for the node - Animation mAnim; - - //! Needed for lights and cameras: target animation channel - //! Should contain position keys only. - Animation mTargetAnim; - - bool mProcessed; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE file mesh */ -struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode -{ - //! Constructor. - Mesh() - : BaseNode (BaseNode::Mesh) - , bSkip (false) - { - // use 2 texture vertex components by default - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - this->mNumUVComponents[c] = 2; - - // setup the default material index by default - iMaterialIndex = Face::DEFAULT_MATINDEX; - } - - //! List of all texture coordinate sets - std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - - //! List of all vertex color sets. - std::vector<aiColor4D> mVertexColors; - - //! List of all bone vertices - std::vector<BoneVertex> mBoneVertices; - - //! List of all bones - std::vector<Bone> mBones; - - //! Material index of the mesh - unsigned int iMaterialIndex; - - //! Number of vertex components for each UVW set - unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - - //! used internally - bool bSkip; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE light source */ -struct Light : public BaseNode -{ - enum LightType - { - OMNI, - TARGET, - FREE, - DIRECTIONAL - }; - - //! Constructor. - Light() - : BaseNode (BaseNode::Light) - , mLightType (OMNI) - , mColor (1.f,1.f,1.f) - , mIntensity (1.f) // light is white by default - , mAngle (45.f) - , mFalloff (0.f) - { - } - - LightType mLightType; - aiColor3D mColor; - float mIntensity; - float mAngle; // in degrees - float mFalloff; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE camera */ -struct Camera : public BaseNode -{ - enum CameraType - { - FREE, - TARGET - }; - - //! Constructor - Camera() - : BaseNode (BaseNode::Camera) - , mFOV (0.75f) // in radians - , mNear (0.1f) - , mFar (1000.f) // could be zero - , mCameraType (FREE) - { - } - - float mFOV, mNear, mFar; - CameraType mCameraType; -}; - -// --------------------------------------------------------------------------- -/** Helper structure to represent an ASE helper object (dummy) */ -struct Dummy : public BaseNode -{ - //! Constructor - Dummy() - : BaseNode (BaseNode::Dummy) - { - } -}; - -// Parameters to Parser::Parse() -#define AI_ASE_NEW_FILE_FORMAT 200 -#define AI_ASE_OLD_FILE_FORMAT 110 - -// Internally we're a little bit more tolerant -#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200) -#define AI_ASE_IS_OLD_FILE_FORMAT() (iFileFormat < 200) - -// ------------------------------------------------------------------------------- -/** \brief Class to parse ASE files - */ -class Parser -{ - -private: - - Parser() {} - -public: - - // ------------------------------------------------------------------- - //! Construct a parser from a given input file which is - //! guaranted to be terminated with zero. - //! @param szFile Input file - //! @param fileFormatDefault Assumed file format version. If the - //! file format is specified in the file the new value replaces - //! the default value. - Parser (const char* szFile, unsigned int fileFormatDefault); - - // ------------------------------------------------------------------- - //! Parses the file into the parsers internal representation - void Parse(); - - -private: - - // ------------------------------------------------------------------- - //! Parse the *SCENE block in a file - void ParseLV1SceneBlock(); - - // ------------------------------------------------------------------- - //! Parse the *MESH_SOFTSKINVERTS block in a file - void ParseLV1SoftSkinBlock(); - - // ------------------------------------------------------------------- - //! Parse the *MATERIAL_LIST block in a file - void ParseLV1MaterialListBlock(); - - // ------------------------------------------------------------------- - //! Parse a *<xxx>OBJECT block in a file - //! \param mesh Node to be filled - void ParseLV1ObjectBlock(BaseNode& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MATERIAL blocks in a material list - //! \param mat Material structure to be filled - void ParseLV2MaterialBlock(Material& mat); - - // ------------------------------------------------------------------- - //! Parse a *NODE_TM block in a file - //! \param mesh Node (!) object to be filled - void ParseLV2NodeTransformBlock(BaseNode& mesh); - - // ------------------------------------------------------------------- - //! Parse a *TM_ANIMATION block in a file - //! \param mesh Mesh object to be filled - void ParseLV2AnimationBlock(BaseNode& mesh); - void ParseLV3PosAnimationBlock(ASE::Animation& anim); - void ParseLV3ScaleAnimationBlock(ASE::Animation& anim); - void ParseLV3RotAnimationBlock(ASE::Animation& anim); - - // ------------------------------------------------------------------- - //! Parse a *MESH block in a file - //! \param mesh Mesh object to be filled - void ParseLV2MeshBlock(Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *LIGHT_SETTINGS block in a file - //! \param light Light object to be filled - void ParseLV2LightSettingsBlock(Light& light); - - // ------------------------------------------------------------------- - //! Parse a *CAMERA_SETTINGS block in a file - //! \param cam Camera object to be filled - void ParseLV2CameraSettingsBlock(Camera& cam); - - // ------------------------------------------------------------------- - //! Parse the *MAP_XXXXXX blocks in a material - //! \param map Texture structure to be filled - void ParseLV3MapBlock(Texture& map); - - // ------------------------------------------------------------------- - //! Parse a *MESH_VERTEX_LIST block in a file - //! \param iNumVertices Value of *MESH_NUMVERTEX, if present. - //! Otherwise zero. This is used to check the consistency of the file. - //! A warning is sent to the logger if the validations fails. - //! \param mesh Mesh object to be filled - void ParseLV3MeshVertexListBlock( - unsigned int iNumVertices,Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_FACE_LIST block in a file - //! \param iNumFaces Value of *MESH_NUMFACES, if present. - //! Otherwise zero. This is used to check the consistency of the file. - //! A warning is sent to the logger if the validations fails. - //! \param mesh Mesh object to be filled - void ParseLV3MeshFaceListBlock( - unsigned int iNumFaces,Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_TVERT_LIST block in a file - //! \param iNumVertices Value of *MESH_NUMTVERTEX, if present. - //! Otherwise zero. This is used to check the consistency of the file. - //! A warning is sent to the logger if the validations fails. - //! \param mesh Mesh object to be filled - //! \param iChannel Output UVW channel - void ParseLV3MeshTListBlock( - unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0); - - // ------------------------------------------------------------------- - //! Parse a *MESH_TFACELIST block in a file - //! \param iNumFaces Value of *MESH_NUMTVFACES, if present. - //! Otherwise zero. This is used to check the consistency of the file. - //! A warning is sent to the logger if the validations fails. - //! \param mesh Mesh object to be filled - //! \param iChannel Output UVW channel - void ParseLV3MeshTFaceListBlock( - unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0); - - // ------------------------------------------------------------------- - //! Parse an additional mapping channel - //! (specified via *MESH_MAPPINGCHANNEL) - //! \param iChannel Channel index to be filled - //! \param mesh Mesh object to be filled - void ParseLV3MappingChannel( - unsigned int iChannel, Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_CVERTLIST block in a file - //! \param iNumVertices Value of *MESH_NUMCVERTEX, if present. - //! Otherwise zero. This is used to check the consistency of the file. - //! A warning is sent to the logger if the validations fails. - //! \param mesh Mesh object to be filled - void ParseLV3MeshCListBlock( - unsigned int iNumVertices, Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_CFACELIST block in a file - //! \param iNumFaces Value of *MESH_NUMCVFACES, if present. - //! Otherwise zero. This is used to check the consistency of the file. - //! A warning is sent to the logger if the validations fails. - //! \param mesh Mesh object to be filled - void ParseLV3MeshCFaceListBlock( - unsigned int iNumFaces, Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_NORMALS block in a file - //! \param mesh Mesh object to be filled - void ParseLV3MeshNormalListBlock(Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_WEIGHTSblock in a file - //! \param mesh Mesh object to be filled - void ParseLV3MeshWeightsBlock(Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse the bone list of a file - //! \param mesh Mesh object to be filled - //! \param iNumBones Number of bones in the mesh - void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse the bone vertices list of a file - //! \param mesh Mesh object to be filled - //! \param iNumVertices Number of vertices to be parsed - void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh); - - // ------------------------------------------------------------------- - //! Parse a *MESH_FACE block in a file - //! \param out receive the face data - void ParseLV4MeshFace(ASE::Face& out); - - // ------------------------------------------------------------------- - //! Parse a *MESH_VERT block in a file - //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) - //! \param apOut Output buffer (3 floats) - //! \param rIndexOut Output index - void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut); - - // ------------------------------------------------------------------- - //! Parse a *MESH_VERT block in a file - //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL ...) - //! \param apOut Output buffer (3 floats) - void ParseLV4MeshFloatTriple(float* apOut); - - // ------------------------------------------------------------------- - //! Parse a *MESH_TFACE block in a file - //! (also works for MESH_CFACE) - //! \param apOut Output buffer (3 ints) - //! \param rIndexOut Output index - void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut); - - // ------------------------------------------------------------------- - //! Parse a *MESH_TFACE block in a file - //! (also works for MESH_CFACE) - //! \param apOut Output buffer (3 ints) - void ParseLV4MeshLongTriple(unsigned int* apOut); - - // ------------------------------------------------------------------- - //! Parse a single float element - //! \param fOut Output float - void ParseLV4MeshFloat(float& fOut); - - // ------------------------------------------------------------------- - //! Parse a single int element - //! \param iOut Output integer - void ParseLV4MeshLong(unsigned int& iOut); - - // ------------------------------------------------------------------- - //! Skip everything to the next: '*' or '\0' - bool SkipToNextToken(); - - // ------------------------------------------------------------------- - //! Skip the current section until the token after the closing }. - //! This function handles embedded subsections correctly - bool SkipSection(); - - // ------------------------------------------------------------------- - //! Output a warning to the logger - //! \param szWarn Warn message - void LogWarning(const char* szWarn); - - // ------------------------------------------------------------------- - //! Output a message to the logger - //! \param szWarn Message - void LogInfo(const char* szWarn); - - // ------------------------------------------------------------------- - //! Output an error to the logger - //! \param szWarn Error message - void LogError(const char* szWarn); - - // ------------------------------------------------------------------- - //! Parse a string, enclosed in double quotation marks - //! \param out Output string - //! \param szName Name of the enclosing element -> used in error - //! messages. - //! \return false if an error occured - bool ParseString(std::string& out,const char* szName); - -public: - - //! Pointer to current data - const char* filePtr; - - //! background color to be passed to the viewer - //! QNAN if none was found - aiColor3D m_clrBackground; - - //! Base ambient color to be passed to all materials - //! QNAN if none was found - aiColor3D m_clrAmbient; - - //! List of all materials found in the file - std::vector<Material> m_vMaterials; - - //! List of all meshes found in the file - std::vector<Mesh> m_vMeshes; - - //! List of all dummies found in the file - std::vector<Dummy> m_vDummies; - - //! List of all lights found in the file - std::vector<Light> m_vLights; - - //! List of all cameras found in the file - std::vector<Camera> m_vCameras; - - //! Current line in the file - unsigned int iLineNumber; - - //! First frame - unsigned int iFirstFrame; - - //! Last frame - unsigned int iLastFrame; - - //! Frame speed - frames per second - unsigned int iFrameSpeed; - - //! Ticks per frame - unsigned int iTicksPerFrame; - - //! true if the last character read was an end-line character - bool bLastWasEndLine; - - //! File format version - unsigned int iFileFormat; -}; - - -} // Namespace ASE -} // Namespace ASSIMP - -#endif // !! include guard diff --git a/3rdparty/assimp/code/Assimp.cpp b/3rdparty/assimp/code/Assimp.cpp deleted file mode 100644 index e2a1f2f7..00000000 --- a/3rdparty/assimp/code/Assimp.cpp +++ /dev/null @@ -1,731 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Assimp.cpp - * @brief Implementation of the Plain-C API - */ - -#include "AssimpPCH.h" -#include "../include/assimp.h" -#include "../include/aiFileIO.h" - -#include "GenericProperty.h" - -// ------------------------------------------------------------------------------------------------ -#ifdef AI_C_THREADSAFE -# include <boost/thread/thread.hpp> -# include <boost/thread/mutex.hpp> -#endif -// ------------------------------------------------------------------------------------------------ -using namespace Assimp; - -namespace Assimp -{ - /** Stores the importer objects for all active import processes */ - typedef std::map<const aiScene*, Assimp::Importer*> ImporterMap; - - /** Stores the LogStream objects for all active C log streams */ - struct mpred { - bool operator () (const aiLogStream& s0, const aiLogStream& s1) const { - return s0.callback<s1.callback&&s0.user<s1.user; - } - }; - typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap; - - /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */ - typedef std::list<Assimp::LogStream*> PredefLogStreamMap; - - /** Local storage of all active import processes */ - static ImporterMap gActiveImports; - - /** Local storage of all active log streams */ - static LogStreamMap gActiveLogStreams; - - /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */ - static PredefLogStreamMap gPredefinedStreams; - - /** Error message of the last failed import process */ - static std::string gLastErrorString; - - /** Verbose logging active or not? */ - static aiBool gVerboseLogging = false; -} - -/** Configuration properties */ -static ImporterPimpl::IntPropertyMap gIntProperties; -static ImporterPimpl::FloatPropertyMap gFloatProperties; -static ImporterPimpl::StringPropertyMap gStringProperties; - -#ifdef AI_C_THREADSAFE -/** Global mutex to manage the access to the importer map */ -static boost::mutex gMutex; - -/** Global mutex to manage the access to the logstream map */ -static boost::mutex gLogStreamMutex; -#endif - -class CIOSystemWrapper; -class CIOStreamWrapper; - -// ------------------------------------------------------------------------------------------------ -// Custom IOStream implementation for the C-API -class CIOStreamWrapper : public IOStream -{ - friend class CIOSystemWrapper; -public: - - CIOStreamWrapper(aiFile* pFile) - : mFile(pFile) - {} - - // ................................................................... - size_t Read(void* pvBuffer, - size_t pSize, - size_t pCount - ){ - // need to typecast here as C has no void* - return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount); - } - - // ................................................................... - size_t Write(const void* pvBuffer, - size_t pSize, - size_t pCount - ){ - // need to typecast here as C has no void* - return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount); - } - - // ................................................................... - aiReturn Seek(size_t pOffset, - aiOrigin pOrigin - ){ - return mFile->SeekProc(mFile,pOffset,pOrigin); - } - - // ................................................................... - size_t Tell(void) const { - return mFile->TellProc(mFile); - } - - // ................................................................... - size_t FileSize() const { - return mFile->FileSizeProc(mFile); - } - - // ................................................................... - void Flush () { - return mFile->FlushProc(mFile); - } - -private: - aiFile* mFile; -}; - -// ------------------------------------------------------------------------------------------------ -// Custom IOStream implementation for the C-API -class CIOSystemWrapper : public IOSystem -{ -public: - CIOSystemWrapper(aiFileIO* pFile) - : mFileSystem(pFile) - {} - - // ................................................................... - bool Exists( const char* pFile) const { - CIOSystemWrapper* pip = const_cast<CIOSystemWrapper*>(this); - IOStream* p = pip->Open(pFile); - if (p){ - pip->Close(p); - return true; - } - return false; - } - - // ................................................................... - char getOsSeparator() const { -#ifndef _WIN32 - return '/'; -#else - return '\\'; -#endif - } - - // ................................................................... - IOStream* Open(const char* pFile,const char* pMode = "rb") { - aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode); - if (!p) { - return NULL; - } - return new CIOStreamWrapper(p); - } - - // ................................................................... - void Close( IOStream* pFile) { - if (!pFile) { - return; - } - mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile); - delete pFile; - } -private: - aiFileIO* mFileSystem; -}; - -// ------------------------------------------------------------------------------------------------ -// Custom LogStream implementation for the C-API -class LogToCallbackRedirector : public LogStream -{ -public: - LogToCallbackRedirector(const aiLogStream& s) - : stream (s) { - ai_assert(NULL != s.callback); - } - - ~LogToCallbackRedirector() { -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gLogStreamMutex); -#endif - // (HACK) Check whether the 'stream.user' pointer points to a - // custom LogStream allocated by #aiGetPredefinedLogStream. - // In this case, we need to delete it, too. Of course, this - // might cause strange problems, but the chance is quite low. - - PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(), - gPredefinedStreams.end(), (Assimp::LogStream*)stream.user); - - if (it != gPredefinedStreams.end()) { - delete *it; - gPredefinedStreams.erase(it); - } - } - - /** @copydoc LogStream::write */ - void write(const char* message) { - stream.callback(message,stream.user); - } - -private: - aiLogStream stream; -}; - -// ------------------------------------------------------------------------------------------------ -void ReportSceneNotFoundError() -{ - DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " - "Are you playing fools with us? Don't mix cpp and c API. Thanks."); - - assert(false); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the given file and returns its content. -const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) -{ - return aiImportFileEx(pFile,pFlags,NULL); -} - -// ------------------------------------------------------------------------------------------------ -const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, - aiFileIO* pFS) -{ - ai_assert(NULL != pFile); - - const aiScene* scene = NULL; - ASSIMP_BEGIN_EXCEPTION_REGION(); - - // create an Importer for this file - Assimp::Importer* imp = new Assimp::Importer(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - // copy the global property lists to the Importer instance - imp->pimpl->mIntProperties = gIntProperties; - imp->pimpl->mFloatProperties = gFloatProperties; - imp->pimpl->mStringProperties = gStringProperties; - -#ifdef AI_C_THREADSAFE - lock.unlock(); -#endif - - // setup a custom IO system if necessary - if (pFS) { - imp->SetIOHandler( new CIOSystemWrapper (pFS) ); - } - - // and have it read the file - scene = imp->ReadFile( pFile, pFlags); - - // if succeeded, place it in the collection of active processes - if ( scene) { -#ifdef AI_C_THREADSAFE - lock.lock(); -#endif - gActiveImports[scene] = imp; - } - else { - // if failed, extract error code and destroy the import - gLastErrorString = imp->GetErrorString(); - delete imp; - } - - // return imported data. If the import failed the pointer is NULL anyways - ASSIMP_END_EXCEPTION_REGION(const aiScene*); - return scene; -} - -// ------------------------------------------------------------------------------------------------ -const aiScene* aiImportFileFromMemory( - const char* pBuffer, - unsigned int pLength, - unsigned int pFlags, - const char* pHint) -{ - ai_assert(NULL != pBuffer && 0 != pLength); - - const aiScene* scene = NULL; - ASSIMP_BEGIN_EXCEPTION_REGION(); - - // create an Importer for this file - Assimp::Importer* imp = new Assimp::Importer(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - // copy the global property lists to the Importer instance - imp->pimpl->mIntProperties = gIntProperties; - imp->pimpl->mFloatProperties = gFloatProperties; - imp->pimpl->mStringProperties = gStringProperties; - -#ifdef AI_C_THREADSAFE - lock.unlock(); -#endif - - // and have it read the file from the memory buffer - scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint); - - // if succeeded, place it in the collection of active processes - if ( scene) { -#ifdef AI_C_THREADSAFE - lock.lock(); -#endif - gActiveImports[scene] = imp; - } - else { - // if failed, extract error code and destroy the import - gLastErrorString = imp->GetErrorString(); - delete imp; - } - // return imported data. If the import failed the pointer is NULL anyways - ASSIMP_END_EXCEPTION_REGION(const aiScene*); - return scene; -} - -// ------------------------------------------------------------------------------------------------ -// Releases all resources associated with the given import process. -void aiReleaseImport( const aiScene* pScene) -{ - if (!pScene) { - return; - } - - ASSIMP_BEGIN_EXCEPTION_REGION(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - - // find the importer associated with this data - ImporterMap::iterator it = gActiveImports.find( pScene); - // it should be there... else the user is playing fools with us - if ( it == gActiveImports.end()) { - ReportSceneNotFoundError(); - return; - } - - // kill the importer, the data dies with it - delete it->second; - gActiveImports.erase( it); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene, - unsigned int pFlags) -{ - const aiScene* sc = NULL; - - - ASSIMP_BEGIN_EXCEPTION_REGION(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - // find the importer associated with this data - ImporterMap::iterator it = gActiveImports.find( pScene); - // it should be there... else the user is playing fools with us - if ( it == gActiveImports.end()) { - ReportSceneNotFoundError(); - return NULL; - } -#ifdef AI_C_THREADSAFE - lock.unlock(); -#endif - sc = it->second->ApplyPostProcessing(pFlags); -#ifdef AI_C_THREADSAFE - lock.lock(); -#endif - if (!sc) { - // kill the importer, the data dies with it - delete it->second; - gActiveImports.erase( it); - return NULL; - } - - ASSIMP_END_EXCEPTION_REGION(const aiScene*); - return sc; -} - -// ------------------------------------------------------------------------------------------------ -void CallbackToLogRedirector (const char* msg, char* dt) -{ - ai_assert(NULL != msg && NULL != dt); - LogStream* s = (LogStream*)dt; - - s->write(msg); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file) -{ - aiLogStream sout; - - ASSIMP_BEGIN_EXCEPTION_REGION(); - LogStream* stream = LogStream::createDefaultStream(pStream,file); - if (!stream) { - sout.callback = NULL; - sout.user = NULL; - } - else { - sout.callback = &CallbackToLogRedirector; - sout.user = (char*)stream; - } - gPredefinedStreams.push_back(stream); - ASSIMP_END_EXCEPTION_REGION(aiLogStream); - return sout; -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiAttachLogStream( const aiLogStream* stream ) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gLogStreamMutex); -#endif - - LogStream* lg = new LogToCallbackRedirector(*stream); - gActiveLogStreams[*stream] = lg; - - if (DefaultLogger::isNullLogger()) { - DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); - } - DefaultLogger::get()->attachStream(lg); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gLogStreamMutex); -#endif - // find the logstream associated with this data - LogStreamMap::iterator it = gActiveLogStreams.find( *stream); - // it should be there... else the user is playing fools with us - if ( it == gActiveLogStreams.end()) { - return AI_FAILURE; - } - DefaultLogger::get()->detatchStream( it->second ); - delete it->second; - - gActiveLogStreams.erase( it); - - if (gActiveLogStreams.empty()) { - DefaultLogger::kill(); - } - ASSIMP_END_EXCEPTION_REGION(aiReturn); - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiDetachAllLogStreams(void) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gLogStreamMutex); -#endif - for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { - DefaultLogger::get()->detatchStream( it->second ); - delete it->second; - } - gActiveLogStreams.clear(); - DefaultLogger::kill(); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiEnableVerboseLogging(aiBool d) -{ - if (!DefaultLogger::isNullLogger()) { - DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); - } - gVerboseLogging = d; -} - -// ------------------------------------------------------------------------------------------------ -// Returns the error text of the last failed import process. -const char* aiGetErrorString() -{ - return gLastErrorString.c_str(); -} - -// ------------------------------------------------------------------------------------------------ -// Returns the error text of the last failed import process. -aiBool aiIsExtensionSupported(const char* szExtension) -{ - ai_assert(NULL != szExtension); - aiBool candoit=AI_FALSE; - ASSIMP_BEGIN_EXCEPTION_REGION(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - - if (!gActiveImports.empty()) { - return ((*(gActiveImports.begin())).second->IsExtensionSupported( szExtension )) ? AI_TRUE : AI_FALSE; - } - - // fixme: no need to create a temporary Importer instance just for that .. - Assimp::Importer tmp; - candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE; - - ASSIMP_END_EXCEPTION_REGION(aiBool); - return candoit; -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all file extensions supported by ASSIMP -void aiGetExtensionList(aiString* szOut) -{ - ai_assert(NULL != szOut); - ASSIMP_BEGIN_EXCEPTION_REGION(); - -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - - if (!gActiveImports.empty()) { - (*(gActiveImports.begin())).second->GetExtensionList(*szOut); - return; - } - // fixme: no need to create a temporary Importer instance just for that .. - Assimp::Importer tmp; - tmp.GetExtensionList(*szOut); - - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Get the memory requirements for a particular import. -void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn, - C_STRUCT aiMemoryInfo* in) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - - // find the importer associated with this data - ImporterMap::iterator it = gActiveImports.find( pIn); - // it should be there... else the user is playing fools with us - if ( it == gActiveImports.end()) { - ReportSceneNotFoundError(); - return; - } - // get memory statistics -#ifdef AI_C_THREADSAFE - lock.unlock(); -#endif - it->second->GetMemoryRequirements(*in); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Importer::SetPropertyInteger -ASSIMP_API void aiSetImportPropertyInteger(const char* szName, int value) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - SetGenericProperty<int>(gIntProperties,szName,value,NULL); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Importer::SetPropertyFloat -ASSIMP_API void aiSetImportPropertyFloat(const char* szName, float value) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - SetGenericProperty<float>(gFloatProperties,szName,value,NULL); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Importer::SetPropertyString -ASSIMP_API void aiSetImportPropertyString(const char* szName, - const C_STRUCT aiString* st) -{ - if (!st) { - return; - } - ASSIMP_BEGIN_EXCEPTION_REGION(); -#ifdef AI_C_THREADSAFE - boost::mutex::scoped_lock lock(gMutex); -#endif - SetGenericProperty<std::string>(gStringProperties,szName, - std::string( st->data ),NULL); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Rotation matrix to quaternion -ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat) -{ - ai_assert(NULL != quat && NULL != mat); - *quat = aiQuaternion(*mat); -} - -// ------------------------------------------------------------------------------------------------ -// Matrix decomposition -ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling, - aiQuaternion* rotation, - aiVector3D* position) -{ - ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat); - mat->Decompose(*scaling,*rotation,*position); -} - -// ------------------------------------------------------------------------------------------------ -// Matrix transpose -ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat) -{ - ai_assert(NULL != mat); - mat->Transpose(); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat) -{ - ai_assert(NULL != mat); - mat->Transpose(); -} - -// ------------------------------------------------------------------------------------------------ -// Vector transformation -ASSIMP_API void aiTransformVecByMatrix3(C_STRUCT aiVector3D* vec, - const C_STRUCT aiMatrix3x3* mat) -{ - ai_assert(NULL != mat && NULL != vec); - *vec *= (*mat); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiTransformVecByMatrix4(C_STRUCT aiVector3D* vec, - const C_STRUCT aiMatrix4x4* mat) -{ - ai_assert(NULL != mat && NULL != vec); - *vec *= (*mat); -} - -// ------------------------------------------------------------------------------------------------ -// Matrix multiplication -ASSIMP_API void aiMultiplyMatrix4( - C_STRUCT aiMatrix4x4* dst, - const C_STRUCT aiMatrix4x4* src) -{ - ai_assert(NULL != dst && NULL != src); - *dst = (*dst) * (*src); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiMultiplyMatrix3( - C_STRUCT aiMatrix3x3* dst, - const C_STRUCT aiMatrix3x3* src) -{ - ai_assert(NULL != dst && NULL != src); - *dst = (*dst) * (*src); -} - -// ------------------------------------------------------------------------------------------------ -// Matrix identity -ASSIMP_API void aiIdentityMatrix3( - C_STRUCT aiMatrix3x3* mat) -{ - ai_assert(NULL != mat); - *mat = aiMatrix3x3(); -} - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiIdentityMatrix4( - C_STRUCT aiMatrix4x4* mat) -{ - ai_assert(NULL != mat); - *mat = aiMatrix4x4(); -} - - diff --git a/3rdparty/assimp/code/AssimpPCH.cpp b/3rdparty/assimp/code/AssimpPCH.cpp deleted file mode 100644 index cdc007c5..00000000 --- a/3rdparty/assimp/code/AssimpPCH.cpp +++ /dev/null @@ -1,70 +0,0 @@ - -// Actually just a dummy, used by the compiler to build the precompiled header. - -#include "AssimpPCH.h" -#include "./../include/aiVersion.h" - -// -------------------------------------------------------------------------------- -// Legal information string - dont't remove from image! -static const char* LEGAL_INFORMATION = - -"Open Asset Import Library (Assimp).\n" -"A free C/C++ library to import various 3D file formats into applications\n\n" - -"(c) 2008-2010, ASSIMP Development Team\n" -"License under the terms and conditions of the 3-clause BSD license\n" -"http://assimp.sourceforge.net\n" -; - -// ------------------------------------------------------------------------------------------------ -// Get legal string -ASSIMP_API const char* aiGetLegalString () { - return LEGAL_INFORMATION; -} - -// ------------------------------------------------------------------------------------------------ -// Get Assimp minor version -ASSIMP_API unsigned int aiGetVersionMinor () { - return 0; -} - -// ------------------------------------------------------------------------------------------------ -// Get Assimp major version -ASSIMP_API unsigned int aiGetVersionMajor () { - return 2; -} - -// ------------------------------------------------------------------------------------------------ -// Get flags used for compilation -ASSIMP_API unsigned int aiGetCompileFlags () { - - unsigned int flags = 0; - -#ifdef ASSIMP_BUILD_BOOST_WORKAROUND - flags |= ASSIMP_CFLAGS_NOBOOST; -#endif -#ifdef ASSIMP_BUILD_SINGLETHREADED - flags |= ASSIMP_CFLAGS_SINGLETHREADED; -#endif -#ifdef ASSIMP_BUILD_DEBUG - flags |= ASSIMP_CFLAGS_DEBUG; -#endif -#ifdef ASSIMP_BUILD_DLL_EXPORT - flags |= ASSIMP_CFLAGS_SHARED; -#endif -#ifdef _STLPORT_VERSION - flags |= ASSIMP_CFLAGS_STLPORT; -#endif - - return flags; -} - -// include current build revision, which is even updated from time to time -- :-) -#include "../revision.h" - -// ------------------------------------------------------------------------------------------------ -ASSIMP_API unsigned int aiGetVersionRevision () -{ - return SVNRevision; -} - diff --git a/3rdparty/assimp/code/AssimpPCH.h b/3rdparty/assimp/code/AssimpPCH.h deleted file mode 100644 index a0eb1fae..00000000 --- a/3rdparty/assimp/code/AssimpPCH.h +++ /dev/null @@ -1,149 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 AssimpPCH.h - * PCH master include. Every unit in Assimp has to include it. - */ - -#ifndef ASSIMP_PCH_INCLUDED -#define ASSIMP_PCH_INCLUDED -#define ASSIMP_INTERNAL_BUILD - -// ---------------------------------------------------------------------------------------- -/* General compile config taken from aiDefines.h. It is important that the user compiles - * using exactly the same settings in aiDefines.h. Settings in AssimpPCH.h may differ, - * they won't affect the public API. - */ -#include "../include/aiDefines.h" - -/* Include our stdint.h replacement header for MSVC, take the global header for gcc/mingw - */ -#ifdef _MSC_VER -# include "pstdint.h" -#else -# include <stdint.h> -#endif - -/* Undefine the min/max macros defined by some platform headers (namely Windows.h) to - * avoid obvious conflicts with std::min() and std::max(). - */ -#undef min -#undef max - -/* Concatenate two tokens after evaluating them - */ -#define _AI_CONCAT(a,b) a ## b -#define AI_CONCAT(a,b) _AI_CONCAT(a,b) - -/* Helper macro to set a pointer to NULL in debug builds - */ -#if (defined _DEBUG) -# define AI_DEBUG_INVALIDATE_PTR(x) x = NULL; -#else -# define AI_DEBUG_INVALIDATE_PTR(x) -#endif - -/* Beginning with MSVC8 some C string manipulation functions are mapped to their _safe_ - * counterparts (e.g. _itoa_s). This avoids a lot of trouble with deprecation warnings. - */ -#if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) -# define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 -#endif - -/* size_t to unsigned int, possible loss of data. The compiler is right with his warning - * but this loss of data won't be a problem for us. So shut up, little boy. - */ -#ifdef _MSC_VER -# pragma warning (disable : 4267) -#endif - -// ---------------------------------------------------------------------------------------- -/* Actually that's not required for MSVC. It is included somewhere in the deeper parts of - * the MSVC STL but it's necessary for proper build with STLport. - */ -#include <ctype.h> - -// Runtime/STL headers -#include <vector> -#include <list> -#include <map> -#include <set> -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> -#include <stack> -#include <queue> -#include <iostream> -#include <algorithm> -#include <numeric> -#include <new> -#include <cstdio> - -// Boost headers -#include <boost/pointer_cast.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/scoped_array.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/shared_array.hpp> -//#include <boost/make_shared.hpp> -#include <boost/format.hpp> -#include <boost/foreach.hpp> -#include <boost/static_assert.hpp> -#include <boost/lexical_cast.hpp> - -// Public ASSIMP headers -#include "../include/DefaultLogger.h" -#include "../include/IOStream.h" -#include "../include/IOSystem.h" -#include "../include/aiScene.h" -#include "../include/aiPostProcess.h" -#include "../include/assimp.hpp" - -// Internal utility headers -#include "BaseImporter.h" -#include "MaterialSystem.h" -#include "StringComparison.h" -#include "StreamReader.h" -#include "qnan.h" - - -#endif // !! ASSIMP_PCH_INCLUDED diff --git a/3rdparty/assimp/code/B3DImporter.cpp b/3rdparty/assimp/code/B3DImporter.cpp deleted file mode 100644 index 983d0db5..00000000 --- a/3rdparty/assimp/code/B3DImporter.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 B3DImporter.cpp - * @brief Implementation of the b3d importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER - -// internal headers -#include "B3DImporter.h" -#include "TextureTransform.h" -#include "ConvertToLHProcess.h" - -using namespace Assimp; -using namespace std; - -// (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings -#ifdef _MSC_VER -# pragma warning (disable: 4018) -#endif - -//#define DEBUG_B3D - -// ------------------------------------------------------------------------------------------------ -bool B3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const{ - - size_t pos=pFile.find_last_of( '.' ); - if ( pos==string::npos ) return false; - - string ext=pFile.substr( pos+1 ); - if ( ext.size()!=3 ) return false; - - return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D'); -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::GetExtensionList( std::set<std::string>& extensions ){ - extensions.insert("b3d"); -} - -#ifdef DEBUG_B3D - extern "C"{ void _stdcall AllocConsole(); } -#endif -// ------------------------------------------------------------------------------------------------ -void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){ - -#ifdef DEBUG_B3D - AllocConsole(); - freopen( "conin$","r",stdin ); - freopen( "conout$","w",stdout ); - freopen( "conout$","w",stderr ); - cout<<"Hello world from the B3DImporter!"<<endl; -#endif - - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open B3D file " + pFile + "."); - - // check whether the .b3d file is large enough to contain - // at least one chunk. - size_t fileSize = file->FileSize(); - if ( fileSize<8 ) throw DeadlyImportError( "B3D File is too small."); - - _pos=0; - _buf.resize( fileSize ); - file->Read( &_buf[0],1,fileSize ); - _stack.clear(); - - ReadBB3D( pScene ); -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::Oops(){ - throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" ); -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::Fail( string str ){ -#ifdef DEBUG_B3D - cout<<"Error in B3D file data: "<<str<<endl; -#endif - throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str ); -} - -// ------------------------------------------------------------------------------------------------ -int B3DImporter::ReadByte(){ - if ( _pos<_buf.size() ) return _buf[_pos++]; - Fail( "EOF" ); - return 0; -} - -// ------------------------------------------------------------------------------------------------ -int B3DImporter::ReadInt(){ - if ( _pos+4<=_buf.size() ){ - int n=*(int*)&_buf[_pos]; - _pos+=4; - return n; - } - Fail( "EOF" ); - return 0; -} - -// ------------------------------------------------------------------------------------------------ -float B3DImporter::ReadFloat(){ - if ( _pos+4<=_buf.size() ){ - float n=*(float*)&_buf[_pos]; - _pos+=4; - return n; - } - Fail( "EOF" ); - return 0.0f; -} - -// ------------------------------------------------------------------------------------------------ -aiVector2D B3DImporter::ReadVec2(){ - float x=ReadFloat(); - float y=ReadFloat(); - return aiVector2D( x,y ); -} - -// ------------------------------------------------------------------------------------------------ -aiVector3D B3DImporter::ReadVec3(){ - float x=ReadFloat(); - float y=ReadFloat(); - float z=ReadFloat(); - return aiVector3D( x,y,z ); -} - -// ------------------------------------------------------------------------------------------------ -aiQuaternion B3DImporter::ReadQuat(){ - // (aramis_acg) Fix to adapt the loader to changed quat orientation - float w=-ReadFloat(); - float x=ReadFloat(); - float y=ReadFloat(); - float z=ReadFloat(); - return aiQuaternion( w,x,y,z ); -} - -// ------------------------------------------------------------------------------------------------ -string B3DImporter::ReadString(){ - string str; - while ( _pos<_buf.size() ){ - char c=(char)ReadByte(); - if ( !c ) return str; - str+=c; - } - Fail( "EOF" ); - return string(); -} - -// ------------------------------------------------------------------------------------------------ -string B3DImporter::ReadChunk(){ - string tag; - for ( int i=0;i<4;++i ){ - tag+=char( ReadByte() ); - } -#ifdef DEBUG_B3D -// cout<<"ReadChunk:"<<tag<<endl; -#endif - unsigned sz=(unsigned)ReadInt(); - _stack.push_back( _pos+sz ); - return tag; -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ExitChunk(){ - _pos=_stack.back(); - _stack.pop_back(); -} - -// ------------------------------------------------------------------------------------------------ -unsigned B3DImporter::ChunkSize(){ - return _stack.back()-_pos; -} -// ------------------------------------------------------------------------------------------------ - -template<class T> -T *B3DImporter::to_array( const vector<T> &v ){ - if ( !v.size() ) return 0; - T *p=new T[v.size()]; - for ( size_t i=0;i<v.size();++i ){ - p[i]=v[i]; - } - return p; -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadTEXS(){ - while ( ChunkSize() ){ - string name=ReadString(); - /*int flags=*/ReadInt(); - /*int blend=*/ReadInt(); - /*aiVector2D pos=*/ReadVec2(); - /*aiVector2D scale=*/ReadVec2(); - /*float rot=*/ReadFloat(); - - _textures.push_back( name ); - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadBRUS(){ - int n_texs=ReadInt(); - if ( n_texs<0 || n_texs>8 ){ - Fail( "Bad texture count" ); - } - while ( ChunkSize() ){ - string name=ReadString(); - aiVector3D color=ReadVec3(); - float alpha=ReadFloat(); - float shiny=ReadFloat(); - /*int blend=**/ReadInt(); - int fx=ReadInt(); - - MaterialHelper *mat=new MaterialHelper; - _materials.push_back( mat ); - - // Name - aiString ainame( name ); - mat->AddProperty( &ainame,AI_MATKEY_NAME ); - - // Diffuse color - mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE ); - - // Opacity - mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY ); - - // Specular color - aiColor3D speccolor( shiny,shiny,shiny ); - mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR ); - - // Specular power - float specpow=shiny*128; - mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS ); - - // Double sided - if ( fx & 0x10 ){ - int i=1; - mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED ); - } - - //Textures - for ( int i=0;i<n_texs;++i ){ - int texid=ReadInt(); - if ( texid<-1 || (texid>=0 && texid>=static_cast<int>(_textures.size())) ){ - Fail( "Bad texture id" ); - } - if ( i==0 && texid>=0 ){ - aiString texname( _textures[texid] ); - mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) ); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadVRTS(){ - _vflags=ReadInt(); - _tcsets=ReadInt(); - _tcsize=ReadInt(); - if ( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){ - Fail( "Bad texcoord data" ); - } - - int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4); - int n_verts=ChunkSize()/sz; - - int v0=_vertices.size(); - _vertices.resize( v0+n_verts ); - - for ( int i=0;i<n_verts;++i ){ - Vertex &v=_vertices[v0+i]; - - memset( v.bones,0,sizeof(v.bones) ); - memset( v.weights,0,sizeof(v.weights) ); - - v.vertex=ReadVec3(); - - if ( _vflags & 1 ) v.normal=ReadVec3(); - - if ( _vflags & 2 ) ReadQuat(); //skip v 4bytes... - - for ( int i=0;i<_tcsets;++i ){ - float t[4]={0,0,0,0}; - for ( int j=0;j<_tcsize;++j ){ - t[j]=ReadFloat(); - } - t[1]=1-t[1]; - if ( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] ); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadTRIS( int v0 ){ - int matid=ReadInt(); - if ( matid==-1 ){ - matid=0; - }else if ( matid<0 || matid>=(int)_materials.size() ){ -#ifdef DEBUG_B3D - cout<<"material id="<<matid<<endl; -#endif - Fail( "Bad material id" ); - } - - aiMesh *mesh=new aiMesh; - _meshes.push_back( mesh ); - - mesh->mMaterialIndex=matid; - mesh->mNumFaces=0; - mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE; - - int n_tris=ChunkSize()/12; - aiFace *face=mesh->mFaces=new aiFace[n_tris]; - - for ( int i=0;i<n_tris;++i ){ - int i0=ReadInt()+v0; - int i1=ReadInt()+v0; - int i2=ReadInt()+v0; - if ( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){ -#ifdef DEBUG_B3D - cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl; -#endif - Fail( "Bad triangle index" ); - continue; - } - face->mNumIndices=3; - face->mIndices=new unsigned[3]; - face->mIndices[0]=i0; - face->mIndices[1]=i1; - face->mIndices[2]=i2; - ++mesh->mNumFaces; - ++face; - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadMESH(){ - /*int matid=*/ReadInt(); - - int v0=_vertices.size(); - - while ( ChunkSize() ){ - string t=ReadChunk(); - if ( t=="VRTS" ){ - ReadVRTS(); - }else if ( t=="TRIS" ){ - ReadTRIS( v0 ); - } - ExitChunk(); - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadBONE( int id ){ - while ( ChunkSize() ){ - int vertex=ReadInt(); - float weight=ReadFloat(); - if ( vertex<0 || vertex>=(int)_vertices.size() ){ - Fail( "Bad vertex index" ); - } - - Vertex &v=_vertices[vertex]; - int i; - for ( i=0;i<4;++i ){ - if ( !v.weights[i] ){ - v.bones[i]=id; - v.weights[i]=weight; - break; - } - } -#ifdef DEBUG_B3D - if ( i==4 ){ - cout<<"Too many bone weights"<<endl; - } -#endif - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadKEYS( aiNodeAnim *nodeAnim ){ - vector<aiVectorKey> trans,scale; - vector<aiQuatKey> rot; - int flags=ReadInt(); - while ( ChunkSize() ){ - int frame=ReadInt(); - if ( flags & 1 ){ - trans.push_back( aiVectorKey( frame,ReadVec3() ) ); - } - if ( flags & 2 ){ - scale.push_back( aiVectorKey( frame,ReadVec3() ) ); - } - if ( flags & 4 ){ - rot.push_back( aiQuatKey( frame,ReadQuat() ) ); - } - } - - if ( flags & 1 ){ - nodeAnim->mNumPositionKeys=trans.size(); - nodeAnim->mPositionKeys=to_array( trans ); - } - - if ( flags & 2 ){ - nodeAnim->mNumScalingKeys=scale.size(); - nodeAnim->mScalingKeys=to_array( scale ); - } - - if ( flags & 4 ){ - nodeAnim->mNumRotationKeys=rot.size(); - nodeAnim->mRotationKeys=to_array( rot ); - } -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadANIM(){ - /*int flags=*/ReadInt(); - int frames=ReadInt(); - float fps=ReadFloat(); - - aiAnimation *anim=new aiAnimation; - _animations.push_back( anim ); - - anim->mDuration=frames; - anim->mTicksPerSecond=fps; -} - -// ------------------------------------------------------------------------------------------------ -aiNode *B3DImporter::ReadNODE( aiNode *parent ){ - - string name=ReadString(); - aiVector3D t=ReadVec3(); - aiVector3D s=ReadVec3(); - aiQuaternion r=ReadQuat(); - - aiMatrix4x4 trans,scale,rot; - - aiMatrix4x4::Translation( t,trans ); - aiMatrix4x4::Scaling( s,scale ); - rot=aiMatrix4x4( r.GetMatrix() ); - - aiMatrix4x4 tform=trans * rot * scale; - - int nodeid=_nodes.size(); - - aiNode *node=new aiNode( name ); - _nodes.push_back( node ); - - node->mParent=parent; - node->mTransformation=tform; - - aiNodeAnim *nodeAnim=0; - vector<unsigned> meshes; - vector<aiNode*> children; - - while ( ChunkSize() ){ - string t=ReadChunk(); - if ( t=="MESH" ){ - int n=_meshes.size(); - ReadMESH(); - for ( int i=n;i<(int)_meshes.size();++i ){ - meshes.push_back( i ); - } - }else if ( t=="BONE" ){ - ReadBONE( nodeid ); - }else if ( t=="ANIM" ){ - ReadANIM(); - }else if ( t=="KEYS" ){ - if ( !nodeAnim ){ - nodeAnim=new aiNodeAnim; - _nodeAnims.push_back( nodeAnim ); - nodeAnim->mNodeName=node->mName; - } - ReadKEYS( nodeAnim ); - }else if ( t=="NODE" ){ - aiNode *child=ReadNODE( node ); - children.push_back( child ); - } - ExitChunk(); - } - - node->mNumMeshes=meshes.size(); - node->mMeshes=to_array( meshes ); - - node->mNumChildren=children.size(); - node->mChildren=to_array( children ); - - return node; -} - -// ------------------------------------------------------------------------------------------------ -void B3DImporter::ReadBB3D( aiScene *scene ){ - - _textures.clear(); - _materials.size(); - - _vertices.clear(); - _meshes.clear(); - - _nodes.clear(); - _nodeAnims.clear(); - _animations.clear(); - - string t=ReadChunk(); - if ( t=="BB3D" ){ - int version=ReadInt(); - - if (!DefaultLogger::isNullLogger()) { - char dmp[128]; - sprintf(dmp,"B3D file format version: %i",version); - DefaultLogger::get()->info(dmp); - } - - while ( ChunkSize() ){ - string t=ReadChunk(); - if ( t=="TEXS" ){ - ReadTEXS(); - }else if ( t=="BRUS" ){ - ReadBRUS(); - }else if ( t=="NODE" ){ - ReadNODE( 0 ); - } - ExitChunk(); - } - } - ExitChunk(); - - if ( !_nodes.size() ) Fail( "No nodes" ); - - if ( !_meshes.size() ) Fail( "No meshes" ); - - //Fix nodes/meshes/bones - for (size_t i=0;i<_nodes.size();++i ){ - aiNode *node=_nodes[i]; - - for ( size_t j=0;j<node->mNumMeshes;++j ){ - aiMesh *mesh=_meshes[node->mMeshes[j]]; - - int n_tris=mesh->mNumFaces; - int n_verts=mesh->mNumVertices=n_tris * 3; - - aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0; - if ( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ]; - if ( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ]; - - aiFace *face=mesh->mFaces; - - vector< vector<aiVertexWeight> > vweights( _nodes.size() ); - - for ( int i=0;i<n_verts;i+=3 ){ - for ( int j=0;j<3;++j ){ - Vertex &v=_vertices[face->mIndices[j]]; - - *mv++=v.vertex; - if ( mn ) *mn++=v.normal; - if ( mc ) *mc++=v.texcoords; - - face->mIndices[j]=i+j; - - for ( int k=0;k<4;++k ){ - if ( !v.weights[k] ) break; - - int bone=v.bones[k]; - float weight=v.weights[k]; - - vweights[bone].push_back( aiVertexWeight(i+j,weight) ); - } - } - ++face; - } - - vector<aiBone*> bones; - for (size_t i=0;i<vweights.size();++i ){ - vector<aiVertexWeight> &weights=vweights[i]; - if ( !weights.size() ) continue; - - aiBone *bone=new aiBone; - bones.push_back( bone ); - - aiNode *bnode=_nodes[i]; - - bone->mName=bnode->mName; - bone->mNumWeights=weights.size(); - bone->mWeights=to_array( weights ); - - aiMatrix4x4 mat=bnode->mTransformation; - while ( bnode->mParent ){ - bnode=bnode->mParent; - mat=bnode->mTransformation * mat; - } - bone->mOffsetMatrix=mat.Inverse(); - } - mesh->mNumBones=bones.size(); - mesh->mBones=to_array( bones ); - } - } - - //nodes - scene->mRootNode=_nodes[0]; - - //material - if ( !_materials.size() ){ - _materials.push_back( new MaterialHelper ); - } - scene->mNumMaterials=_materials.size(); - scene->mMaterials=to_array( _materials ); - - //meshes - scene->mNumMeshes=_meshes.size(); - scene->mMeshes=to_array( _meshes ); - - //animations - if ( _animations.size()==1 && _nodeAnims.size() ){ - - aiAnimation *anim=_animations.back(); - anim->mNumChannels=_nodeAnims.size(); - anim->mChannels=to_array( _nodeAnims ); - - scene->mNumAnimations=_animations.size(); - scene->mAnimations=to_array( _animations ); - } - - // convert to RH - MakeLeftHandedProcess makeleft; - makeleft.Execute( scene ); - - FlipWindingOrderProcess flip; - flip.Execute( scene ); -} - -#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER diff --git a/3rdparty/assimp/code/B3DImporter.h b/3rdparty/assimp/code/B3DImporter.h deleted file mode 100644 index fa627694..00000000 --- a/3rdparty/assimp/code/B3DImporter.h +++ /dev/null @@ -1,126 +0,0 @@ - -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Definition of the .b3d importer class. */ - -#ifndef AI_B3DIMPORTER_H_INC -#define AI_B3DIMPORTER_H_INC - -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include "../include/aiMaterial.h" - -#include <string> -#include <vector> - -namespace Assimp{ - -class B3DImporter : public BaseImporter{ -public: - - virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; - -protected: - - virtual void GetExtensionList(std::set<std::string>& extensions); - virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - -private: - - int ReadByte(); - int ReadInt(); - float ReadFloat(); - aiVector2D ReadVec2(); - aiVector3D ReadVec3(); - aiQuaternion ReadQuat(); - std::string ReadString(); - std::string ReadChunk(); - void ExitChunk(); - unsigned ChunkSize(); - - template<class T> - T *to_array( const std::vector<T> &v ); - - struct Vertex{ - aiVector3D vertex; - aiVector3D normal; - aiVector3D texcoords; - unsigned char bones[4]; - float weights[4]; - }; - - void Oops(); - void Fail( std::string str ); - - void ReadTEXS(); - void ReadBRUS(); - - void ReadVRTS(); - void ReadTRIS( int v0 ); - void ReadMESH(); - void ReadBONE( int id ); - void ReadKEYS( aiNodeAnim *nodeAnim ); - void ReadANIM(); - - aiNode *ReadNODE( aiNode *parent ); - - void ReadBB3D( aiScene *scene ); - - unsigned _pos; -// unsigned _size; - std::vector<unsigned char> _buf; - std::vector<unsigned> _stack; - - std::vector<std::string> _textures; - std::vector<aiMaterial*> _materials; - - int _vflags,_tcsets,_tcsize; - std::vector<Vertex> _vertices; - - std::vector<aiNode*> _nodes; - std::vector<aiMesh*> _meshes; - std::vector<aiNodeAnim*> _nodeAnims; - std::vector<aiAnimation*> _animations; -}; - -} - -#endif diff --git a/3rdparty/assimp/code/BVHLoader.cpp b/3rdparty/assimp/code/BVHLoader.cpp deleted file mode 100644 index 8272ce62..00000000 --- a/3rdparty/assimp/code/BVHLoader.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/** Implementation of the BVH loader */ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. ---------------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER - -#include "BVHLoader.h" -#include "fast_atof.h" -#include "SkeletonMeshBuilder.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -BVHLoader::BVHLoader() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BVHLoader::~BVHLoader() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool BVHLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const -{ - // check file extension - const std::string extension = GetExtension(pFile); - - if ( extension == "bvh") - return true; - - if ((!extension.length() || cs) && pIOHandler) { - const char* tokens[] = {"HIERARCHY"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - mFileName = pFile; - - // read file into memory - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open file " + pFile + "."); - - size_t fileSize = file->FileSize(); - if ( fileSize == 0) - throw DeadlyImportError( "File is too small."); - - mBuffer.resize( fileSize); - file->Read( &mBuffer.front(), 1, fileSize); - - // start reading - mReader = mBuffer.begin(); - mLine = 1; - ReadStructure( pScene); - - // build a dummy mesh for the skeleton so that we see something at least - SkeletonMeshBuilder meshBuilder( pScene); - - // construct an animation from all the motion data we read - CreateAnimation( pScene); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the file -void BVHLoader::ReadStructure( aiScene* pScene) -{ - // first comes hierarchy - std::string header = GetNextToken(); - if ( header != "HIERARCHY") - ThrowException( "Expected header string \"HIERARCHY\"."); - ReadHierarchy( pScene); - - // then comes the motion data - std::string motion = GetNextToken(); - if ( motion != "MOTION") - ThrowException( "Expected beginning of motion data \"MOTION\"."); - ReadMotion( pScene); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the hierarchy -void BVHLoader::ReadHierarchy( aiScene* pScene) -{ - std::string root = GetNextToken(); - if ( root != "ROOT") - ThrowException( "Expected root node \"ROOT\"."); - - // Go read the hierarchy from here - pScene->mRootNode = ReadNode(); -} - -// ------------------------------------------------------------------------------------------------ -// Reads a node and recursively its childs and returns the created node; -aiNode* BVHLoader::ReadNode() -{ - // first token is name - std::string nodeName = GetNextToken(); - if ( nodeName.empty() || nodeName == "{") - ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName)); - - // then an opening brace should follow - std::string openBrace = GetNextToken(); - if ( openBrace != "{") - ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace)); - - // Create a node - aiNode* node = new aiNode( nodeName); - std::vector<aiNode*> childNodes; - - // and create an bone entry for it - mNodes.push_back( Node( node)); - Node& internNode = mNodes.back(); - - // now read the node's contents - while ( 1) - { - std::string token = GetNextToken(); - - // node offset to parent node - if ( token == "OFFSET") - ReadNodeOffset( node); - else if ( token == "CHANNELS") - ReadNodeChannels( internNode); - else if ( token == "JOINT") - { - // child node follows - aiNode* child = ReadNode(); - child->mParent = node; - childNodes.push_back( child); - } - else if ( token == "End") - { - // The real symbol is "End Site". Second part comes in a separate token - std::string siteToken = GetNextToken(); - if ( siteToken != "Site") - ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken)); - - aiNode* child = ReadEndSite( nodeName); - child->mParent = node; - childNodes.push_back( child); - } - else if ( token == "}") - { - // we're done with that part of the hierarchy - break; - } else - { - // everything else is a parse error - ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token)); - } - } - - // add the child nodes if there are any - if ( childNodes.size() > 0) - { - node->mNumChildren = childNodes.size(); - node->mChildren = new aiNode*[node->mNumChildren]; - std::copy( childNodes.begin(), childNodes.end(), node->mChildren); - } - - // and return the sub-hierarchy we built here - return node; -} - -// ------------------------------------------------------------------------------------------------ -// Reads an end node and returns the created node. -aiNode* BVHLoader::ReadEndSite( const std::string& pParentName) -{ - // check opening brace - std::string openBrace = GetNextToken(); - if ( openBrace != "{") - ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace)); - - // Create a node - aiNode* node = new aiNode( "EndSite_" + pParentName); - - // now read the node's contents. Only possible entry is "OFFSET" - while ( 1) - { - std::string token = GetNextToken(); - - // end node's offset - if ( token == "OFFSET") - { - ReadNodeOffset( node); - } - else if ( token == "}") - { - // we're done with the end node - break; - } else - { - // everything else is a parse error - ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token)); - } - } - - // and return the sub-hierarchy we built here - return node; -} -// ------------------------------------------------------------------------------------------------ -// Reads a node offset for the given node -void BVHLoader::ReadNodeOffset( aiNode* pNode) -{ - // Offset consists of three floats to read - aiVector3D offset; - offset.x = GetNextTokenAsFloat(); - offset.y = GetNextTokenAsFloat(); - offset.z = GetNextTokenAsFloat(); - - // build a transformation matrix from it - pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y, - 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the animation channels for the given node -void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode) -{ - // number of channels. Use the float reader because we're lazy - float numChannelsFloat = GetNextTokenAsFloat(); - unsigned int numChannels = (unsigned int) numChannelsFloat; - - for ( unsigned int a = 0; a < numChannels; a++) - { - std::string channelToken = GetNextToken(); - - if ( channelToken == "Xposition") - pNode.mChannels.push_back( Channel_PositionX); - else if ( channelToken == "Yposition") - pNode.mChannels.push_back( Channel_PositionY); - else if ( channelToken == "Zposition") - pNode.mChannels.push_back( Channel_PositionZ); - else if ( channelToken == "Xrotation") - pNode.mChannels.push_back( Channel_RotationX); - else if ( channelToken == "Yrotation") - pNode.mChannels.push_back( Channel_RotationY); - else if ( channelToken == "Zrotation") - pNode.mChannels.push_back( Channel_RotationZ); - else - ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken)); - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the motion data -void BVHLoader::ReadMotion( aiScene* pScene) -{ - // Read number of frames - std::string tokenFrames = GetNextToken(); - if ( tokenFrames != "Frames:") - ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames)); - - float numFramesFloat = GetNextTokenAsFloat(); - mAnimNumFrames = (unsigned int) numFramesFloat; - - // Read frame duration - std::string tokenDuration1 = GetNextToken(); - std::string tokenDuration2 = GetNextToken(); - if ( tokenDuration1 != "Frame" || tokenDuration2 != "Time:") - ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2)); - - mAnimTickDuration = GetNextTokenAsFloat(); - - // resize value vectors for each node - for ( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it) - it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames); - - // now read all the data and store it in the corresponding node's value vector - for ( unsigned int frame = 0; frame < mAnimNumFrames; ++frame) - { - // on each line read the values for all nodes - for ( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it) - { - // get as many values as the node has channels - for ( unsigned int c = 0; c < it->mChannels.size(); ++c) - it->mChannelValues.push_back( GetNextTokenAsFloat()); - } - - // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it - } -} - -// ------------------------------------------------------------------------------------------------ -// Retrieves the next token -std::string BVHLoader::GetNextToken() -{ - // skip any preceeding whitespace - while ( mReader != mBuffer.end()) - { - if ( !isspace( *mReader)) - break; - - // count lines - if ( *mReader == '\n') - mLine++; - - ++mReader; - } - - // collect all chars till the next whitespace. BVH is easy in respect to that. - std::string token; - while ( mReader != mBuffer.end()) - { - if ( isspace( *mReader)) - break; - - token.push_back( *mReader); - ++mReader; - - // little extra logic to make sure braces are counted correctly - if ( token == "{" || token == "}") - break; - } - - // empty token means end of file, which is just fine - return token; -} - -// ------------------------------------------------------------------------------------------------ -// Reads the next token as a float -float BVHLoader::GetNextTokenAsFloat() -{ - std::string token = GetNextToken(); - if ( token.empty()) - ThrowException( "Unexpected end of file while trying to read a float"); - - // check if the float is valid by testing if the atof() function consumed every char of the token - const char* ctoken = token.c_str(); - float result = 0.0f; - ctoken = fast_atof_move( ctoken, result); - - if ( ctoken != token.c_str() + token.length()) - ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token)); - - return result; -} - -// ------------------------------------------------------------------------------------------------ -// Aborts the file reading with an exception -void BVHLoader::ThrowException( const std::string& pError) -{ - throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError)); -} - -// ------------------------------------------------------------------------------------------------ -// Constructs an animation for the motion data and stores it in the given scene -void BVHLoader::CreateAnimation( aiScene* pScene) -{ - // create the animation - pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[1]; - aiAnimation* anim = new aiAnimation; - pScene->mAnimations[0] = anim; - - // put down the basic parameters - anim->mName.Set( "Motion"); - anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration); - anim->mDuration = double( mAnimNumFrames - 1); - - // now generate the tracks for all nodes - anim->mNumChannels = mNodes.size(); - anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - - // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown - for (unsigned int i = 0; i < anim->mNumChannels;++i) - anim->mChannels[i] = NULL; - - for ( unsigned int a = 0; a < anim->mNumChannels; a++) - { - const Node& node = mNodes[a]; - const std::string nodeName = std::string( node.mNode->mName.data ); - aiNodeAnim* nodeAnim = new aiNodeAnim; - anim->mChannels[a] = nodeAnim; - nodeAnim->mNodeName.Set( nodeName); - - // translational part, if given - if ( node.mChannels.size() == 6) - { - nodeAnim->mNumPositionKeys = mAnimNumFrames; - nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames]; - aiVectorKey* poskey = nodeAnim->mPositionKeys; - for ( unsigned int fr = 0; fr < mAnimNumFrames; ++fr) - { - poskey->mTime = double( fr); - - // Now compute all translations in the right order - for ( unsigned int channel = 0; channel < 3; ++channel) - { - switch( node.mChannels[channel]) - { - case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); - } - } - ++poskey; - } - } else - { - // if no translation part is given, put a default sequence - aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4); - nodeAnim->mNumPositionKeys = 1; - nodeAnim->mPositionKeys = new aiVectorKey[1]; - nodeAnim->mPositionKeys[0].mTime = 0.0; - nodeAnim->mPositionKeys[0].mValue = nodePos; - } - - // rotation part. Always present. First find value offsets - { - unsigned int rotOffset = 0; - if ( node.mChannels.size() == 6) - { - // Offset all further calculations - rotOffset = 3; - } - - // Then create the number of rotation keys - nodeAnim->mNumRotationKeys = mAnimNumFrames; - nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames]; - aiQuatKey* rotkey = nodeAnim->mRotationKeys; - for ( unsigned int fr = 0; fr < mAnimNumFrames; ++fr) - { - aiMatrix4x4 temp; - aiMatrix3x3 rotMatrix; - - for ( unsigned int channel = 0; channel < 3; ++channel) - { - // translate ZXY euler angels into a quaternion - const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f; - - // Compute rotation transformations in the right order - switch (node.mChannels[rotOffset+channel]) - { - case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); - } - } - - rotkey->mTime = double( fr); - rotkey->mValue = aiQuaternion( rotMatrix); - ++rotkey; - } - } - - // scaling part. Always just a default track - { - nodeAnim->mNumScalingKeys = 1; - nodeAnim->mScalingKeys = new aiVectorKey[1]; - nodeAnim->mScalingKeys[0].mTime = 0.0; - nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f); - } - } -} - -#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER diff --git a/3rdparty/assimp/code/BVHLoader.h b/3rdparty/assimp/code/BVHLoader.h deleted file mode 100644 index 74800a18..00000000 --- a/3rdparty/assimp/code/BVHLoader.h +++ /dev/null @@ -1,173 +0,0 @@ -/** Defines the BHV motion capturing loader class */ - -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BVHLoader.h - * @brief Biovision BVH import - */ - -#ifndef AI_BVHLOADER_H_INC -#define AI_BVHLOADER_H_INC - -#include "BaseImporter.h" - -namespace Assimp -{ - -// -------------------------------------------------------------------------------- -/** Loader class to read Motion Capturing data from a .bvh file. - * - * This format only contains a hierarchy of joints and a series of keyframes for - * the hierarchy. It contains no actual mesh data, but we generate a dummy mesh - * inside the loader just to be able to see something. -*/ -class BVHLoader : public BaseImporter -{ - friend class Importer; - - /** Possible animation channels for which the motion data holds the values */ - enum ChannelType - { - Channel_PositionX, - Channel_PositionY, - Channel_PositionZ, - Channel_RotationX, - Channel_RotationY, - Channel_RotationZ - }; - - /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */ - struct Node - { - const aiNode* mNode; - std::vector<ChannelType> mChannels; - std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames - - Node() { } - Node( const aiNode* pNode) : mNode( pNode) { } - }; - -protected: - /** Constructor to be privately used by Importer */ - BVHLoader(); - - /** Destructor, private as well */ - ~BVHLoader(); - -public: - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const; - -protected: - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions) - { - extensions.insert("bvh"); - } - - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - -protected: - /** Reads the file */ - void ReadStructure( aiScene* pScene); - - /** Reads the hierarchy */ - void ReadHierarchy( aiScene* pScene); - - /** Reads a node and recursively its childs and returns the created node. */ - aiNode* ReadNode(); - - /** Reads an end node and returns the created node. */ - aiNode* ReadEndSite( const std::string& pParentName); - - /** Reads a node offset for the given node */ - void ReadNodeOffset( aiNode* pNode); - - /** Reads the animation channels into the given node */ - void ReadNodeChannels( BVHLoader::Node& pNode); - - /** Reads the motion data */ - void ReadMotion( aiScene* pScene); - - /** Retrieves the next token */ - std::string GetNextToken(); - - /** Reads the next token as a float */ - float GetNextTokenAsFloat(); - - /** Aborts the file reading with an exception */ - void ThrowException( const std::string& pError); - - /** Constructs an animation for the motion data and stores it in the given scene */ - void CreateAnimation( aiScene* pScene); - -protected: - /** Filename, for a verbose error message */ - std::string mFileName; - - /** Buffer to hold the loaded file */ - std::vector<char> mBuffer; - - /** Next char to read from the buffer */ - std::vector<char>::const_iterator mReader; - - /** Current line, for error messages */ - unsigned int mLine; - - /** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index. - * Also contain the motion data for the node's channels - */ - std::vector<Node> mNodes; - - /** basic Animation parameters */ - float mAnimTickDuration; - unsigned int mAnimNumFrames; -}; - -} // end of namespace Assimp - -#endif // AI_BVHLOADER_H_INC diff --git a/3rdparty/assimp/code/BaseImporter.cpp b/3rdparty/assimp/code/BaseImporter.cpp deleted file mode 100644 index 06422679..00000000 --- a/3rdparty/assimp/code/BaseImporter.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BaseImporter.cpp - * @brief Implementation of BaseImporter - */ - -#include "AssimpPCH.h" -#include "BaseImporter.h" -#include "FileSystemFilter.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -BaseImporter::BaseImporter() -: progress() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BaseImporter::~BaseImporter() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file and returns the imported data. -aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) -{ - progress = pImp->GetProgressHandler(); - ai_assert(progress); - - // Gather configuration properties for this run - SetupProperties( pImp ); - - // Construct a file system filter to improve our success ratio at reading external files - FileSystemFilter filter(pFile,pIOHandler); - - // create a scene object to hold the data - ScopeGuard<aiScene> sc(new aiScene()); - - // dispatch importing - try - { - InternReadFile( pFile, sc, &filter); - - } catch( const std::exception& err ) { - // extract error description - mErrorText = err.what(); - DefaultLogger::get()->error(mErrorText); - return NULL; - } - - // return what we gathered from the import. - sc.dismiss(); - return sc; -} - -// ------------------------------------------------------------------------------------------------ -void BaseImporter::SetupProperties(const Importer* pImp) -{ - // the default implementation does nothing -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler, - const std::string& pFile, - const char** tokens, - unsigned int numTokens, - unsigned int searchBytes /* = 200 */) -{ - ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes); - if (!pIOHandler) - return false; - - boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile)); - if (pStream.get() ) { - // read 200 characters from the file - boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]); - char* buffer = _buffer.get(); - - const unsigned int read = pStream->Read(buffer,1,searchBytes); - if (!read) - return false; - - for (unsigned int i = 0; i < read;++i) - buffer[i] = ::tolower(buffer[i]); - - // It is not a proper handling of unicode files here ... - // ehm ... but it works in most cases. - char* cur = buffer,*cur2 = buffer,*end = &buffer[read]; - while (cur != end) { - if (*cur) - *cur2++ = *cur; - ++cur; - } - *cur2 = '\0'; - - for (unsigned int i = 0; i < numTokens;++i) { - ai_assert(NULL != tokens[i]); - - if (::strstr(buffer,tokens[i])) { - DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]); - return true; - } - } - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Simple check for file extension -/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile, - const char* ext0, - const char* ext1, - const char* ext2) -{ - std::string::size_type pos = pFile.find_last_of('.'); - - // no file extension - can't read - if ( pos == std::string::npos) - return false; - - const char* ext_real = & pFile[ pos+1 ]; - if ( !ASSIMP_stricmp(ext_real,ext0) ) - return true; - - // check for other, optional, file extensions - if (ext1 && !ASSIMP_stricmp(ext_real,ext1)) - return true; - - if (ext2 && !ASSIMP_stricmp(ext_real,ext2)) - return true; - - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get file extension from path -/*static*/ std::string BaseImporter::GetExtension (const std::string& pFile) -{ - std::string::size_type pos = pFile.find_last_of('.'); - - // no file extension at all - if ( pos == std::string::npos) - return ""; - - std::string ret = pFile.substr(pos+1); - std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint - return ret; -} - -// ------------------------------------------------------------------------------------------------ -// Check for magic bytes at the beginning of the file. -/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, - const void* _magic, unsigned int num, unsigned int offset, unsigned int size) -{ - ai_assert(size <= 16 && _magic); - - if (!pIOHandler) { - return false; - } - union { - const char* magic; - const uint16_t* magic_u16; - const uint32_t* magic_u32; - }; - magic = reinterpret_cast<const char*>(_magic); - boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile)); - if (pStream.get() ) { - - // skip to offset - pStream->Seek(offset,aiOrigin_SET); - - // read 'size' characters from the file - union { - char data[16]; - uint16_t data_u16[8]; - uint32_t data_u32[4]; - }; - if (size != pStream->Read(data,1,size)) { - return false; - } - - for (unsigned int i = 0; i < num; ++i) { - // also check against big endian versions of tokens with size 2,4 - // that's just for convinience, the chance that we cause conflicts - // is quite low and it can save some lines and prevent nasty bugs - if (2 == size) { - uint16_t rev = *magic_u16; - ByteSwap::Swap(&rev); - if (data_u16[0] == *magic_u16 || data_u16[0] == rev) { - return true; - } - } - else if (4 == size) { - uint32_t rev = *magic_u32; - ByteSwap::Swap(&rev); - if (data_u32[0] == *magic_u32 || data_u32[0] == rev) { - return true; - } - } - else { - // any length ... just compare - if (!memcmp(magic,data,size)) { - return true; - } - } - magic += size; - } - } - return false; -} - -#include "../contrib/ConvertUTF/ConvertUTF.h" - -// ------------------------------------------------------------------------------------------------ -void ReportResult(ConversionResult res) -{ - if (res == sourceExhausted) { - DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails"); - } - else if (res == sourceIllegal) { - DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails"); - } -} - -// ------------------------------------------------------------------------------------------------ -// Convert to UTF8 data -void BaseImporter::ConvertToUTF8(std::vector<char>& data) -{ - ConversionResult result; - if (data.size() < 8) { - throw DeadlyImportError("File is too small"); - } - - // UTF 8 with BOM - if ((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) { - DefaultLogger::get()->debug("Found UTF-8 BOM ..."); - - std::copy(data.begin()+3,data.end(),data.begin()); - data.resize(data.size()-3); - return; - } - - // UTF 32 BE with BOM - if (*((uint32_t*)&data.front()) == 0xFFFE0000) { - - // swap the endianess .. - for (uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) { - AI_SWAP4P(p); - } - } - - // UTF 32 LE with BOM - if (*((uint32_t*)&data.front()) == 0x0000FFFE) { - DefaultLogger::get()->debug("Found UTF-32 BOM ..."); - - const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1; - char* dstart,*dend; - std::vector<char> output; - do { - output.resize(output.size()?output.size()*3/2:data.size()/2); - dstart = &output.front(),dend = &output.back()+1; - - result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion); - } while (result == targetExhausted); - - ReportResult(result); - - // copy to output buffer. - const size_t outlen = (size_t)(dstart-&output.front()); - data.assign(output.begin(),output.begin()+outlen); - return; - } - - // UTF 16 BE with BOM - if (*((uint16_t*)&data.front()) == 0xFFFE) { - - // swap the endianess .. - for (uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) { - ByteSwap::Swap2(p); - } - } - - // UTF 16 LE with BOM - if (*((uint16_t*)&data.front()) == 0xFEFF) { - DefaultLogger::get()->debug("Found UTF-16 BOM ..."); - - const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)&data.back()+1; - char* dstart,*dend; - std::vector<char> output; - do { - output.resize(output.size()?output.size()*3/2:data.size()*3/4); - dstart = &output.front(),dend = &output.back()+1; - - result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion); - } while (result == targetExhausted); - - ReportResult(result); - - // copy to output buffer. - const size_t outlen = (size_t)(dstart-&output.front()); - data.assign(output.begin(),output.begin()+outlen); - return; - } -} - -// ------------------------------------------------------------------------------------------------ -void BaseImporter::TextFileToBuffer(IOStream* stream, - std::vector<char>& data) -{ - ai_assert(NULL != stream); - - const size_t fileSize = stream->FileSize(); - if (!fileSize) { - throw DeadlyImportError("File is empty"); - } - - data.reserve(fileSize+1); - data.resize(fileSize); - if (fileSize != stream->Read( &data[0], 1, fileSize)) { - throw DeadlyImportError("File read error"); - } - - ConvertToUTF8(data); - - // append a binary zero to simplify string parsing - data.push_back(0); -} - -// ------------------------------------------------------------------------------------------------ -namespace Assimp -{ - // Represents an import request - struct LoadRequest - { - LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id) - : file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id) - { - if (_map) - map = *_map; - } - - const std::string file; - unsigned int flags; - unsigned int refCnt; - aiScene* scene; - bool loaded; - BatchLoader::PropertyMap map; - unsigned int id; - - bool operator== (const std::string& f) { - return file == f; - } - }; -} - -// ------------------------------------------------------------------------------------------------ -// BatchLoader::pimpl data structure -struct Assimp::BatchData -{ - BatchData() - : next_id(0xffff) - {} - - // IO system to be used for all imports - IOSystem* pIOSystem; - - // Importer used to load all meshes - Importer* pImporter; - - // List of all imports - std::list<LoadRequest> requests; - - // Base path - std::string pathBase; - - // Id for next item - unsigned int next_id; -}; - -// ------------------------------------------------------------------------------------------------ -BatchLoader::BatchLoader(IOSystem* pIO) -{ - ai_assert(NULL != pIO); - - data = new BatchData(); - data->pIOSystem = pIO; - - data->pImporter = new Importer(); - data->pImporter->SetIOHandler(data->pIOSystem); -} - -// ------------------------------------------------------------------------------------------------ -BatchLoader::~BatchLoader() -{ - // delete all scenes wthat have not been polled by the user - for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { - - delete (*it).scene; - } - data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */ - delete data->pImporter; - delete data; -} - - -// ------------------------------------------------------------------------------------------------ -unsigned int BatchLoader::AddLoadRequest (const std::string& file, - unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/) -{ - ai_assert(!file.empty()); - - // check whether we have this loading request already - std::list<LoadRequest>::iterator it; - for (it = data->requests.begin();it != data->requests.end(); ++it) { - - // Call IOSystem's path comparison function here - if (data->pIOSystem->ComparePaths((*it).file,file)) { - - if (map) { - if (!((*it).map == *map)) - continue; - } - else if (!(*it).map.empty()) - continue; - - (*it).refCnt++; - return (*it).id; - } - } - - // no, we don't have it. So add it to the queue ... - data->requests.push_back(LoadRequest(file,steps,map,data->next_id)); - return data->next_id++; -} - -// ------------------------------------------------------------------------------------------------ -aiScene* BatchLoader::GetImport (unsigned int which) -{ - for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { - - if ((*it).id == which && (*it).loaded) { - - aiScene* sc = (*it).scene; - if (!(--(*it).refCnt)) { - data->requests.erase(it); - } - return sc; - } - } - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -void BatchLoader::LoadAll() -{ - // no threaded implementation for the moment - for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) { - // force validation in debug builds - unsigned int pp = (*it).flags; -#ifdef _DEBUG - pp |= aiProcess_ValidateDataStructure; -#endif - // setup config properties if necessary - data->pImporter->pimpl->mFloatProperties = (*it).map.floats; - data->pImporter->pimpl->mIntProperties = (*it).map.ints; - data->pImporter->pimpl->mStringProperties = (*it).map.strings; - - if (!DefaultLogger::isNullLogger()) - { - DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%"); - DefaultLogger::get()->info("File: " + (*it).file); - } - data->pImporter->ReadFile((*it).file,pp); - (*it).scene = const_cast<aiScene*>(data->pImporter->GetOrphanedScene()); - (*it).loaded = true; - - DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%"); - } -} - - - - diff --git a/3rdparty/assimp/code/BaseImporter.h b/3rdparty/assimp/code/BaseImporter.h deleted file mode 100644 index 39ac3bf5..00000000 --- a/3rdparty/assimp/code/BaseImporter.h +++ /dev/null @@ -1,499 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Definition of the base class for all importer worker classes. */ -#ifndef INCLUDED_AI_BASEIMPORTER_H -#define INCLUDED_AI_BASEIMPORTER_H - -#include "Exceptional.h" - -#include <string> -#include <map> -#include <vector> -#include "./../include/aiTypes.h" - -struct aiScene; - -namespace Assimp { - -class IOSystem; -class Importer; -class BaseImporter; -class BaseProcess; -class SharedPostProcessInfo; -class IOStream; - -// utility to do char4 to uint32 in a portable manner -#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ - (string[1] << 16) + (string[2] << 8) + string[3])) - -// --------------------------------------------------------------------------- -template <typename T> -struct ScopeGuard -{ - ScopeGuard(T* obj) : obj(obj), mdismiss() {} - ~ScopeGuard () throw() { - if (!mdismiss) { - delete obj; - } - obj = NULL; - } - - T* dismiss() { - mdismiss=true; - return obj; - } - - operator T*() { - return obj; - } - - T* operator -> () { - return obj; - } - -private: - T* obj; - bool mdismiss; -}; - -//! @cond never -// --------------------------------------------------------------------------- -/** @brief Internal PIMPL implementation for Assimp::Importer - * - * Using this idiom here allows us to drop the dependency from - * std::vector and std::map in the public headers. Furthermore we are dropping - * any STL interface problems caused by mismatching STL settings. All - * size calculation are now done by us, not the app heap. */ -class ASSIMP_API ImporterPimpl -{ -public: - - // Data type to store the key hash - typedef unsigned int KeyType; - - // typedefs for our three configuration maps. - // We don't need more, so there is no need for a generic solution - typedef std::map<KeyType, int> IntPropertyMap; - typedef std::map<KeyType, float> FloatPropertyMap; - typedef std::map<KeyType, std::string> StringPropertyMap; - -public: - - /** IO handler to use for all file accesses. */ - IOSystem* mIOHandler; - bool mIsDefaultHandler; - - /** Progress handler for feedback. */ - ProgressHandler* mProgressHandler; - bool mIsDefaultProgressHandler; - - /** Format-specific importer worker objects - one for each format we can read.*/ - std::vector<BaseImporter*> mImporter; - - /** Post processing steps we can apply at the imported data. */ - std::vector<BaseProcess*> mPostProcessingSteps; - - /** The imported data, if ReadFile() was successful, NULL otherwise. */ - aiScene* mScene; - - /** The error description, if there was one. */ - std::string mErrorString; - - /** List of integer properties */ - IntPropertyMap mIntProperties; - - /** List of floating-point properties */ - FloatPropertyMap mFloatProperties; - - /** List of string properties */ - StringPropertyMap mStringProperties; - - /** Used for testing - extra verbose mode causes the ValidateDataStructure-Step - * to be executed before and after every single postprocess step */ - bool bExtraVerbose; - - /** Used by post-process steps to share data */ - SharedPostProcessInfo* mPPShared; -}; -//! @endcond - -// --------------------------------------------------------------------------- -/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface - * for all importer worker classes. - * - * The interface defines two functions: CanRead() is used to check if the - * importer can handle the format of the given file. If an implementation of - * this function returns true, the importer then calls ReadFile() which - * imports the given file. ReadFile is not overridable, it just calls - * InternReadFile() and catches any ImportErrorException that might occur. - */ -class ASSIMP_API BaseImporter -{ - friend class Importer; - -protected: - - /** Constructor to be privately used by #Importer */ - BaseImporter(); - - /** Destructor, private as well */ - virtual ~BaseImporter(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * - * The implementation should be as quick as possible. A check for - * the file extension is enough. If no suitable loader is found with - * this strategy, CanRead() is called again, the 'checkSig' parameter - * set to true this time. Now the implementation is expected to - * perform a full check of the file structure, possibly searching the - * first bytes of the file for magic identifiers or keywords. - * - * @param pFile Path and file name of the file to be examined. - * @param pIOHandler The IO handler to use for accessing any file. - * @param checkSig Set to true if this method is called a second time. - * This time, the implementation may take more time to examine the - * contents of the file to be loaded for magic bytes, keywords, etc - * to be able to load files with unknown/not existent file extensions. - * @return true if the class can read this file, false if not. - */ - virtual bool CanRead( - const std::string& pFile, - IOSystem* pIOHandler, - bool checkSig - ) const = 0; - - // ------------------------------------------------------------------- - /** Imports the given file and returns the imported data. - * If the import succeeds, ownership of the data is transferred to - * the caller. If the import fails, NULL is returned. The function - * takes care that any partially constructed data is destroyed - * beforehand. - * - * @param pImp #Importer object hosting this loader. - * @param pFile Path of the file to be imported. - * @param pIOHandler IO-Handler used to open this and possible other files. - * @return The imported data or NULL if failed. If it failed a - * human-readable error description can be retrieved by calling - * GetErrorText() - * - * @note This function is not intended to be overridden. Implement - * InternReadFile() to do the import. If an exception is thrown somewhere - * in InternReadFile(), this function will catch it and transform it into - * a suitable response to the caller. - */ - aiScene* ReadFile( - const Importer* pImp, - const std::string& pFile, - IOSystem* pIOHandler - ); - - // ------------------------------------------------------------------- - /** Returns the error description of the last error that occured. - * @return A description of the last error that occured. An empty - * string if there was no error. - */ - const std::string& GetErrorText() const { - return mErrorText; - } - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - * @param pImp Importer instance - */ - virtual void SetupProperties( - const Importer* pImp - ); - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * Implementations are expected to insert() all file extensions - * handled by them into the extension set. A loader capable of - * reading certain files with the extension BLA would place the - * string bla (lower-case!) in the output set. - * @param extensions Output set. */ - virtual void GetExtensionList( - std::set<std::string>& extensions - ) = 0; - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. The - * function is expected to throw an ImportErrorException if there is - * an error. If it terminates normally, the data in aiScene is - * expected to be correct. Override this function to implement the - * actual importing. - * <br> - * The output scene must meet the following requirements:<br> - * <ul> - * <li>At least a root node must be there, even if its only purpose - * is to reference one mesh.</li> - * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives - * in the mesh are determined automatically in this case.</li> - * <li>the vertex data is stored in a pseudo-indexed "verbose" format. - * In fact this means that every vertex that is referenced by - * a face is unique. Or the other way round: a vertex index may - * not occur twice in a single aiMesh.</li> - * <li>aiAnimation::mDuration may be -1. Assimp determines the length - * of the animation automatically in this case as the length of - * the longest animation channel.</li> - * <li>aiMesh::mBitangents may be NULL if tangents and normals are - * given. In this case bitangents are computed as the cross product - * between normal and tangent.</li> - * <li>There needn't be a material. If none is there a default material - * is generated. However, it is recommended practice for loaders - * to generate a default material for yourself that matches the - * default material setting for the file format better than Assimp's - * generic default material. Note that default materials *should* - * be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded - * or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy) - * texture. </li> - * </ul> - * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul> - * <li> at least one mesh must be there</li> - * <li> there may be no meshes with 0 vertices or faces</li> - * </ul> - * This won't be checked (except by the validation step): Assimp will - * crash if one of the conditions is not met! - * - * @param pFile Path of the file to be imported. - * @param pScene The scene object to hold the imported data. - * NULL is not a valid parameter. - * @param pIOHandler The IO handler to use for any file access. - * NULL is not a valid parameter. */ - virtual void InternReadFile( - const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler - ) = 0; - -public: // static utilities - - // ------------------------------------------------------------------- - /** A utility for CanRead(). - * - * The function searches the header of a file for a specific token - * and returns true if this token is found. This works for text - * files only. There is a rudimentary handling of UNICODE files. - * The comparison is case independent. - * - * @param pIOSystem IO System to work with - * @param file File name of the file - * @param tokens List of tokens to search for - * @param numTokens Size of the token array - * @param searchBytes Number of bytes to be searched for the tokens. - */ - static bool SearchFileHeaderForToken( - IOSystem* pIOSystem, - const std::string& file, - const char** tokens, - unsigned int numTokens, - unsigned int searchBytes = 200); - - - // ------------------------------------------------------------------- - /** @brief Check whether a file has a specific file extension - * @param pFile Input file - * @param ext0 Extension to check for. Lowercase characters only, no dot! - * @param ext1 Optional second extension - * @param ext2 Optional third extension - * @note Case-insensitive - */ - static bool SimpleExtensionCheck ( - const std::string& pFile, - const char* ext0, - const char* ext1 = NULL, - const char* ext2 = NULL); - - // ------------------------------------------------------------------- - /** @brief Extract file extension from a string - * @param pFile Input file - * @return Extension without trailing dot, all lowercase - */ - static std::string GetExtension ( - const std::string& pFile); - - // ------------------------------------------------------------------- - /** @brief Check whether a file starts with one or more magic tokens - * @param pFile Input file - * @param pIOHandler IO system to be used - * @param magic n magic tokens - * @params num Size of magic - * @param offset Offset from file start where tokens are located - * @param Size of one token, in bytes. Maximally 16 bytes. - * @return true if one of the given tokens was found - * - * @note For convinence, the check is also performed for the - * byte-swapped variant of all tokens (big endian). Only for - * tokens of size 2,4. - */ - static bool CheckMagicToken( - IOSystem* pIOHandler, - const std::string& pFile, - const void* magic, - unsigned int num, - unsigned int offset = 0, - unsigned int size = 4); - - // ------------------------------------------------------------------- - /** An utility for all text file loaders. It converts a file to our - * UTF8 character set. Errors are reported, but ignored. - * - * @param data File buffer to be converted to UTF8 data. The buffer - * is resized as appropriate. */ - static void ConvertToUTF8( - std::vector<char>& data); - - // ------------------------------------------------------------------- - /** Utility for text file loaders which copies the contents of the - * file into a memory buffer and converts it to our UTF8 - * representation. - * @param stream Stream to read from. - * @param data Output buffer to be resized and filled with the - * converted text file data. The buffer is terminated with - * a binary 0. */ - static void TextFileToBuffer( - IOStream* stream, - std::vector<char>& data); - -protected: - - /** Error description in case there was one. */ - std::string mErrorText; - - /** Currently set progress handler */ - ProgressHandler* progress; -}; - -struct BatchData; - -// --------------------------------------------------------------------------- -/** FOR IMPORTER PLUGINS ONLY: A helper class for the pleasure of importers - * which need to load many extern meshes recursively. - * - * The class uses several threads to load these meshes (or at least it - * could, this has not yet been implemented at the moment). - * - * @note The class may not be used by more than one thread*/ -class ASSIMP_API BatchLoader -{ - // friend of Importer - -public: - - //! @cond never - // ------------------------------------------------------------------- - /** Wraps a full list of configuration properties for an importer. - * Properties can be set using SetGenericProperty */ - struct PropertyMap - { - ImporterPimpl::IntPropertyMap ints; - ImporterPimpl::FloatPropertyMap floats; - ImporterPimpl::StringPropertyMap strings; - - bool operator == (const PropertyMap& prop) const { - // fixme: really isocpp? gcc complains - return ints == prop.ints && floats == prop.floats && strings == prop.strings; - } - - bool empty () const { - return ints.empty() && floats.empty() && strings.empty(); - } - }; - //! @endcond - -public: - - - // ------------------------------------------------------------------- - /** Construct a batch loader from a given IO system to be used - * to acess external files */ - BatchLoader(IOSystem* pIO); - ~BatchLoader(); - - - // ------------------------------------------------------------------- - /** Add a new file to the list of files to be loaded. - * @param file File to be loaded - * @param steps Post-processing steps to be executed on the file - * @param map Optional configuration properties - * @return 'Load request channel' - an unique ID that can later - * be used to access the imported file data. - * @see GetImport */ - unsigned int AddLoadRequest ( - const std::string& file, - unsigned int steps = 0, - const PropertyMap* map = NULL - ); - - - // ------------------------------------------------------------------- - /** Get an imported scene. - * This polls the import from the internal request list. - * If an import is requested several times, this function - * can be called several times, too. - * - * @param which LRWC returned by AddLoadRequest(). - * @return NULL if there is no scene with this file name - * in the queue of the scene hasn't been loaded yet. */ - aiScene* GetImport( - unsigned int which - ); - - - // ------------------------------------------------------------------- - /** Waits until all scenes have been loaded. This returns - * immediately if no scenes are queued.*/ - void LoadAll(); - -private: - - // No need to have that in the public API ... - BatchData* data; -}; - -} // end of namespace Assimp - -#endif // AI_BASEIMPORTER_H_INC diff --git a/3rdparty/assimp/code/BaseProcess.cpp b/3rdparty/assimp/code/BaseProcess.cpp deleted file mode 100644 index ce8fbce9..00000000 --- a/3rdparty/assimp/code/BaseProcess.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BaseProcess */ - -#include "AssimpPCH.h" -#include "BaseImporter.h" -#include "BaseProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -BaseProcess::BaseProcess() -: shared() -, progress() -{ -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BaseProcess::~BaseProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -void BaseProcess::ExecuteOnScene( Importer* pImp) -{ - ai_assert(NULL != pImp && NULL != pImp->pimpl->mScene); - - progress = pImp->GetProgressHandler(); - ai_assert(progress); - - SetupProperties( pImp ); - - // catch exceptions thrown inside the PostProcess-Step - try - { - Execute(pImp->pimpl->mScene); - - } catch( const std::exception& err ) { - - // extract error description - pImp->pimpl->mErrorString = err.what(); - DefaultLogger::get()->error(pImp->pimpl->mErrorString); - - // and kill the partially imported data - delete pImp->pimpl->mScene; - pImp->pimpl->mScene = NULL; - } -} - -// ------------------------------------------------------------------------------------------------ -void BaseProcess::SetupProperties(const Importer* pImp) -{ - // the default implementation does nothing -} diff --git a/3rdparty/assimp/code/BaseProcess.h b/3rdparty/assimp/code/BaseProcess.h deleted file mode 100644 index 6d32d441..00000000 --- a/3rdparty/assimp/code/BaseProcess.h +++ /dev/null @@ -1,289 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Base class of all import post processing steps */ -#ifndef INCLUDED_AI_BASEPROCESS_H -#define INCLUDED_AI_BASEPROCESS_H - -#include <map> - -#include "../include/aiTypes.h" -#include "GenericProperty.h" - -struct aiScene; - -namespace Assimp { - -class Importer; - -// --------------------------------------------------------------------------- -/** Helper class to allow post-processing steps to interact with each other. - * - * The class maintains a simple property list that can be used by pp-steps - * to provide additional information to other steps. This is primarily - * intended for cross-step optimizations. - */ -class ASSIMP_API SharedPostProcessInfo -{ -public: - - struct Base - { - virtual ~Base() - {} - }; - - //! Represents data that is allocated on the heap, thus needs to be deleted - template <typename T> - struct THeapData : public Base - { - THeapData(T* in) - : data (in) - {} - - ~THeapData() - { - delete data; - } - T* data; - }; - - //! Represents static, by-value data not allocated on the heap - template <typename T> - struct TStaticData : public Base - { - TStaticData(T in) - : data (in) - {} - - ~TStaticData() - {} - - T data; - }; - - // some typedefs for cleaner code - typedef unsigned int KeyType; - typedef std::map<KeyType, Base*> PropertyMap; - -public: - - //! Destructor - ~SharedPostProcessInfo() - { - Clean(); - } - - //! Remove all stored properties from the table - void Clean() - { - // invoke the virtual destructor for all stored properties - for (PropertyMap::iterator it = pmap.begin(), end = pmap.end(); - it != end; ++it) - { - delete (*it).second; - } - pmap.clear(); - } - - //! Add a heap property to the list - template <typename T> - void AddProperty( const char* name, T* in ){ - AddProperty(name,(Base*)new THeapData<T>(in)); - } - - //! Add a static by-value property to the list - template <typename T> - void AddProperty( const char* name, T in ){ - AddProperty(name,(Base*)new TStaticData<T>(in)); - } - - - //! Get a heap property - template <typename T> - bool GetProperty( const char* name, T*& out ) const - { - THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name); - if (!t) - { - out = NULL; - return false; - } - out = t->data; - return true; - } - - //! Get a static, by-value property - template <typename T> - bool GetProperty( const char* name, T& out ) const - { - TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name); - if (!t)return false; - out = t->data; - return true; - } - - //! Remove a property of a specific type - void RemoveProperty( const char* name) { - SetGenericPropertyPtr<Base>(pmap,name,NULL); - } - -private: - - void AddProperty( const char* name, Base* data) { - SetGenericPropertyPtr<Base>(pmap,name,data); - } - - Base* GetPropertyInternal( const char* name) const { - return GetGenericProperty<Base*>(pmap,name,NULL); - } - -private: - - //! Map of all stored properties - PropertyMap pmap; -}; - -#if 0 - -// --------------------------------------------------------------------------- -/** @brief Represents a dependency table for a postprocessing steps. - * - * For future use. - */ - struct PPDependencyTable - { - unsigned int execute_me_before_these; - unsigned int execute_me_after_these; - unsigned int only_if_these_are_not_specified; - unsigned int mutually_exclusive_with; - }; - -#endif - - -#define AI_SPP_SPATIAL_SORT "$Spat" - -// --------------------------------------------------------------------------- -/** The BaseProcess defines a common interface for all post processing steps. - * A post processing step is run after a successful import if the caller - * specified the corresponding flag when calling ReadFile(). - * Enum #aiPostProcessSteps defines which flags are available. - * After a successful import the Importer iterates over its internal array - * of processes and calls IsActive() on each process to evaluate if the step - * should be executed. If the function returns true, the class' Execute() - * function is called subsequently. - */ -class ASSIMP_API BaseProcess -{ - friend class Importer; - -public: - - /** Constructor to be privately used by Importer */ - BaseProcess(); - - /** Destructor, private as well */ - virtual ~BaseProcess(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. - * @param pFlags The processing flags the importer was called with. A - * bitwise combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, - * false if not. - */ - virtual bool IsActive( unsigned int pFlags) const = 0; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * The function deletes the scene if the postprocess step fails ( - * the object pointer will be set to NULL). - * @param pImp Importer instance (pImp->mScene must be valid) - */ - void ExecuteOnScene( Importer* pImp); - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - virtual void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * A process should throw an ImportErrorException* if it fails. - * This method must be implemented by deriving classes. - * @param pScene The imported data to work at. - */ - virtual void Execute( aiScene* pScene) = 0; - - - // ------------------------------------------------------------------- - /** Assign a new SharedPostProcessInfo to the step. This object - * allows multiple postprocess steps to share data. - * @param sh May be NULL - */ - inline void SetSharedData(SharedPostProcessInfo* sh) { - shared = sh; - } - - // ------------------------------------------------------------------- - /** Get the shared data that is assigned to the step. - */ - inline SharedPostProcessInfo* GetSharedData() { - return shared; - } - -protected: - - /** See the doc of #SharedPostProcessInfo for more details */ - SharedPostProcessInfo* shared; - - /** Currently active progress handler */ - ProgressHandler* progress; -}; - - -} // end of namespace Assimp - -#endif // AI_BASEPROCESS_H_INC diff --git a/3rdparty/assimp/code/BlenderDNA.cpp b/3rdparty/assimp/code/BlenderDNA.cpp deleted file mode 100644 index f7cf8e65..00000000 --- a/3rdparty/assimp/code/BlenderDNA.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderDNA.cpp - * @brief Implementation of the Blender `DNA`, that is its own - * serialized set of data structures. - */ -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER -#include "BlenderDNA.h" -#include "StreamReader.h" -#include "fast_atof.h" - -using namespace Assimp; -using namespace Assimp::Blender; -using namespace Assimp::Formatter; - -#define for_each BOOST_FOREACH -bool match4(StreamReaderAny& stream, const char* string) { - char tmp[] = { - (stream).GetI1(), - (stream).GetI1(), - (stream).GetI1(), - (stream).GetI1() - }; - return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]); -} - -struct Type { - size_t size; - std::string name; -}; - -// ------------------------------------------------------------------------------------------------ -void DNAParser :: Parse () -{ - StreamReaderAny& stream = *db.reader.get(); - DNA& dna = db.dna; - - if (!match4(stream,"SDNA")) { - throw DeadlyImportError("BlenderDNA: Expected SDNA chunk"); - } - - // name dictionary - if (!match4(stream,"NAME")) { - throw DeadlyImportError("BlenderDNA: Expected NAME field"); - } - - std::vector<std::string> names (stream.GetI4()); - for_each(std::string& s, names) { - while (char c = stream.GetI1()) { - s += c; - } - } - - // type dictionary - for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); - if (!match4(stream,"TYPE")) { - throw DeadlyImportError("BlenderDNA: Expected TYPE field"); - } - - std::vector<Type> types (stream.GetI4()); - for_each(Type& s, types) { - while (char c = stream.GetI1()) { - s.name += c; - } - } - - // type length dictionary - for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); - if (!match4(stream,"TLEN")) { - throw DeadlyImportError("BlenderDNA: Expected TLEN field"); - } - - for_each(Type& s, types) { - s.size = stream.GetI2(); - } - - // structures dictionary - for (;stream.GetCurrentPos() & 0x3; stream.GetI1()); - if (!match4(stream,"STRC")) { - throw DeadlyImportError("BlenderDNA: Expected STRC field"); - } - - size_t end = stream.GetI4(), fields = 0; - - dna.structures.reserve(end); - for (size_t i = 0; i != end; ++i) { - - uint16_t n = stream.GetI2(); - if (n >= types.size()) { - throw DeadlyImportError((format(), - "BlenderDNA: Invalid type index in structure name" ,n, - " (there are only ", types.size(), " entries)" - )); - } - - // maintain separate indexes - dna.indices[types[n].name] = dna.structures.size(); - - dna.structures.push_back(Structure()); - Structure& s = dna.structures.back(); - s.name = types[n].name; - //s.index = dna.structures.size()-1; - - n = stream.GetI2(); - s.fields.reserve(n); - - size_t offset = 0; - for (size_t m = 0; m < n; ++m, ++fields) { - - uint16_t j = stream.GetI2(); - if (j >= types.size()) { - throw DeadlyImportError((format(), - "BlenderDNA: Invalid type index in structure field ", j, - " (there are only ", types.size(), " entries)" - )); - } - s.fields.push_back(Field()); - Field& f = s.fields.back(); - f.offset = offset; - - f.type = types[j].name; - f.size = types[j].size; - - j = stream.GetI2(); - if (j >= names.size()) { - throw DeadlyImportError((format(), - "BlenderDNA: Invalid name index in structure field ", j, - " (there are only ", names.size(), " entries)" - )); - } - - f.name = names[j]; - f.flags = 0u; - - // pointers always specify the size of the pointee instead of their own. - // The pointer asterisk remains a property of the lookup name. - if (f.name[0] == '*') { - f.size = db.i64bit ? 8 : 4; - f.flags |= FieldFlag_Pointer; - } - - // arrays, however, specify the size of a single element so we - // need to parse the (possibly multi-dimensional) array declaration - // in order to obtain the actual size of the array in the file. - // Also we need to alter the lookup name to include no array - // brackets anymore or size fixup won't work (if our size does - // not match the size read from the DNA). - if (*f.name.rbegin() == ']') { - const std::string::size_type rb = f.name.find('['); - if (rb == std::string::npos) { - throw DeadlyImportError((format(), - "BlenderDNA: Encountered invalid array declaration ", - f.name - )); - } - - f.flags |= FieldFlag_Array; - DNA::ExtractArraySize(f.name,f.array_sizes); - f.name = f.name.substr(0,rb); - - f.size *= f.array_sizes[0] * f.array_sizes[1]; - } - - // maintain separate indexes - s.indices[f.name] = s.fields.size()-1; - offset += f.size; - } - s.size = offset; - } - - DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(), - " structures with totally ",fields," fields")); - -#ifdef ASSIMP_BUILD_BLENDER_DEBUG - dna.DumpToFile(); -#endif - - dna.AddPrimitiveStructures(); - dna.RegisterConverters(); -} - - -#ifdef ASSIMP_BUILD_BLENDER_DEBUG - -#include <fstream> -// ------------------------------------------------------------------------------------------------ -void DNA :: DumpToFile() -{ - // we dont't bother using the VFS here for this is only for debugging. - // (and all your bases are belong to us). - - std::ofstream f("dna.txt"); - if (f.fail()) { - DefaultLogger::get()->error("Could not dump dna to dna.txt"); - return; - } - f << "Field format: type name offset size" << "\n"; - f << "Structure format: name size" << "\n"; - - for_each(const Structure& s, structures) { - f << s.name << " " << s.size << "\n\n"; - for_each(const Field& ff, s.fields) { - f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl; - } - f << std::endl; - } - DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt"); -} -#endif - -// ------------------------------------------------------------------------------------------------ -/*static*/ void DNA :: ExtractArraySize( - const std::string& out, - size_t array_sizes[2] -) -{ - array_sizes[0] = array_sizes[1] = 1; - std::string::size_type pos = out.find('['); - if (pos++ == std::string::npos) { - return; - } - array_sizes[0] = strtol10(&out[pos]); - - pos = out.find('[',pos); - if (pos++ == std::string::npos) { - return; - } - array_sizes[1] = strtol10(&out[pos]); -} - -// ------------------------------------------------------------------------------------------------ -boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure( - const Structure& structure, - const FileDatabase& db -) const -{ - std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name); - if (it == converters.end()) { - return boost::shared_ptr< ElemBase >(); - } - - boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))(); - (structure.*((*it).second.second))(ret,db); - - return ret; -} - -// ------------------------------------------------------------------------------------------------ -DNA::FactoryPair DNA :: GetBlobToStructureConverter( - const Structure& structure, - const FileDatabase& db -) const -{ - std::map<std::string, FactoryPair>::const_iterator it = converters.find(structure.name); - return it == converters.end() ? FactoryPair() : (*it).second; -} - -// basing on http://www.blender.org/development/architecture/notes-on-sdna/ -// ------------------------------------------------------------------------------------------------ -void DNA :: AddPrimitiveStructures() -{ - // NOTE: these are just dummies. Their presence enforces - // Structure::Convert<target_type> to be called on these - // empty structures. These converters are special - // overloads which scan the name of the structure and - // perform the required data type conversion if one - // of these special names is found in the structure - // in question. - - indices["int"] = structures.size(); - structures.push_back( Structure() ); - structures.back().name = "int"; - structures.back().size = 4; - - indices["short"] = structures.size(); - structures.push_back( Structure() ); - structures.back().name = "short"; - structures.back().size = 2; - - - indices["char"] = structures.size(); - structures.push_back( Structure() ); - structures.back().name = "char"; - structures.back().size = 1; - - - indices["float"] = structures.size(); - structures.push_back( Structure() ); - structures.back().name = "float"; - structures.back().size = 4; - - - indices["double"] = structures.size(); - structures.push_back( Structure() ); - structures.back().name = "double"; - structures.back().size = 8; - - // no long, seemingly. -} - -// ------------------------------------------------------------------------------------------------ -void SectionParser :: Next() -{ - stream.SetCurrentPos(current.start + current.size); - - const char tmp[] = { - stream.GetI1(), - stream.GetI1(), - stream.GetI1(), - stream.GetI1() - }; - current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1); - - current.size = stream.GetI4(); - current.address.val = ptr64 ? stream.GetU8() : stream.GetU4(); - - current.dna_index = stream.GetI4(); - current.num = stream.GetI4(); - - current.start = stream.GetCurrentPos(); - if (stream.GetRemainingSizeToLimit() < current.size) { - throw DeadlyImportError("BLEND: invalid size of file block"); - } - -#ifdef ASSIMP_BUILD_BLENDER_DEBUG - DefaultLogger::get()->debug(current.id); -#endif -} - - - -#endif diff --git a/3rdparty/assimp/code/BlenderDNA.h b/3rdparty/assimp/code/BlenderDNA.h deleted file mode 100644 index 3e24c60b..00000000 --- a/3rdparty/assimp/code/BlenderDNA.h +++ /dev/null @@ -1,866 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderDNA.h - * @brief Blender `DNA` (file format specification embedded in - * blend file itself) loader. - */ -#ifndef INCLUDED_AI_BLEND_DNA_H -#define INCLUDED_AI_BLEND_DNA_H - -#include "BaseImporter.h" -#include "TinyFormatter.h" - -// enable verbose log output. really verbose, so be careful. -#ifdef _DEBUG -# define ASSIMP_BUILD_BLENDER_DEBUG -#endif - -// #define ASSIMP_BUILD_BLENDER_NO_STATS - -namespace Assimp { - template <bool,bool> class StreamReader; - typedef StreamReader<true,true> StreamReaderAny; - - namespace Blender { - class FileDatabase; - struct FileBlockHead; - - template <template <typename> class TOUT> - class ObjectCache; - -// ------------------------------------------------------------------------------- -/** Exception class used by the blender loader to selectively catch exceptions - * thrown in its own code (DeadlyImportErrors thrown in general utility - * functions are untouched then). If such an exception is not caught by - * the loader itself, it will still be caught by Assimp due to its - * ancestry. */ -// ------------------------------------------------------------------------------- -struct Error : DeadlyImportError -{ - Error (const std::string& s) - : DeadlyImportError(s) - {} -}; - -// ------------------------------------------------------------------------------- -/** The only purpose of this structure is to feed a virtual dtor into its - * descendents. It serves as base class for all data structure fields. */ -// ------------------------------------------------------------------------------- -struct ElemBase -{ - virtual ~ElemBase() {} - - /** Type name of the element. The type - * string points is the `c_str` of the `name` attribute of the - * corresponding `Structure`, that is, it is only valid as long - * as the DNA is not modified. The dna_type is only set if the - * data type is not static, i.e. a boost::shared_ptr<ElemBase> - * in the scene description would have its type resolved - * at runtime, so this member is always set. */ - const char* dna_type; -}; - - -// ------------------------------------------------------------------------------- -/** Represents a generic pointer to a memory location, which can be either 32 - * or 64 bits. These pointers are loaded from the BLEND file and finally - * fixed to point to the real, converted representation of the objects - * they used to point to.*/ -// ------------------------------------------------------------------------------- -struct Pointer -{ - Pointer() : val() {} - uint64_t val; -}; - -// ------------------------------------------------------------------------------- -/** Represents a generic offset within a BLEND file */ -// ------------------------------------------------------------------------------- -struct FileOffset -{ - FileOffset() : val() {} - uint64_t val; -}; - -// ------------------------------------------------------------------------------- -/** Dummy derivate of std::vector to be able to use it in templates simultaenously - * with boost::shared_ptr, which takes only one template argument - * while std::vector takes three. Also we need to provide some special member - * functions of shared_ptr */ -// ------------------------------------------------------------------------------- -template <typename T> -class vector : public std::vector<T> -{ -public: - using std::vector<T>::resize; - using std::vector<T>::empty; - - void reset() { - resize(0); - } - - operator bool () const { - return !empty(); - } -}; - -// ------------------------------------------------------------------------------- -/** Mixed flags for use in #Field */ -// ------------------------------------------------------------------------------- -enum FieldFlags -{ - FieldFlag_Pointer = 0x1, - FieldFlag_Array = 0x2 -}; - -// ------------------------------------------------------------------------------- -/** Represents a single member of a data structure in a BLEND file */ -// ------------------------------------------------------------------------------- -struct Field -{ - std::string name; - std::string type; - - size_t size; - size_t offset; - - /** Size of each array dimension. For flat arrays, - * the second dimension is set to 1. */ - size_t array_sizes[2]; - - /** Any of the #FieldFlags enumerated values */ - unsigned int flags; -}; - -// ------------------------------------------------------------------------------- -/** Range of possible behaviours for fields absend in the input file. Some are - * mission critical so we need them, while others can silently be default - * initialized and no animations are harmed. */ -// ------------------------------------------------------------------------------- -enum ErrorPolicy -{ - /** Substitute default value and ignore */ - ErrorPolicy_Igno, - /** Substitute default value and write to log */ - ErrorPolicy_Warn, - /** Substitute a massive error message and crash the whole matrix. Its time for another zion */ - ErrorPolicy_Fail -}; - -#ifdef ASSIMP_BUILD_BLENDER_DEBUG -# define ErrorPolicy_Igno ErrorPolicy_Warn -#endif - -// ------------------------------------------------------------------------------- -/** Represents a data structure in a BLEND file. A Structure defines n fields - * and their locatios and encodings the input stream. Usually, every - * Structure instance pertains to one equally-named data structure in the - * BlenderScene.h header. This class defines various utilities to map a - * binary `blob` read from the file to such a structure instance with - * meaningful contents. */ -// ------------------------------------------------------------------------------- -class Structure -{ - template <template <typename> class> friend class ObjectCache; - -public: - - Structure() - : cache_idx(-1) - {} - -public: - - // publicly accessible members - std::string name; - vector< Field > fields; - std::map<std::string, size_t> indices; - - size_t size; - -public: - - // -------------------------------------------------------- - /** Access a field of the structure by its canonical name. The pointer version - * returns NULL on failure while the reference version raises an import error. */ - inline const Field& operator [] (const std::string& ss) const; - inline const Field* Get (const std::string& ss) const; - - // -------------------------------------------------------- - /** Access a field of the structure by its index */ - inline const Field& operator [] (const size_t i) const; - - // -------------------------------------------------------- - inline bool operator== (const Structure& other) const { - return name == other.name; // name is meant to be an unique identifier - } - - // -------------------------------------------------------- - inline bool operator!= (const Structure& other) const { - return name != other.name; - } - -public: - - // -------------------------------------------------------- - /** Try to read an instance of the structure from the stream - * and attempt to convert to `T`. This is done by - * an appropriate specialization. If none is available, - * a compiler complain is the result. - * @param dest Destination value to be written - * @param db File database, including input stream. */ - template <typename T> inline void Convert (T& dest, - const FileDatabase& db) const; - - - - // -------------------------------------------------------- - // generic converter - template <typename T> - void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const; - - // -------------------------------------------------------- - // generic allocator - template <typename T> boost::shared_ptr<ElemBase> Allocate() const; - - - - // -------------------------------------------------------- - // field parsing for 1d arrays - template <int error_policy, typename T, size_t M> - void ReadFieldArray(T (& out)[M], const char* name, - const FileDatabase& db) const; - - // -------------------------------------------------------- - // field parsing for 2d arrays - template <int error_policy, typename T, size_t M, size_t N> - void ReadFieldArray2(T (& out)[M][N], const char* name, - const FileDatabase& db) const; - - // -------------------------------------------------------- - // field parsing for pointer or dynamic array types - // (boost::shared_ptr or boost::shared_array) - template <int error_policy, template <typename> class TOUT, typename T> - void ReadFieldPtr(TOUT<T>& out, const char* name, - const FileDatabase& db) const; - - // -------------------------------------------------------- - // field parsing for static arrays of pointer or dynamic - // array types (boost::shared_ptr[] or boost::shared_array[]) - template <int error_policy, template <typename> class TOUT, typename T, size_t N> - void ReadFieldPtr(TOUT<T> (&out)[N], const char* name, - const FileDatabase& db) const; - - // -------------------------------------------------------- - // field parsing for `normal` values - template <int error_policy, typename T> - void ReadField(T& out, const char* name, - const FileDatabase& db) const; - -private: - - // -------------------------------------------------------- - template <template <typename> class TOUT, typename T> - void ResolvePointer(TOUT<T>& out, const Pointer & ptrval, - const FileDatabase& db, const Field& f) const; - - // -------------------------------------------------------- - template <template <typename> class TOUT, typename T> - void ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, - const FileDatabase& db, const Field& f) const; - - // -------------------------------------------------------- - void ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, - const FileDatabase& db, const Field& f) const; - - // -------------------------------------------------------- - inline const FileBlockHead* LocateFileBlockForAddress( - const Pointer & ptrval, - const FileDatabase& db) const; - -private: - - // ------------------------------------------------------------------------------ - template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const { - out = boost::shared_ptr<T>(new T()); - s = 1; - return out.get(); - } - - template <typename T> T* _allocate(vector<T>& out, size_t& s) const { - out.resize(s); - return s ? &out.front() : NULL; - } - - // -------------------------------------------------------- - template <int error_policy> - struct _defaultInitializer { - - template <typename T, unsigned int N> - void operator ()(T (& out)[N], const char* = NULL) { - for (unsigned int i = 0; i < N; ++i) { - out[i] = T(); - } - } - - template <typename T, unsigned int N, unsigned int M> - void operator ()(T (& out)[N][M], const char* = NULL) { - for (unsigned int i = 0; i < N; ++i) { - for (unsigned int j = 0; j < M; ++j) { - out[i][j] = T(); - } - } - } - - template <typename T> - void operator ()(T& out, const char* = NULL) { - out = T(); - } - }; - -private: - - mutable size_t cache_idx; -}; - -// -------------------------------------------------------- -template <> struct Structure :: _defaultInitializer<ErrorPolicy_Warn> { - - template <typename T> - void operator ()(T& out, const char* reason = "<add reason>") { - DefaultLogger::get()->warn(reason); - - // ... and let the show go on - _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out); - } -}; - -template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> { - - template <typename T> - void operator ()(T& out,const char* = "") { - // obviously, it is crucial that _DefaultInitializer is used - // only from within a catch clause. - throw; - } -}; - -// ------------------------------------------------------------------------------------------------------- -template <> inline void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, - const Pointer & ptrval, - const FileDatabase& db, - const Field& f - ) const; - - -// ------------------------------------------------------------------------------- -/** Represents the full data structure information for a single BLEND file. - * This data is extracted from the DNA1 chunk in the file. - * #DNAParser does the reading and represents currently the only place where - * DNA is altered.*/ -// ------------------------------------------------------------------------------- -class DNA -{ -public: - - typedef void (Structure::*ConvertProcPtr) ( - boost::shared_ptr<ElemBase> in, - const FileDatabase& - ) const; - - typedef boost::shared_ptr<ElemBase> ( - Structure::*AllocProcPtr) () const; - - typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair; - -public: - - std::map<std::string, FactoryPair > converters; - vector<Structure > structures; - std::map<std::string, size_t> indices; - -public: - - // -------------------------------------------------------- - /** Access a structure by its canonical name, the pointer version returns NULL on failure - * while the reference version raises an error. */ - inline const Structure& operator [] (const std::string& ss) const; - inline const Structure* Get (const std::string& ss) const; - - // -------------------------------------------------------- - /** Access a structure by its index */ - inline const Structure& operator [] (const size_t i) const; - -public: - - // -------------------------------------------------------- - /** Add structure definitions for all the primitive types, - * i.e. integer, short, char, float */ - void AddPrimitiveStructures(); - - // -------------------------------------------------------- - /** Fill the @c converters member with converters for all - * known data types. The implementation of this method is - * in BlenderScene.cpp and is machine-generated. - * Converters are used to quickly handle objects whose - * exact data type is a runtime-property and not yet - * known at compile time (consier Object::data).*/ - void RegisterConverters(); - - - // -------------------------------------------------------- - /** Take an input blob from the stream, interpret it according to - * a its structure name and convert it to the intermediate - * representation. - * @param structure Destination structure definition - * @param db File database. - * @return A null pointer if no appropriate converter is available.*/ - boost::shared_ptr< ElemBase > ConvertBlobToStructure( - const Structure& structure, - const FileDatabase& db - ) const; - - // -------------------------------------------------------- - /** Find a suitable conversion function for a given Structure. - * Such a converter function takes a blob from the input - * stream, reads as much as it needs, and builds up a - * complete object in intermediate representation. - * @param structure Destination structure definition - * @param db File database. - * @return A null pointer in .first if no appropriate converter is available.*/ - FactoryPair GetBlobToStructureConverter( - const Structure& structure, - const FileDatabase& db - ) const; - - -#ifdef ASSIMP_BUILD_BLENDER_DEBUG - // -------------------------------------------------------- - /** Dump the DNA to a text file. This is for debugging purposes. - * The output file is `dna.txt` in the current working folder*/ - void DumpToFile(); -#endif - - // -------------------------------------------------------- - /** Extract array dimensions from a C array declaration, such - * as `...[4][6]`. Returned string would be `...[][]`. - * @param out - * @param array_sizes Receive maximally two array dimensions, - * the second element is set to 1 if the array is flat. - * Both are set to 1 if the input is not an array. - * @throw DeadlyImportError if more than 2 dimensions are - * encountered. */ - static void ExtractArraySize( - const std::string& out, - size_t array_sizes[2] - ); -}; - -// special converters for primitive types -template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const; -template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const; -template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const; -template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const; -template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const; -template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const; - -// ------------------------------------------------------------------------------- -/** Describes a master file block header. Each master file sections holds n - * elements of a certain SDNA structure (or otherwise unspecified data). */ -// ------------------------------------------------------------------------------- -struct FileBlockHead -{ - // points right after the header of the file block - StreamReaderAny::pos start; - - std::string id; - size_t size; - - // original memory address of the data - Pointer address; - - // index into DNA - unsigned int dna_index; - - // number of structure instances to follow - size_t num; - - - - // file blocks are sorted by address to quickly locate specific memory addresses - bool operator < (const FileBlockHead& o) const { - return address.val < o.address.val; - } - - // for std::upper_bound - operator const Pointer& () const { - return address; - } -}; - -// for std::upper_bound -inline bool operator< (const Pointer& a, const Pointer& b) { - return a.val < b.val; -} - -// ------------------------------------------------------------------------------- -/** Utility to read all master file blocks in turn. */ -// ------------------------------------------------------------------------------- -class SectionParser -{ -public: - - // -------------------------------------------------------- - /** @param stream Inout stream, must point to the - * first section in the file. Call Next() once - * to have it read. - * @param ptr64 Pointer size in file is 64 bits? */ - SectionParser(StreamReaderAny& stream,bool ptr64) - : stream(stream) - , ptr64(ptr64) - { - current.size = current.start = 0; - } - -public: - - // -------------------------------------------------------- - const FileBlockHead& GetCurrent() const { - return current; - } - - -public: - - // -------------------------------------------------------- - /** Advance to the next section. - * @throw DeadlyImportError if the last chunk was passed. */ - void Next(); - -public: - - FileBlockHead current; - StreamReaderAny& stream; - bool ptr64; -}; - - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS -// ------------------------------------------------------------------------------- -/** Import statistics, i.e. number of file blocks read*/ -// ------------------------------------------------------------------------------- -class Statistics { - -public: - - Statistics () - : fields_read () - , pointers_resolved () - , cache_hits () -// , blocks_read () - , cached_objects () - {} - -public: - - /** total number of fields we read */ - unsigned int fields_read; - - /** total number of resolved pointers */ - unsigned int pointers_resolved; - - /** number of pointers resolved from the cache */ - unsigned int cache_hits; - - /** number of blocks (from FileDatabase::entries) - we did actually read from. */ - // unsigned int blocks_read; - - /** objects in FileData::cache */ - unsigned int cached_objects; -}; -#endif - -// ------------------------------------------------------------------------------- -/** The object cache - all objects addressed by pointers are added here. This - * avoids circular references and avoids object duplication. */ -// ------------------------------------------------------------------------------- -template <template <typename> class TOUT> -class ObjectCache -{ -public: - - typedef std::map< Pointer, TOUT<ElemBase> > StructureCache; - -public: - - ObjectCache(const FileDatabase& db) - : db(db) - { - // currently there are only ~400 structure records per blend file. - // we read only a small part of them and don't cache objects - // which we don't need, so this should suffice. - caches.reserve(64); - } - -public: - - // -------------------------------------------------------- - /** Check whether a specific item is in the cache. - * @param s Data type of the item - * @param out Output pointer. Unchanged if the - * cache doens't know the item yet. - * @param ptr Item address to look for. */ - template <typename T> void get ( - const Structure& s, - TOUT<T>& out, - const Pointer& ptr) const; - - // -------------------------------------------------------- - /** Add an item to the cache after the item has - * been fully read. Do not insert anything that - * may be faulty or might cause the loading - * to abort. - * @param s Data type of the item - * @param out Item to insert into the cache - * @param ptr address (cache key) of the item. */ - template <typename T> void set - (const Structure& s, - const TOUT<T>& out, - const Pointer& ptr); - -private: - - mutable vector<StructureCache> caches; - const FileDatabase& db; -}; - -// ------------------------------------------------------------------------------- -// ------------------------------------------------------------------------------- -template <> class ObjectCache<Blender::vector> -{ -public: - - ObjectCache(const FileDatabase&) {} - - template <typename T> void get(const Structure&, vector<T>&t, const Pointer&) {} - template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {} -}; - -#ifdef _MSC_VER -# pragma warning(disable:4355) -#endif - -// ------------------------------------------------------------------------------- -/** Memory representation of a full BLEND file and all its dependencies. The - * output aiScene is constructed from an instance of this data structure. */ -// ------------------------------------------------------------------------------- -class FileDatabase -{ - template <template <typename> class TOUT> friend class ObjectCache; - -public: - - - FileDatabase() - : next_cache_idx() - , _cacheArrays(*this) - , _cache(*this) - {} - -public: - - // publicly accessible fields - bool i64bit; - bool little; - - DNA dna; - boost::shared_ptr< StreamReaderAny > reader; - vector< FileBlockHead > entries; - -public: - - Statistics& stats() const { - return _stats; - } - - // For all our templates to work on both shared_ptr's and vector's - // using the same code, a dummy cache for arrays is provided. Actually, - // arrays of objects are never cached because we can't easily - // ensure their proper destruction. - template <typename T> - ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& in) const { - return _cache; - } - - template <typename T> - ObjectCache<vector>& cache(vector<T>& in) const { - return _cacheArrays; - } - -private: - - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - mutable Statistics _stats; -#endif - - mutable ObjectCache<vector> _cacheArrays; - mutable ObjectCache<boost::shared_ptr> _cache; - - mutable size_t next_cache_idx; -}; - -#ifdef _MSC_VER -# pragma warning(default:4355) -#endif - -// ------------------------------------------------------------------------------- -/** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */ -// ------------------------------------------------------------------------------- -class DNAParser -{ - -public: - - /** Bind the parser to a empty DNA and an input stream */ - DNAParser(FileDatabase& db) - : db(db) - {} - -public: - - // -------------------------------------------------------- - /** Locate the DNA in the file and parse it. The input - * stream is expected to point to the beginning of the DN1 - * chunk at the time this method is called and is - * undefined afterwards. - * @throw DeadlyImportError if the DNA cannot be read. - * @note The position of the stream pointer is undefined - * afterwards.*/ - void Parse (); - -public: - - /** Obtain a reference to the extracted DNA information */ - const Blender::DNA& GetDNA() const { - return db.dna; - } - -private: - - FileDatabase& db; -}; - -//-------------------------------------------------------------------------------- -template <> inline void Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, - const Pointer & ptrval, - const FileDatabase& db, - const Field& /* f */ - ) const -{ - // Special case when the data type needs to be determined at runtime. - // Less secure than in the `strongly-typed` case. - - out.reset(); - if (!ptrval.val) { - return; - } - - // find the file block the pointer is pointing to - const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); - - // determine the target type from the block header - const Structure& s = db.dna[block->dna_index]; - - // try to retrieve the object from the cache - db.cache(out).get(s,out,ptrval); - if (out) { - return; - } - - // seek to this location, but save the previous stream pointer. - const StreamReaderAny::pos pold = db.reader->GetCurrentPos(); - db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) )); - // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems. - // I really ought to improve StreamReader to work with 64 bit indices exclusively. - - // continue conversion after allocating the required storage - DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db); - if (!builders.first) { - // this might happen if DNA::RegisterConverters hasn't been called so far - // or if the target type is not contained in `our` DNA. - out.reset(); - DefaultLogger::get()->warn((Formatter::format(), - "Failed to find a converter for the `",s.name,"` structure" - )); - return; - } - - // allocate the object hull - out = (s.*builders.first)(); - - // cache the object immediately to prevent infinite recursion in a - // circular list with a single element (i.e. a self-referencing element). - db.cache(out).set(s,out,ptrval); - - // and do the actual conversion - (s.*builders.second)(out,db); - db.reader->SetCurrentPos(pold); - - // store a pointer to the name string of the actual type - // in the object itself. This allows the conversion code - // to perform additional type checking. - out->dna_type = s.name.c_str(); - - - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().pointers_resolved; -#endif -} - - } // end Blend -} // end Assimp - -#include "BlenderDNA.inl" - -#endif diff --git a/3rdparty/assimp/code/BlenderDNA.inl b/3rdparty/assimp/code/BlenderDNA.inl deleted file mode 100644 index 511e7878..00000000 --- a/3rdparty/assimp/code/BlenderDNA.inl +++ /dev/null @@ -1,638 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderDNA.inl - * @brief Blender `DNA` (file format specification embedded in - * blend file itself) loader. - */ -#ifndef INCLUDED_AI_BLEND_DNA_INL -#define INCLUDED_AI_BLEND_DNA_INL - -namespace Assimp { - namespace Blender { - -//-------------------------------------------------------------------------------- -const Field& Structure :: operator [] (const std::string& ss) const -{ - std::map<std::string, size_t>::const_iterator it = indices.find(ss); - if (it == indices.end()) { - throw Error((Formatter::format(), - "BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`" - )); - } - - return fields[(*it).second]; -} - -//-------------------------------------------------------------------------------- -const Field* Structure :: Get (const std::string& ss) const -{ - std::map<std::string, size_t>::const_iterator it = indices.find(ss); - return it == indices.end() ? NULL : &fields[(*it).second]; -} - -//-------------------------------------------------------------------------------- -const Field& Structure :: operator [] (const size_t i) const -{ - if (i >= fields.size()) { - throw Error((Formatter::format(), - "BlendDNA: There is no field with index `",i,"` in structure `",name,"`" - )); - } - - return fields[i]; -} - -//-------------------------------------------------------------------------------- -template <typename T> boost::shared_ptr<ElemBase> Structure :: Allocate() const -{ - return boost::shared_ptr<T>(new T()); -} - -//-------------------------------------------------------------------------------- -template <typename T> void Structure :: Convert( - boost::shared_ptr<ElemBase> in, - const FileDatabase& db) const -{ - Convert<T> (*static_cast<T*> ( in.get() ),db); -} - -//-------------------------------------------------------------------------------- -template <int error_policy, typename T, size_t M> -void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatabase& db) const -{ - const StreamReaderAny::pos old = db.reader->GetCurrentPos(); - try { - const Field& f = (*this)[name]; - const Structure& s = db.dna[f.type]; - - // is the input actually an array? - if (!(f.flags & FieldFlag_Array)) { - throw Error((Formatter::format(),"Field `",name,"` of structure `", - this->name,"` ought to be an array of size ",M - )); - } - - db.reader->IncPtr(f.offset); - - // size conversions are always allowed, regardless of error_policy - unsigned int i = 0; - for (; i < std::min(f.array_sizes[0],M); ++i) { - s.Convert(out[i],db); - } - for (; i < M; ++i) { - _defaultInitializer<ErrorPolicy_Igno>()(out[i]); - } - } - catch (const Error& e) { - _defaultInitializer<error_policy>()(out,e.what()); - } - - // and recover the previous stream position - db.reader->SetCurrentPos(old); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().fields_read; -#endif -} - -//-------------------------------------------------------------------------------- -template <int error_policy, typename T, size_t M, size_t N> -void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileDatabase& db) const -{ - const StreamReaderAny::pos old = db.reader->GetCurrentPos(); - try { - const Field& f = (*this)[name]; - const Structure& s = db.dna[f.type]; - - // is the input actually an array? - if (!(f.flags & FieldFlag_Array)) { - throw Error((Formatter::format(),"Field `",name,"` of structure `", - this->name,"` ought to be an array of size ",M,"*",N - )); - } - - db.reader->IncPtr(f.offset); - - // size conversions are always allowed, regardless of error_policy - unsigned int i = 0; - for (; i < std::min(f.array_sizes[0],M); ++i) { - unsigned int j = 0; - for (; j < std::min(f.array_sizes[1],N); ++j) { - s.Convert(out[i][j],db); - } - for (; j < N; ++j) { - _defaultInitializer<ErrorPolicy_Igno>()(out[i][j]); - } - } - for (; i < M; ++i) { - _defaultInitializer<ErrorPolicy_Igno>()(out[i]); - } - } - catch (const Error& e) { - _defaultInitializer<error_policy>()(out,e.what()); - } - - // and recover the previous stream position - db.reader->SetCurrentPos(old); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().fields_read; -#endif -} - -//-------------------------------------------------------------------------------- -template <int error_policy, template <typename> class TOUT, typename T> -void Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db) const -{ - const StreamReaderAny::pos old = db.reader->GetCurrentPos(); - Pointer ptrval; - const Field* f; - try { - f = &(*this)[name]; - - // sanity check, should never happen if the genblenddna script is right - if (!(f->flags & FieldFlag_Pointer)) { - throw Error((Formatter::format(),"Field `",name,"` of structure `", - this->name,"` ought to be a pointer")); - } - - db.reader->IncPtr(f->offset); - Convert(ptrval,db); - // actually it is meaningless on which Structure the Convert is called - // because the `Pointer` argument triggers a special implementation. - } - catch (const Error& e) { - _defaultInitializer<error_policy>()(out,e.what()); - - out.reset(); - return; - } - - // resolve the pointer and load the corresponding structure - ResolvePointer(out,ptrval,db,*f); - - // and recover the previous stream position - db.reader->SetCurrentPos(old); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().fields_read; -#endif -} - -//-------------------------------------------------------------------------------- -template <int error_policy, template <typename> class TOUT, typename T, size_t N> -void Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name, - const FileDatabase& db) const -{ - // XXX see if we can reduce this to call to the 'normal' ReadFieldPtr - const StreamReaderAny::pos old = db.reader->GetCurrentPos(); - Pointer ptrval[N]; - const Field* f; - try { - f = &(*this)[name]; - - // sanity check, should never happen if the genblenddna script is right - if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) { - throw Error((Formatter::format(),"Field `",name,"` of structure `", - this->name,"` ought to be a pointer AND an array")); - } - - db.reader->IncPtr(f->offset); - - size_t i = 0; - for (; i < std::min(f->array_sizes[0],N); ++i) { - Convert(ptrval[i],db); - } - for (; i < N; ++i) { - _defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]); - } - - // actually it is meaningless on which Structure the Convert is called - // because the `Pointer` argument triggers a special implementation. - } - catch (const Error& e) { - _defaultInitializer<error_policy>()(out,e.what()); - for (size_t i = 0; i < N; ++i) { - out[i].reset(); - } - return; - } - for (size_t i = 0; i < N; ++i) { - // resolve the pointer and load the corresponding structure - ResolvePointer(out[i],ptrval[i],db,*f); - } - - // and recover the previous stream position - db.reader->SetCurrentPos(old); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().fields_read; -#endif -} - -//-------------------------------------------------------------------------------- -template <int error_policy, typename T> -void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) const -{ - const StreamReaderAny::pos old = db.reader->GetCurrentPos(); - try { - const Field& f = (*this)[name]; - // find the structure definition pertaining to this field - const Structure& s = db.dna[f.type]; - - db.reader->IncPtr(f.offset); - s.Convert(out,db); - } - catch (const Error& e) { - _defaultInitializer<error_policy>()(out,e.what()); - } - - // and recover the previous stream position - db.reader->SetCurrentPos(old); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().fields_read; -#endif -} - - -//-------------------------------------------------------------------------------- -template <template <typename> class TOUT, typename T> -void Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const -{ - out.reset(); - if (!ptrval.val) { - return; - } - const Structure& s = db.dna[f.type]; - // find the file block the pointer is pointing to - const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); - - // also determine the target type from the block header - // and check if it matches the type which we expect. - const Structure& ss = db.dna[block->dna_index]; - if (ss != s) { - throw Error((Formatter::format(),"Expected target to be of type `",s.name, - "` but seemingly it is a `",ss.name,"` instead" - )); - } - - // try to retrieve the object from the cache - db.cache(out).get(s,out,ptrval); - if (out) { - return; - } - - // seek to this location, but save the previous stream pointer. - const StreamReaderAny::pos pold = db.reader->GetCurrentPos(); - db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) )); - // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems. - // I really ought to improve StreamReader to work with 64 bit indices exclusively. - - // continue conversion after allocating the required storage - size_t num = block->size / ss.size; - T* o = _allocate(out,num); - - // cache the object before we convert it to avoid cyclic recursion. - db.cache(out).set(s,out,ptrval); - - for (size_t i = 0; i < num; ++i,++o) { - s.Convert(*o,db); - } - - db.reader->SetCurrentPos(pold); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - if (out) { - ++db.stats().pointers_resolved; - } -#endif -} - -//-------------------------------------------------------------------------------- -inline void Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, const FileDatabase& db, const Field& /* f */ ) const -{ - // Currently used exclusively by PackedFile::data to represent - // a simple offset into the mapped BLEND file. - out.reset(); - if (!ptrval.val) { - return; - } - - // find the file block the pointer is pointing to - const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); - - out = boost::shared_ptr< FileOffset > (new FileOffset()); - out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) ); -} - -//-------------------------------------------------------------------------------- -template <template <typename> class TOUT, typename T> -void Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, const FileDatabase& db, const Field& f) const -{ - // This is a function overload, not a template specialization. According to - // the partial ordering rules, it should be selected by the compiler - // for array-of-pointer inputs, i.e. Object::mats. - - out.reset(); - if (!ptrval.val) { - return; - } - - // find the file block the pointer is pointing to - const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db); - const size_t num = block->size / (db.i64bit?8:4); - - // keep the old stream position - const StreamReaderAny::pos pold = db.reader->GetCurrentPos(); - db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) )); - - // allocate raw storage for the array - out.resize(num); - for (size_t i = 0; i< num; ++i) { - Pointer val; - Convert(val,db); - - // and resolve the pointees - ResolvePointer(out[i],val,db,f); - } - - db.reader->SetCurrentPos(pold); -} - -//-------------------------------------------------------------------------------- -const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrval, const FileDatabase& db) const -{ - // the file blocks appear in list sorted by - // with ascending base addresses so we can run a - // binary search to locate the pointee quickly. - - // NOTE: Blender seems to distinguish between side-by-side - // data (stored in the same data block) and far pointers, - // which are only used for structures starting with an ID. - // We don't need to make this distinction, our algorithm - // works regardless where the data is stored. - vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval); - if (it == db.entries.end()) { - // this is crucial, pointers may not be invalid. - // this is either a corrupted file or an attempted attack. - throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x", - std::hex,ptrval.val,", no file block falls into this address range" - )); - } - if (ptrval.val >= (*it).address.val + (*it).size) { - throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x", - std::hex,ptrval.val,", nearest file block starting at 0x", - (*it).address.val," ends at 0x", - (*it).address.val + (*it).size - )); - } - return &*it; -} - -// ------------------------------------------------------------------------------------------------ -// NOTE: The MSVC debugger keeps showing up this annoying `a cast to a smaller data type has -// caused a loss of data`-warning. Avoid this warning by a masking with an appropriate bitmask. - -template <typename T> struct signless; -template <> struct signless<char> {typedef unsigned char type;}; -template <> struct signless<short> {typedef unsigned short type;}; -template <> struct signless<int> {typedef unsigned int type;}; - -template <typename T> -struct static_cast_silent { - template <typename V> - T operator()(V in) { - return static_cast<T>(in & static_cast<typename signless<T>::type>(-1)); - } -}; - -template <> struct static_cast_silent<float> { - template <typename V> float operator()(V in) { - return static_cast<float> (in); - } -}; - -template <> struct static_cast_silent<double> { - template <typename V> double operator()(V in) { - return static_cast<double>(in); - } -}; - -// ------------------------------------------------------------------------------------------------ -template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,const FileDatabase& db) -{ - if (in.name == "int") { - out = static_cast_silent<T>()(db.reader->GetU4()); - } - else if (in.name == "short") { - out = static_cast_silent<T>()(db.reader->GetU2()); - } - else if (in.name == "char") { - out = static_cast_silent<T>()(db.reader->GetU1()); - } - else if (in.name == "float") { - out = static_cast<T>(db.reader->GetF4()); - } - else if (in.name == "double") { - out = static_cast<T>(db.reader->GetF8()); - } - else { - throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name); - } -} - -// ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert<int> (int& dest,const FileDatabase& db) const -{ - ConvertDispatcher(dest,*this,db); -} - -// ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert<short> (short& dest,const FileDatabase& db) const -{ - // automatic rescaling from short to float and vice versa (seems to be used by normals) - if (name == "float") { - dest = static_cast<short>(db.reader->GetF4() * 32767.f); - //db.reader->IncPtr(-4); - return; - } - else if (name == "double") { - dest = static_cast<short>(db.reader->GetF8() * 32767.); - //db.reader->IncPtr(-8); - return; - } - ConvertDispatcher(dest,*this,db); -} - -// ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert<char> (char& dest,const FileDatabase& db) const -{ - // automatic rescaling from char to float and vice versa (seems useful for RGB colors) - if (name == "float") { - dest = static_cast<char>(db.reader->GetF4() * 255.f); - return; - } - else if (name == "double") { - dest = static_cast<char>(db.reader->GetF8() * 255.f); - return; - } - ConvertDispatcher(dest,*this,db); -} - -// ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert<float> (float& dest,const FileDatabase& db) const -{ - // automatic rescaling from char to float and vice versa (seems useful for RGB colors) - if (name == "char") { - dest = db.reader->GetI1() / 255.f; - return; - } - // automatic rescaling from short to float and vice versa (used by normals) - else if (name == "short") { - dest = db.reader->GetI2() / 32767.f; - return; - } - ConvertDispatcher(dest,*this,db); -} - -// ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const -{ - if (name == "char") { - dest = db.reader->GetI1() / 255.; - return; - } - else if (name == "short") { - dest = db.reader->GetI2() / 32767.; - return; - } - ConvertDispatcher(dest,*this,db); -} - -// ------------------------------------------------------------------------------------------------ -template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const -{ - if (db.i64bit) { - dest.val = db.reader->GetU8(); - //db.reader->IncPtr(-8); - return; - } - dest.val = db.reader->GetU4(); - //db.reader->IncPtr(-4); -} - -//-------------------------------------------------------------------------------- -const Structure& DNA :: operator [] (const std::string& ss) const -{ - std::map<std::string, size_t>::const_iterator it = indices.find(ss); - if (it == indices.end()) { - throw Error((Formatter::format(), - "BlendDNA: Did not find a structure named `",ss,"`" - )); - } - - return structures[(*it).second]; -} - -//-------------------------------------------------------------------------------- -const Structure* DNA :: Get (const std::string& ss) const -{ - std::map<std::string, size_t>::const_iterator it = indices.find(ss); - return it == indices.end() ? NULL : &structures[(*it).second]; -} - -//-------------------------------------------------------------------------------- -const Structure& DNA :: operator [] (const size_t i) const -{ - if (i >= structures.size()) { - throw Error((Formatter::format(), - "BlendDNA: There is no structure with index `",i,"`" - )); - } - - return structures[i]; -} - -//-------------------------------------------------------------------------------- -template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: get ( - const Structure& s, - TOUT<T>& out, - const Pointer& ptr -) const { - - if (s.cache_idx == static_cast<size_t>(-1)) { - s.cache_idx = db.next_cache_idx++; - caches.resize(db.next_cache_idx); - return; - } - - typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr); - if (it != caches[s.cache_idx].end()) { - out = boost::static_pointer_cast<T>( (*it).second ); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().cache_hits; -#endif - } - // otherwise, out remains untouched -} - - -//-------------------------------------------------------------------------------- -template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: set ( - const Structure& s, - const TOUT<T>& out, - const Pointer& ptr -) { - if (s.cache_idx == static_cast<size_t>(-1)) { - s.cache_idx = db.next_cache_idx++; - caches.resize(db.next_cache_idx); - } - caches[s.cache_idx][ptr] = boost::static_pointer_cast<ElemBase>( out ); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ++db.stats().cached_objects; -#endif -} - -}} -#endif diff --git a/3rdparty/assimp/code/BlenderIntermediate.h b/3rdparty/assimp/code/BlenderIntermediate.h deleted file mode 100644 index 99e0e64e..00000000 --- a/3rdparty/assimp/code/BlenderIntermediate.h +++ /dev/null @@ -1,183 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderIntermediate.h - * @brief Internal utility structures for the BlenderLoader. It also serves - * as master include file for the whole (internal) Blender subsystem. - */ -#ifndef INCLUDED_AI_BLEND_INTERMEDIATE_H -#define INCLUDED_AI_BLEND_INTERMEDIATE_H - -#include "BlenderLoader.h" -#include "BlenderDNA.h" -#include "BlenderScene.h" -#include "BlenderSceneGen.h" - -#define for_each(x,y) BOOST_FOREACH(x,y) - -namespace Assimp { -namespace Blender { - - // -------------------------------------------------------------------- - /** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */ - // -------------------------------------------------------------------- - template <template <typename,typename> class TCLASS, typename T> - struct TempArray { - typedef TCLASS< T*,std::allocator<T*> > mywrap; - - TempArray() { - } - - ~TempArray () { - for_each(T* elem, arr) { - delete elem; - } - } - - void dismiss() { - arr.clear(); - } - - mywrap* operator -> () { - return &arr; - } - - operator mywrap& () { - return arr; - } - - operator const mywrap& () const { - return arr; - } - - mywrap& get () { - return arr; - } - - const mywrap& get () const { - return arr; - } - - T* operator[] (size_t idx) const { - return arr[idx]; - } - - T*& operator[] (size_t idx) { - return arr[idx]; - } - - private: - // no copy semantics - void operator= (const TempArray&) { - } - - TempArray(const TempArray& arr) { - } - - private: - mywrap arr; - }; - -#ifdef _MSC_VER -# pragma warning(disable:4351) -#endif - // -------------------------------------------------------------------- - /** ConversionData acts as intermediate storage location for - * the various ConvertXXX routines in BlenderImporter.*/ - // -------------------------------------------------------------------- - struct ConversionData - { - ConversionData(const FileDatabase& db) - : sentinel_cnt() - , next_texture() - , db(db) - {} - - std::set<const Object*> objects; - - TempArray <std::vector, aiMesh> meshes; - TempArray <std::vector, aiCamera> cameras; - TempArray <std::vector, aiLight> lights; - TempArray <std::vector, aiMaterial> materials; - TempArray <std::vector, aiTexture> textures; - - // set of all materials referenced by at least one mesh in the scene - std::deque< boost::shared_ptr< Material > > materials_raw; - - // counter to name sentinel textures inserted as substitutes for procedural textures. - unsigned int sentinel_cnt; - - // next texture ID for each texture type, respectively - unsigned int next_texture[aiTextureType_UNKNOWN+1]; - - // original file data - const FileDatabase& db; - }; -#ifdef _MSC_VER -# pragma warning(default:4351) -#endif - -// ------------------------------------------------------------------------------------------------ -inline const char* GetTextureTypeDisplayString(Tex::Type t) -{ - switch (t) { - case Tex::Type_CLOUDS : return "Clouds"; - case Tex::Type_WOOD : return "Wood"; - case Tex::Type_MARBLE : return "Marble"; - case Tex::Type_MAGIC : return "Magic"; - case Tex::Type_BLEND : return "Blend"; - case Tex::Type_STUCCI : return "Stucci"; - case Tex::Type_NOISE : return "Noise"; - case Tex::Type_PLUGIN : return "Plugin"; - case Tex::Type_MUSGRAVE : return "Musgrave"; - case Tex::Type_VORONOI : return "Voronoi"; - case Tex::Type_DISTNOISE : return "DistortedNoise"; - case Tex::Type_ENVMAP : return "EnvMap"; - case Tex::Type_IMAGE : return "Image"; - default: - break; - } - return "<Unknown>"; -} - -} // ! Blender -} // ! Assimp - -#endif // ! INCLUDED_AI_BLEND_INTERMEDIATE_H diff --git a/3rdparty/assimp/code/BlenderLoader.cpp b/3rdparty/assimp/code/BlenderLoader.cpp deleted file mode 100644 index 3d587b0f..00000000 --- a/3rdparty/assimp/code/BlenderLoader.cpp +++ /dev/null @@ -1,1005 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderLoader.cpp - * @brief Implementation of the Blender3D importer class. - */ -#include "AssimpPCH.h" - -//#define ASSIMP_BUILD_NO_COMPRESSED_BLEND -// Uncomment this to disable support for (gzip)compressed .BLEND files - -#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER - -#include "BlenderIntermediate.h" -#include "BlenderModifier.h" - -#include "StreamReader.h" -#include "TinyFormatter.h" -#include "MemoryIOWrapper.h" - -// zlib is needed for compressed blend files -#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include <zlib.h> -# else -# include "../contrib/zlib/zlib.h" -# endif -#endif - -using namespace Assimp; -using namespace Assimp::Blender; -using namespace Assimp::Formatter; - - -static const aiLoaderDesc blenderDesc = { - "Blender 3D Importer \nhttp://www.blender3d.org", - "Assimp Team", - "", - "", - aiLoaderFlags_SupportBinaryFlavour | aiLoaderFlags_Experimental, - 0, - 0, - 2, - 50 -}; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -BlenderImporter::BlenderImporter() -: modifier_cache(new BlenderModifierShowcase()) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -BlenderImporter::~BlenderImporter() -{ - delete modifier_cache; -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string& extension = GetExtension(pFile); - if (extension == "blend") { - return true; - } - - else if ((!extension.length() || checkSig) && pIOHandler) { - // note: this won't catch compressed files - const char* tokens[] = {"BLENDER"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// List all extensions handled by this loader -void BlenderImporter::GetExtensionList(std::set<std::string>& app) -{ - app.insert("blend"); -} - -// ------------------------------------------------------------------------------------------------ -// Loader registry entry -const aiLoaderDesc& BlenderImporter::GetInfo () const -{ - return blenderDesc; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties for the loader -void BlenderImporter::SetupProperties(const Importer* pImp) -{ - // nothing to be done for the moment -} - -struct free_it -{ - free_it(void* free) : free(free) {} - ~free_it() { - ::free(this->free); - } - - void* free; -}; - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void BlenderImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ -#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND - Bytef* dest = NULL; - free_it free_it_really(dest); -#endif - - FileDatabase file; - boost::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb")); - if (!stream) { - ThrowException("Could not open file for reading"); - } - - char magic[8] = {0}; - stream->Read(magic,7,1); - if (strcmp(magic,"BLENDER")) { - // Check for presence of the gzip header. If yes, assume it is a - // compressed blend file and try uncompressing it, else fail. This is to - // avoid uncompressing random files which our loader might end up with. -#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND - ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?"); -#else - - if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) { - ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either"); - } - - LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file"); - if (magic[2] != 8) { - ThrowException("Unsupported GZIP compression method"); - } - - // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer - stream->Seek(0L,aiOrigin_SET); - boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream)); - - // build a zlib stream - z_stream zstream; - zstream.opaque = Z_NULL; - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.data_type = Z_BINARY; - - // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib - inflateInit2(&zstream, 16+MAX_WBITS); - - zstream.next_in = reinterpret_cast<Bytef*>( reader->GetPtr() ); - zstream.avail_in = reader->GetRemainingSize(); - - size_t total = 0l; - - // and decompress the data .... do 1k chunks in the hope that we won't kill the stack -#define MYBLOCK 1024 - Bytef block[MYBLOCK]; - int ret; - do { - zstream.avail_out = MYBLOCK; - zstream.next_out = block; - ret = inflate(&zstream, Z_NO_FLUSH); - - if (ret != Z_STREAM_END && ret != Z_OK) { - ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file"); - } - const size_t have = MYBLOCK - zstream.avail_out; - total += have; - dest = reinterpret_cast<Bytef*>( realloc(dest,total) ); - memcpy(dest + total - have,block,have); - } - while (ret != Z_STREAM_END); - - // terminate zlib - inflateEnd(&zstream); - - // replace the input stream with a memory stream - stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total)); - - // .. and retry - stream->Read(magic,7,1); - if (strcmp(magic,"BLENDER")) { - ThrowException("Found no BLENDER magic word in decompressed GZIP file"); - } -#endif - } - - file.i64bit = (stream->Read(magic,1,1),magic[0]=='-'); - file.little = (stream->Read(magic,1,1),magic[0]=='v'); - - stream->Read(magic,3,1); - magic[3] = '\0'; - - LogInfo((format(),"Blender version is ",magic[0],".",magic+1, - " (64bit: ",file.i64bit?"true":"false", - ", little endian: ",file.little?"true":"false",")" - )); - - ParseBlendFile(file,stream); - - Scene scene; - ExtractScene(scene,file); - - ConvertBlendFile(pScene,scene,file); -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::ParseBlendFile(FileDatabase& out, boost::shared_ptr<IOStream> stream) -{ - out.reader = boost::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little)); - - DNAParser dna_reader(out); - const DNA* dna = NULL; - - out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks - SectionParser parser(*out.reader.get(),out.i64bit); - - // first parse the file in search for the DNA and insert all other sections into the database - while ((parser.Next(),1)) { - const FileBlockHead& head = parser.GetCurrent(); - - if (head.id == "ENDB") { - break; // only valid end of the file - } - else if (head.id == "DNA1") { - dna_reader.Parse(); - dna = &dna_reader.GetDNA(); - continue; - } - - out.entries.push_back(head); - } - } - if (!dna) { - ThrowException("SDNA not found"); - } - - std::sort(out.entries.begin(),out.entries.end()); -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file) -{ - const FileBlockHead* block = NULL; - std::map<std::string,size_t>::const_iterator it = file.dna.indices.find("Scene"); - if (it == file.dna.indices.end()) { - ThrowException("There is no `Scene` structure record"); - } - - const Structure& ss = file.dna.structures[(*it).second]; - - // we need a scene somewhere to start with. - for_each(const FileBlockHead& bl,file.entries) { - if (bl.id == "SC") { - block = &bl; - break; - } - } - - if (!block) { - ThrowException("There is not a single `Scene` record to load"); - } - - file.reader->SetCurrentPos(block->start); - ss.Convert(out,file); - -#ifndef ASSIMP_BUILD_BLENDER_NO_STATS - DefaultLogger::get()->info((format(), - "(Stats) Fields read: " ,file.stats().fields_read, - ", pointers resolved: " ,file.stats().pointers_resolved, - ", cache hits: " ,file.stats().cache_hits, - ", cached objects: " ,file.stats().cached_objects - )); -#endif -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file) -{ - ConversionData conv(file); - - // FIXME it must be possible to take the hierarchy directly from - // the file. This is terrible. Here, we're first looking for - // all objects which don't have parent objects at all - - std::deque<const Object*> no_parents; - for (boost::shared_ptr<Base> cur = boost::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) { - if (cur->object) { - if (!cur->object->parent) { - no_parents.push_back(cur->object.get()); - } - else conv.objects.insert(cur->object.get()); - } - } - for (boost::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) { - if (cur->object) { - if (cur->object->parent) { - conv.objects.insert(cur->object.get()); - } - } - } - - if (no_parents.empty()) { - ThrowException("Expected at least one object with no parent"); - } - - aiNode* root = out->mRootNode = new aiNode("<BlenderRoot>"); - - root->mNumChildren = static_cast<unsigned int>(no_parents.size()); - root->mChildren = new aiNode*[root->mNumChildren](); - for (unsigned int i = 0; i < root->mNumChildren; ++i) { - root->mChildren[i] = ConvertNode(in, no_parents[i], conv); - root->mChildren[i]->mParent = root; - } - - BuildMaterials(conv); - - if (conv.meshes->size()) { - out->mMeshes = new aiMesh*[out->mNumMeshes = static_cast<unsigned int>( conv.meshes->size() )]; - std::copy(conv.meshes->begin(),conv.meshes->end(),out->mMeshes); - conv.meshes.dismiss(); - } - - if (conv.lights->size()) { - out->mLights = new aiLight*[out->mNumLights = static_cast<unsigned int>( conv.lights->size() )]; - std::copy(conv.lights->begin(),conv.lights->end(),out->mLights); - conv.lights.dismiss(); - } - - if (conv.cameras->size()) { - out->mCameras = new aiCamera*[out->mNumCameras = static_cast<unsigned int>( conv.cameras->size() )]; - std::copy(conv.cameras->begin(),conv.cameras->end(),out->mCameras); - conv.cameras.dismiss(); - } - - if (conv.materials->size()) { - out->mMaterials = new aiMaterial*[out->mNumMaterials = static_cast<unsigned int>( conv.materials->size() )]; - std::copy(conv.materials->begin(),conv.materials->end(),out->mMaterials); - conv.materials.dismiss(); - } - - if (conv.textures->size()) { - out->mTextures = new aiTexture*[out->mNumTextures = static_cast<unsigned int>( conv.textures->size() )]; - std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures); - conv.textures.dismiss(); - } - - // acknowledge that the scene might come out incomplete - // by Assimps definition of `complete`: blender scenes - // can consist of thousands of cameras or lights with - // not a single mesh between them. - if (!out->mNumMeshes) { - out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::ResolveImage(MaterialHelper* out, const Material* mat, const MTex* tex, const Image* img, ConversionData& conv_data) -{ - mat; tex; conv_data; - aiString name; - - // check if the file contents are bundled with the BLEND file - if (img->packedfile) { - name.data[0] = '*'; - name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size()); - - conv_data.textures->push_back(new aiTexture()); - aiTexture* tex = conv_data.textures->back(); - - // usually 'img->name' will be the original file name of the embedded textures, - // so we can extract the file extension from it. - const size_t nlen = strlen( img->name ); - const char* s = img->name+nlen, *e = s; - - while (s >= img->name && *s != '.')--s; - - tex->achFormatHint[0] = s+1>e ? '\0' : s[1]; - tex->achFormatHint[1] = s+2>e ? '\0' : s[2]; - tex->achFormatHint[2] = s+3>e ? '\0' : s[3]; - tex->achFormatHint[3] = '\0'; - - // tex->mHeight = 0; - tex->mWidth = img->packedfile->size; - uint8_t* ch = new uint8_t[tex->mWidth]; - - conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val)); - conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth); - - tex->pcData = reinterpret_cast<aiTexel*>(ch); - - LogInfo("Reading embedded texture, original file was "+std::string(img->name)); - } - else { - name = aiString( img->name ); - } - out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE( - conv_data.next_texture[aiTextureType_DIFFUSE]++) - ); -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::AddSentinelTexture(MaterialHelper* out, const Material* mat, const MTex* tex, ConversionData& conv_data) -{ - mat; tex; conv_data; - - aiString name; - name.length = sprintf(name.data, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++, - GetTextureTypeDisplayString(tex->tex->type) - ); - out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE( - conv_data.next_texture[aiTextureType_DIFFUSE]++) - ); -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::ResolveTexture(MaterialHelper* out, const Material* mat, const MTex* tex, ConversionData& conv_data) -{ - const Tex* rtex = tex->tex.get(); - if (!rtex || !rtex->type) { - return; - } - - // We can't support most of the texture types because the're mostly procedural. - // These are substituted by a dummy texture. - const char* dispnam = ""; - switch( rtex->type ) - { - // these are listed in blender's UI - case Tex::Type_CLOUDS : - case Tex::Type_WOOD : - case Tex::Type_MARBLE : - case Tex::Type_MAGIC : - case Tex::Type_BLEND : - case Tex::Type_STUCCI : - case Tex::Type_NOISE : - case Tex::Type_PLUGIN : - case Tex::Type_MUSGRAVE : - case Tex::Type_VORONOI : - case Tex::Type_DISTNOISE : - case Tex::Type_ENVMAP : - - // these do no appear in the UI, why? - case Tex::Type_POINTDENSITY : - case Tex::Type_VOXELDATA : - - LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam); - AddSentinelTexture(out, mat, tex, conv_data); - break; - - case Tex::Type_IMAGE : - if (!rtex->ima) { - LogError("A texture claims to be an Image, but no image reference is given"); - break; - } - ResolveImage(out, mat, tex, rtex->ima.get(),conv_data); - break; - - default: - ai_assert(false); - }; -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::BuildMaterials(ConversionData& conv_data) -{ - conv_data.materials->reserve(conv_data.materials_raw.size()); - - // add a default material if necessary - unsigned int index = static_cast<unsigned int>( -1 ); - for_each( aiMesh* mesh, conv_data.meshes.get() ) { - if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) { - - if (index == static_cast<unsigned int>( -1 )) { - - // ok, we need to add a dedicated default material for some poor material-less meshes - boost::shared_ptr<Material> p(new Material()); - strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME ); - - p->r = p->g = p->b = 0.6f; - p->specr = p->specg = p->specb = 0.6f; - p->ambir = p->ambig = p->ambib = 0.0f; - p->mirr = p->mirg = p->mirb = 0.0f; - p->emit = 0.f; - p->alpha = 0.f; - - // XXX add more / or add default c'tor to Material - - index = static_cast<unsigned int>( conv_data.materials_raw.size() ); - conv_data.materials_raw.push_back(p); - - LogInfo("Adding default material ..."); - } - mesh->mMaterialIndex = index; - } - } - - for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) { - - // reset per material global counters - for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) { - conv_data.next_texture[i] = 0 ; - } - - MaterialHelper* mout = new MaterialHelper(); - conv_data.materials->push_back(mout); - - // set material name - aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA' - mout->AddProperty(&name,AI_MATKEY_NAME); - - - // basic material colors - aiColor3D col(mat->r,mat->g,mat->b); - if (mat->r || mat->g || mat->b ) { - - // Usually, zero diffuse color means no diffuse color at all in the equation - seemingly. - // So we ommit this member to express this intent. - mout->AddProperty(&col,1,AI_MATKEY_COLOR_DIFFUSE); - } - - col = aiColor3D(mat->specr,mat->specg,mat->specb); - mout->AddProperty(&col,1,AI_MATKEY_COLOR_SPECULAR); - - col = aiColor3D(mat->ambir,mat->ambig,mat->ambib); - mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT); - - col = aiColor3D(mat->mirr,mat->mirg,mat->mirb); - mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE); - - for (size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) { - if (!mat->mtex[i]) { - continue; - } - - ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::CheckActualType(const ElemBase* dt, const char* check) -{ - ai_assert(dt); - if (strcmp(dt->dna_type,check)) { - ThrowException((format(), - "Expected object at ",std::hex,dt," to be of type `",check, - "`, but it claims to be a `",dt->dna_type,"`instead" - )); - } -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::NotSupportedObjectType(const Object* obj, const char* type) -{ - LogWarn((format(), "Object `",obj->id.name,"` - type is unsupported: `",type, "`, skipping" )); -} - -// ------------------------------------------------------------------------------------------------ -void BlenderImporter::ConvertMesh(const Scene& in, const Object* obj, const Mesh* mesh, - ConversionData& conv_data, TempArray<std::vector,aiMesh>& temp - ) -{ - typedef std::pair<const int,size_t> MyPair; - if (!mesh->totface || !mesh->totvert) { - return; - } - - // some sanity checks - if (static_cast<size_t> ( mesh->totface ) > mesh->mface.size() ){ - ThrowException("Number of faces is larger than the corresponding array"); - } - - if (static_cast<size_t> ( mesh->totvert ) > mesh->mvert.size()) { - ThrowException("Number of vertices is larger than the corresponding array"); - } - - // collect per-submesh numbers - std::map<int,size_t> per_mat; - for (int i = 0; i < mesh->totface; ++i) { - - const MFace& mf = mesh->mface[i]; - per_mat[ mf.mat_nr ]++; - } - - // ... and allocate the corresponding meshes - const size_t old = temp->size(); - temp->reserve(temp->size() + per_mat.size()); - - std::map<size_t,size_t> mat_num_to_mesh_idx; - for_each(MyPair& it, per_mat) { - - mat_num_to_mesh_idx[it.first] = temp->size(); - temp->push_back(new aiMesh()); - - aiMesh* out = temp->back(); - out->mVertices = new aiVector3D[it.second*4]; - out->mNormals = new aiVector3D[it.second*4]; - - //out->mNumFaces = 0 - //out->mNumVertices = 0 - out->mFaces = new aiFace[it.second](); - - // all submeshes created from this mesh are named equally. this allows - // curious users to recover the original adjacency. - out->mName = aiString(mesh->id.name+2); - // skip over the name prefix 'ME' - - // resolve the material reference and add this material to the set of - // output materials. The (temporary) material index is the index - // of the material entry within the list of resolved materials. - if (mesh->mat) { - - if (static_cast<size_t> ( it.first ) >= mesh->mat.size() ) { - ThrowException("Material index is out of range"); - } - - boost::shared_ptr<Material> mat = mesh->mat[it.first]; - const std::deque< boost::shared_ptr<Material> >::iterator has = std::find( - conv_data.materials_raw.begin(), - conv_data.materials_raw.end(),mat - ); - - if (has != conv_data.materials_raw.end()) { - out->mMaterialIndex = static_cast<unsigned int>( std::distance(conv_data.materials_raw.begin(),has)); - } - else { - out->mMaterialIndex = static_cast<unsigned int>( conv_data.materials_raw.size() ); - conv_data.materials_raw.push_back(mat); - } - } - else out->mMaterialIndex = static_cast<unsigned int>( -1 ); - } - - for (int i = 0; i < mesh->totface; ++i) { - - const MFace& mf = mesh->mface[i]; - - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ]; - aiFace& f = out->mFaces[out->mNumFaces++]; - - f.mIndices = new unsigned int[ f.mNumIndices = mf.v4?4:3 ]; - aiVector3D* vo = out->mVertices + out->mNumVertices; - aiVector3D* vn = out->mNormals + out->mNumVertices; - - // XXX we can't fold this easily, because we are restricted - // to the member names from the BLEND file (v1,v2,v3,v4) - // which are assigned by the genblenddna.py script and - // cannot be changed without breaking the entire - // import process. - - if (mf.v1 >= mesh->totvert) { - ThrowException("Vertex index v1 out of range"); - } - const MVert* v = &mesh->mvert[mf.v1]; - vo->x = v->co[0]; - vo->y = v->co[1]; - vo->z = v->co[2]; - vn->x = v->no[0]; - vn->y = v->no[1]; - vn->z = v->no[2]; - f.mIndices[0] = out->mNumVertices++; - ++vo; - ++vn; - - // if (f.mNumIndices >= 2) { - if (mf.v2 >= mesh->totvert) { - ThrowException("Vertex index v2 out of range"); - } - v = &mesh->mvert[mf.v2]; - vo->x = v->co[0]; - vo->y = v->co[1]; - vo->z = v->co[2]; - vn->x = v->no[0]; - vn->y = v->no[1]; - vn->z = v->no[2]; - f.mIndices[1] = out->mNumVertices++; - ++vo; - ++vn; - - if (mf.v3 >= mesh->totvert) { - ThrowException("Vertex index v3 out of range"); - } - // if (f.mNumIndices >= 3) { - v = &mesh->mvert[mf.v3]; - vo->x = v->co[0]; - vo->y = v->co[1]; - vo->z = v->co[2]; - vn->x = v->no[0]; - vn->y = v->no[1]; - vn->z = v->no[2]; - f.mIndices[2] = out->mNumVertices++; - ++vo; - ++vn; - - if (mf.v4 >= mesh->totvert) { - ThrowException("Vertex index v4 out of range"); - } - // if (f.mNumIndices >= 4) { - if (mf.v4) { - v = &mesh->mvert[mf.v4]; - vo->x = v->co[0]; - vo->y = v->co[1]; - vo->z = v->co[2]; - vn->x = v->no[0]; - vn->y = v->no[1]; - vn->z = v->no[2]; - f.mIndices[3] = out->mNumVertices++; - ++vo; - ++vn; - - out->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - } - else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - - // } - // } - // } - } - - // collect texture coordinates, they're stored in a separate per-face buffer - if (mesh->mtface) { - if (mesh->totface > static_cast<int> ( mesh->mtface.size())) { - ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)"); - } - for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) { - ai_assert((*it)->mNumVertices && (*it)->mNumFaces); - - (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; - (*it)->mNumFaces = (*it)->mNumVertices = 0; - } - - for (int i = 0; i < mesh->totface; ++i) { - const MTFace* v = &mesh->mtface[i]; - - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; - - aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; - for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) { - vo->x = v->uv[i][0]; - vo->y = v->uv[i][1]; - } - } - } - - // collect texture coordinates, old-style (marked as deprecated in current blender sources) - if (mesh->tface) { - if (mesh->totface > static_cast<int> ( mesh->mtface.size())) { - ThrowException("Number of faces is larger than the corresponding UV face array (#2)"); - } - for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) { - ai_assert((*it)->mNumVertices && (*it)->mNumFaces); - - (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices]; - (*it)->mNumFaces = (*it)->mNumVertices = 0; - } - - for (int i = 0; i < mesh->totface; ++i) { - const TFace* v = &mesh->tface[i]; - - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; - - aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices]; - for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) { - vo->x = v->uv[i][0]; - vo->y = v->uv[i][1]; - } - } - } - - // collect vertex colors, stored separately as well - if (mesh->mcol) { - if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) { - ThrowException("Number of faces is larger than the corresponding color face array"); - } - for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) { - ai_assert((*it)->mNumVertices && (*it)->mNumFaces); - - (*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices]; - (*it)->mNumFaces = (*it)->mNumVertices = 0; - } - - for (int i = 0; i < mesh->totface; ++i) { - - aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ]; - const aiFace& f = out->mFaces[out->mNumFaces++]; - - aiColor4D* vo = &out->mColors[0][out->mNumVertices]; - for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo,++out->mNumVertices) { - const MCol* col = &mesh->mcol[(i<<2)+n]; - - vo->r = col->r; - vo->g = col->g; - vo->b = col->b; - vo->a = col->a; - } - for (unsigned int n = f.mNumIndices; n < 4; ++n); - } - } - - return; -} - -// ------------------------------------------------------------------------------------------------ -aiCamera* BlenderImporter::ConvertCamera(const Scene& in, const Object* obj, const Camera* mesh, ConversionData& conv_data) -{ - ScopeGuard<aiCamera> out(new aiCamera()); - - return NULL ; //out.dismiss(); -} - -// ------------------------------------------------------------------------------------------------ -aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* mesh, ConversionData& conv_data) -{ - ScopeGuard<aiLight> out(new aiLight()); - - return NULL ; //out.dismiss(); -} - -// ------------------------------------------------------------------------------------------------ -aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data) -{ - std::deque<const Object*> children; - for (std::set<const Object*>::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) { - const Object* object = *it; - if (object->parent.get() == obj) { - children.push_back(object); - - conv_data.objects.erase(it++); - continue; - } - ++it; - } - - ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB' - if (obj->data) { - switch (obj->type) - { - case Object :: Type_EMPTY: - break; // do nothing - - - // supported object types - case Object :: Type_MESH: { - const size_t old = conv_data.meshes->size(); - - CheckActualType(obj->data.get(),"Mesh"); - ConvertMesh(in,obj,static_cast<const Mesh*>(obj->data.get()),conv_data,conv_data.meshes); - - if (conv_data.meshes->size() > old) { - node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)]; - for (unsigned int i = 0; i < node->mNumMeshes; ++i) { - node->mMeshes[i] = i + old; - } - }} - break; - case Object :: Type_LAMP: { - CheckActualType(obj->data.get(),"Lamp"); - aiLight* mesh = ConvertLight(in,obj,static_cast<const Lamp*>( - obj->data.get()),conv_data); - - if (mesh) { - conv_data.lights->push_back(mesh); - }} - break; - case Object :: Type_CAMERA: { - CheckActualType(obj->data.get(),"Camera"); - aiCamera* mesh = ConvertCamera(in,obj,static_cast<const Camera*>( - obj->data.get()),conv_data); - - if (mesh) { - conv_data.cameras->push_back(mesh); - }} - break; - - - // unsupported object types / log, but do not break - case Object :: Type_CURVE: - NotSupportedObjectType(obj,"Curve"); - break; - case Object :: Type_SURF: - NotSupportedObjectType(obj,"Surface"); - break; - case Object :: Type_FONT: - NotSupportedObjectType(obj,"Font"); - break; - case Object :: Type_MBALL: - NotSupportedObjectType(obj,"MetaBall"); - break; - case Object :: Type_WAVE: - NotSupportedObjectType(obj,"Wave"); - break; - case Object :: Type_LATTICE: - NotSupportedObjectType(obj,"Lattice"); - break; - - // invalid or unknown type - default: - break; - } - } - - for (unsigned int x = 0; x < 4; ++x) { - for (unsigned int y = 0; y < 4; ++y) { - node->mTransformation[y][x] = obj->parentinv[x][y]; - } - } - - aiMatrix4x4 m; - for (unsigned int x = 0; x < 4; ++x) { - for (unsigned int y = 0; y < 4; ++y) { - m[y][x] = obj->obmat[x][y]; - } - } - - node->mTransformation = m*node->mTransformation; - - if (children.size()) { - node->mNumChildren = static_cast<unsigned int>(children.size()); - aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren](); - for_each (const Object* nobj,children) { - *nd = ConvertNode(in,nobj,conv_data); - (*nd++)->mParent = node; - } - } - - // apply modifiers - modifier_cache->ApplyModifiers(*node,conv_data,in,*obj); - - return node.dismiss(); -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ void BlenderImporter::ThrowException(const std::string& msg) -{ - throw DeadlyImportError("BLEND: "+msg); -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ void BlenderImporter::LogWarn(const Formatter::format& message) { - DefaultLogger::get()->warn(std::string("BLEND: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ void BlenderImporter::LogError(const Formatter::format& message) { - DefaultLogger::get()->error(std::string("BLEND: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ void BlenderImporter::LogInfo(const Formatter::format& message) { - DefaultLogger::get()->info(std::string("BLEND: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ void BlenderImporter::LogDebug(const Formatter::format& message) { - DefaultLogger::get()->debug(std::string("BLEND: ")+=message); -} - -#endif diff --git a/3rdparty/assimp/code/BlenderLoader.h b/3rdparty/assimp/code/BlenderLoader.h deleted file mode 100644 index ee95de83..00000000 --- a/3rdparty/assimp/code/BlenderLoader.h +++ /dev/null @@ -1,261 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderLoader.h - * @brief Declaration of the Blender 3D (*.blend) importer class. - */ -#ifndef INCLUDED_AI_BLEND_LOADER_H -#define INCLUDED_AI_BLEND_LOADER_H - -#include "BaseImporter.h" -namespace Assimp { - - // TinyFormatter.h - namespace Formatter { - template <typename T,typename TR, typename A> class basic_formatter; - typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format; - } - - // BlenderDNA.h - namespace Blender { - class FileDatabase; - struct ElemBase; - } - - // BlenderScene.h - namespace Blender { - struct Scene; - struct Object; - struct Mesh; - struct Camera; - struct Lamp; - struct MTex; - struct Image; - struct Material; - } - - // BlenderIntermediate.h - namespace Blender { - struct ConversionData; - template <template <typename,typename> class TCLASS, typename T> struct TempArray; - } - - // BlenderModifier.h - namespace Blender { - class BlenderModifierShowcase; - class BlenderModifier; - } - -enum aiLoaderFlags -{ - aiLoaderFlags_SupportAsciiFlavour = 0x1, - aiLoaderFlags_SupportBinaryFlavour = 0x2, - aiLoaderFlags_SupportCompressedFlavour = 0x4, - - aiLoaderFlags_LimitedSupport = 0x8, - - aiLoaderFlags_Experimental = 0x10, - aiLoaderFlags_Testing = 0x20, - aiLoaderFlags_Production = 0x40, -}; - -struct aiLoaderDesc -{ - const char* mName; - const char* mAuthor; - const char* mMaintainer; - const char* mComments; - unsigned int mFlags; - - unsigned int mMinMajor; - unsigned int mMinMinor; - unsigned int mMaxMajor; - unsigned int mMaxMinor; -}; - - -// ------------------------------------------------------------------------------------------- -/** Load blenders official binary format. The actual file structure (the `DNA` how they - * call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the - * conversion from intermediate format to aiScene. */ -// ------------------------------------------------------------------------------------------- -class BlenderImporter : public BaseImporter -{ - friend class Importer; - -protected: - - /** Constructor to be privately used by Importer */ - BlenderImporter(); - - /** Destructor, private as well */ - ~BlenderImporter(); - -public: - - // -------------------- - bool CanRead( const std::string& pFile, - IOSystem* pIOHandler, - bool checkSig - ) const; - -protected: - - // -------------------- - const aiLoaderDesc& GetInfo () const; - - // -------------------- - void GetExtensionList(std::set<std::string>& app); - - // -------------------- - void SetupProperties(const Importer* pImp); - - // -------------------- - void InternReadFile( const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler - ); - - // -------------------- - void ParseBlendFile(Blender::FileDatabase& out, - boost::shared_ptr<IOStream> stream - ); - - // -------------------- - void ExtractScene(Blender::Scene& out, - const Blender::FileDatabase& file - ); - - // -------------------- - void ConvertBlendFile(aiScene* out, - const Blender::Scene& in, - const Blender::FileDatabase& file - ); - -private: - - // -------------------- - aiNode* ConvertNode(const Blender::Scene& in, - const Blender::Object* obj, - Blender::ConversionData& conv_info - ); - - // -------------------- - void ConvertMesh(const Blender::Scene& in, - const Blender::Object* obj, - const Blender::Mesh* mesh, - Blender::ConversionData& conv_data, - Blender::TempArray<std::vector,aiMesh>& temp - ); - - // -------------------- - aiLight* ConvertLight(const Blender::Scene& in, - const Blender::Object* obj, - const Blender::Lamp* mesh, - Blender::ConversionData& conv_data - ); - - // -------------------- - aiCamera* ConvertCamera(const Blender::Scene& in, - const Blender::Object* obj, - const Blender::Camera* mesh, - Blender::ConversionData& conv_data - ); - - // -------------------- - void BuildMaterials( - Blender::ConversionData& conv_data - ) ; - - // -------------------- - void ResolveTexture( - MaterialHelper* out, - const Blender::Material* mat, - const Blender::MTex* tex, - Blender::ConversionData& conv_data - ); - - // -------------------- - void ResolveImage( - MaterialHelper* out, - const Blender::Material* mat, - const Blender::MTex* tex, - const Blender::Image* img, - Blender::ConversionData& conv_data - ); - - void AddSentinelTexture( - MaterialHelper* out, - const Blender::Material* mat, - const Blender::MTex* tex, - Blender::ConversionData& conv_data - ); - -private: // static stuff, mostly logging and error reporting. - - // -------------------- - static void CheckActualType(const Blender::ElemBase* dt, - const char* check - ); - - // -------------------- - static void NotSupportedObjectType(const Blender::Object* obj, - const char* type - ); - - // ------------------------------------------------------------------- - /** Prepend 'BLEND: ' and throw msg.*/ - static void ThrowException(const std::string& msg); - - // ------------------------------------------------------------------- - /** @defgroup blog Prepend 'BLEND: ' and write @c message to log.*/ - static void LogWarn (const Formatter::format& message); //! @ingroup blog - static void LogError (const Formatter::format& message); //! @ingroup blog - static void LogInfo (const Formatter::format& message); //! @ingroup blog - static void LogDebug (const Formatter::format& message); //! @ingroup blog - -private: - - Blender::BlenderModifierShowcase* modifier_cache; - -}; // !class BlenderImporter - -} // end of namespace Assimp -#endif // AI_UNREALIMPORTER_H_INC diff --git a/3rdparty/assimp/code/BlenderModifier.cpp b/3rdparty/assimp/code/BlenderModifier.cpp deleted file mode 100644 index 64711346..00000000 --- a/3rdparty/assimp/code/BlenderModifier.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderModifier.cpp - * @brief Implementation of some blender modifiers (i.e subdivision, mirror). - */ -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER -#include "BlenderModifier.h" -#include "SceneCombiner.h" -#include "Subdivision.h" - -using namespace Assimp; -using namespace Assimp::Blender; - -template <typename T> BlenderModifier* god() { - return new T(); -} - -// add all available modifiers here -typedef BlenderModifier* (*fpCreateModifier)(); -static const fpCreateModifier creators[] = { - &god<BlenderModifier_Mirror>, - &god<BlenderModifier_Subdivision>, - - NULL // sentinel -}; - -// ------------------------------------------------------------------------------------------------ -// just testing out some new macros to simplify logging -#define ASSIMP_LOG_WARN_F(string,...)\ - DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__)) - -#define ASSIMP_LOG_ERROR_F(string,...)\ - DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__)) - -#define ASSIMP_LOG_DEBUG_F(string,...)\ - DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__)) - -#define ASSIMP_LOG_INFO_F(string,...)\ - DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__)) - - -#define ASSIMP_LOG_WARN(string)\ - DefaultLogger::get()->warn(string) - -#define ASSIMP_LOG_ERROR(string)\ - DefaultLogger::get()->error(string) - -#define ASSIMP_LOG_DEBUG(string)\ - DefaultLogger::get()->debug(string) - -#define ASSIMP_LOG_INFO(string)\ - DefaultLogger::get()->info(string) - - -// ------------------------------------------------------------------------------------------------ -struct SharedModifierData : ElemBase -{ - ModifierData modifier; -}; - -// ------------------------------------------------------------------------------------------------ -void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object ) -{ - size_t cnt = 0u, ful = 0u; - - // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before - // we're allowed to dereference the pointers without risking to crash. We might still be - // invoking UB btw - we're assuming that the ModifierData member of the respective modifier - // structures is at offset sizeof(vftable) with no padding. - const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() ); - for (; cur; cur = boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) { - ai_assert(cur->dna_type); - - const Structure* s = conv_data.db.dna.Get( cur->dna_type ); - if (!s) { - ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type); - continue; - } - - // this is a common trait of all XXXMirrorData structures in BlenderDNA - const Field* f = s->Get("modifier"); - if (!f || f->offset != 0) { - ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0"); - continue; - } - - s = conv_data.db.dna.Get( f->type ); - if (!s || s->name != "ModifierData") { - ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member"); - continue; - } - - // now, we can be sure that we should be fine to dereference *cur* as - // ModifierData (with the above note). - const ModifierData& dat = cur->modifier; - - const fpCreateModifier* curgod = creators; - std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end(); - - for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly - if (curmod == endmod) { - cached_modifiers->push_back((*curgod)()); - - endmod = cached_modifiers->end(); - curmod = endmod-1; - } - - BlenderModifier* const modifier = *curmod; - if (modifier->IsActive(dat)) { - modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object); - cnt++; - - curgod = NULL; - break; - } - } - if (curgod) { - ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name); - } - } - - // Even though we managed to resolve some or all of the modifiers on this - // object, we still can't say whether our modifier implementations were - // able to fully do their job. - if (ful) { - ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name, - "`, check log messages above for errors"); - } -} - - - -// ------------------------------------------------------------------------------------------------ -bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin) -{ - return modin.type == ModifierData::eModifierType_Mirror; -} - -// ------------------------------------------------------------------------------------------------ -void BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, - const Scene& in, - const Object& orig_object ) -{ - // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() - const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier); - ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror); - - // XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ... - - // take all input meshes and clone them - for (unsigned int i = 0; i < out.mNumMeshes; ++i) { - aiMesh* mesh; - SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]); - - const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f; - const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f; - const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f; - - if (mir.mirror_ob) { - const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] ); - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mVertices[i]; - - v.x = center.x + xs*(center.x - v.x); - v.y = center.y + ys*(center.y - v.y); - v.z = center.z + zs*(center.z - v.z); - } - } - else { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mVertices[i]; - v.x *= xs;v.y *= ys;v.z *= zs; - } - } - - if (mesh->mNormals) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mNormals[i]; - v.x *= xs;v.y *= ys;v.z *= zs; - } - } - - if (mesh->mTangents) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mTangents[i]; - v.x *= xs;v.y *= ys;v.z *= zs; - } - } - - if (mesh->mBitangents) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mBitangents[i]; - v.x *= xs;v.y *= ys;v.z *= zs; - } - } - - const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f; - const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f; - - for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - aiVector3D& v = mesh->mTextureCoords[n][i]; - v.x *= us;v.y *= vs; - } - } - - conv_data.meshes->push_back(mesh); - } - unsigned int* nind = new unsigned int[out.mNumMeshes*2]; - - std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind); - std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes, - std::bind1st(std::plus< unsigned int >(),out.mNumMeshes)); - - delete[] out.mMeshes; - out.mMeshes = nind; - out.mNumMeshes *= 2; - - ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", - orig_object.id.name,"`"); -} - - - - -// ------------------------------------------------------------------------------------------------ -bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin) -{ - return modin.type == ModifierData::eModifierType_Subsurf; -} - -// ------------------------------------------------------------------------------------------------ -void BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data, const ElemBase& orig_modifier, - const Scene& in, - const Object& orig_object ) -{ - // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers() - const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier); - ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf); - - Subdivider::Algorithm algo; - switch (mir.subdivType) - { - case SubsurfModifierData::TYPE_CatmullClarke: - algo = Subdivider::CATMULL_CLARKE; - break; - - case SubsurfModifierData::TYPE_Simple: - ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke"); - algo = Subdivider::CATMULL_CLARKE; - break; - - default: - ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType); - return; - }; - - boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo)); - ai_assert(subd); - - aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes]; - boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]()); - - subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true); - std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes); - - ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", - orig_object.id.name,"`"); -} - -#endif diff --git a/3rdparty/assimp/code/BlenderModifier.h b/3rdparty/assimp/code/BlenderModifier.h deleted file mode 100644 index c5e6bd43..00000000 --- a/3rdparty/assimp/code/BlenderModifier.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderModifier.h - * @brief Declare dedicated helper classes to simulate some blender modifiers (i.e. mirror) - */ -#ifndef INCLUDED_AI_BLEND_MODIFIER_H -#define INCLUDED_AI_BLEND_MODIFIER_H - -#include "BlenderIntermediate.h" -#include "TinyFormatter.h" -namespace Assimp { - namespace Blender { - -// ------------------------------------------------------------------------------------------- -/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so - * they should be stateless and not try to cache model data. */ -// ------------------------------------------------------------------------------------------- -class BlenderModifier -{ -public: - - virtual ~BlenderModifier() { - } - -public: - - // -------------------- - /** Check if *this* modifier is active, given a ModifierData& block.*/ - virtual bool IsActive( const ModifierData& modin) { - return false; - } - - // -------------------- - /** Apply the modifier to a given output node. The original data used - * to construct the node is given as well. Not called unless IsActive() - * was called and gave positive response. */ - virtual void DoIt(aiNode& out, - ConversionData& conv_data, - const ElemBase& orig_modifier, - const Scene& in, - const Object& orig_object - ) { - DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type)); - return; - } -}; - - -// ------------------------------------------------------------------------------------------- -/** Manage all known modifiers and instance and apply them if necessary */ -// ------------------------------------------------------------------------------------------- -class BlenderModifierShowcase -{ -public: - - // -------------------- - /** Apply all requested modifiers provided we support them. */ - void ApplyModifiers(aiNode& out, - ConversionData& conv_data, - const Scene& in, - const Object& orig_object - ); - -private: - - TempArray< std::vector,BlenderModifier > cached_modifiers; -}; - - - - - -// MODIFIERS - - - -// ------------------------------------------------------------------------------------------- -/** Mirror modifier. Status: implemented. */ -// ------------------------------------------------------------------------------------------- -class BlenderModifier_Mirror : public BlenderModifier -{ -public: - - // -------------------- - virtual bool IsActive( const ModifierData& modin); - - // -------------------- - virtual void DoIt(aiNode& out, - ConversionData& conv_data, - const ElemBase& orig_modifier, - const Scene& in, - const Object& orig_object - ) ; -}; - -// ------------------------------------------------------------------------------------------- -/** Subdivision modifier. Status: dummy. */ -// ------------------------------------------------------------------------------------------- -class BlenderModifier_Subdivision : public BlenderModifier -{ -public: - - // -------------------- - virtual bool IsActive( const ModifierData& modin); - - // -------------------- - virtual void DoIt(aiNode& out, - ConversionData& conv_data, - const ElemBase& orig_modifier, - const Scene& in, - const Object& orig_object - ) ; -}; - - -}} -#endif // !INCLUDED_AI_BLEND_MODIFIER_H diff --git a/3rdparty/assimp/code/BlenderScene.cpp b/3rdparty/assimp/code/BlenderScene.cpp deleted file mode 100644 index f8d13e17..00000000 --- a/3rdparty/assimp/code/BlenderScene.cpp +++ /dev/null @@ -1,596 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderScene.cpp - * @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py - */ -#include "AssimpPCH.h" -#ifndef AI_BUILD_NO_BLEND_IMPORTER - -#include "BlenderDNA.h" -#include "BlenderScene.h" -#include "BlenderSceneGen.h" - -using namespace Assimp; -using namespace Assimp::Blender; - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Object> ( - Object& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db); - ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db); - ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db); - ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.track,"*track",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy,"*proxy",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_from,"*proxy_from",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.proxy_group,"*proxy_group",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.dup_group,"*dup_group",db); - ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db); - ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Group> ( - Group& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MTex> ( - MTex& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db); - ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db); - ReadField<ErrorPolicy_Igno>((int&)dest.projx,"projx",db); - ReadField<ErrorPolicy_Igno>((int&)dest.projy,"projy",db); - ReadField<ErrorPolicy_Igno>((int&)dest.projz,"projz",db); - ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db); - ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db); - ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db); - ReadField<ErrorPolicy_Igno>(dest.rot,"rot",db); - ReadField<ErrorPolicy_Igno>(dest.texflag,"texflag",db); - ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db); - ReadField<ErrorPolicy_Igno>(dest.pmapto,"pmapto",db); - ReadField<ErrorPolicy_Igno>(dest.pmaptoneg,"pmaptoneg",db); - ReadField<ErrorPolicy_Warn>(dest.r,"r",db); - ReadField<ErrorPolicy_Warn>(dest.g,"g",db); - ReadField<ErrorPolicy_Warn>(dest.b,"b",db); - ReadField<ErrorPolicy_Warn>(dest.k,"k",db); - ReadField<ErrorPolicy_Igno>(dest.colspecfac,"colspecfac",db); - ReadField<ErrorPolicy_Igno>(dest.mirrfac,"mirrfac",db); - ReadField<ErrorPolicy_Igno>(dest.alphafac,"alphafac",db); - ReadField<ErrorPolicy_Igno>(dest.difffac,"difffac",db); - ReadField<ErrorPolicy_Igno>(dest.specfac,"specfac",db); - ReadField<ErrorPolicy_Igno>(dest.emitfac,"emitfac",db); - ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<TFace> ( - TFace& dest, - const FileDatabase& db - ) const -{ - - ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db); - ReadFieldArray<ErrorPolicy_Fail>(dest.col,"col",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db); - ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db); - ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<SubsurfModifierData> ( - SubsurfModifierData& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db); - ReadField<ErrorPolicy_Igno>(dest.subdivType,"subdivType",db); - ReadField<ErrorPolicy_Igno>(dest.levels,"levels",db); - ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db); - ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MFace> ( - MFace& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db); - ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db); - ReadField<ErrorPolicy_Fail>(dest.v3,"v3",db); - ReadField<ErrorPolicy_Fail>(dest.v4,"v4",db); - ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Lamp> ( - Lamp& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db); - ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db); - ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db); - ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db); - ReadField<ErrorPolicy_Warn>(dest.r,"r",db); - ReadField<ErrorPolicy_Warn>(dest.g,"g",db); - ReadField<ErrorPolicy_Warn>(dest.b,"b",db); - ReadField<ErrorPolicy_Warn>(dest.k,"k",db); - ReadField<ErrorPolicy_Igno>(dest.energy,"energy",db); - ReadField<ErrorPolicy_Igno>(dest.dist,"dist",db); - ReadField<ErrorPolicy_Igno>(dest.spotsize,"spotsize",db); - ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db); - ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db); - ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db); - ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db); - ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MDeformWeight> ( - MDeformWeight& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db); - ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<PackedFile> ( - PackedFile& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Warn>(dest.size,"size",db); - ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Base> ( - Base& dest, - const FileDatabase& db - ) const -{ - - ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.object,"*object",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MTFace> ( - MTFace& dest, - const FileDatabase& db - ) const -{ - - ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db); - ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db); - ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Material> ( - Material& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadField<ErrorPolicy_Warn>(dest.r,"r",db); - ReadField<ErrorPolicy_Warn>(dest.g,"g",db); - ReadField<ErrorPolicy_Warn>(dest.b,"b",db); - ReadField<ErrorPolicy_Warn>(dest.specr,"specr",db); - ReadField<ErrorPolicy_Warn>(dest.specg,"specg",db); - ReadField<ErrorPolicy_Warn>(dest.specb,"specb",db); - ReadField<ErrorPolicy_Warn>(dest.ambir,"ambir",db); - ReadField<ErrorPolicy_Warn>(dest.ambig,"ambig",db); - ReadField<ErrorPolicy_Warn>(dest.ambib,"ambib",db); - ReadField<ErrorPolicy_Igno>(dest.mirr,"mirr",db); - ReadField<ErrorPolicy_Igno>(dest.mirg,"mirg",db); - ReadField<ErrorPolicy_Igno>(dest.mirb,"mirb",db); - ReadField<ErrorPolicy_Warn>(dest.emit,"emit",db); - ReadField<ErrorPolicy_Warn>(dest.alpha,"alpha",db); - ReadField<ErrorPolicy_Igno>(dest.ref,"ref",db); - ReadField<ErrorPolicy_Igno>(dest.translucency,"translucency",db); - ReadField<ErrorPolicy_Igno>(dest.roughness,"roughness",db); - ReadField<ErrorPolicy_Igno>(dest.darkness,"darkness",db); - ReadField<ErrorPolicy_Igno>(dest.refrac,"refrac",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.group,"*group",db); - ReadField<ErrorPolicy_Warn>(dest.diff_shader,"diff_shader",db); - ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Mesh> ( - Mesh& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db); - ReadField<ErrorPolicy_Fail>(dest.totedge,"totedge",db); - ReadField<ErrorPolicy_Fail>(dest.totvert,"totvert",db); - ReadField<ErrorPolicy_Igno>(dest.subdiv,"subdiv",db); - ReadField<ErrorPolicy_Igno>(dest.subdivr,"subdivr",db); - ReadField<ErrorPolicy_Igno>(dest.subsurftype,"subsurftype",db); - ReadField<ErrorPolicy_Igno>(dest.smoothresh,"smoothresh",db); - ReadFieldPtr<ErrorPolicy_Fail>(dest.mface,"*mface",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.mtface,"*mtface",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.tface,"*tface",db); - ReadFieldPtr<ErrorPolicy_Fail>(dest.mvert,"*mvert",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.medge,"*medge",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.dvert,"*dvert",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db); - ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MDeformVert> ( - MDeformVert& dest, - const FileDatabase& db - ) const -{ - - ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db); - ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<World> ( - World& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MVert> ( - MVert& dest, - const FileDatabase& db - ) const -{ - - ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db); - ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db); - ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MEdge> ( - MEdge& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db); - ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db); - ReadField<ErrorPolicy_Igno>(dest.crease,"crease",db); - ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<GroupObject> ( - GroupObject& dest, - const FileDatabase& db - ) const -{ - - ReadFieldPtr<ErrorPolicy_Fail>(dest.prev,"*prev",db); - ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<ListBase> ( - ListBase& dest, - const FileDatabase& db - ) const -{ - - ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<ModifierData> ( - ModifierData& dest, - const FileDatabase& db - ) const -{ - - ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db); - ReadField<ErrorPolicy_Igno>(dest.type,"type",db); - ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db); - ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<ID> ( - ID& dest, - const FileDatabase& db - ) const -{ - - ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MCol> ( - MCol& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.r,"r",db); - ReadField<ErrorPolicy_Fail>(dest.g,"g",db); - ReadField<ErrorPolicy_Fail>(dest.b,"b",db); - ReadField<ErrorPolicy_Fail>(dest.a,"a",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Image> ( - Image& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db); - ReadField<ErrorPolicy_Igno>(dest.ok,"ok",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - ReadField<ErrorPolicy_Igno>(dest.source,"source",db); - ReadField<ErrorPolicy_Igno>(dest.type,"type",db); - ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db); - ReadField<ErrorPolicy_Igno>(dest.pad1,"pad1",db); - ReadField<ErrorPolicy_Igno>(dest.lastframe,"lastframe",db); - ReadField<ErrorPolicy_Igno>(dest.tpageflag,"tpageflag",db); - ReadField<ErrorPolicy_Igno>(dest.totbind,"totbind",db); - ReadField<ErrorPolicy_Igno>(dest.xrep,"xrep",db); - ReadField<ErrorPolicy_Igno>(dest.yrep,"yrep",db); - ReadField<ErrorPolicy_Igno>(dest.twsta,"twsta",db); - ReadField<ErrorPolicy_Igno>(dest.twend,"twend",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.packedfile,"*packedfile",db); - ReadField<ErrorPolicy_Igno>(dest.lastupdate,"lastupdate",db); - ReadField<ErrorPolicy_Igno>(dest.lastused,"lastused",db); - ReadField<ErrorPolicy_Igno>(dest.animspeed,"animspeed",db); - ReadField<ErrorPolicy_Igno>(dest.gen_x,"gen_x",db); - ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db); - ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Scene> ( - Scene& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.camera,"*camera",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.world,"*world",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db); - ReadField<ErrorPolicy_Igno>(dest.base,"base",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Library> ( - Library& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db); - ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Tex> ( - Tex& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db); - ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<Camera> ( - Camera& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.id,"id",db); - ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db); - ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db); - ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -template <> void Structure :: Convert<MirrorModifierData> ( - MirrorModifierData& dest, - const FileDatabase& db - ) const -{ - - ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db); - ReadField<ErrorPolicy_Igno>(dest.axis,"axis",db); - ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db); - ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db); - ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db); - - db.reader->IncPtr(size); -} - -//-------------------------------------------------------------------------------- -void DNA::RegisterConverters() { - - converters["Object"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Object>), static_cast<ConvertProcPtr>(&Structure::Convert<Object>) ); - converters["Group"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Group>), static_cast<ConvertProcPtr>(&Structure::Convert<Group>) ); - converters["MTex"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MTex>), static_cast<ConvertProcPtr>(&Structure::Convert<MTex>) ); - converters["TFace"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<TFace>), static_cast<ConvertProcPtr>(&Structure::Convert<TFace>) ); - converters["SubsurfModifierData"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<SubsurfModifierData>), static_cast<ConvertProcPtr>(&Structure::Convert<SubsurfModifierData>) ); - converters["MFace"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MFace>), static_cast<ConvertProcPtr>(&Structure::Convert<MFace>) ); - converters["Lamp"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Lamp>), static_cast<ConvertProcPtr>(&Structure::Convert<Lamp>) ); - converters["MDeformWeight"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MDeformWeight>), static_cast<ConvertProcPtr>(&Structure::Convert<MDeformWeight>) ); - converters["PackedFile"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<PackedFile>), static_cast<ConvertProcPtr>(&Structure::Convert<PackedFile>) ); - converters["Base"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Base>), static_cast<ConvertProcPtr>(&Structure::Convert<Base>) ); - converters["MTFace"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MTFace>), static_cast<ConvertProcPtr>(&Structure::Convert<MTFace>) ); - converters["Material"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Material>), static_cast<ConvertProcPtr>(&Structure::Convert<Material>) ); - converters["Mesh"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Mesh>), static_cast<ConvertProcPtr>(&Structure::Convert<Mesh>) ); - converters["MDeformVert"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MDeformVert>), static_cast<ConvertProcPtr>(&Structure::Convert<MDeformVert>) ); - converters["World"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<World>), static_cast<ConvertProcPtr>(&Structure::Convert<World>) ); - converters["MVert"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MVert>), static_cast<ConvertProcPtr>(&Structure::Convert<MVert>) ); - converters["MEdge"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MEdge>), static_cast<ConvertProcPtr>(&Structure::Convert<MEdge>) ); - converters["GroupObject"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<GroupObject>), static_cast<ConvertProcPtr>(&Structure::Convert<GroupObject>) ); - converters["ListBase"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<ListBase>), static_cast<ConvertProcPtr>(&Structure::Convert<ListBase>) ); - converters["ModifierData"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<ModifierData>), static_cast<ConvertProcPtr>(&Structure::Convert<ModifierData>) ); - converters["ID"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<ID>), static_cast<ConvertProcPtr>(&Structure::Convert<ID>) ); - converters["MCol"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MCol>), static_cast<ConvertProcPtr>(&Structure::Convert<MCol>) ); - converters["Image"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Image>), static_cast<ConvertProcPtr>(&Structure::Convert<Image>) ); - converters["Scene"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Scene>), static_cast<ConvertProcPtr>(&Structure::Convert<Scene>) ); - converters["Library"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Library>), static_cast<ConvertProcPtr>(&Structure::Convert<Library>) ); - converters["Tex"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Tex>), static_cast<ConvertProcPtr>(&Structure::Convert<Tex>) ); - converters["Camera"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<Camera>), static_cast<ConvertProcPtr>(&Structure::Convert<Camera>) ); - converters["MirrorModifierData"] = DNA::FactoryPair( static_cast<AllocProcPtr>(&Structure::Allocate<MirrorModifierData>), static_cast<ConvertProcPtr>(&Structure::Convert<MirrorModifierData>) ); -} - - -#endif diff --git a/3rdparty/assimp/code/BlenderScene.h b/3rdparty/assimp/code/BlenderScene.h deleted file mode 100644 index 5cfb7092..00000000 --- a/3rdparty/assimp/code/BlenderScene.h +++ /dev/null @@ -1,683 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderScene.h - * @brief Intermediate representation of a BLEND scene. - */ -#ifndef INCLUDED_AI_BLEND_SCENE_H -#define INCLUDED_AI_BLEND_SCENE_H - -namespace Assimp { - namespace Blender { - -// Minor parts of this file are extracts from blender data structures, -// declared in the ./source/blender/makesdna directory. -// Stuff that is not used by Assimp is commented. - - -// NOTE -// this file serves as input data to the `./scripts/genblenddna.py` -// script. This script generates the actual binding code to read a -// blender file with a possibly different DNA into our structures. -// Only `struct` declarations are considered and the following -// rules must be obeyed in order for the script to work properly: -// -// * C++ style comments only -// -// * Structures may include the primitive types char, int, short, -// float, double. Signedness specifiers are not allowed on -// integers. Enum types are allowed, but they must have been -// defined in this header. -// -// * Structures may aggregate other structures, unless not defined -// in this header. -// -// * Pointers to other structures or primitive types are allowed. -// No references or double pointers or arrays of pointers. -// A pointer to a T is written as boost::shared_ptr, while a -// pointer to an array of elements is written as boost:: -// shared_array. -// -// * Arrays can have maximally two-dimensions. Any non-pointer -// type can form them. -// -// * Multiple fields can be declare in a single line (i.e `int a,b;`) -// provided they are neither pointers nor arrays. -// -// * One of WARN, FAIL can be appended to the declaration ( -// prior to the semiolon to specifiy the error handling policy if -// this field is missing in the input DNA). If none of those -// is specified the default policy is to subtitute a default -// value for the field. -// - -#define WARN // warn if field is missing, substitute default value -#define FAIL // fail the import if the field does not exist - -struct Object; -struct MTex; - -#define AI_BLEND_MESH_MAX_VERTS 2000000000L - -// ------------------------------------------------------------------------------- -struct ID : ElemBase { - - char name[24] WARN; - short flag; -}; - -// ------------------------------------------------------------------------------- -struct ListBase : ElemBase { - - boost::shared_ptr<ElemBase> first; - boost::shared_ptr<ElemBase> last; -}; - - -// ------------------------------------------------------------------------------- -struct PackedFile : ElemBase { - int size WARN; - int seek WARN; - boost::shared_ptr< FileOffset > data WARN; -}; - -// ------------------------------------------------------------------------------- -struct GroupObject : ElemBase { - - boost::shared_ptr<GroupObject> prev,next FAIL; - boost::shared_ptr<Object> ob; -}; - -// ------------------------------------------------------------------------------- -struct Group : ElemBase { - ID id FAIL; - int layer; - - boost::shared_ptr<GroupObject> gobject; -}; - -// ------------------------------------------------------------------------------- -struct World : ElemBase { - ID id FAIL; - -}; - -// ------------------------------------------------------------------------------- -struct MVert : ElemBase { - float co[3] FAIL; - float no[3] FAIL; - char flag; - int mat_nr WARN; - int bweight; -}; - -// ------------------------------------------------------------------------------- -struct MEdge : ElemBase { - int v1, v2 FAIL; - char crease, bweight; - short flag; -}; - -// ------------------------------------------------------------------------------- -struct MCol : ElemBase { - char r,g,b,a FAIL; -}; - -// ------------------------------------------------------------------------------- -struct MFace : ElemBase { - int v1,v2,v3,v4 FAIL; - int mat_nr FAIL; - char flag; -}; - -// ------------------------------------------------------------------------------- -struct TFace : ElemBase { - float uv[4][2] FAIL; - int col[4] FAIL; - char flag; - short mode; - short tile; - short unwrap; -}; - -// ------------------------------------------------------------------------------- -struct MTFace : ElemBase { - - float uv[4][2] FAIL; - char flag; - short mode; - short tile; - short unwrap; - - // boost::shared_ptr<Image> tpage; -}; - -// ------------------------------------------------------------------------------- -struct MDeformWeight : ElemBase { - int def_nr FAIL; - float weight FAIL; -}; - -// ------------------------------------------------------------------------------- -struct MDeformVert : ElemBase { - - vector<MDeformWeight> dw WARN; - int totweight; -}; - -// ------------------------------------------------------------------------------- -struct Material : ElemBase { - ID id FAIL; - - float r,g,b WARN; - float specr,specg,specb WARN; - float ambir,ambig,ambib WARN; - float mirr,mirg,mirb; - float emit WARN; - float alpha WARN; - float ref; - float translucency; - float roughness; - float darkness; - float refrac; - - boost::shared_ptr<Group> group; - - short diff_shader WARN; - short spec_shader WARN; - - boost::shared_ptr<MTex> mtex[18]; -}; - -// ------------------------------------------------------------------------------- -struct Mesh : ElemBase { - ID id FAIL; - - int totface FAIL; - int totedge FAIL; - int totvert FAIL; - - short subdiv; - short subdivr; - short subsurftype; - short smoothresh; - - vector<MFace> mface FAIL; - vector<MTFace> mtface; - vector<TFace> tface; - vector<MVert> mvert FAIL; - vector<MEdge> medge WARN; - vector<MDeformVert> dvert; - vector<MCol> mcol; - - vector< boost::shared_ptr<Material> > mat FAIL; -}; - -// ------------------------------------------------------------------------------- -struct Library : ElemBase { - ID id FAIL; - - char name[240] WARN; - char filename[240] FAIL; - boost::shared_ptr<Library> parent WARN; -}; - -// ------------------------------------------------------------------------------- -struct Camera : ElemBase { - enum Type { - Type_PERSP = 0 - ,Type_ORTHO = 1 - }; - - ID id FAIL; - - // struct AnimData *adt; - - Type type,flag WARN; - float angle WARN; - //float passepartalpha, angle; - //float clipsta, clipend; - //float lens, ortho_scale, drawsize; - //float shiftx, shifty; - - //float YF_dofdist, YF_aperture; - //short YF_bkhtype, YF_bkhbias; - //float YF_bkhrot; -}; - - -// ------------------------------------------------------------------------------- -struct Lamp : ElemBase { - - enum FalloffType { - FalloffType_Constant = 0x0 - ,FalloffType_InvLinear = 0x1 - ,FalloffType_InvSquare = 0x2 - //,FalloffType_Curve = 0x3 - //,FalloffType_Sliders = 0x4 - }; - - enum Type { - Type_Local = 0x0 - ,Type_Sun = 0x1 - ,Type_Spot = 0x2 - ,Type_Hemi = 0x3 - ,Type_Area = 0x4 - //,Type_YFPhoton = 0x5 - }; - - ID id FAIL; - //AnimData *adt; - - Type type FAIL; - short flags; - - //int mode; - - short colormodel, totex; - float r,g,b,k WARN; - //float shdwr, shdwg, shdwb; - - float energy, dist, spotsize, spotblend; - //float haint; - - float att1, att2; - //struct CurveMapping *curfalloff; - FalloffType falloff_type; - - //float clipsta, clipend, shadspotsize; - //float bias, soft, compressthresh; - //short bufsize, samp, buffers, filtertype; - //char bufflag, buftype; - - //short ray_samp, ray_sampy, ray_sampz; - //short ray_samp_type; - //short area_shape; - //float area_size, area_sizey, area_sizez; - //float adapt_thresh; - //short ray_samp_method; - - //short texact, shadhalostep; - - //short sun_effect_type; - //short skyblendtype; - //float horizon_brightness; - //float spread; - float sun_brightness; - //float sun_size; - //float backscattered_light; - //float sun_intensity; - //float atm_turbidity; - //float atm_inscattering_factor; - //float atm_extinction_factor; - //float atm_distance_factor; - //float skyblendfac; - //float sky_exposure; - //short sky_colorspace; - - // int YF_numphotons, YF_numsearch; - // short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad; - // float YF_causticblur, YF_ltradius; - - // float YF_glowint, YF_glowofs; - // short YF_glowtype, YF_pad2; - - //struct Ipo *ipo; - //struct MTex *mtex[18]; - // short pr_texture; - - //struct PreviewImage *preview; -}; - -// ------------------------------------------------------------------------------- -struct ModifierData : ElemBase { - enum ModifierType { - eModifierType_None = 0, - eModifierType_Subsurf, - eModifierType_Lattice, - eModifierType_Curve, - eModifierType_Build, - eModifierType_Mirror, - eModifierType_Decimate, - eModifierType_Wave, - eModifierType_Armature, - eModifierType_Hook, - eModifierType_Softbody, - eModifierType_Boolean, - eModifierType_Array, - eModifierType_EdgeSplit, - eModifierType_Displace, - eModifierType_UVProject, - eModifierType_Smooth, - eModifierType_Cast, - eModifierType_MeshDeform, - eModifierType_ParticleSystem, - eModifierType_ParticleInstance, - eModifierType_Explode, - eModifierType_Cloth, - eModifierType_Collision, - eModifierType_Bevel, - eModifierType_Shrinkwrap, - eModifierType_Fluidsim, - eModifierType_Mask, - eModifierType_SimpleDeform, - eModifierType_Multires, - eModifierType_Surface, - eModifierType_Smoke, - eModifierType_ShapeKey - }; - - boost::shared_ptr<ElemBase> next WARN; - boost::shared_ptr<ElemBase> prev WARN; - - int type, mode; - char name[32]; -}; - -// ------------------------------------------------------------------------------- -struct SubsurfModifierData : ElemBase { - - enum Type { - - TYPE_CatmullClarke = 0x0, - TYPE_Simple = 0x1 - }; - - enum Flags { - // some ommitted - FLAGS_SubsurfUV =1<<3 - }; - - ModifierData modifier FAIL; - short subdivType WARN; - short levels FAIL; - short renderLevels ; - short flags; -}; - -// ------------------------------------------------------------------------------- -struct MirrorModifierData : ElemBase { - - enum Flags { - Flags_CLIPPING =1<<0, - Flags_MIRROR_U =1<<1, - Flags_MIRROR_V =1<<2, - Flags_AXIS_X =1<<3, - Flags_AXIS_Y =1<<4, - Flags_AXIS_Z =1<<5, - Flags_VGROUP =1<<6 - }; - - ModifierData modifier FAIL; - - short axis, flag; - float tolerance; - boost::shared_ptr<Object> mirror_ob; -}; - -// ------------------------------------------------------------------------------- -struct Object : ElemBase { - ID id FAIL; - - enum Type { - Type_EMPTY = 0 - ,Type_MESH = 1 - ,Type_CURVE = 2 - ,Type_SURF = 3 - ,Type_FONT = 4 - ,Type_MBALL = 5 - - ,Type_LAMP = 10 - ,Type_CAMERA = 11 - - ,Type_WAVE = 21 - ,Type_LATTICE = 22 - }; - - Type type FAIL; - float obmat[4][4] WARN; - float parentinv[4][4] WARN; - char parsubstr[32] WARN; - - boost::shared_ptr<Object> parent WARN; - boost::shared_ptr<Object> track WARN; - - boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN; - boost::shared_ptr<Group> dup_group WARN; - boost::shared_ptr<ElemBase> data FAIL; - - ListBase modifiers; -}; - - -// ------------------------------------------------------------------------------- -struct Base : ElemBase { - boost::shared_ptr<Base> prev WARN; - boost::shared_ptr<Base> next WARN; - boost::shared_ptr<Object> object WARN; -}; - -// ------------------------------------------------------------------------------- -struct Scene : ElemBase { - ID id FAIL; - - boost::shared_ptr<Object> camera WARN; - boost::shared_ptr<World> world WARN; - boost::shared_ptr<Base> basact WARN; - - ListBase base; -}; - - -// ------------------------------------------------------------------------------- -struct Image : ElemBase { - ID id FAIL; - - char name[240] WARN; - - //struct anim *anim; - - short ok, flag; - short source, type, pad, pad1; - int lastframe; - - short tpageflag, totbind; - short xrep, yrep; - short twsta, twend; - //unsigned int bindcode; - //unsigned int *repbind; - - boost::shared_ptr<PackedFile> packedfile; - //struct PreviewImage * preview; - - float lastupdate; - int lastused; - short animspeed; - - short gen_x, gen_y, gen_type; -}; - -// ------------------------------------------------------------------------------- -struct Tex : ElemBase { - - // actually, the only texture type we support is Type_IMAGE - enum Type { - Type_CLOUDS = 1 - ,Type_WOOD = 2 - ,Type_MARBLE = 3 - ,Type_MAGIC = 4 - ,Type_BLEND = 5 - ,Type_STUCCI = 6 - ,Type_NOISE = 7 - ,Type_IMAGE = 8 - ,Type_PLUGIN = 9 - ,Type_ENVMAP = 10 - ,Type_MUSGRAVE = 11 - ,Type_VORONOI = 12 - ,Type_DISTNOISE = 13 - ,Type_POINTDENSITY = 14 - ,Type_VOXELDATA = 15 - }; - - ID id FAIL; - // AnimData *adt; - - //float noisesize, turbul; - //float bright, contrast, rfac, gfac, bfac; - //float filtersize; - - //float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain; - //float dist_amount, ns_outscale; - - //float vn_w1; - //float vn_w2; - //float vn_w3; - //float vn_w4; - //float vn_mexp; - //short vn_distm, vn_coltype; - - //short noisedepth, noisetype; - //short noisebasis, noisebasis2; - - //short imaflag, flag; - Type type FAIL; - //short stype; - - //float cropxmin, cropymin, cropxmax, cropymax; - //int texfilter; - //int afmax; - //short xrepeat, yrepeat; - //short extend; - - //short fie_ima; - //int len; - //int frames, offset, sfra; - - //float checkerdist, nabla; - //float norfac; - - //ImageUser iuser; - - //bNodeTree *nodetree; - //Ipo *ipo; - boost::shared_ptr<Image> ima WARN; - //PluginTex *plugin; - //ColorBand *coba; - //EnvMap *env; - //PreviewImage * preview; - //PointDensity *pd; - //VoxelData *vd; - - //char use_nodes; -}; - -// ------------------------------------------------------------------------------- -struct MTex : ElemBase { - - enum Projection { - Proj_N = 0 - ,Proj_X = 1 - ,Proj_Y = 2 - ,Proj_Z = 3 - }; - - enum Flag { - Flag_RGBTOINT = 0x1 - ,Flag_STENCIL = 0x2 - ,Flag_NEGATIVE = 0x4 - ,Flag_ALPHAMIX = 0x8 - ,Flag_VIEWSPACE = 0x10 - }; - - enum BlendType { - BlendType_BLEND = 0 - ,BlendType_MUL = 1 - ,BlendType_ADD = 2 - ,BlendType_SUB = 3 - ,BlendType_DIV = 4 - ,BlendType_DARK = 5 - ,BlendType_DIFF = 6 - ,BlendType_LIGHT = 7 - ,BlendType_SCREEN = 8 - ,BlendType_OVERLAY = 9 - ,BlendType_BLEND_HUE = 10 - ,BlendType_BLEND_SAT = 11 - ,BlendType_BLEND_VAL = 12 - ,BlendType_BLEND_COLOR = 13 - }; - - // short texco, mapto, maptoneg; - - BlendType blendtype; - boost::shared_ptr<Object> object; - boost::shared_ptr<Tex> tex; - char uvname[32]; - - Projection projx,projy,projz; - char mapping; - float ofs[3], size[3], rot; - - int texflag; - short colormodel, pmapto, pmaptoneg; - //short normapspace, which_output; - //char brush_map_mode; - float r,g,b,k WARN; - //float def_var, rt; - - //float colfac, varfac; - - //float norfac, dispfac, warpfac; - float colspecfac, mirrfac, alphafac; - float difffac, specfac, emitfac, hardfac; - //float raymirrfac, translfac, ambfac; - //float colemitfac, colreflfac, coltransfac; - //float densfac, scatterfac, reflfac; - - //float timefac, lengthfac, clumpfac; - //float kinkfac, roughfac, padensfac; - //float lifefac, sizefac, ivelfac, pvelfac; - //float shadowfac; - //float zenupfac, zendownfac, blendfac; -}; - - - } -} -#endif diff --git a/3rdparty/assimp/code/BlenderSceneGen.h b/3rdparty/assimp/code/BlenderSceneGen.h deleted file mode 100644 index 3ef5d341..00000000 --- a/3rdparty/assimp/code/BlenderSceneGen.h +++ /dev/null @@ -1,223 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 BlenderSceneGen.h - * @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py - */ -#ifndef INCLUDED_AI_BLEND_SCENEGEN_H -#define INCLUDED_AI_BLEND_SCENEGEN_H - -namespace Assimp { - namespace Blender { - - -template <> void Structure :: Convert<Object> ( - Object& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Group> ( - Group& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MTex> ( - MTex& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<TFace> ( - TFace& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<SubsurfModifierData> ( - SubsurfModifierData& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MFace> ( - MFace& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Lamp> ( - Lamp& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MDeformWeight> ( - MDeformWeight& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<PackedFile> ( - PackedFile& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Base> ( - Base& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MTFace> ( - MTFace& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Material> ( - Material& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Mesh> ( - Mesh& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MDeformVert> ( - MDeformVert& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<World> ( - World& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MVert> ( - MVert& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MEdge> ( - MEdge& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<GroupObject> ( - GroupObject& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<ListBase> ( - ListBase& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<ModifierData> ( - ModifierData& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<ID> ( - ID& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MCol> ( - MCol& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Image> ( - Image& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Scene> ( - Scene& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Library> ( - Library& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Tex> ( - Tex& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<Camera> ( - Camera& dest, - const FileDatabase& db - ) const -; - -template <> void Structure :: Convert<MirrorModifierData> ( - MirrorModifierData& dest, - const FileDatabase& db - ) const -; - - - } -} - -#endif diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt b/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt deleted file mode 100644 index 36b7cd93..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp deleted file mode 100644 index e244cd57..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/foreach.hpp +++ /dev/null @@ -1,93 +0,0 @@ - -#ifndef BOOST_FOREACH - -/////////////////////////////////////////////////////////////////////////////// -// A stripped down version of FOREACH for -// illustration purposes. NOT FOR GENERAL USE. -// For a complete implementation, see BOOST_FOREACH at -// http://boost-sandbox.sourceforge.net/vault/index.php?directory=eric_niebler -// -// Copyright 2004 Eric Niebler. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Adapted to Assimp November 29th, 2008 (Alexander Gessler). -// Added code to handle both const and non-const iterators, simplified some -// parts. -/////////////////////////////////////////////////////////////////////////////// - -namespace boost { -namespace foreach_detail { - -/////////////////////////////////////////////////////////////////////////////// -// auto_any - -struct auto_any_base -{ - operator bool() const { return false; } -}; - -template<typename T> -struct auto_any : auto_any_base -{ - auto_any(T const& t) : item(t) {} - mutable T item; -}; - -template<typename T> -T& auto_any_cast(auto_any_base const& any) -{ - return static_cast<auto_any<T> const&>(any).item; -} - -/////////////////////////////////////////////////////////////////////////////// -// FOREACH helper function - -template<typename T> -auto_any<typename T::const_iterator> begin(T const& t) -{ - return t.begin(); -} - -template<typename T> -auto_any<typename T::const_iterator> end(T const& t) -{ - return t.end(); -} - -// iterator -template<typename T> -bool done(auto_any_base const& cur, auto_any_base const& end, T&) -{ - typedef typename T::iterator iter_type; - return auto_any_cast<iter_type>(cur) == auto_any_cast<iter_type>(end); -} - -template<typename T> -void next(auto_any_base const& cur, T&) -{ - ++auto_any_cast<typename T::iterator>(cur); -} - -template<typename T> -typename T::reference deref(auto_any_base const& cur, T&) -{ - return *auto_any_cast<typename T::iterator>(cur); -} - -} // end foreach_detail - -/////////////////////////////////////////////////////////////////////////////// -// FOREACH - -#define BOOST_FOREACH(item, container) \ - if (boost::foreach_detail::auto_any_base const& b = boost::foreach_detail::begin(container)) {} else \ - if (boost::foreach_detail::auto_any_base const& e = boost::foreach_detail::end(container)) {} else \ - for (;!boost::foreach_detail::done(b,e,container); boost::foreach_detail::next(b,container)) \ - if (bool ugly_and_unique_break = false) {} else \ - for (item = boost::foreach_detail::deref(b,container); !ugly_and_unique_break; ugly_and_unique_break = true) - -} // end boost - -#endif diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp deleted file mode 100644 index 0afae4dd..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/format.hpp +++ /dev/null @@ -1,81 +0,0 @@ - - - -/* DEPRECATED! - use code/TinyFormatter.h instead. - * - * - * */ - -#ifndef AI_BOOST_FORMAT_DUMMY_INCLUDED -#define AI_BOOST_FORMAT_DUMMY_INCLUDED - -#if (!defined BOOST_FORMAT_HPP) || (defined ASSIMP_FORCE_NOBOOST) - -#include <string> -#include <vector> - -namespace boost -{ - - - class format - { - public: - format (const std::string& _d) - : d(_d) - { - } - - template <typename T> - format& operator % (T in) - { - // XXX add replacement for boost::lexical_cast? - - std::stringstream ss; - ss << in; // note: ss cannot be an rvalue, or the global operator << (const char*) is not called for T == const char*. - chunks.push_back( ss.str()); - return *this; - } - - - operator std::string () const { - std::string res; // pray for NRVO to kick in - - size_t start = 0, last = 0; - - std::vector<std::string>::const_iterator chunkin = chunks.begin(); - - for ( start = d.find('%');start != std::string::npos; start = d.find('%',last)) { - res += d.substr(last,start-last); - last = start+2; - if (d[start+1] == '%') { - res += "%"; - continue; - } - - if (chunkin == chunks.end()) { - break; - } - - res += *chunkin++; - } - res += d.substr(last); - return res; - } - - private: - std::string d; - std::vector<std::string> chunks; - }; - - inline std::string str(const std::string& s) { - return s; - } -} - - -#else -# error "format.h was already included" -#endif // -#endif // !! AI_BOOST_FORMAT_DUMMY_INCLUDED - diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp deleted file mode 100644 index 6c3f7819..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/lexical_cast.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/// A quick replacement for boost::lexical_cast for all the Boost haters out there - -#ifndef __AI_BOOST_WORKAROUND_LEXICAL_CAST -#define __AI_BOOST_WORKAROUND_LEXICAL_CAST - -namespace boost -{ - - /// A quick replacement for boost::lexical_cast - should work for all types a stringstream can handle - template <typename TargetType, typename SourceType> - TargetType lexical_cast( const SourceType& source) - { - std::stringstream stream; - TargetType result; - - stream << source; - stream >> result; - return result; - } - -} // namespace boost - -#endif // __AI_BOOST_WORKAROUND_LEXICAL_CAST diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp deleted file mode 100644 index 76dd9b10..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/math/common_factor_rt.hpp +++ /dev/null @@ -1,37 +0,0 @@ - - -#ifndef BOOST_MATH_COMMON_FACTOR_RT_HPP -#define BOOST_MATH_COMMON_FACTOR_RT_HPP - - -namespace boost { -namespace math { - -// TODO: use binary GCD for unsigned integers .... -template < typename IntegerType > -IntegerType gcd( IntegerType a, IntegerType b ) -{ - const IntegerType zero = (IntegerType)0; - while ( true ) - { - if ( a == zero ) - return b; - b %= a; - - if ( b == zero ) - return a; - a %= b; - } -} - -template < typename IntegerType > -IntegerType lcm( IntegerType a, IntegerType b ) -{ - const IntegerType t = gcd (a,b); - if (!t)return t; - return a / t * b; -} - -}} - -#endif diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp deleted file mode 100644 index ce188c13..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/pointer_cast.hpp +++ /dev/null @@ -1,45 +0,0 @@ -////////////////////////////////////////////////////////////////////////////// -// -// (C) Copyright Ion Gaztanaga 2005. -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -////////////////////////////////////////////////////////////////////////////// - -#ifndef BOOST_POINTER_CAST_HPP -#define BOOST_POINTER_CAST_HPP - -namespace boost { - -//static_pointer_cast overload for raw pointers -template<class T, class U> -inline T* static_pointer_cast(U *ptr) -{ - return static_cast<T*>(ptr); -} - -//dynamic_pointer_cast overload for raw pointers -template<class T, class U> -inline T* dynamic_pointer_cast(U *ptr) -{ - return dynamic_cast<T*>(ptr); -} - -//const_pointer_cast overload for raw pointers -template<class T, class U> -inline T* const_pointer_cast(U *ptr) -{ - return const_cast<T*>(ptr); -} - -//reinterpret_pointer_cast overload for raw pointers -template<class T, class U> -inline T* reinterpret_pointer_cast(U *ptr) -{ - return reinterpret_cast<T*>(ptr); -} - -} // namespace boost - -#endif //BOOST_POINTER_CAST_HPP diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp deleted file mode 100644 index ebb97171..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/scoped_array.hpp +++ /dev/null @@ -1,79 +0,0 @@ - -#ifndef __AI_BOOST_SCOPED_ARRAY_INCLUDED -#define __AI_BOOST_SCOPED_ARRAY_INCLUDED - -#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED - -namespace boost { - -// small replacement for boost::scoped_array -template <class T> -class scoped_array -{ -public: - - // provide a default construtctor - scoped_array() - : ptr(0) - { - } - - // construction from an existing heap object of type T - scoped_array(T* _ptr) - : ptr(_ptr) - { - } - - // automatic destruction of the wrapped object at the - // end of our lifetime - ~scoped_array() - { - delete[] ptr; - } - - inline T* get() - { - return ptr; - } - - inline T* operator-> () - { - return ptr; - } - - inline void reset (T* t = 0) - { - delete[] ptr; - ptr = t; - } - - T & operator[](std::ptrdiff_t i) const - { - return ptr[i]; - } - - void swap(scoped_array & b) - { - std::swap(ptr, b.ptr); - } - -private: - - // encapsulated object pointer - T* ptr; - -}; - -template<class T> -inline void swap(scoped_array<T> & a, scoped_array<T> & b) -{ - a.swap(b); -} - -} // end of namespace boost - -#else -# error "scoped_array.h was already included" -#endif -#endif // __AI_BOOST_SCOPED_ARRAY_INCLUDED - diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp deleted file mode 100644 index 1ddee564..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/scoped_ptr.hpp +++ /dev/null @@ -1,79 +0,0 @@ - -#ifndef __AI_BOOST_SCOPED_PTR_INCLUDED -#define __AI_BOOST_SCOPED_PTR_INCLUDED - -#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED - -namespace boost { - -// small replacement for boost::scoped_ptr -template <class T> -class scoped_ptr -{ -public: - - // provide a default construtctor - scoped_ptr() - : ptr(0) - { - } - - // construction from an existing heap object of type T - scoped_ptr(T* _ptr) - : ptr(_ptr) - { - } - - // automatic destruction of the wrapped object at the - // end of our lifetime - ~scoped_ptr() - { - delete ptr; - } - - inline T* get() const - { - return ptr; - } - - inline operator T*() - { - return ptr; - } - - inline T* operator-> () - { - return ptr; - } - - inline void reset (T* t = 0) - { - delete ptr; - ptr = t; - } - - void swap(scoped_ptr & b) - { - std::swap(ptr, b.ptr); - } - -private: - - // encapsulated object pointer - T* ptr; - -}; - -template<class T> -inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) -{ - a.swap(b); -} - -} // end of namespace boost - -#else -# error "scoped_ptr.h was already included" -#endif -#endif // __AI_BOOST_SCOPED_PTR_INCLUDED - diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp deleted file mode 100644 index ad58bd0d..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/shared_array.hpp +++ /dev/null @@ -1,228 +0,0 @@ - -#ifndef INCLUDED_AI_BOOST_SHARED_ARRAY -#define INCLUDED_AI_BOOST_SHARED_ARRAY - -#ifndef BOOST_SCOPED_ARRAY_HPP_INCLUDED - -// ------------------------------ -// Internal stub -namespace boost { - namespace array_detail { - class controller { - public: - - controller() - : cnt(1) - {} - - public: - - template <typename T> - controller* decref(T* pt) { - if (--cnt <= 0) { - delete this; - delete[] pt; - } - return NULL; - } - - controller* incref() { - ++cnt; - return this; - } - - long get() const { - return cnt; - } - - private: - long cnt; - }; - - struct empty {}; - - template <typename DEST, typename SRC> - struct is_convertible_stub { - - struct yes {char s[1];}; - struct no {char s[2];}; - - static yes foo(DEST*); - static no foo(...); - - enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; - }; - - template <bool> struct enable_if {}; - template <> struct enable_if<true> { - typedef empty result; - }; - - template <typename DEST, typename SRC> - struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > { - }; - } - -// ------------------------------ -// Small replacement for boost::shared_array, not threadsafe because no -// atomic reference counter is in use. -// ------------------------------ -template <class T> -class shared_array -{ - template <typename TT> friend class shared_array; - - template<class TT> friend bool operator== (const shared_array<TT>& a, const shared_array<TT>& b); - template<class TT> friend bool operator!= (const shared_array<TT>& a, const shared_array<TT>& b); - template<class TT> friend bool operator< (const shared_array<TT>& a, const shared_array<TT>& b); - -public: - - typedef T element_type; - -public: - - // provide a default constructor - shared_array() - : ptr() - , ctr(NULL) - { - } - - // construction from an existing object of type T - explicit shared_array(T* ptr) - : ptr(ptr) - , ctr(ptr ? new array_detail::controller() : NULL) - { - } - - shared_array(const shared_array& r) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - template <typename Y> - shared_array(const shared_array<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty()) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - // automatic destruction of the wrapped object when all - // references are freed. - ~shared_array() { - if (ctr) { - ctr = ctr->decref(ptr); - } - } - - shared_array& operator=(const shared_array& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - template <typename Y> - shared_array& operator=(const shared_array<Y>& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - // pointer access - inline operator T*() { - return ptr; - } - - inline T* operator-> () const { - return ptr; - } - - // standard semantics - inline T* get() { - return ptr; - } - - T& operator[] (std::ptrdiff_t index) const { - return ptr[index]; - } - - inline const T* get() const { - return ptr; - } - - inline operator bool () const { - return ptr != NULL; - } - - inline bool unique() const { - return use_count() == 1; - } - - inline long use_count() const { - return ctr->get(); - } - - inline void reset (T* t = 0) { - if (ctr) { - ctr->decref(ptr); - } - ptr = t; - ctr = ptr?new array_detail::controller():NULL; - } - - void swap(shared_array & b) { - std::swap(ptr, b.ptr); - std::swap(ctr, b.ctr); - } - - -private: - - // encapsulated object pointer - T* ptr; - - // control block - array_detail::controller* ctr; -}; - -template<class T> -inline void swap(shared_array<T> & a, shared_array<T> & b) -{ - a.swap(b); -} - -template<class T> -bool operator== (const shared_array<T>& a, const shared_array<T>& b) { - return a.ptr == b.ptr; -} -template<class T> -bool operator!= (const shared_array<T>& a, const shared_array<T>& b) { - return a.ptr != b.ptr; -} - -template<class T> -bool operator< (const shared_array<T>& a, const shared_array<T>& b) { - return a.ptr < b.ptr; -} - - -} // end of namespace boost - -#else -# error "shared_array.h was already included" -#endif -#endif // INCLUDED_AI_BOOST_SHARED_ARRAY diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp deleted file mode 100644 index e5f430c2..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/shared_ptr.hpp +++ /dev/null @@ -1,257 +0,0 @@ - -#ifndef INCLUDED_AI_BOOST_SHARED_PTR -#define INCLUDED_AI_BOOST_SHARED_PTR - -#ifndef BOOST_SCOPED_PTR_HPP_INCLUDED - -// ------------------------------ -// Internal stub -namespace boost { - namespace detail { - class controller { - public: - - controller() - : cnt(1) - {} - - public: - - template <typename T> - controller* decref(T* pt) { - if (--cnt <= 0) { - delete this; - delete pt; - } - return NULL; - } - - controller* incref() { - ++cnt; - return this; - } - - long get() const { - return cnt; - } - - private: - long cnt; - }; - - struct empty {}; - - template <typename DEST, typename SRC> - struct is_convertible_stub { - - struct yes {char s[1];}; - struct no {char s[2];}; - - static yes foo(DEST*); - static no foo(...); - - enum {result = (sizeof(foo((SRC*)0)) == sizeof(yes) ? 1 : 0)}; - }; - - template <bool> struct enable_if {}; - template <> struct enable_if<true> { - typedef empty result; - }; - - template <typename DEST, typename SRC> - struct is_convertible : public enable_if<is_convertible_stub<DEST,SRC>::result > { - }; - } - -// ------------------------------ -// Small replacement for boost::shared_ptr, not threadsafe because no -// atomic reference counter is in use. -// ------------------------------ -template <class T> -class shared_ptr -{ - template <typename TT> friend class shared_ptr; - - template<class TT, class U> friend shared_ptr<TT> static_pointer_cast (shared_ptr<U> ptr); - template<class TT, class U> friend shared_ptr<TT> dynamic_pointer_cast (shared_ptr<U> ptr); - template<class TT, class U> friend shared_ptr<TT> const_pointer_cast (shared_ptr<U> ptr); - - template<class TT> friend bool operator== (const shared_ptr<TT>& a, const shared_ptr<TT>& b); - template<class TT> friend bool operator!= (const shared_ptr<TT>& a, const shared_ptr<TT>& b); - template<class TT> friend bool operator< (const shared_ptr<TT>& a, const shared_ptr<TT>& b); - -public: - - typedef T element_type; - -public: - - // provide a default constructor - shared_ptr() - : ptr() - , ctr(NULL) - { - } - - // construction from an existing object of type T - explicit shared_ptr(T* ptr) - : ptr(ptr) - , ctr(ptr ? new detail::controller() : NULL) - { - } - - shared_ptr(const shared_ptr& r) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - template <typename Y> - shared_ptr(const shared_ptr<Y>& r,typename detail::is_convertible<T,Y>::result = detail::empty()) - : ptr(r.ptr) - , ctr(r.ctr ? r.ctr->incref() : NULL) - { - } - - // automatic destruction of the wrapped object when all - // references are freed. - ~shared_ptr() { - if (ctr) { - ctr = ctr->decref(ptr); - } - } - - shared_ptr& operator=(const shared_ptr& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - template <typename Y> - shared_ptr& operator=(const shared_ptr<Y>& r) { - if (this == &r) { - return *this; - } - if (ctr) { - ctr->decref(ptr); - } - ptr = r.ptr; - ctr = ptr?r.ctr->incref():NULL; - return *this; - } - - // pointer access - inline operator T*() { - return ptr; - } - - inline T* operator-> () const { - return ptr; - } - - // standard semantics - inline T* get() { - return ptr; - } - - inline const T* get() const { - return ptr; - } - - inline operator bool () const { - return ptr != NULL; - } - - inline bool unique() const { - return use_count() == 1; - } - - inline long use_count() const { - return ctr->get(); - } - - inline void reset (T* t = 0) { - if (ctr) { - ctr->decref(ptr); - } - ptr = t; - ctr = ptr?new detail::controller():NULL; - } - - void swap(shared_ptr & b) { - std::swap(ptr, b.ptr); - std::swap(ctr, b.ctr); - } - -private: - - - // for use by the various xxx_pointer_cast helper templates - explicit shared_ptr(T* ptr, detail::controller* ctr) - : ptr(ptr) - , ctr(ctr->incref()) - { - } - -private: - - // encapsulated object pointer - T* ptr; - - // control block - detail::controller* ctr; -}; - -template<class T> -inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) -{ - a.swap(b); -} - -template<class T> -bool operator== (const shared_ptr<T>& a, const shared_ptr<T>& b) { - return a.ptr == b.ptr; -} -template<class T> -bool operator!= (const shared_ptr<T>& a, const shared_ptr<T>& b) { - return a.ptr != b.ptr; -} - -template<class T> -bool operator< (const shared_ptr<T>& a, const shared_ptr<T>& b) { - return a.ptr < b.ptr; -} - - -template<class T, class U> -inline shared_ptr<T> static_pointer_cast( shared_ptr<U> ptr) -{ - return shared_ptr<T>(static_cast<T*>(ptr.ptr),ptr.ctr); -} - -template<class T, class U> -inline shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> ptr) -{ - return shared_ptr<T>(dynamic_cast<T*>(ptr.ptr),ptr.ctr); -} - -template<class T, class U> -inline shared_ptr<T> const_pointer_cast( shared_ptr<U> ptr) -{ - return shared_ptr<T>(const_cast<T*>(ptr.ptr),ptr.ctr); -} - - - -} // end of namespace boost - -#else -# error "shared_ptr.h was already included" -#endif -#endif // INCLUDED_AI_BOOST_SCOPED_PTR diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp deleted file mode 100644 index 4b6489a7..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/static_assert.hpp +++ /dev/null @@ -1,20 +0,0 @@ - -#ifndef AI_BOOST_STATIC_ASSERT_INCLUDED -#define AI_BOOST_STATIC_ASSERT_INCLUDED - -#ifndef BOOST_STATIC_ASSERT - -namespace boost { - namespace detail { - - template <bool b> class static_assertion_failure; - template <> class static_assertion_failure<true> {}; - } -} - - -#define BOOST_STATIC_ASSERT(eval) \ -{boost::detail::static_assertion_failure<(eval)> assert_dummy;assert_dummy;} - -#endif -#endif // !! AI_BOOST_STATIC_ASSERT_INCLUDED diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp deleted file mode 100644 index df93b25f..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/timer.hpp +++ /dev/null @@ -1,72 +0,0 @@ -// boost timer.hpp header file ---------------------------------------------// - -// Copyright Beman Dawes 1994-99. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/timer for documentation. - -// Revision History -// 01 Apr 01 Modified to use new <boost/limits.hpp> header. (JMaddock) -// 12 Jan 01 Change to inline implementation to allow use without library -// builds. See docs for more rationale. (Beman Dawes) -// 25 Sep 99 elapsed_max() and elapsed_min() added (John Maddock) -// 16 Jul 99 Second beta -// 6 Jul 99 Initial boost version - -#ifndef BOOST_TIMER_HPP -#define BOOST_TIMER_HPP - -//#include <boost/config.hpp> -#include <ctime> -//#include <boost/limits.hpp> - -# ifdef BOOST_NO_STDC_NAMESPACE - namespace std { using ::clock_t; using ::clock; } -# endif - - -namespace boost { - -// timer -------------------------------------------------------------------// - -// A timer object measures elapsed time. - -// It is recommended that implementations measure wall clock rather than CPU -// time since the intended use is performance measurement on systems where -// total elapsed time is more important than just process or CPU time. - -// Warnings: The maximum measurable elapsed time may well be only 596.5+ hours -// due to implementation limitations. The accuracy of timings depends on the -// accuracy of timing information provided by the underlying platform, and -// this varies a great deal from platform to platform. - -class timer -{ - public: - timer() { _start_time = std::clock(); } // postcondition: elapsed()==0 -// timer( const timer& src ); // post: elapsed()==src.elapsed() -// ~timer(){} -// timer& operator=( const timer& src ); // post: elapsed()==src.elapsed() - void restart() { _start_time = std::clock(); } // post: elapsed()==0 - double elapsed() const // return elapsed time in seconds - { return double(std::clock() - _start_time) / CLOCKS_PER_SEC; } - - double elapsed_max() const // return estimated maximum value for elapsed() - // Portability warning: elapsed_max() may return too high a value on systems - // where std::clock_t overflows or resets at surprising values. - { - return (double((std::numeric_limits<std::clock_t>::max)()) - - double(_start_time)) / double(CLOCKS_PER_SEC); - } - - double elapsed_min() const // return minimum value for elapsed() - { return double(1)/double(CLOCKS_PER_SEC); } - - private: - std::clock_t _start_time; -}; // timer - -} // namespace boost - -#endif // BOOST_TIMER_HPP diff --git a/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp b/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp deleted file mode 100644 index d23f28a9..00000000 --- a/3rdparty/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp +++ /dev/null @@ -1,285 +0,0 @@ -// A very small replacement for boost::tuple -// (c) Alexander Gessler, 2008 [alexander.gessler@gmx.net] - -#ifndef BOOST_TUPLE_INCLUDED -#define BOOST_TUPLE_INCLUDED - -namespace boost { - namespace detail { - - // Represents an empty tuple slot (up to 5 supported) - struct nulltype {}; - - // For readable error messages - struct tuple_component_idx_out_of_bounds; - - // To share some code for the const/nonconst versions of the getters - template <bool b, typename T> - struct ConstIf { - typedef T t; - }; - - template <typename T> - struct ConstIf<true,T> { - typedef const T t; - }; - - // Predeclare some stuff - template <typename, unsigned, typename, bool, unsigned> struct value_getter; - - // Helper to obtain the type of a tuple element - template <typename T, unsigned NIDX, typename TNEXT, unsigned N /*= 0*/> - struct type_getter { - typedef type_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type,N> next_elem_getter; - typedef typename next_elem_getter::type type; - }; - - template <typename T, unsigned NIDX, typename TNEXT > - struct type_getter <T,NIDX,TNEXT,NIDX> { - typedef T type; - }; - - // Base class for all explicit specializations of list_elem - template <typename T, unsigned NIDX, typename TNEXT > - struct list_elem_base { - - // Store template parameters - typedef TNEXT next_type; - typedef T type; - - static const unsigned nidx = NIDX; - }; - - // Represents an element in the tuple component list - template <typename T, unsigned NIDX, typename TNEXT > - struct list_elem : list_elem_base<T,NIDX,TNEXT>{ - - // Real members - T me; - TNEXT next; - - // Get the value of a specific tuple element - template <unsigned N> - typename type_getter<T,NIDX,TNEXT,N>::type& get () { - value_getter <T,NIDX,TNEXT,false,N> s; - return s(*this); - } - - // Get the value of a specific tuple element - template <unsigned N> - const typename type_getter<T,NIDX,TNEXT,N>::type& get () const { - value_getter <T,NIDX,TNEXT,true,N> s; - return s(*this); - } - - // Explicit cast - template <typename T2, typename TNEXT2 > - operator list_elem<T2,NIDX,TNEXT2> () const { - list_elem<T2,NIDX,TNEXT2> ret; - ret.me = (T2)me; - ret.next = next; - return ret; - } - - // Recursively compare two elements (last element returns always true) - bool operator == (const list_elem& s) const { - return (me == s.me && next == s.next); - } - }; - - // Represents a non-used tuple element - the very last element processed - template <typename TNEXT, unsigned NIDX > - struct list_elem<nulltype,NIDX,TNEXT> : list_elem_base<nulltype,NIDX,TNEXT> { - template <unsigned N, bool IS_CONST = true> struct value_getter { - /* just dummy members to produce readable error messages */ - tuple_component_idx_out_of_bounds operator () (typename ConstIf<IS_CONST,list_elem>::t& me); - }; - template <unsigned N> struct type_getter { - /* just dummy members to produce readable error messages */ - typedef tuple_component_idx_out_of_bounds type; - }; - - // dummy - list_elem& operator = (const list_elem& other) { - return *this; - } - - // dummy - bool operator == (const list_elem& other) { - return true; - } - }; - - // Represents the absolute end of the list - typedef list_elem<nulltype,0,int> list_end; - - // Helper obtain to query the value of a tuple element - // NOTE: This can't be a nested class as the compiler won't accept a full or - // partial specialization of a nested class of a non-specialized template - template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST, unsigned N> - struct value_getter { - - // calling list_elem - typedef list_elem<T,NIDX,TNEXT> outer_elem; - - // typedef for the getter for next element - typedef value_getter<typename TNEXT::type,NIDX+1,typename TNEXT::next_type, - IS_CONST, N> next_value_getter; - - typename ConstIf<IS_CONST,typename type_getter<T,NIDX,TNEXT,N>::type>::t& - operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) { - - next_value_getter s; - return s(me.next); - } - }; - - template <typename T, unsigned NIDX, typename TNEXT, bool IS_CONST> - struct value_getter <T,NIDX,TNEXT,IS_CONST,NIDX> { - typedef list_elem<T,NIDX,TNEXT> outer_elem; - - typename ConstIf<IS_CONST,T>::t& operator () (typename ConstIf<IS_CONST,outer_elem >::t& me) { - return me.me; - } - }; - }; - - // A very minimal implementation for up to 5 elements - template <typename T0 = detail::nulltype, - typename T1 = detail::nulltype, - typename T2 = detail::nulltype, - typename T3 = detail::nulltype, - typename T4 = detail::nulltype> - class tuple { - - template <typename T0b, - typename T1b, - typename T2b, - typename T3b, - typename T4b > - friend class tuple; - - private: - - typedef detail::list_elem<T0,0, - detail::list_elem<T1,1, - detail::list_elem<T2,2, - detail::list_elem<T3,3, - detail::list_elem<T4,4, - detail::list_end > > > > > very_long; - - very_long m; - - public: - - // Get a specific tuple element - template <unsigned N> - typename detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () { - return m.get<N>(); - } - - // ... and the const version - template <unsigned N> - typename const detail::type_getter<T0,0,typename very_long::next_type, N>::type& get () const { - return m.get<N>(); - } - - - // comparison operators - bool operator== (const tuple& other) const { - return m == other.m; - } - - // ... and the other way round - bool operator!= (const tuple& other) const { - return !(m == other.m); - } - - // cast to another tuple - all single elements must be convertible - template < typename T0, typename T1,typename T2, - typename T3, typename T4> - - operator tuple <T0,T1,T2,T3,T4> () const { - tuple <T0,T1,T2,T3,T4> s; - s.m = (tuple <T0,T1,T2,T3,T4>::very_long)m; - return s; - } - }; - - // Another way to access an element ... - template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4> - inline typename tuple<T0,T1,T2,T3,T4>::very_long::type_getter<N>::type& get ( - tuple<T0,T1,T2,T3,T4>& m) { - return m.get<N>(); - } - - // ... and the const version - template <unsigned N,typename T0,typename T1,typename T2,typename T3,typename T4> - inline const typename tuple<T0,T1,T2,T3,T4>::very_long::type_getter<N>::type& get ( - const tuple<T0,T1,T2,T3,T4>& m) { - return m.get<N>(); - } - - // Constructs a tuple with 5 elements - template <typename T0,typename T1,typename T2,typename T3,typename T4> - inline tuple <T0,T1,T2,T3,T4> make_tuple (const T0& t0, - const T1& t1,const T2& t2,const T3& t3,const T4& t4) { - - tuple <T0,T1,T2,T3,T4> t; - t.get<0>() = t0; - t.get<1>() = t1; - t.get<2>() = t2; - t.get<3>() = t3; - t.get<4>() = t4; - return t; - } - - // Constructs a tuple with 4 elements - template <typename T0,typename T1,typename T2,typename T3> - inline tuple <T0,T1,T2,T3> make_tuple (const T0& t0, - const T1& t1,const T2& t2,const T3& t3) { - tuple <T0,T1,T2,T3> t; - t.get<0>() = t0; - t.get<1>() = t1; - t.get<2>() = t2; - t.get<3>() = t3; - return t; - } - - // Constructs a tuple with 3 elements - template <typename T0,typename T1,typename T2> - inline tuple <T0,T1,T2> make_tuple (const T0& t0, - const T1& t1,const T2& t2) { - tuple <T0,T1,T2> t; - t.get<0>() = t0; - t.get<1>() = t1; - t.get<2>() = t2; - return t; - } - - // Constructs a tuple with 2 elements (fucking idiot, use std::pair instead!) - template <typename T0,typename T1> - inline tuple <T0,T1> make_tuple (const T0& t0, - const T1& t1) { - tuple <T0,T1> t; - t.get<0>() = t0; - t.get<1>() = t1; - return t; - } - - // Constructs a tuple with 1 elements (no comment ...) - template <typename T0> - inline tuple <T0> make_tuple (const T0& t0) { - tuple <T0> t; - t.get<0>() = t0; - return t; - } - - // Constructs a tuple with 0 elements (ehm? Try http://www.promillerechner.net) - inline tuple <> make_tuple () { - tuple <> t; - return t; - } -}; - -#endif // !! BOOST_TUPLE_INCLUDED diff --git a/3rdparty/assimp/code/ByteSwap.h b/3rdparty/assimp/code/ByteSwap.h deleted file mode 100644 index c61b96df..00000000 --- a/3rdparty/assimp/code/ByteSwap.h +++ /dev/null @@ -1,245 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Helper class tp perform various byte oder swappings - (e.g. little to big endian) */ -#ifndef AI_BYTESWAP_H_INC -#define AI_BYTESWAP_H_INC - -#include "../include/aiAssert.h" -#include "../include/aiTypes.h" - -#if _MSC_VER >= 1400 -#include <stdlib.h> -#endif - -namespace Assimp { -// -------------------------------------------------------------------------------------- -/** Defines some useful byte order swap routines. - * - * This is required to read big-endian model formats on little-endian machines, - * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */ -// -------------------------------------------------------------------------------------- -class ByteSwap -{ - ByteSwap() {} - -public: - - // ---------------------------------------------------------------------- - /** Swap two bytes of data - * @param[inout] _szOut A void* to save the reintcasts for the caller. */ - static inline void Swap2(void* _szOut) - { - ai_assert(_szOut); - -#if _MSC_VER >= 1400 - uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut); - *szOut = _byteswap_ushort(*szOut); -#else - uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); - std::swap(szOut[0],szOut[1]); -#endif - } - - // ---------------------------------------------------------------------- - /** Swap four bytes of data - * @param[inout] _szOut A void* to save the reintcasts for the caller. */ - static inline void Swap4(void* _szOut) - { - ai_assert(_szOut); - -#if _MSC_VER >= 1400 - uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut); - *szOut = _byteswap_ulong(*szOut); -#else - uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); - std::swap(szOut[0],szOut[3]); - std::swap(szOut[1],szOut[2]); -#endif - } - - // ---------------------------------------------------------------------- - /** Swap eight bytes of data - * @param[inout] _szOut A void* to save the reintcasts for the caller. */ - static inline void Swap8(void* _szOut) - { - ai_assert(_szOut); - -#if _MSC_VER >= 1400 - uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut); - *szOut = _byteswap_uint64(*szOut); -#else - uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut); - std::swap(szOut[0],szOut[7]); - std::swap(szOut[1],szOut[6]); - std::swap(szOut[2],szOut[5]); - std::swap(szOut[3],szOut[4]); -#endif - } - - // ---------------------------------------------------------------------- - /** ByteSwap a float. Not a joke. - * @param[inout] fOut ehm. .. */ - static inline void Swap(float* fOut) { - Swap4(fOut); - } - - // ---------------------------------------------------------------------- - /** ByteSwap a double. Not a joke. - * @param[inout] fOut ehm. .. */ - static inline void Swap(double* fOut) { - Swap8(fOut); - } - - - // ---------------------------------------------------------------------- - /** ByteSwap an int16t. Not a joke. - * @param[inout] fOut ehm. .. */ - static inline void Swap(int16_t* fOut) { - Swap2(fOut); - } - - static inline void Swap(uint16_t* fOut) { - Swap2(fOut); - } - - // ---------------------------------------------------------------------- - /** ByteSwap an int32t. Not a joke. - * @param[inout] fOut ehm. .. */ - static inline void Swap(int32_t* fOut){ - Swap4(fOut); - } - - static inline void Swap(uint32_t* fOut){ - Swap4(fOut); - } - - // ---------------------------------------------------------------------- - /** ByteSwap an int64t. Not a joke. - * @param[inout] fOut ehm. .. */ - static inline void Swap(int64_t* fOut) { - Swap8(fOut); - } - - static inline void Swap(uint64_t* fOut) { - Swap8(fOut); - } - - // ---------------------------------------------------------------------- - //! Templatized ByteSwap - //! \returns param tOut as swapped - template<typename Type> - static inline Type Swapped(Type tOut) - { - return _swapper<Type,sizeof(Type)>()(tOut); - } - -private: - - template <typename T, size_t size> struct _swapper; -}; - -template <typename T> struct ByteSwap::_swapper<T,2> { - T operator() (T tOut) { - Swap2(&tOut); - return tOut; - } -}; - -template <typename T> struct ByteSwap::_swapper<T,4> { - T operator() (T tOut) { - Swap4(&tOut); - return tOut; - } -}; - -template <typename T> struct ByteSwap::_swapper<T,8> { - T operator() (T tOut) { - Swap8(&tOut); - return tOut; - } -}; - -} // Namespace Assimp - - -// -------------------------------------------------------------------------------------- -// ByteSwap macros for BigEndian/LittleEndian support -// -------------------------------------------------------------------------------------- -#if (defined AI_BUILD_BIG_ENDIAN) -# define AI_LE(t) (t) -# define AI_BE(t) ByteSwap::Swapped(t) -# define AI_LSWAP2(p) -# define AI_LSWAP4(p) -# define AI_LSWAP8(p) -# define AI_LSWAP2P(p) -# define AI_LSWAP4P(p) -# define AI_LSWAP8P(p) -# define LE_NCONST const -# define AI_SWAP2(p) ByteSwap::Swap2(&(p)) -# define AI_SWAP4(p) ByteSwap::Swap4(&(p)) -# define AI_SWAP8(p) ByteSwap::Swap8(&(p)) -# define AI_SWAP2P(p) ByteSwap::Swap2((p)) -# define AI_SWAP4P(p) ByteSwap::Swap4((p)) -# define AI_SWAP8P(p) ByteSwap::Swap8((p)) -# define BE_NCONST -#else -# define AI_BE(t) (t) -# define AI_LE(t) ByteSwap::Swapped(t) -# define AI_SWAP2(p) -# define AI_SWAP4(p) -# define AI_SWAP8(p) -# define AI_SWAP2P(p) -# define AI_SWAP4P(p) -# define AI_SWAP8P(p) -# define BE_NCONST const -# define AI_LSWAP2(p) ByteSwap::Swap2(&(p)) -# define AI_LSWAP4(p) ByteSwap::Swap4(&(p)) -# define AI_LSWAP8(p) ByteSwap::Swap8(&(p)) -# define AI_LSWAP2P(p) ByteSwap::Swap2((p)) -# define AI_LSWAP4P(p) ByteSwap::Swap4((p)) -# define AI_LSWAP8P(p) ByteSwap::Swap8((p)) -# define LE_NCONST -#endif - - - -#endif //!! AI_BYTESWAP_H_INC diff --git a/3rdparty/assimp/code/COBLoader.cpp b/3rdparty/assimp/code/COBLoader.cpp deleted file mode 100644 index 7079b359..00000000 --- a/3rdparty/assimp/code/COBLoader.cpp +++ /dev/null @@ -1,1278 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 COBLoader.cpp - * @brief Implementation of the TrueSpace COB/SCN importer class. - */ -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_COB_IMPORTER -#include "COBLoader.h" -#include "COBScene.h" - -#include "StreamReader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -#include "LineSplitter.h" -#include "TinyFormatter.h" - -using namespace Assimp; -using namespace Assimp::COB; -using namespace Assimp::Formatter; - -#define for_each BOOST_FOREACH - - -static const float units[] = { - 1000.f, - 100.f, - 1.f, - 0.001f, - 1.f/0.0254f, - 1.f/0.3048f, - 1.f/0.9144f, - 1.f/1609.344f -}; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -COBImporter::COBImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -COBImporter::~COBImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string& extension = GetExtension(pFile); - if (extension == "cob" || extension == "scn") { - return true; - } - - else if ((!extension.length() || checkSig) && pIOHandler) { - const char* tokens[] = {"Caligary"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// List all extensions handled by this loader -void COBImporter::GetExtensionList(std::set<std::string>& app) -{ - app.insert("cob"); - app.insert("scn"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties for the loader -void COBImporter::SetupProperties(const Importer* pImp) -{ - // nothing to be done for the moment -} - -// ------------------------------------------------------------------------------------------------ -/*static*/ void COBImporter::ThrowException(const std::string& msg) -{ - throw DeadlyImportError("COB: "+msg); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void COBImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - COB::Scene scene; - boost::scoped_ptr<StreamReaderLE> stream(new StreamReaderLE( pIOHandler->Open(pFile,"rb")) ); - - // check header - char head[32]; - stream->CopyAndAdvance(head,32); - if (strncmp(head,"Caligari ",9)) { - ThrowException("Could not found magic id: `Caligari`"); - } - - DefaultLogger::get()->info("File format tag: "+std::string(head+9,6)); - void (COBImporter::* load)(Scene&,StreamReaderLE*)= head[15]=='A'?&COBImporter::ReadAsciiFile:&COBImporter::ReadBinaryFile; - if (head[16]!='L') { - ThrowException("File is big-endian, which is not supported"); - } - - // load data into intermediate structures - (this->*load)(scene,stream.get()); - if (scene.nodes.empty()) { - ThrowException("No nodes loaded"); - } - - // sort faces by material indices - for_each(boost::shared_ptr< Node >& n,scene.nodes) { - if (n->type == Node::TYPE_MESH) { - Mesh& mesh = (Mesh&)(*n.get()); - for_each(Face& f,mesh.faces) { - mesh.temp_map[f.material].push_back(&f); - } - } - } - - // count meshes - for_each(boost::shared_ptr< Node >& n,scene.nodes) { - if (n->type == Node::TYPE_MESH) { - Mesh& mesh = (Mesh&)(*n.get()); - if (mesh.vertex_positions.size() && mesh.texture_coords.size()) { - pScene->mNumMeshes += mesh.temp_map.size(); - } - } - } - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes](); - pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes](); - pScene->mNumMeshes = 0; - - // count lights and cameras - for_each(boost::shared_ptr< Node >& n,scene.nodes) { - if (n->type == Node::TYPE_LIGHT) { - ++pScene->mNumLights; - } - else if (n->type == Node::TYPE_CAMERA) { - ++pScene->mNumCameras; - } - } - - if (pScene->mNumLights) { - pScene->mLights = new aiLight*[pScene->mNumLights](); - } - if (pScene->mNumCameras) { - pScene->mCameras = new aiCamera*[pScene->mNumCameras](); - } - pScene->mNumLights = pScene->mNumCameras = 0; - - // resolve parents by their IDs and build the output graph - boost::scoped_ptr<Node> root(new Group()); - for (size_t n = 0; n < scene.nodes.size(); ++n) { - const Node& nn = *scene.nodes[n].get(); - if (nn.parent_id==0) { - root->temp_children.push_back(&nn); - } - - for (size_t m = n; m < scene.nodes.size(); ++m) { - const Node& mm = *scene.nodes[m].get(); - if (mm.parent_id == nn.id) { - nn.temp_children.push_back(&mm); - } - } - } - - pScene->mRootNode = BuildNodes(*root.get(),scene,pScene); -} - -// ------------------------------------------------------------------------------------------------ -void ConvertTexture(boost::shared_ptr< Texture > tex, MaterialHelper* out, aiTextureType type) -{ - const aiString path( tex->path ); - out->AddProperty(&path,AI_MATKEY_TEXTURE(type,0)); - out->AddProperty(&tex->transform,1,AI_MATKEY_UVTRANSFORM(type,0)); -} - -// ------------------------------------------------------------------------------------------------ -aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill) -{ - aiNode* nd = new aiNode(); - nd->mName.Set(root.name); - nd->mTransformation = root.transform; - - // Note to everybody believing Voodoo is appropriate here: - // I know polymorphism, run as fast as you can ;-) - if (Node::TYPE_MESH == root.type) { - const Mesh& ndmesh = (const Mesh&)(root); - if (ndmesh.vertex_positions.size() && ndmesh.texture_coords.size()) { - - typedef std::pair<unsigned int,Mesh::FaceRefList> Entry; - for_each(const Entry& reflist,ndmesh.temp_map) { - { // create mesh - size_t n = 0; - for_each(Face* f, reflist.second) { - n += f->indices.size(); - } - if (!n) { - continue; - } - aiMesh* outmesh = fill->mMeshes[fill->mNumMeshes++] = new aiMesh(); - ++nd->mNumMeshes; - - outmesh->mVertices = new aiVector3D[n]; - outmesh->mTextureCoords[0] = new aiVector3D[n]; - - outmesh->mFaces = new aiFace[reflist.second.size()](); - for_each(Face* f, reflist.second) { - if (f->indices.empty()) { - continue; - } - - aiFace& fout = outmesh->mFaces[outmesh->mNumFaces++]; - fout.mIndices = new unsigned int[f->indices.size()]; - - for_each(VertexIndex& v, f->indices) { - if (v.pos_idx >= ndmesh.vertex_positions.size()) { - ThrowException("Position index out of range"); - } - if (v.uv_idx >= ndmesh.texture_coords.size()) { - ThrowException("UV index out of range"); - } - outmesh->mVertices[outmesh->mNumVertices] = ndmesh.vertex_positions[ v.pos_idx ]; - outmesh->mTextureCoords[0][outmesh->mNumVertices] = aiVector3D( - ndmesh.texture_coords[ v.uv_idx ].x, - ndmesh.texture_coords[ v.uv_idx ].y, - 0.f - ); - - fout.mIndices[fout.mNumIndices++] = outmesh->mNumVertices++; - } - } - outmesh->mMaterialIndex = fill->mNumMaterials; - }{ // create material - const Material* min = NULL; - for_each(const Material& m, scin.materials) { - if (m.parent_id == ndmesh.id && m.matnum == reflist.first) { - min = &m; - break; - } - } - boost::scoped_ptr<const Material> defmat; - if (!min) { - DefaultLogger::get()->debug(format()<<"Could not resolve material index " - <<reflist.first<<" - creating default material for this slot"); - - defmat.reset(min=new Material()); - } - - MaterialHelper* mat = new MaterialHelper(); - fill->mMaterials[fill->mNumMaterials++] = mat; - - const aiString s(format("#mat_")<<fill->mNumMeshes<<"_"<<min->matnum); - mat->AddProperty(&s,AI_MATKEY_NAME); - - if (int tmp = ndmesh.draw_flags & Mesh::WIRED ? 1 : 0) { - mat->AddProperty(&tmp,1,AI_MATKEY_ENABLE_WIREFRAME); - } - - { int shader; - switch(min->shader) - { - case Material::FLAT: - shader = aiShadingMode_Gouraud; - break; - - case Material::PHONG: - shader = aiShadingMode_Phong; - break; - - case Material::METAL: - shader = aiShadingMode_CookTorrance; - break; - - default: - ai_assert(false); // shouldn't be here - } - mat->AddProperty(&shader,1,AI_MATKEY_SHADING_MODEL); - if (shader != aiShadingMode_Gouraud) { - mat->AddProperty(&min->exp,1,AI_MATKEY_SHININESS); - } - } - - mat->AddProperty(&min->ior,1,AI_MATKEY_REFRACTI); - mat->AddProperty(&min->rgb,1,AI_MATKEY_COLOR_DIFFUSE); - - aiColor3D c = aiColor3D(min->rgb)*min->ks; - mat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR); - - c = aiColor3D(min->rgb)*min->ka; - mat->AddProperty(&c,1,AI_MATKEY_COLOR_AMBIENT); - - // convert textures if some exist. - if (min->tex_color) { - ConvertTexture(min->tex_color,mat,aiTextureType_DIFFUSE); - } - if (min->tex_env) { - ConvertTexture(min->tex_env ,mat,aiTextureType_UNKNOWN); - } - if (min->tex_bump) { - ConvertTexture(min->tex_bump ,mat,aiTextureType_HEIGHT); - } - } - } - } - } - else if (Node::TYPE_LIGHT == root.type) { - const Light& ndlight = (const Light&)(root); - aiLight* outlight = fill->mLights[fill->mNumLights++] = new aiLight(); - - outlight->mName.Set(ndlight.name); - outlight->mColorDiffuse = outlight->mColorAmbient = outlight->mColorSpecular = ndlight.color; - - outlight->mAngleOuterCone = AI_DEG_TO_RAD(ndlight.angle); - outlight->mAngleInnerCone = AI_DEG_TO_RAD(ndlight.inner_angle); - - // XXX - outlight->mType = ndlight.ltype==Light::SPOT ? aiLightSource_SPOT : aiLightSource_DIRECTIONAL; - } - else if (Node::TYPE_CAMERA == root.type) { - const Camera& ndcam = (const Camera&)(root); - aiCamera* outcam = fill->mCameras[fill->mNumCameras++] = new aiCamera(); - - outcam->mName.Set(ndcam.name); - } - - // add meshes - if (nd->mNumMeshes) { // mMeshes must be NULL if count is 0 - nd->mMeshes = new unsigned int[nd->mNumMeshes]; - for (unsigned int i = 0; i < nd->mNumMeshes;++i) { - nd->mMeshes[i] = fill->mNumMeshes-i-1; - } - } - - // add children recursively - nd->mChildren = new aiNode*[root.temp_children.size()](); - for_each(const Node* n, root.temp_children) { - (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n,scin,fill))->mParent = nd; - } - - return nd; -} - -// ------------------------------------------------------------------------------------------------ -// Read an ASCII file into the given scene data structure -void COBImporter::ReadAsciiFile(Scene& out, StreamReaderLE* stream) -{ - ChunkInfo ci; - for (LineSplitter splitter(*stream);splitter;++splitter) { - - // add all chunks to be recognized here. /else ../ ommitted intentionally. - if (splitter.match_start("PolH ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadPolH_Ascii(out,splitter,ci); - } - if (splitter.match_start("BitM ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadBitM_Ascii(out,splitter,ci); - } - if (splitter.match_start("Mat1 ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadMat1_Ascii(out,splitter,ci); - } - if (splitter.match_start("Grou ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadGrou_Ascii(out,splitter,ci); - } - if (splitter.match_start("Lght ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadLght_Ascii(out,splitter,ci); - } - if (splitter.match_start("Came ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadCame_Ascii(out,splitter,ci); - } - if (splitter.match_start("Bone ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadBone_Ascii(out,splitter,ci); - } - if (splitter.match_start("Chan ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadChan_Ascii(out,splitter,ci); - } - if (splitter.match_start("Unit ")) { - ReadChunkInfo_Ascii(ci,splitter); - ReadUnit_Ascii(out,splitter,ci); - } - if (splitter.match_start("END ")) { - // we don't need this, but I guess there is a reason this - // chunk has been implemented into COB for. - return; - } - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadChunkInfo_Ascii(ChunkInfo& out, const LineSplitter& splitter) -{ - const char* all_tokens[8]; - splitter.get_tokens(all_tokens); - - out.version = (all_tokens[1][1]-'0')*100+(all_tokens[1][3]-'0')*10+(all_tokens[1][4]-'0'); - out.id = strtol10(all_tokens[3]); - out.parent_id = strtol10(all_tokens[5]); - out.size = strtol10s(all_tokens[7]); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo& nfo, const char* name) -{ - const std::string error = format("Encountered unsupported chunk: ") << name << - " [version: "<<nfo.version<<", size: "<<nfo.size<<"]"; - - // we can recover if the chunk size was specified. - if (nfo.size != static_cast<unsigned int>(-1)) { - DefaultLogger::get()->error(error); - - // (HACK) - our current position in the stream is the beginning of the - // head line of the next chunk. That's fine, but the caller is going - // to call ++ on `splitter`, which we need to swallow to avoid - // missing the next line. - splitter.get_stream().IncPtr(nfo.size); - splitter.swallow_next_increment(); - } - else ThrowException(error); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message) { - LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message) { - LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message) { - LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message) { - LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogWarn_Ascii(const Formatter::format& message) { - DefaultLogger::get()->warn(std::string("COB: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogError_Ascii(const Formatter::format& message) { - DefaultLogger::get()->error(std::string("COB: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogInfo_Ascii(const Formatter::format& message) { - DefaultLogger::get()->info(std::string("COB: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::LogDebug_Ascii(const Formatter::format& message) { - DefaultLogger::get()->debug(std::string("COB: ")+=message); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& nfo) -{ - for (;splitter;++splitter) { - if (splitter.match_start("Name")) { - msh.name = std::string(splitter[1]); - - // make nice names by merging the dupe count - std::replace(msh.name.begin(),msh.name.end(), - ',','_'); - } - else if (splitter.match_start("Transform")) { - for (unsigned int y = 0; y < 4 && ++splitter; ++y) { - const char* s = splitter->c_str(); - for (unsigned int x = 0; x < 4; ++x) { - SkipSpaces(&s); - msh.transform[y][x] = fast_atof(&s); - } - } - // we need the transform chunk, so we won't return until we have it. - return; - } - } -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -void COBImporter::ReadFloat3Tuple_Ascii(T& fill, const char** in) -{ - const char* rgb = *in; - for (unsigned int i = 0; i < 3; ++i) { - SkipSpaces(&rgb); - if (*rgb == ',')++rgb; - SkipSpaces(&rgb); - - fill[i] = fast_atof(&rgb); - } - *in = rgb; -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 8) { - return UnsupportedChunk_Ascii(splitter,nfo,"Mat1"); - } - - ++splitter; - if (!splitter.match_start("mat# ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `mat#` line in `Mat1` chunk "<<nfo.id); - return; - } - - out.materials.push_back(Material()); - Material& mat = out.materials.back(); - mat = nfo; - - mat.matnum = strtol10(splitter[1]); - ++splitter; - - if (!splitter.match_start("shader: ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `mat#` line in `Mat1` chunk "<<nfo.id); - return; - } - std::string shader = std::string(splitter[1]); - shader = shader.substr(0,shader.find_first_of(" \t")); - - if (shader == "metal") { - mat.shader = Material::METAL; - } - else if (shader == "phong") { - mat.shader = Material::PHONG; - } - else if (shader != "flat") { - LogWarn_Ascii(splitter,format()<< - "Unknown value for `shader` in `Mat1` chunk "<<nfo.id); - } - - ++splitter; - if (!splitter.match_start("rgb ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `rgb` line in `Mat1` chunk "<<nfo.id); - } - - const char* rgb = splitter[1]; - ReadFloat3Tuple_Ascii(mat.rgb,&rgb); - - ++splitter; - if (!splitter.match_start("alpha ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `alpha` line in `Mat1` chunk "<<nfo.id); - } - - const char* tokens[10]; - splitter.get_tokens(tokens); - - mat.alpha = fast_atof( tokens[1] ); - mat.ka = fast_atof( tokens[3] ); - mat.ks = fast_atof( tokens[5] ); - mat.exp = fast_atof( tokens[7] ); - mat.ior = fast_atof( tokens[9] ); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 1) { - return UnsupportedChunk_Ascii(splitter,nfo,"Unit"); - } - ++splitter; - if (!splitter.match_start("Units ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `Units` line in `Unit` chunk "<<nfo.id); - return; - } - - // parent chunks preceede their childs, so we should have the - // corresponding chunk already. - for_each(boost::shared_ptr< Node >& nd, out.nodes) { - if (nd->id == nfo.parent_id) { - const unsigned int t=strtol10(splitter[1]); - - nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?( - LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id) - ,1.f):units[t]; - return; - } - } - LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of " - <<nfo.parent_id<<" which does not exist"); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadChan_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 8) { - return UnsupportedChunk_Ascii(splitter,nfo,"Chan"); - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 8) { - return UnsupportedChunk_Ascii(splitter,nfo,"Lght"); - } - - out.nodes.push_back(boost::shared_ptr<Light>(new Light())); - Light& msh = (Light&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); - - if (splitter.match_start("Infinite ")) { - msh.ltype = Light::INFINITE; - } - else if (splitter.match_start("Local ")) { - msh.ltype = Light::LOCAL; - } - else if (splitter.match_start("Spot ")) { - msh.ltype = Light::SPOT; - } - else { - LogWarn_Ascii(splitter,format()<< - "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter); - msh.ltype = Light::SPOT; - } - - ++splitter; - if (!splitter.match_start("color ")) { - LogWarn_Ascii(splitter,format()<< - "Expected `color` line in `Lght` chunk "<<nfo.id); - } - - const char* rgb = splitter[1]; - ReadFloat3Tuple_Ascii(msh.color ,&rgb); - - SkipSpaces(&rgb); - if (strncmp(rgb,"cone angle",10)) { - LogWarn_Ascii(splitter,format()<< - "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id); - } - SkipSpaces(rgb+10,&rgb); - msh.angle = fast_atof(&rgb); - - SkipSpaces(&rgb); - if (strncmp(rgb,"inner angle",11)) { - LogWarn_Ascii(splitter,format()<< - "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id); - } - SkipSpaces(rgb+11,&rgb); - msh.inner_angle = fast_atof(&rgb); - - // skip the rest for we can't handle this kind of physically-based lighting information. -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadCame_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 2) { - return UnsupportedChunk_Ascii(splitter,nfo,"Came"); - } - - out.nodes.push_back(boost::shared_ptr<Camera>(new Camera())); - Camera& msh = (Camera&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); - - // skip the next line, we don't know this differenciation between a - // standard camera and a panoramic camera. - ++splitter; -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBone_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 5) { - return UnsupportedChunk_Ascii(splitter,nfo,"Bone"); - } - - out.nodes.push_back(boost::shared_ptr<Bone>(new Bone())); - Bone& msh = (Bone&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); - - // TODO -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadGrou_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 1) { - return UnsupportedChunk_Ascii(splitter,nfo,"Grou"); - } - - out.nodes.push_back(boost::shared_ptr<Group>(new Group())); - Group& msh = (Group&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 8) { - return UnsupportedChunk_Ascii(splitter,nfo,"PolH"); - } - - out.nodes.push_back(boost::shared_ptr<Mesh>(new Mesh())); - Mesh& msh = (Mesh&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Ascii(msh,++splitter,nfo); - - // the chunk has a fixed order of components, but some are not interesting of us so - // we're just looking for keywords in arbitrary order. The end of the chunk is - // either the last `Face` or the `DrawFlags` attribute, depending on the format ver. - for (;splitter;++splitter) { - if (splitter.match_start("World Vertices")) { - const unsigned int cnt = strtol10(splitter[2]); - msh.vertex_positions.resize(cnt); - - for (unsigned int cur = 0;cur < cnt && ++splitter;++cur) { - const char* s = splitter->c_str(); - - aiVector3D& v = msh.vertex_positions[cur]; - - SkipSpaces(&s); - v.x = fast_atof(&s); - SkipSpaces(&s); - v.y = fast_atof(&s); - SkipSpaces(&s); - v.z = fast_atof(&s); - } - } - else if (splitter.match_start("Texture Vertices")) { - const unsigned int cnt = strtol10(splitter[2]); - msh.texture_coords.resize(cnt); - - for (unsigned int cur = 0;cur < cnt && ++splitter;++cur) { - const char* s = splitter->c_str(); - - aiVector2D& v = msh.texture_coords[cur]; - - SkipSpaces(&s); - v.x = fast_atof(&s); - SkipSpaces(&s); - v.y = fast_atof(&s); - } - } - else if (splitter.match_start("Faces")) { - const unsigned int cnt = strtol10(splitter[1]); - msh.faces.reserve(cnt); - - for (unsigned int cur = 0; cur < cnt && ++splitter ;++cur) { - if (splitter.match_start("Hole")) { - LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line"); - continue; - } - - if (!splitter.match_start("Face")) { - ThrowException("Expected Face line"); - } - - msh.faces.push_back(Face()); - Face& face = msh.faces.back(); - - face.indices.resize(strtol10(splitter[2])); - face.flags = strtol10(splitter[4]); - face.material = strtol10(splitter[6]); - - const char* s = (++splitter)->c_str(); - for (size_t i = 0; i < face.indices.size(); ++i) { - if (!SkipSpaces(&s)) { - ThrowException("Expected EOL token in Face entry"); - } - if ('<' != *s++) { - ThrowException("Expected < token in Face entry"); - } - face.indices[i].pos_idx = strtol10(s,&s); - if (',' != *s++) { - ThrowException("Expected , token in Face entry"); - } - face.indices[i].uv_idx = strtol10(s,&s); - if ('>' != *s++) { - ThrowException("Expected < token in Face entry"); - } - } - } - if (nfo.version <= 4) { - break; - } - } - else if (splitter.match_start("DrawFlags")) { - msh.draw_flags = strtol10(splitter[1]); - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBitM_Ascii(Scene& out, LineSplitter& splitter, const ChunkInfo& nfo) -{ - if (nfo.version > 1) { - return UnsupportedChunk_Ascii(splitter,nfo,"BitM"); - } -/* - "\nThumbNailHdrSize %ld" - "\nThumbHeader: %02hx 02hx %02hx " - "\nColorBufSize %ld" - "\nColorBufZipSize %ld" - "\nZippedThumbnail: %02hx 02hx %02hx " -*/ - - const unsigned int head = strtol10((++splitter)[1]); - if (head != sizeof(Bitmap::BitmapHeader)) { - LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk"); - return; - } - - /*union { - Bitmap::BitmapHeader data; - char opaq[sizeof Bitmap::BitmapHeader()]; - };*/ -// ReadHexOctets(opaq,head,(++splitter)[1]); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadString_Binary(std::string& out, StreamReaderLE& reader) -{ - out.resize( reader.GetI2()); - for_each(char& c,out) { - c = reader.GetI1(); - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBasicNodeInfo_Binary(Node& msh, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - const unsigned int dupes = reader.GetI2(); - ReadString_Binary(msh.name,reader); - - msh.name = format(msh.name)<<'_'<<dupes; - - // skip local axes for the moment - reader.IncPtr(48); - - msh.transform = aiMatrix4x4(); - for (unsigned int y = 0; y < 3; ++y) { - for (unsigned int x =0; x < 4; ++x) { - msh.transform[y][x] = reader.GetF4(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkInfo& nfo, const char* name) -{ - const std::string error = format("Encountered unsupported chunk: ") << name << - " [version: "<<nfo.version<<", size: "<<nfo.size<<"]"; - - // we can recover if the chunk size was specified. - if (nfo.size != static_cast<unsigned int>(-1)) { - DefaultLogger::get()->error(error); - reader.IncPtr(nfo.size); - } - else ThrowException(error); -} - -// ------------------------------------------------------------------------------------------------ -// tiny utility guard to aid me at staying within chunk boundaries. -class chunk_guard { - -public: - - chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader) - : nfo(nfo) - , reader(reader) - , cur(reader.GetCurrentPos()) - { - } - - ~chunk_guard() { - // don't do anything if the size is not given - if (nfo.size != static_cast<unsigned int>(-1)) { - reader.IncPtr(static_cast<int>(nfo.size)-reader.GetCurrentPos()+cur); - } - } - -private: - - const COB::ChunkInfo& nfo; - StreamReaderLE& reader; - long cur; -}; - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBinaryFile(Scene& out, StreamReaderLE* reader) -{ - while (1) { - std::string type; - type += reader -> GetI1() - ,type += reader -> GetI1() - ,type += reader -> GetI1() - ,type += reader -> GetI1() - ; - - ChunkInfo nfo; - nfo.version = reader -> GetI2()*10; - nfo.version += reader -> GetI2(); - - nfo.id = reader->GetI4(); - nfo.parent_id = reader->GetI4(); - nfo.size = reader->GetI4(); - - if (type == "PolH") { - ReadPolH_Binary(out,*reader,nfo); - } - else if (type == "BitM") { - ReadBitM_Binary(out,*reader,nfo); - } - else if (type == "Grou") { - ReadGrou_Binary(out,*reader,nfo); - } - else if (type == "Lght") { - ReadLght_Binary(out,*reader,nfo); - } - else if (type == "Came") { - ReadCame_Binary(out,*reader,nfo); - } - else if (type == "Mat1") { - ReadMat1_Binary(out,*reader,nfo); - } - /* else if (type == "Bone") { - ReadBone_Binary(out,*reader,nfo); - } - else if (type == "Chan") { - ReadChan_Binary(out,*reader,nfo); - }*/ - else if (type == "Unit") { - ReadUnit_Binary(out,*reader,nfo); - } - else if (type == "OLay") { - // ignore layer index silently. - if (nfo.size != static_cast<unsigned int>(-1) ) { - reader->IncPtr(nfo.size); - } - else return UnsupportedChunk_Binary(*reader,nfo,type.c_str()); - } - else if (type == "END ") { - return; - } - else UnsupportedChunk_Binary(*reader,nfo,type.c_str()); - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 8) { - return UnsupportedChunk_Binary(reader,nfo,"PolH"); - } - const chunk_guard cn(nfo,reader); - - out.nodes.push_back(boost::shared_ptr<Mesh>(new Mesh())); - Mesh& msh = (Mesh&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Binary(msh,reader,nfo); - - msh.vertex_positions.resize(reader.GetI4()); - for_each(aiVector3D& v,msh.vertex_positions) { - v.x = reader.GetF4(); - v.y = reader.GetF4(); - v.z = reader.GetF4(); - } - - msh.texture_coords.resize(reader.GetI4()); - for_each(aiVector2D& v,msh.texture_coords) { - v.x = reader.GetF4(); - v.y = reader.GetF4(); - } - - const size_t numfuck = reader.GetI4(); - msh.faces.reserve(numfuck); - for (size_t i = 0; i < numfuck; ++i) { - // XXX backface culling flag is 0x10 in flags - - // hole? - bool hole; - if ((hole = (reader.GetI1() & 0x08) != 0)) { - // XXX Basically this should just work fine - then triangulator - // should output properly triangulated data even for polygons - // with holes. Test data specific to COB is needed to confirm it. - if (msh.faces.empty()) { - ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id); - } - } - else msh.faces.push_back(Face()); - Face& f = msh.faces.back(); - - const size_t num = reader.GetI2(); - f.indices.reserve(f.indices.size() + num); - - if (!hole) { - f.material = reader.GetI2(); - f.flags = 0; - } - - for (size_t x = 0; x < num; ++x) { - f.indices.push_back(VertexIndex()); - - VertexIndex& v = f.indices.back(); - v.pos_idx = reader.GetI4(); - v.uv_idx = reader.GetI4(); - } - - if (hole) { - std::reverse(f.indices.rbegin(),f.indices.rbegin()+num); - } - } - if (nfo.version>4) { - msh.draw_flags = reader.GetI4(); - } - nfo.version>5 && nfo.version<8 ? reader.GetI4() : 0; -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 1) { - return UnsupportedChunk_Binary(reader,nfo,"BitM"); - } - - const chunk_guard cn(nfo,reader); - - const uint32_t len = reader.GetI4(); - reader.IncPtr(len); - - reader.GetI4(); - reader.IncPtr(reader.GetI4()); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 8) { - return UnsupportedChunk_Binary(reader,nfo,"Mat1"); - } - - const chunk_guard cn(nfo,reader); - - out.materials.push_back(Material()); - Material& mat = out.materials.back(); - mat = nfo; - - mat.matnum = reader.GetI2(); - switch(reader.GetI1()) { - case 'f': - mat.type = Material::FLAT; - break; - case 'p': - mat.type = Material::PHONG; - break; - case 'm': - mat.type = Material::METAL; - break; - default: - LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id); - mat.type = Material::FLAT; - } - - switch(reader.GetI1()) { - case 'f': - mat.autofacet = Material::FACETED; - break; - case 'a': - mat.autofacet = Material::AUTOFACETED; - break; - case 's': - mat.autofacet = Material::SMOOTH; - break; - default: - LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id); - mat.autofacet = Material::FACETED; - } - mat.autofacet_angle = static_cast<float>(reader.GetI1()); - - mat.rgb.r = reader.GetF4(); - mat.rgb.g = reader.GetF4(); - mat.rgb.b = reader.GetF4(); - - mat.alpha = reader.GetF4(); - mat.ka = reader.GetF4(); - mat.ks = reader.GetF4(); - mat.exp = reader.GetF4(); - mat.ior = reader.GetF4(); - - char id[2]; - id[0] = reader.GetI1(),id[1] = reader.GetI1(); - - if (id[0] == 'e' && id[1] == ':') { - mat.tex_env.reset(new Texture()); - - reader.GetI1(); - ReadString_Binary(mat.tex_env->path,reader); - - // advance to next texture-id - id[0] = reader.GetI1(),id[1] = reader.GetI1(); - } - - if (id[0] == 't' && id[1] == ':') { - mat.tex_color.reset(new Texture()); - - reader.GetI1(); - ReadString_Binary(mat.tex_color->path,reader); - - mat.tex_color->transform.mTranslation.x = reader.GetF4(); - mat.tex_color->transform.mTranslation.y = reader.GetF4(); - - mat.tex_color->transform.mScaling.x = reader.GetF4(); - mat.tex_color->transform.mScaling.y = reader.GetF4(); - - // advance to next texture-id - id[0] = reader.GetI1(),id[1] = reader.GetI1(); - } - - if (id[0] == 'b' && id[1] == ':') { - mat.tex_bump.reset(new Texture()); - - reader.GetI1(); - ReadString_Binary(mat.tex_bump->path,reader); - - mat.tex_bump->transform.mTranslation.x = reader.GetF4(); - mat.tex_bump->transform.mTranslation.y = reader.GetF4(); - - mat.tex_bump->transform.mScaling.x = reader.GetF4(); - mat.tex_bump->transform.mScaling.y = reader.GetF4(); - - // skip amplitude for I don't know its purpose. - reader.GetF4(); - } - reader.IncPtr(-2); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 2) { - return UnsupportedChunk_Binary(reader,nfo,"Came"); - } - - const chunk_guard cn(nfo,reader); - - out.nodes.push_back(boost::shared_ptr<Camera>(new Camera())); - Camera& msh = (Camera&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Binary(msh,reader,nfo); - - // the rest is not interesting for us, so we skip over it. - if (nfo.version > 1) { - if (reader.GetI2()==512) { - reader.IncPtr(42); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 2) { - return UnsupportedChunk_Binary(reader,nfo,"Lght"); - } - - const chunk_guard cn(nfo,reader); - - out.nodes.push_back(boost::shared_ptr<Light>(new Light())); - Light& msh = (Light&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Binary(msh,reader,nfo); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 2) { - return UnsupportedChunk_Binary(reader,nfo,"Grou"); - } - - const chunk_guard cn(nfo,reader); - - out.nodes.push_back(boost::shared_ptr<Group>(new Group())); - Group& msh = (Group&)(*out.nodes.back().get()); - msh = nfo; - - ReadBasicNodeInfo_Binary(msh,reader,nfo); -} - -// ------------------------------------------------------------------------------------------------ -void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const ChunkInfo& nfo) -{ - if (nfo.version > 1) { - return UnsupportedChunk_Binary(reader,nfo,"Unit"); - } - - const chunk_guard cn(nfo,reader); - - // parent chunks preceede their childs, so we should have the - // corresponding chunk already. - for_each(boost::shared_ptr< Node >& nd, out.nodes) { - if (nd->id == nfo.parent_id) { - const unsigned int t=reader.GetI2(); - nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?( - LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id) - ,1.f):units[t]; - - return; - } - } - LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of " - <<nfo.parent_id<<" which does not exist"); -} - - -#endif diff --git a/3rdparty/assimp/code/COBLoader.h b/3rdparty/assimp/code/COBLoader.h deleted file mode 100644 index 55e484b3..00000000 --- a/3rdparty/assimp/code/COBLoader.h +++ /dev/null @@ -1,175 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 COBLoader.h - * @brief Declaration of the TrueSpace (*.cob,*.scn) importer class. - */ -#ifndef INCLUDED_AI_COB_LOADER_H -#define INCLUDED_AI_COB_LOADER_H - -#include "BaseImporter.h" -namespace Assimp { - class LineSplitter; - - // TinyFormatter.h - namespace Formatter { - template <typename T,typename TR, typename A> class basic_formatter; - typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format; - } - - // COBScene.h - namespace COB { - struct ChunkInfo; - struct Node; - struct Scene; - } - -// ------------------------------------------------------------------------------------------- -/** Importer class to load TrueSpace files (cob,scn) up to v6. - * - * Currently relatively limited, loads only ASCII files and needs more test coverage. */ -// ------------------------------------------------------------------------------------------- -class COBImporter : public BaseImporter -{ - friend class Importer; - -protected: - - /** Constructor to be privately used by Importer */ - COBImporter(); - - /** Destructor, private as well */ - ~COBImporter(); - -public: - - // -------------------- - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // -------------------- - void GetExtensionList(std::set<std::string>& app); - - // -------------------- - void SetupProperties(const Importer* pImp); - - // -------------------- - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - - // ------------------------------------------------------------------- - /** Prepend 'COB: ' and throw msg.*/ - static void ThrowException(const std::string& msg); - - // ------------------------------------------------------------------- - /** @brief Read from an ascii scene/object file - * @param out Receives output data. - * @param stream Stream to read from. */ - void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream); - - // ------------------------------------------------------------------- - /** @brief Read from a binary scene/object file - * @param out Receives output data. - * @param stream Stream to read from. */ - void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream); - - -private: - - // Conversion to Assimp output format - - aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill); - -private: - - // ASCII file support - - void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name); - void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter); - void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo); - template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in); - - void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo); - - - // ASCII file logging stuff to add proper line numbers to messages - - static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message); - static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message); - static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message); - static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message); - - static void LogWarn_Ascii (const Formatter::format& message); - static void LogError_Ascii (const Formatter::format& message); - static void LogInfo_Ascii (const Formatter::format& message); - static void LogDebug_Ascii (const Formatter::format& message); - - - // Binary file support - - void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name); - void ReadString_Binary(std::string& out, StreamReaderLE& reader); - void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - - void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo); - - -}; // !class COBImporter - -} // end of namespace Assimp -#endif // AI_UNREALIMPORTER_H_INC diff --git a/3rdparty/assimp/code/COBScene.h b/3rdparty/assimp/code/COBScene.h deleted file mode 100644 index 794ee137..00000000 --- a/3rdparty/assimp/code/COBScene.h +++ /dev/null @@ -1,272 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 COBScene.h -* @brief Utilities for the COB importer. -*/ -#ifndef INCLUDED_AI_COB_SCENE_H -#define INCLUDED_AI_COB_SCENE_H - -#include <boost/shared_ptr.hpp> -#include "BaseImporter.h" - -namespace Assimp { - namespace COB { - -// ------------------ -/** Represents a single vertex index in a face */ -struct VertexIndex -{ - // intentionally uninitialized - unsigned int pos_idx,uv_idx; -}; - -// ------------------ -/** COB Face data structure */ -struct Face -{ - // intentionally uninitialized - unsigned int material, flags; - std::vector<VertexIndex> indices; -}; - -// ------------------ -/** COB chunk header information */ -struct ChunkInfo -{ - enum {NO_SIZE=0xffffffff}; - - ChunkInfo () - : id (0) - , parent_id (0) - , version (0) - , size (NO_SIZE) - {} - - // Id of this chunk, unique within file - unsigned int id; - - // and the corresponding parent - unsigned int parent_id; - - // version. v1.23 becomes 123 - unsigned int version; - - // chunk size in bytes, only relevant for binary files - // NO_SIZE is also valid. - unsigned int size; -}; - -// ------------------ -/** A node in the scenegraph */ -struct Node : public ChunkInfo -{ - using ChunkInfo::operator=; - enum Type { - TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE - }; - - virtual ~Node() {} - Node(Type type) : type(type), unit_scale(1.f){} - - Type type; - - // used during resolving - typedef std::deque<const Node*> ChildList; - mutable ChildList temp_children; - - // unique name - std::string name; - - // local mesh transformation - aiMatrix4x4 transform; - - // scaling for this node to get to the metric system - float unit_scale; -}; - -// ------------------ -/** COB Mesh data structure */ -struct Mesh : public Node -{ - using ChunkInfo::operator=; - enum DrawFlags { - SOLID = 0x1, - TRANS = 0x2, - WIRED = 0x4, - BBOX = 0x8, - HIDE = 0x10 - }; - - Mesh() - : Node(TYPE_MESH) - , draw_flags(SOLID) - {} - - // vertex elements - std::vector<aiVector2D> texture_coords; - std::vector<aiVector3D> vertex_positions; - - // face data - std::vector<Face> faces; - - // misc. drawing flags - unsigned int draw_flags; - - // used during resolving - typedef std::deque<Face*> FaceRefList; - typedef std::map< unsigned int,FaceRefList > TempMap; - TempMap temp_map; -}; - -// ------------------ -/** COB Group data structure */ -struct Group : public Node -{ - using ChunkInfo::operator=; - Group() : Node(TYPE_GROUP) {} -}; - -// ------------------ -/** COB Bone data structure */ -struct Bone : public Node -{ - using ChunkInfo::operator=; - Bone() : Node(TYPE_BONE) {} -}; - -// ------------------ -/** COB Light data structure */ -struct Light : public Node -{ - enum LightType { - SPOT,LOCAL,INFINITE - }; - - using ChunkInfo::operator=; - Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {} - - aiColor3D color; - float angle,inner_angle; - - LightType ltype; -}; - -// ------------------ -/** COB Camera data structure */ -struct Camera : public Node -{ - using ChunkInfo::operator=; - Camera() : Node(TYPE_CAMERA) {} -}; - -// ------------------ -/** COB Texture data structure */ -struct Texture -{ - std::string path; - aiUVTransform transform; -}; - -// ------------------ -/** COB Material data structure */ -struct Material : ChunkInfo -{ - using ChunkInfo::operator=; - enum Shader { - FLAT,PHONG,METAL - }; - - enum AutoFacet { - FACETED,AUTOFACETED,SMOOTH - }; - - Material() : alpha(),exp(),ior(),ka(),ks(1.f), - matnum(0xffffffff), - shader(FLAT),autofacet(FACETED), - autofacet_angle() - {} - - std::string type; - - aiColor3D rgb; - float alpha, exp, ior,ka,ks; - - unsigned int matnum; - Shader shader; - - AutoFacet autofacet; - float autofacet_angle; - - boost::shared_ptr<Texture> tex_env,tex_bump,tex_color; -}; - -// ------------------ -/** Embedded bitmap, for instance for the thumbnail image */ -struct Bitmap : ChunkInfo -{ - Bitmap() : orig_size() {} - struct BitmapHeader - { - }; - - BitmapHeader head; - size_t orig_size; - std::vector<char> buff_zipped; -}; - -typedef std::deque< boost::shared_ptr<Node> > NodeList; -typedef std::vector< Material > MaterialList; - -// ------------------ -/** Represents a master COB scene, even if we loaded just a single COB file */ -struct Scene -{ - NodeList nodes; - MaterialList materials; - - // becomes *0 later - Bitmap thumbnail; -}; - - } // end COB -} // end Assimp - -#endif diff --git a/3rdparty/assimp/code/CSMLoader.cpp b/3rdparty/assimp/code/CSMLoader.cpp deleted file mode 100644 index 2348c738..00000000 --- a/3rdparty/assimp/code/CSMLoader.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2009, ASSIMP Development 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 Development 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 CSMLoader.cpp - * Implementation of the CSM importer class. - */ - -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER - -#include "CSMLoader.h" -#include "SkeletonMeshBuilder.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -CSMImporter::CSMImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -CSMImporter::~CSMImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - // check file extension - const std::string extension = GetExtension(pFile); - - if ( extension == "csm") - return true; - - if ((checkSig || !extension.length()) && pIOHandler) { - const char* tokens[] = {"$Filename"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Build a string of all file extensions supported -void CSMImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("csm"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties for the loader -void CSMImporter::SetupProperties(const Importer* pImp) -{ - // nothing to be done for the moment -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void CSMImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open CSM file " + pFile + "."); - } - - // allocate storage and copy the contents of the file to a memory buffer - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; - - aiAnimation* anim = new aiAnimation(); - int first = 0, last = 0x00ffffff; - - // now process the file and look out for '$' sections - while (1) { - SkipSpaces(&buffer); - if ('\0' == *buffer) - break; - - if ('$' == *buffer) { - ++buffer; - if (TokenMatchI(buffer,"firstframe",10)) { - SkipSpaces(&buffer); - first = strtol10s(buffer,&buffer); - } - else if (TokenMatchI(buffer,"lastframe",9)) { - SkipSpaces(&buffer); - last = strtol10s(buffer,&buffer); - } - else if (TokenMatchI(buffer,"rate",4)) { - SkipSpaces(&buffer); - float d; - buffer = fast_atof_move(buffer,d); - anim->mTicksPerSecond = d; - } - else if (TokenMatchI(buffer,"order",5)) { - std::vector< aiNodeAnim* > anims_temp; - anims_temp.reserve(30); - while (1) { - SkipSpaces(&buffer); - if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$') - break; // next section - - // Construct a new node animation channel and setup its name - anims_temp.push_back(new aiNodeAnim()); - aiNodeAnim* nda = anims_temp.back(); - - char* ot = nda->mNodeName.data; - while (!IsSpaceOrNewLine(*buffer)) - *ot++ = *buffer++; - - *ot = '\0'; - nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data); - } - - anim->mNumChannels = anims_temp.size(); - if (!anim->mNumChannels) - throw DeadlyImportError("CSM: Empty $order section"); - - // copy over to the output animation - anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels); - } - else if (TokenMatchI(buffer,"points",6)) { - if (!anim->mNumChannels) - throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'"); - - // If we know how many frames we'll read, we can preallocate some storage - unsigned int alloc = 100; - if (last != 0x00ffffff) - { - alloc = last-first; - alloc += alloc>>2u; // + 25% - for (unsigned int i = 0; i < anim->mNumChannels;++i) - anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc]; - } - - unsigned int filled = 0; - - // Now read all point data. - while (1) { - SkipSpaces(&buffer); - if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$')) { - break; // next section - } - - // read frame - const int frame = ::strtol10(buffer,&buffer); - last = std::max(frame,last); - first = std::min(frame,last); - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - - aiNodeAnim* s = anim->mChannels[i]; - if (s->mNumPositionKeys == alloc) { /* need to reallocate? */ - - aiVectorKey* old = s->mPositionKeys; - s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2]; - ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc); - delete[] old; - } - - // read x,y,z - if (!SkipSpacesAndLineEnd(&buffer)) - throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord"); - - if (TokenMatchI(buffer, "DROPOUT", 7)) { - // seems this is invalid marker data; at least the doc says it's possible - DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)"); - } - else { - aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys; - sub->mTime = (double)frame; - buffer = fast_atof_move(buffer, (float&)sub->mValue.x); - - if (!SkipSpacesAndLineEnd(&buffer)) - throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord"); - buffer = fast_atof_move(buffer, (float&)sub->mValue.y); - - if (!SkipSpacesAndLineEnd(&buffer)) - throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord"); - buffer = fast_atof_move(buffer, (float&)sub->mValue.z); - - ++s->mNumPositionKeys; - } - } - - // update allocation granularity - if (filled == alloc) - alloc *= 2; - - ++filled; - } - // all channels must be complete in order to continue safely. - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - - if (!anim->mChannels[i]->mNumPositionKeys) - throw DeadlyImportError("CSM: Invalid marker track"); - } - } - } - else { - // advance to the next line - SkipLine(&buffer); - } - } - - // Setup a proper animation duration - anim->mDuration = last - std::min( first, 0 ); - - // build a dummy root node with the tiny markers as children - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("$CSM_DummyRoot"); - - pScene->mRootNode->mNumChildren = anim->mNumChannels; - pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels]; - - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - aiNodeAnim* na = anim->mChannels[i]; - - aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode(); - nd->mName = anim->mChannels[i]->mNodeName; - nd->mParent = pScene->mRootNode; - - aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation); - } - - // Store the one and only animation in the scene - pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations=1]; - pScene->mAnimations[0] = anim; - anim->mName.Set("$CSM_MasterAnim"); - - // mark the scene as incomplete and run SkeletonMeshBuilder on it - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true); -} - -#endif // !! ASSIMP_BUILD_NO_CSM_IMPORTER diff --git a/3rdparty/assimp/code/CSMLoader.h b/3rdparty/assimp/code/CSMLoader.h deleted file mode 100644 index 2b5e8e63..00000000 --- a/3rdparty/assimp/code/CSMLoader.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 CSMLoader.h - * Declaration of the CharacterStudio Motion importer class. - */ -#ifndef INCLUDED_AI_CSM_LOADER_H -#define INCLUDED_AI_CSM_LOADER_H -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Importer class to load MOCAPs in CharacterStudio Motion format. - * - * A very rudimentary loader for the moment. No support for the hierarchy, - * every marker is returned as child of root. - * - * Link to file format specification: - * <max_8_dvd>\samples\Motion\Docs\CSM.rtf -*/ -class CSMImporter : public BaseImporter -{ - friend class Importer; -protected: - /** Constructor to be privately used by Importer */ - CSMImporter(); - - /** Destructor, private as well */ - ~CSMImporter(); - -public: - // ------------------------------------------------------------------- - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: -}; // end of class CSMImporter -} // end of namespace Assimp -#endif // AI_AC3DIMPORTER_H_INC - diff --git a/3rdparty/assimp/code/CalcTangentsProcess.cpp b/3rdparty/assimp/code/CalcTangentsProcess.cpp deleted file mode 100644 index 83ec00a5..00000000 --- a/3rdparty/assimp/code/CalcTangentsProcess.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to calculate - * tangents and bitangents for all imported meshes - */ - -#include "AssimpPCH.h" - -// internal headers -#include "CalcTangentsProcess.h" -#include "ProcessHelper.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -CalcTangentsProcess::CalcTangentsProcess() -{ - this->configMaxAngle = AI_DEG_TO_RAD(45.f); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -CalcTangentsProcess::~CalcTangentsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool CalcTangentsProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_CalcTangentSpace) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void CalcTangentsProcess::SetupProperties(const Importer* pImp) -{ - // get the current value of the property - this->configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f); - this->configMaxAngle = std::max(std::min(this->configMaxAngle,45.0f),0.0f); - this->configMaxAngle = AI_DEG_TO_RAD(this->configMaxAngle); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void CalcTangentsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("CalcTangentsProcess begin"); - - bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - if (ProcessMesh( pScene->mMeshes[a],a))bHas = true; - - if (bHas)DefaultLogger::get()->debug("CalcTangentsProcess finished. Tangents have been calculated"); - else DefaultLogger::get()->debug("CalcTangentsProcess finished"); -} - -// ------------------------------------------------------------------------------------------------ -// Calculates tangents and bitangents for the given mesh -bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) -{ - // we assume that the mesh is still in the verbose vertex format where each face has its own set - // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to - // assert() it here. - //assert( must be verbose, dammit); - - if (pMesh->mTangents) // thisimplies that mBitangents is also there - return false; - - // If the mesh consists of lines and/or points but not of - // triangles or higher-order polygons the normal vectors - // are undefined. - if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) - { - DefaultLogger::get()->info("Tangents are undefined for line and point meshes"); - return false; - } - - // what we can check, though, is if the mesh has normals and texture coord. That's a requirement - if ( pMesh->mNormals == NULL || pMesh->mTextureCoords[0] == NULL) - { - DefaultLogger::get()->error("Unable to compute tangents: UV0 and normals must be there "); - return false; - } - const float angleEpsilon = 0.9999f; - - std::vector<bool> vertexDone( pMesh->mNumVertices, false); - const float qnan = get_qnan(); - - // create space for the tangents and bitangents - pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; - pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; - - const aiVector3D* meshPos = pMesh->mVertices; - const aiVector3D* meshNorm = pMesh->mNormals; - const aiVector3D* meshTex = pMesh->mTextureCoords[0]; - aiVector3D* meshTang = pMesh->mTangents; - aiVector3D* meshBitang = pMesh->mBitangents; - - // calculate the tangent and bitangent for every face - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - const aiFace& face = pMesh->mFaces[a]; - if (face.mNumIndices < 3) - { - // There are less than three indices, thus the tangent vector - // is not defined. We are finished with these vertices now, - // their tangent vectors are set to qnan. - for (unsigned int i = 0; i < face.mNumIndices;++i) - { - register unsigned int idx = face.mIndices[i]; - vertexDone [idx] = true; - meshTang [idx] = qnan; - meshBitang [idx] = qnan; - } - - continue; - } - - // triangle or polygon... we always use only the first three indices. A polygon - // is supposed to be planar anyways.... - // FIXME: (thom) create correct calculation for multi-vertex polygons maybe? - const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2]; - - // position differences p1->p2 and p1->p3 - aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0]; - - // texture offset p1->p2 and p1->p3 - float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y; - float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y; - float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f; - - // tangent points in the direction where to positive X axis of the texture coords would point in model space - // bitangents points along the positive Y axis of the texture coords, respectively - aiVector3D tangent, bitangent; - tangent.x = (w.x * sy - v.x * ty) * dirCorrection; - tangent.y = (w.y * sy - v.y * ty) * dirCorrection; - tangent.z = (w.z * sy - v.z * ty) * dirCorrection; - bitangent.x = (w.x * sx - v.x * tx) * dirCorrection; - bitangent.y = (w.y * sx - v.y * tx) * dirCorrection; - bitangent.z = (w.z * sx - v.z * tx) * dirCorrection; - - // store for every vertex of that face - for ( unsigned int b = 0; b < face.mNumIndices; b++) - { - unsigned int p = face.mIndices[b]; - - // project tangent and bitangent into the plane formed by the vertex' normal - aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]); - aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]); - localTangent.Normalize(); localBitangent.Normalize(); - - // and write it into the mesh. - meshTang[p] = localTangent; - meshBitang[p] = localBitangent; - } - } - - - // create a helper to quickly find locally close vertices among the vertex array - // FIX: check whether we can reuse the SpatialSort of a previous step - SpatialSort* vertexFinder = NULL; - SpatialSort _vertexFinder; - float posEpsilon; - if (shared) - { - std::vector<std::pair<SpatialSort,float> >* avf; - shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); - if (avf) - { - std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex); - vertexFinder = &blubb.first; - posEpsilon = blubb.second;; - } - } - if (!vertexFinder) - { - _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); - vertexFinder = &_vertexFinder; - posEpsilon = ComputePositionEpsilon(pMesh); - } - std::vector<unsigned int> verticesFound; - - const float fLimit = cosf(this->configMaxAngle); - std::vector<unsigned int> closeVertices; - - // in the second pass we now smooth out all tangents and bitangents at the same local position - // if they are not too far off. - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) - { - if ( vertexDone[a]) - continue; - - const aiVector3D& origPos = pMesh->mVertices[a]; - const aiVector3D& origNorm = pMesh->mNormals[a]; - const aiVector3D& origTang = pMesh->mTangents[a]; - const aiVector3D& origBitang = pMesh->mBitangents[a]; - closeVertices.clear(); - - // find all vertices close to that position - vertexFinder->FindPositions( origPos, posEpsilon, verticesFound); - - closeVertices.reserve (verticesFound.size()+5); - closeVertices.push_back( a); - - // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent - for ( unsigned int b = 0; b < verticesFound.size(); b++) - { - unsigned int idx = verticesFound[b]; - if ( vertexDone[idx]) - continue; - if ( meshNorm[idx] * origNorm < angleEpsilon) - continue; - if ( meshTang[idx] * origTang < fLimit) - continue; - if ( meshBitang[idx] * origBitang < fLimit) - continue; - - // it's similar enough -> add it to the smoothing group - closeVertices.push_back( idx); - vertexDone[idx] = true; - } - - // smooth the tangents and bitangents of all vertices that were found to be close enough - aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0); - for ( unsigned int b = 0; b < closeVertices.size(); ++b) - { - smoothTangent += meshTang[ closeVertices[b] ]; - smoothBitangent += meshBitang[ closeVertices[b] ]; - } - smoothTangent.Normalize(); - smoothBitangent.Normalize(); - - // and write it back into all affected tangents - for ( unsigned int b = 0; b < closeVertices.size(); ++b) - { - meshTang[ closeVertices[b] ] = smoothTangent; - meshBitang[ closeVertices[b] ] = smoothBitangent; - } - } - return true; -} diff --git a/3rdparty/assimp/code/CalcTangentsProcess.h b/3rdparty/assimp/code/CalcTangentsProcess.h deleted file mode 100644 index 189710ff..00000000 --- a/3rdparty/assimp/code/CalcTangentsProcess.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to calculate tangents and - bitangents on all imported meshes.*/ -#ifndef AI_CALCTANGENTSPROCESS_H_INC -#define AI_CALCTANGENTSPROCESS_H_INC - -#include "BaseProcess.h" - -struct aiMesh; - -namespace Assimp -{ - -// --------------------------------------------------------------------------- -/** The CalcTangentsProcess calculates the tangent and bitangent for any vertex - * of all meshes. It is expected to be run before the JoinVerticesProcess runs - * because the joining of vertices also considers tangents and bitangents for - * uniqueness. - */ -class ASSIMP_API CalcTangentsProcess : public BaseProcess -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - CalcTangentsProcess(); - - /** Destructor, private as well */ - ~CalcTangentsProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. - * @param pFlags The processing flags the importer was called with. - * A bitwise combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, - * false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - - - // setter for configMaxAngle - inline void SetMaxSmoothAngle(float f) - { - configMaxAngle =f; - } - -protected: - - // ------------------------------------------------------------------- - /** Calculates tangents and bitangents for a specific mesh. - * @param pMesh The mesh to process. - * @param meshIndex Index of the mesh - */ - bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex); - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - -private: - - /** Configuration option: maximum smoothing angle, in radians*/ - float configMaxAngle; -}; - -} // end of namespace Assimp - -#endif // AI_CALCTANGENTSPROCESS_H_INC diff --git a/3rdparty/assimp/code/ColladaHelper.h b/3rdparty/assimp/code/ColladaHelper.h deleted file mode 100644 index 355571f0..00000000 --- a/3rdparty/assimp/code/ColladaHelper.h +++ /dev/null @@ -1,601 +0,0 @@ -/** Helper structures for the Collada loader */ - -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef AI_COLLADAHELPER_H_INC -#define AI_COLLADAHELPER_H_INC - -namespace Assimp { -namespace Collada { - -/** Collada file versions which evolved during the years ... */ -enum FormatVersion -{ - FV_1_5_n, - FV_1_4_n, - FV_1_3_n -}; - - -/** Transformation types that can be applied to a node */ -enum TransformType -{ - TF_LOOKAT, - TF_ROTATE, - TF_TRANSLATE, - TF_SCALE, - TF_SKEW, - TF_MATRIX -}; - -/** Different types of input data to a vertex or face */ -enum InputType -{ - IT_Invalid, - IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data. - IT_Position, - IT_Normal, - IT_Texcoord, - IT_Color, - IT_Tangent, - IT_Bitangent -}; - -/** Contains all data for one of the different transformation types */ -struct Transform -{ - std::string mID; ///< SID of the transform step, by which anim channels address their target node - TransformType mType; - float f[16]; ///< Interpretation of data depends on the type of the transformation -}; - -/** A collada camera. */ -struct Camera -{ - Camera() - : mOrtho (false) - , mHorFov (10e10f) - , mVerFov (10e10f) - , mAspect (10e10f) - , mZNear (0.1f) - , mZFar (1000.f) - {} - - // Name of camera - std::string mName; - - // True if it is an orthografic camera - bool mOrtho; - - //! Horizontal field of view in degrees - float mHorFov; - - //! Vertical field of view in degrees - float mVerFov; - - //! Screen aspect - float mAspect; - - //! Near& far z - float mZNear, mZFar; -}; - -#define aiLightSource_AMBIENT 0xdeaddead - -/** A collada light source. */ -struct Light -{ - Light() - : mAttConstant (1.f) - , mAttLinear (0.f) - , mAttQuadratic (0.f) - , mFalloffAngle (180.f) - , mFalloffExponent (0.f) - , mPenumbraAngle (10e10f) - , mOuterAngle (10e10f) - , mIntensity (1.f) - {} - - //! Type of the light source aiLightSourceType + ambient - unsigned int mType; - - //! Color of the light - aiColor3D mColor; - - //! Light attenuation - float mAttConstant,mAttLinear,mAttQuadratic; - - //! Spot light falloff - float mFalloffAngle; - float mFalloffExponent; - - // ----------------------------------------------------- - // FCOLLADA extension from here - - //! ... related stuff from maja and max extensions - float mPenumbraAngle; - float mOuterAngle; - - //! Common light intensity - float mIntensity; -}; - -/** Short vertex index description */ -struct InputSemanticMapEntry -{ - InputSemanticMapEntry() - : mSet (0) - {} - - //! Index of set, optional - unsigned int mSet; - - //! Name of referenced vertex input - InputType mType; -}; - -/** Table to map from effect to vertex input semantics */ -struct SemanticMappingTable -{ - //! Name of material - std::string mMatName; - - //! List of semantic map commands, grouped by effect semantic name - std::map<std::string, InputSemanticMapEntry> mMap; - - //! For std::find - bool operator == (const std::string& s) const { - return s == mMatName; - } -}; - -/** A reference to a mesh inside a node, including materials assigned to the various subgroups. - * The ID refers to either a mesh or a controller which specifies the mesh - */ -struct MeshInstance -{ - ///< ID of the mesh or controller to be instanced - std::string mMeshOrController; - - ///< Map of materials by the subgroup ID they're applied to - std::map<std::string, SemanticMappingTable> mMaterials; -}; - -/** A reference to a camera inside a node*/ -struct CameraInstance -{ - ///< ID of the camera - std::string mCamera; -}; - -/** A reference to a light inside a node*/ -struct LightInstance -{ - ///< ID of the camera - std::string mLight; -}; - -/** A reference to a node inside a node*/ -struct NodeInstance -{ - ///< ID of the node - std::string mNode; -}; - -/** A node in a scene hierarchy */ -struct Node -{ - std::string mName; - std::string mID; - std::string mSID; - Node* mParent; - std::vector<Node*> mChildren; - - /** Operations in order to calculate the resulting transformation to parent. */ - std::vector<Transform> mTransforms; - - /** Meshes at this node */ - std::vector<MeshInstance> mMeshes; - - /** Lights at this node */ - std::vector<LightInstance> mLights; - - /** Cameras at this node */ - std::vector<CameraInstance> mCameras; - - /** Node instances at this node */ - std::vector<NodeInstance> mNodeInstances; - - /** Rootnodes: Name of primary camera, if any */ - std::string mPrimaryCamera; - - //! Constructor. Begin with a zero parent - Node() { - mParent = NULL; - } - - //! Destructor: delete all children subsequently - ~Node() { - for ( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) - delete *it; - } -}; - -/** Data source array: either floats or strings */ -struct Data -{ - bool mIsStringArray; - std::vector<float> mValues; - std::vector<std::string> mStrings; -}; - -/** Accessor to a data array */ -struct Accessor -{ - size_t mCount; // in number of objects - size_t mSize; // size of an object, in elements (floats or strings, mostly 1) - size_t mOffset; // in number of values - size_t mStride; // Stride in number of values - std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore. - size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on. - // For example, SubOffset[0] denotes which of the values inside the object is the vector X component. - std::string mSource; // URL of the source array - mutable const Data* mData; // Pointer to the source array, if resolved. NULL else - - Accessor() - { - mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL; - mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0; - } -}; - -/** A single face in a mesh */ -struct Face -{ - std::vector<size_t> mIndices; -}; - -/** An input channel for mesh data, referring to a single accessor */ -struct InputChannel -{ - InputType mType; // Type of the data - size_t mIndex; // Optional index, if multiple sets of the same data type are given - size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better. - std::string mAccessor; // ID of the accessor where to read the actual values from. - mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else - - InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; } -}; - -/** Subset of a mesh with a certain material */ -struct SubMesh -{ - std::string mMaterial; ///< subgroup identifier - size_t mNumFaces; ///< number of faces in this submesh -}; - -/** Contains data for a single mesh */ -struct Mesh -{ - Mesh() - { - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - mNumUVComponents[i] = 2; - } - - // just to check if there's some sophisticated addressing involved... - // which we don't support, and therefore should warn about. - std::string mVertexID; - - // Vertex data addressed by vertex indices - std::vector<InputChannel> mPerVertexData; - - // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed - std::vector<aiVector3D> mPositions; - std::vector<aiVector3D> mNormals; - std::vector<aiVector3D> mTangents; - std::vector<aiVector3D> mBitangents; - std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; - - unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - - // Faces. Stored are only the number of vertices for each face. - // 1 == point, 2 == line, 3 == triangle, 4+ == poly - std::vector<size_t> mFaceSize; - - // Position indices for all faces in the sequence given in mFaceSize - - // necessary for bone weight assignment - std::vector<size_t> mFacePosIndices; - - // Submeshes in this mesh, each with a given material - std::vector<SubMesh> mSubMeshes; -}; - -/** Which type of primitives the ReadPrimitives() function is going to read */ -enum PrimitiveType -{ - Prim_Invalid, - Prim_Lines, - Prim_LineStrip, - Prim_Triangles, - Prim_TriStrips, - Prim_TriFans, - Prim_Polylist, - Prim_Polygon -}; - -/** A skeleton controller to deform a mesh with the use of joints */ -struct Controller -{ - // the URL of the mesh deformed by the controller. - std::string mMeshId; - - // accessor URL of the joint names - std::string mJointNameSource; - - ///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases - float mBindShapeMatrix[16]; - - // accessor URL of the joint inverse bind matrices - std::string mJointOffsetMatrixSource; - - // input channel: joint names. - InputChannel mWeightInputJoints; - // input channel: joint weights - InputChannel mWeightInputWeights; - - // Number of weights per vertex. - std::vector<size_t> mWeightCounts; - - // JointIndex-WeightIndex pairs for all vertices - std::vector< std::pair<size_t, size_t> > mWeights; -}; - -/** A collada material. Pretty much the only member is a reference to an effect. */ -struct Material -{ - std::string mEffect; -}; - -/** Type of the effect param */ -enum ParamType -{ - Param_Sampler, - Param_Surface -}; - -/** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */ -struct EffectParam -{ - ParamType mType; - std::string mReference; // to which other thing the param is referring to. -}; - -/** Shading type supported by the standard effect spec of Collada */ -enum ShadeType -{ - Shade_Invalid, - Shade_Constant, - Shade_Lambert, - Shade_Phong, - Shade_Blinn -}; - -/** Represents a texture sampler in collada */ -struct Sampler -{ - Sampler() - : mWrapU (true) - , mWrapV (true) - , mMirrorU () - , mMirrorV () - , mOp (aiTextureOp_Multiply) - , mUVId (0xffffffff) - , mWeighting (1.f) - , mMixWithPrevious (1.f) - {} - - /** Name of image reference - */ - std::string mName; - - /** Wrap U? - */ - bool mWrapU; - - /** Wrap V? - */ - bool mWrapV; - - /** Mirror U? - */ - bool mMirrorU; - - /** Mirror V? - */ - bool mMirrorV; - - /** Blend mode - */ - aiTextureOp mOp; - - /** UV transformation - */ - aiUVTransform mTransform; - - /** Name of source UV channel - */ - std::string mUVChannel; - - /** Resolved UV channel index or 0xffffffff if not known - */ - unsigned int mUVId; - - // OKINO/MAX3D extensions from here - // ------------------------------------------------------- - - /** Weighting factor - */ - float mWeighting; - - /** Mixing factor from OKINO - */ - float mMixWithPrevious; -}; - -/** A collada effect. Can contain about anything according to the Collada spec, - but we limit our version to a reasonable subset. */ -struct Effect -{ - // Shading mode - ShadeType mShadeType; - - // Colors - aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular, - mTransparent, mReflective; - - // Textures - Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular, - mTexTransparent, mTexBump, mTexReflective; - - // Scalar factory - float mShininess, mRefractIndex, mReflectivity; - float mTransparency; - - // local params referring to each other by their SID - typedef std::map<std::string, Collada::EffectParam> ParamLibrary; - ParamLibrary mParams; - - // MAX3D extensions - // --------------------------------------------------------- - // Double-sided? - bool mDoubleSided, mWireframe, mFaceted; - - Effect() - : mShadeType (Shade_Phong) - , mEmissive ( 0, 0, 0, 1) - , mAmbient ( 0.1f, 0.1f, 0.1f, 1) - , mDiffuse ( 0.6f, 0.6f, 0.6f, 1) - , mSpecular ( 0.4f, 0.4f, 0.4f, 1) - , mTransparent ( 0, 0, 0, 1) - , mShininess (10.0f) - , mRefractIndex (1.f) - , mReflectivity (1.f) - , mTransparency (0.f) - , mDoubleSided (false) - , mWireframe (false) - , mFaceted (false) - { - } -}; - -/** An image, meaning texture */ -struct Image -{ - std::string mFileName; - - /** If image file name is zero, embedded image data - */ - std::vector<uint8_t> mImageData; - - /** If image file name is zero, file format of - * embedded image data. - */ - std::string mEmbeddedFormat; - -}; - -/** An animation channel. */ -struct AnimationChannel -{ - /** URL of the data to animate. Could be about anything, but we support only the - * "NodeID/TransformID.SubElement" notation - */ - std::string mTarget; - - /** Source URL of the time values. Collada calls them "input". Meh. */ - std::string mSourceTimes; - /** Source URL of the value values. Collada calls them "output". */ - std::string mSourceValues; -}; - -/** An animation. Container for 0-x animation channels or 0-x animations */ -struct Animation -{ - /** Anim name */ - std::string mName; - - /** the animation channels, if any */ - std::vector<AnimationChannel> mChannels; - - /** the sub-animations, if any */ - std::vector<Animation*> mSubAnims; - - /** Destructor */ - ~Animation() - { - for ( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) - delete *it; - } -}; - -/** Description of a collada animation channel which has been determined to affect the current node */ -struct ChannelEntry -{ - const Collada::AnimationChannel* mChannel; ///> the source channel - std::string mTransformId; // the ID of the transformation step of the node which is influenced - size_t mTransformIndex; // Index into the node's transform chain to apply the channel to - size_t mSubElement; // starting index inside the transform data - - // resolved data references - const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values - const Collada::Data* mTimeData; ///> Source data array for the time values - const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values - const Collada::Data* mValueData; ///> Source datat array for the key value values - - ChannelEntry() { mChannel = NULL; mSubElement = 0; } -}; - -} // end of namespace Collada -} // end of namespace Assimp - -#endif // AI_COLLADAHELPER_H_INC diff --git a/3rdparty/assimp/code/ColladaLoader.cpp b/3rdparty/assimp/code/ColladaLoader.cpp deleted file mode 100644 index 7f7ce804..00000000 --- a/3rdparty/assimp/code/ColladaLoader.cpp +++ /dev/null @@ -1,1492 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Collada loader */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_DAE_IMPORTER - -#include "../include/aiAnim.h" -#include "ColladaLoader.h" -#include "ColladaParser.h" - -#include "fast_atof.h" -#include "ParsingUtils.h" -#include "SkeletonMeshBuilder.h" - -#include "time.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -ColladaLoader::ColladaLoader() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ColladaLoader::~ColladaLoader() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - // check file extension - std::string extension = GetExtension(pFile); - - if ( extension == "dae") - return true; - - // XML - too generic, we need to open the file and search for typical keywords - if ( extension == "xml" || !extension.length() || checkSig) { - /* If CanRead() is called in order to check whether we - * support a specific file extension in general pIOHandler - * might be NULL and it's our duty to return true here. - */ - if (!pIOHandler)return true; - const char* tokens[] = {"collada"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get file extension list -void ColladaLoader::GetExtensionList( std::set<std::string>& extensions ) -{ - extensions.insert("dae"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - mFileName = pFile; - - // clean all member arrays - just for safety, it should work even if we did not - mMeshIndexByID.clear(); - mMaterialIndexByName.clear(); - mMeshes.clear(); - newMats.clear(); - mLights.clear(); - mCameras.clear(); - mTextures.clear(); - - // parse the input file - ColladaParser parser( pIOHandler, pFile); - - if ( !parser.mRootNode) - throw DeadlyImportError( "Collada: File came out empty. Something is wrong here."); - - // reserve some storage to avoid unnecessary reallocs - newMats.reserve(parser.mMaterialLibrary.size()*2); - mMeshes.reserve(parser.mMeshLibrary.size()*2); - - mCameras.reserve(parser.mCameraLibrary.size()); - mLights.reserve(parser.mLightLibrary.size()); - - // create the materials first, for the meshes to find - BuildMaterials( parser, pScene); - - // build the node hierarchy from it - pScene->mRootNode = BuildHierarchy( parser, parser.mRootNode); - - // ... then fill the materials with the now adjusted settings - FillMaterials(parser, pScene); - - // Convert to Y_UP, if different orientation - if ( parser.mUpDirection == ColladaParser::UP_X) - pScene->mRootNode->mTransformation *= aiMatrix4x4( - 0, -1, 0, 0, - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1); - else if ( parser.mUpDirection == ColladaParser::UP_Z) - pScene->mRootNode->mTransformation *= aiMatrix4x4( - 1, 0, 0, 0, - 0, 0, 1, 0, - 0, -1, 0, 0, - 0, 0, 0, 1); - - // store all meshes - StoreSceneMeshes( pScene); - - // store all materials - StoreSceneMaterials( pScene); - - // store all lights - StoreSceneLights( pScene); - - // store all cameras - StoreSceneCameras( pScene); - - // store all animations - StoreAnimations( pScene, parser); - - - // If no meshes have been loaded, it's probably just an animated skeleton. - if (!pScene->mNumMeshes) { - - SkeletonMeshBuilder hero(pScene); - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursively constructs a scene node for the given parser node and returns it. -aiNode* ColladaLoader::BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode) -{ - // create a node for it - aiNode* node = new aiNode(); - - // find a name for the new node. It's more complicated than you might think - node->mName.Set( FindNameForNode( pNode)); - - // calculate the transformation matrix for it - node->mTransformation = pParser.CalculateResultTransform( pNode->mTransforms); - - // now resolve node instances - std::vector<const Collada::Node*> instances; - ResolveNodeInstances(pParser,pNode,instances); - - // add children. first the *real* ones - node->mNumChildren = pNode->mChildren.size()+instances.size(); - node->mChildren = new aiNode*[node->mNumChildren]; - - for ( size_t a = 0; a < pNode->mChildren.size(); a++) - { - node->mChildren[a] = BuildHierarchy( pParser, pNode->mChildren[a]); - node->mChildren[a]->mParent = node; - } - - // ... and finally the resolved node instances - for ( size_t a = 0; a < instances.size(); a++) - { - node->mChildren[pNode->mChildren.size() + a] = BuildHierarchy( pParser, instances[a]); - node->mChildren[pNode->mChildren.size() + a]->mParent = node; - } - - // construct meshes - BuildMeshesForNode( pParser, pNode, node); - - // construct cameras - BuildCamerasForNode(pParser, pNode, node); - - // construct lights - BuildLightsForNode(pParser, pNode, node); - return node; -} - -// ------------------------------------------------------------------------------------------------ -// Resolve node instances -void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode, - std::vector<const Collada::Node*>& resolved) -{ - // reserve enough storage - resolved.reserve(pNode->mNodeInstances.size()); - - // ... and iterate through all nodes to be instanced as children of pNode - for (std::vector<Collada::NodeInstance>::const_iterator it = pNode->mNodeInstances.begin(), - end = pNode->mNodeInstances.end(); it != end; ++it) - { - // find the corresponding node in the library - const ColladaParser::NodeLibrary::const_iterator itt = pParser.mNodeLibrary.find((*it).mNode); - Collada::Node* nd = itt == pParser.mNodeLibrary.end() ? NULL : (*itt).second; - - // FIX for http://sourceforge.net/tracker/?func=detail&aid=3054873&group_id=226462&atid=1067632 - // need to check for both name and ID to catch all. To avoid breaking valid files, - // the workaround is only enabled when the first attempt to resolve the node has failed. - if (!nd) { - nd = const_cast<Collada::Node*>(FindNode(pParser.mRootNode,(*it).mNode)); - } - if (!nd) - DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + (*it).mNode); - - else { - // attach this node to the list of children - resolved.push_back(nd); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Resolve UV channels -void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler, - const Collada::SemanticMappingTable& table) -{ - std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel); - if (it != table.mMap.end()) { - if (it->second.mType != Collada::IT_Texcoord) - DefaultLogger::get()->error("Collada: Unexpected effect input mapping"); - - sampler.mUVId = it->second.mSet; - } -} - -// ------------------------------------------------------------------------------------------------ -// Builds lights for the given node and references them -void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) -{ - BOOST_FOREACH( const Collada::LightInstance& lid, pNode->mLights) - { - // find the referred light - ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight); - if ( srcLightIt == pParser.mLightLibrary.end()) - { - DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping."); - continue; - } - const Collada::Light* srcLight = &srcLightIt->second; - if (srcLight->mType == aiLightSource_AMBIENT) { - DefaultLogger::get()->error("Collada: Skipping ambient light for the moment"); - continue; - } - - // now fill our ai data structure - aiLight* out = new aiLight(); - out->mName = pTarget->mName; - out->mType = (aiLightSourceType)srcLight->mType; - - // collada lights point in -Z by default, rest is specified in node transform - out->mDirection = aiVector3D(0.f,0.f,-1.f); - - out->mAttenuationConstant = srcLight->mAttConstant; - out->mAttenuationLinear = srcLight->mAttLinear; - out->mAttenuationQuadratic = srcLight->mAttQuadratic; - - // collada doesn't differenciate between these color types - out->mColorDiffuse = out->mColorSpecular = out->mColorAmbient = srcLight->mColor*srcLight->mIntensity; - - // convert falloff angle and falloff exponent in our representation, if given - if (out->mType == aiLightSource_SPOT) { - - out->mAngleInnerCone = AI_DEG_TO_RAD( srcLight->mFalloffAngle ); - - // ... some extension magic. FUCKING COLLADA. - if (srcLight->mOuterAngle == 10e10f) - { - // ... some deprecation magic. FUCKING FCOLLADA. - if (srcLight->mPenumbraAngle == 10e10f) - { - // Need to rely on falloff_exponent. I don't know how to interpret it, so I need to guess .... - // epsilon chosen to be 0.1 - out->mAngleOuterCone = AI_DEG_TO_RAD (acos(pow(0.1f,1.f/srcLight->mFalloffExponent))+ - srcLight->mFalloffAngle); - } - else { - out->mAngleOuterCone = out->mAngleInnerCone + AI_DEG_TO_RAD( srcLight->mPenumbraAngle ); - if (out->mAngleOuterCone < out->mAngleInnerCone) - std::swap(out->mAngleInnerCone,out->mAngleOuterCone); - } - } - else out->mAngleOuterCone = AI_DEG_TO_RAD( srcLight->mOuterAngle ); - } - - // add to light list - mLights.push_back(out); - } -} - -// ------------------------------------------------------------------------------------------------ -// Builds cameras for the given node and references them -void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) -{ - BOOST_FOREACH( const Collada::CameraInstance& cid, pNode->mCameras) - { - // find the referred light - ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera); - if ( srcCameraIt == pParser.mCameraLibrary.end()) - { - DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping."); - continue; - } - const Collada::Camera* srcCamera = &srcCameraIt->second; - - // orthographic cameras not yet supported in Assimp - if (srcCamera->mOrtho) { - DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported."); - } - - // now fill our ai data structure - aiCamera* out = new aiCamera(); - out->mName = pTarget->mName; - - // collada cameras point in -Z by default, rest is specified in node transform - out->mLookAt = aiVector3D(0.f,0.f,-1.f); - - // near/far z is already ok - out->mClipPlaneFar = srcCamera->mZFar; - out->mClipPlaneNear = srcCamera->mZNear; - - // ... but for the rest some values are optional - // and we need to compute the others in any combination. FUCKING COLLADA. - if (srcCamera->mAspect != 10e10f) - out->mAspect = srcCamera->mAspect; - - if (srcCamera->mHorFov != 10e10f) { - out->mHorizontalFOV = srcCamera->mHorFov; - - if (srcCamera->mVerFov != 10e10f && srcCamera->mAspect == 10e10f) { - out->mAspect = tan(AI_DEG_TO_RAD(srcCamera->mHorFov)) / - tan(AI_DEG_TO_RAD(srcCamera->mVerFov)); - } - } - else if (srcCamera->mAspect != 10e10f && srcCamera->mVerFov != 10e10f) { - out->mHorizontalFOV = 2.0f * AI_RAD_TO_DEG(atan(srcCamera->mAspect * - tan(AI_DEG_TO_RAD(srcCamera->mVerFov) * 0.5f))); - } - - // Collada uses degrees, we use radians - out->mHorizontalFOV = AI_DEG_TO_RAD(out->mHorizontalFOV); - - // add to camera list - mCameras.push_back(out); - } -} - -// ------------------------------------------------------------------------------------------------ -// Builds meshes for the given node and references them -void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, aiNode* pTarget) -{ - // accumulated mesh references by this node - std::vector<size_t> newMeshRefs; - newMeshRefs.reserve(pNode->mMeshes.size()); - - // add a mesh for each subgroup in each collada mesh - BOOST_FOREACH( const Collada::MeshInstance& mid, pNode->mMeshes) - { - const Collada::Mesh* srcMesh = NULL; - const Collada::Controller* srcController = NULL; - - // find the referred mesh - ColladaParser::MeshLibrary::const_iterator srcMeshIt = pParser.mMeshLibrary.find( mid.mMeshOrController); - if ( srcMeshIt == pParser.mMeshLibrary.end()) - { - // if not found in the mesh-library, it might also be a controller referring to a mesh - ColladaParser::ControllerLibrary::const_iterator srcContrIt = pParser.mControllerLibrary.find( mid.mMeshOrController); - if ( srcContrIt != pParser.mControllerLibrary.end()) - { - srcController = &srcContrIt->second; - srcMeshIt = pParser.mMeshLibrary.find( srcController->mMeshId); - if ( srcMeshIt != pParser.mMeshLibrary.end()) - srcMesh = srcMeshIt->second; - } - - if ( !srcMesh) - { - DefaultLogger::get()->warn( boost::str( boost::format( "Collada: Unable to find geometry for ID \"%s\". Skipping.") % mid.mMeshOrController)); - continue; - } - } else - { - // ID found in the mesh library -> direct reference to an unskinned mesh - srcMesh = srcMeshIt->second; - } - - // build a mesh for each of its subgroups - size_t vertexStart = 0, faceStart = 0; - for ( size_t sm = 0; sm < srcMesh->mSubMeshes.size(); ++sm) - { - const Collada::SubMesh& submesh = srcMesh->mSubMeshes[sm]; - if ( submesh.mNumFaces == 0) - continue; - - // find material assigned to this submesh - std::string meshMaterial; - std::map<std::string, Collada::SemanticMappingTable >::const_iterator meshMatIt = mid.mMaterials.find( submesh.mMaterial); - - const Collada::SemanticMappingTable* table = NULL; - if ( meshMatIt != mid.mMaterials.end()) - { - table = &meshMatIt->second; - meshMaterial = table->mMatName; - } - else - { - DefaultLogger::get()->warn( boost::str( boost::format( "Collada: No material specified for subgroup \"%s\" in geometry \"%s\".") % submesh.mMaterial % mid.mMeshOrController)); - if ( !mid.mMaterials.empty() ) - meshMaterial = mid.mMaterials.begin()->second.mMatName; - } - - // OK ... here the *real* fun starts ... we have the vertex-input-to-effect-semantic-table - // given. The only mapping stuff which we do actually support is the UV channel. - std::map<std::string, size_t>::const_iterator matIt = mMaterialIndexByName.find( meshMaterial); - unsigned int matIdx; - if ( matIt != mMaterialIndexByName.end()) - matIdx = matIt->second; - else - matIdx = 0; - - if (table && !table->mMap.empty() ) { - std::pair<Collada::Effect*, aiMaterial*>& mat = newMats[matIdx]; - - // Iterate through all texture channels assigned to the effect and - // check whether we have mapping information for it. - ApplyVertexToEffectSemanticMapping(mat.first->mTexDiffuse, *table); - ApplyVertexToEffectSemanticMapping(mat.first->mTexAmbient, *table); - ApplyVertexToEffectSemanticMapping(mat.first->mTexSpecular, *table); - ApplyVertexToEffectSemanticMapping(mat.first->mTexEmissive, *table); - ApplyVertexToEffectSemanticMapping(mat.first->mTexTransparent,*table); - ApplyVertexToEffectSemanticMapping(mat.first->mTexBump, *table); - } - - // built lookup index of the Mesh-Submesh-Material combination - ColladaMeshIndex index( mid.mMeshOrController, sm, meshMaterial); - - // if we already have the mesh at the library, just add its index to the node's array - std::map<ColladaMeshIndex, size_t>::const_iterator dstMeshIt = mMeshIndexByID.find( index); - if ( dstMeshIt != mMeshIndexByID.end()) { - newMeshRefs.push_back( dstMeshIt->second); - } - else - { - // else we have to add the mesh to the collection and store its newly assigned index at the node - aiMesh* dstMesh = CreateMesh( pParser, srcMesh, submesh, srcController, vertexStart, faceStart); - - // store the mesh, and store its new index in the node - newMeshRefs.push_back( mMeshes.size()); - mMeshIndexByID[index] = mMeshes.size(); - mMeshes.push_back( dstMesh); - vertexStart += dstMesh->mNumVertices; faceStart += submesh.mNumFaces; - - // assign the material index - dstMesh->mMaterialIndex = matIdx; - } - } - } - - // now place all mesh references we gathered in the target node - pTarget->mNumMeshes = newMeshRefs.size(); - if ( newMeshRefs.size()) - { - pTarget->mMeshes = new unsigned int[pTarget->mNumMeshes]; - std::copy( newMeshRefs.begin(), newMeshRefs.end(), pTarget->mMeshes); - } -} - -// ------------------------------------------------------------------------------------------------ -// Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh -aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, - const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace) -{ - aiMesh* dstMesh = new aiMesh; - - // count the vertices addressed by its faces - const size_t numVertices = std::accumulate( pSrcMesh->mFaceSize.begin() + pStartFace, - pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, 0); - - // copy positions - dstMesh->mNumVertices = numVertices; - dstMesh->mVertices = new aiVector3D[numVertices]; - std::copy( pSrcMesh->mPositions.begin() + pStartVertex, pSrcMesh->mPositions.begin() + - pStartVertex + numVertices, dstMesh->mVertices); - - // normals, if given. HACK: (thom) Due to the fucking Collada spec we never - // know if we have the same number of normals as there are positions. So we - // also ignore any vertex attribute if it has a different count - if ( pSrcMesh->mNormals.size() >= pStartVertex + numVertices) - { - dstMesh->mNormals = new aiVector3D[numVertices]; - std::copy( pSrcMesh->mNormals.begin() + pStartVertex, pSrcMesh->mNormals.begin() + - pStartVertex + numVertices, dstMesh->mNormals); - } - - // tangents, if given. - if ( pSrcMesh->mTangents.size() >= pStartVertex + numVertices) - { - dstMesh->mTangents = new aiVector3D[numVertices]; - std::copy( pSrcMesh->mTangents.begin() + pStartVertex, pSrcMesh->mTangents.begin() + - pStartVertex + numVertices, dstMesh->mTangents); - } - - // bitangents, if given. - if ( pSrcMesh->mBitangents.size() >= pStartVertex + numVertices) - { - dstMesh->mBitangents = new aiVector3D[numVertices]; - std::copy( pSrcMesh->mBitangents.begin() + pStartVertex, pSrcMesh->mBitangents.begin() + - pStartVertex + numVertices, dstMesh->mBitangents); - } - - // same for texturecoords, as many as we have - // empty slots are not allowed, need to pack and adjust UV indexes accordingly - for ( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) - { - if ( pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) - { - dstMesh->mTextureCoords[real] = new aiVector3D[numVertices]; - for ( size_t b = 0; b < numVertices; ++b) - dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex+b]; - - dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a]; - ++real; - } - } - - // same for vertex colors, as many as we have. again the same packing to avoid empty slots - for ( size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; a++) - { - if ( pSrcMesh->mColors[a].size() >= pStartVertex + numVertices) - { - dstMesh->mColors[real] = new aiColor4D[numVertices]; - std::copy( pSrcMesh->mColors[a].begin() + pStartVertex, pSrcMesh->mColors[a].begin() + pStartVertex + numVertices,dstMesh->mColors[real]); - ++real; - } - } - - // create faces. Due to the fact that each face uses unique vertices, we can simply count up on each vertex - size_t vertex = 0; - dstMesh->mNumFaces = pSubMesh.mNumFaces; - dstMesh->mFaces = new aiFace[dstMesh->mNumFaces]; - for ( size_t a = 0; a < dstMesh->mNumFaces; ++a) - { - size_t s = pSrcMesh->mFaceSize[ pStartFace + a]; - aiFace& face = dstMesh->mFaces[a]; - face.mNumIndices = s; - face.mIndices = new unsigned int[s]; - for ( size_t b = 0; b < s; ++b) - face.mIndices[b] = vertex++; - } - - // create bones if given - if ( pSrcController) - { - // refuse if the vertex count does not match -// if ( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices) -// throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count"); - - // resolve references - joint names - const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource); - const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource); - // joint offset matrices - const Collada::Accessor& jointMatrixAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointOffsetMatrixSource); - const Collada::Data& jointMatrices = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointMatrixAcc.mSource); - // joint vertex_weight name list - should refer to the same list as the joint names above. If not, report and reconsider - const Collada::Accessor& weightNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mWeightInputJoints.mAccessor); - if ( &weightNamesAcc != &jointNamesAcc) - throw DeadlyImportError( "Temporary implementational lazyness. If you read this, please report to the author."); - // vertex weights - const Collada::Accessor& weightsAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mWeightInputWeights.mAccessor); - const Collada::Data& weights = pParser.ResolveLibraryReference( pParser.mDataLibrary, weightsAcc.mSource); - - if ( !jointNames.mIsStringArray || jointMatrices.mIsStringArray || weights.mIsStringArray) - throw DeadlyImportError( "Data type mismatch while resolving mesh joints"); - // sanity check: we rely on the vertex weights always coming as pairs of BoneIndex-WeightIndex - if ( pSrcController->mWeightInputJoints.mOffset != 0 || pSrcController->mWeightInputWeights.mOffset != 1) - throw DeadlyImportError( "Unsupported vertex_weight adresssing scheme. Fucking collada spec."); - - // create containers to collect the weights for each bone - size_t numBones = jointNames.mStrings.size(); - std::vector<std::vector<aiVertexWeight> > dstBones( numBones); - - // build a temporary array of pointers to the start of each vertex's weights - typedef std::vector< std::pair<size_t, size_t> > IndexPairVector; - std::vector<IndexPairVector::const_iterator> weightStartPerVertex( pSrcController->mWeightCounts.size()); - IndexPairVector::const_iterator pit = pSrcController->mWeights.begin(); - for ( size_t a = 0; a < pSrcController->mWeightCounts.size(); ++a) - { - weightStartPerVertex[a] = pit; - pit += pSrcController->mWeightCounts[a]; - } - - // now for each vertex put the corresponding vertex weights into each bone's weight collection - for ( size_t a = pStartVertex; a < pStartVertex + numVertices; ++a) - { - // which position index was responsible for this vertex? that's also the index by which - // the controller assigns the vertex weights - size_t orgIndex = pSrcMesh->mFacePosIndices[a]; - // find the vertex weights for this vertex - IndexPairVector::const_iterator iit = weightStartPerVertex[orgIndex]; - size_t pairCount = pSrcController->mWeightCounts[orgIndex]; - - for ( size_t b = 0; b < pairCount; ++b, ++iit) - { - size_t jointIndex = iit->first; - size_t vertexIndex = iit->second; - - float weight = ReadFloat( weightsAcc, weights, vertexIndex, 0); - - // one day I gonna kill that XSI Collada exporter - if ( weight > 0.0f) - { - aiVertexWeight w; - w.mVertexId = a - pStartVertex; - w.mWeight = weight; - dstBones[jointIndex].push_back( w); - } - } - } - - // count the number of bones which influence vertices of the current submesh - size_t numRemainingBones = 0; - for ( std::vector<std::vector<aiVertexWeight> >::const_iterator it = dstBones.begin(); it != dstBones.end(); ++it) - if ( it->size() > 0) - numRemainingBones++; - - // create bone array and copy bone weights one by one - dstMesh->mNumBones = numRemainingBones; - dstMesh->mBones = new aiBone*[numRemainingBones]; - size_t boneCount = 0; - for ( size_t a = 0; a < numBones; ++a) - { - // omit bones without weights - if ( dstBones[a].size() == 0) - continue; - - // create bone with its weights - aiBone* bone = new aiBone; - bone->mName = ReadString( jointNamesAcc, jointNames, a); - bone->mOffsetMatrix.a1 = ReadFloat( jointMatrixAcc, jointMatrices, a, 0); - bone->mOffsetMatrix.a2 = ReadFloat( jointMatrixAcc, jointMatrices, a, 1); - bone->mOffsetMatrix.a3 = ReadFloat( jointMatrixAcc, jointMatrices, a, 2); - bone->mOffsetMatrix.a4 = ReadFloat( jointMatrixAcc, jointMatrices, a, 3); - bone->mOffsetMatrix.b1 = ReadFloat( jointMatrixAcc, jointMatrices, a, 4); - bone->mOffsetMatrix.b2 = ReadFloat( jointMatrixAcc, jointMatrices, a, 5); - bone->mOffsetMatrix.b3 = ReadFloat( jointMatrixAcc, jointMatrices, a, 6); - bone->mOffsetMatrix.b4 = ReadFloat( jointMatrixAcc, jointMatrices, a, 7); - bone->mOffsetMatrix.c1 = ReadFloat( jointMatrixAcc, jointMatrices, a, 8); - bone->mOffsetMatrix.c2 = ReadFloat( jointMatrixAcc, jointMatrices, a, 9); - bone->mOffsetMatrix.c3 = ReadFloat( jointMatrixAcc, jointMatrices, a, 10); - bone->mOffsetMatrix.c4 = ReadFloat( jointMatrixAcc, jointMatrices, a, 11); - bone->mNumWeights = dstBones[a].size(); - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - std::copy( dstBones[a].begin(), dstBones[a].end(), bone->mWeights); - - // apply bind shape matrix to offset matrix - aiMatrix4x4 bindShapeMatrix; - bindShapeMatrix.a1 = pSrcController->mBindShapeMatrix[0]; - bindShapeMatrix.a2 = pSrcController->mBindShapeMatrix[1]; - bindShapeMatrix.a3 = pSrcController->mBindShapeMatrix[2]; - bindShapeMatrix.a4 = pSrcController->mBindShapeMatrix[3]; - bindShapeMatrix.b1 = pSrcController->mBindShapeMatrix[4]; - bindShapeMatrix.b2 = pSrcController->mBindShapeMatrix[5]; - bindShapeMatrix.b3 = pSrcController->mBindShapeMatrix[6]; - bindShapeMatrix.b4 = pSrcController->mBindShapeMatrix[7]; - bindShapeMatrix.c1 = pSrcController->mBindShapeMatrix[8]; - bindShapeMatrix.c2 = pSrcController->mBindShapeMatrix[9]; - bindShapeMatrix.c3 = pSrcController->mBindShapeMatrix[10]; - bindShapeMatrix.c4 = pSrcController->mBindShapeMatrix[11]; - bindShapeMatrix.d1 = pSrcController->mBindShapeMatrix[12]; - bindShapeMatrix.d2 = pSrcController->mBindShapeMatrix[13]; - bindShapeMatrix.d3 = pSrcController->mBindShapeMatrix[14]; - bindShapeMatrix.d4 = pSrcController->mBindShapeMatrix[15]; - bone->mOffsetMatrix *= bindShapeMatrix; - - // HACK: (thom) Some exporters address the bone nodes by SID, others address them by ID or even name. - // Therefore I added a little name replacement here: I search for the bone's node by either name, ID or SID, - // and replace the bone's name by the node's name so that the user can use the standard - // find-by-name method to associate nodes with bones. - const Collada::Node* bnode = FindNode( pParser.mRootNode, bone->mName.data); - if ( !bnode) - bnode = FindNodeBySID( pParser.mRootNode, bone->mName.data); - - // assign the name that we would have assigned for the source node - if ( bnode) - bone->mName.Set( FindNameForNode( bnode)); - else - DefaultLogger::get()->warn( boost::str( boost::format( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"%s\".") % bone->mName.data)); - - // and insert bone - dstMesh->mBones[boneCount++] = bone; - } - } - - return dstMesh; -} - -// ------------------------------------------------------------------------------------------------ -// Stores all meshes in the given scene -void ColladaLoader::StoreSceneMeshes( aiScene* pScene) -{ - pScene->mNumMeshes = mMeshes.size(); - if ( mMeshes.size() > 0) - { - pScene->mMeshes = new aiMesh*[mMeshes.size()]; - std::copy( mMeshes.begin(), mMeshes.end(), pScene->mMeshes); - mMeshes.clear(); - } -} - -// ------------------------------------------------------------------------------------------------ -// Stores all cameras in the given scene -void ColladaLoader::StoreSceneCameras( aiScene* pScene) -{ - pScene->mNumCameras = mCameras.size(); - if ( mCameras.size() > 0) - { - pScene->mCameras = new aiCamera*[mCameras.size()]; - std::copy( mCameras.begin(), mCameras.end(), pScene->mCameras); - mCameras.clear(); - } -} - -// ------------------------------------------------------------------------------------------------ -// Stores all lights in the given scene -void ColladaLoader::StoreSceneLights( aiScene* pScene) -{ - pScene->mNumLights = mLights.size(); - if ( mLights.size() > 0) - { - pScene->mLights = new aiLight*[mLights.size()]; - std::copy( mLights.begin(), mLights.end(), pScene->mLights); - mLights.clear(); - } -} - -// ------------------------------------------------------------------------------------------------ -// Stores all textures in the given scene -void ColladaLoader::StoreSceneTextures( aiScene* pScene) -{ - pScene->mNumTextures = mTextures.size(); - if ( mTextures.size() > 0) - { - pScene->mTextures = new aiTexture*[mTextures.size()]; - std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures); - mTextures.clear(); - } -} - -// ------------------------------------------------------------------------------------------------ -// Stores all materials in the given scene -void ColladaLoader::StoreSceneMaterials( aiScene* pScene) -{ - pScene->mNumMaterials = newMats.size(); - - if (newMats.size() > 0) { - pScene->mMaterials = new aiMaterial*[newMats.size()]; - for (unsigned int i = 0; i < newMats.size();++i) - pScene->mMaterials[i] = newMats[i].second; - - newMats.clear(); - } -} - -// ------------------------------------------------------------------------------------------------ -// Stores all animations -void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser) -{ - // recursivly collect all animations from the collada scene - StoreAnimations( pScene, pParser, &pParser.mAnims, ""); - - // catch special case: many animations with the same length, each affecting only a single node. - // we need to unite all those single-node-anims to a proper combined animation - for ( size_t a = 0; a < mAnims.size(); ++a) - { - aiAnimation* templateAnim = mAnims[a]; - if ( templateAnim->mNumChannels == 1) - { - // search for other single-channel-anims with the same duration - std::vector<size_t> collectedAnimIndices; - for ( size_t b = a+1; b < mAnims.size(); ++b) - { - aiAnimation* other = mAnims[b]; - if ( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond ) - collectedAnimIndices.push_back( b); - } - - // if there are other animations which fit the template anim, combine all channels into a single anim - if ( !collectedAnimIndices.empty() ) - { - aiAnimation* combinedAnim = new aiAnimation(); - combinedAnim->mName = aiString( std::string( "combinedAnim_") + char( '0' + a)); - combinedAnim->mDuration = templateAnim->mDuration; - combinedAnim->mTicksPerSecond = templateAnim->mTicksPerSecond; - combinedAnim->mNumChannels = collectedAnimIndices.size() + 1; - combinedAnim->mChannels = new aiNodeAnim*[combinedAnim->mNumChannels]; - // add the template anim as first channel by moving its aiNodeAnim to the combined animation - combinedAnim->mChannels[0] = templateAnim->mChannels[0]; - templateAnim->mChannels[0] = NULL; - delete templateAnim; - // combined animation replaces template animation in the anim array - mAnims[a] = combinedAnim; - - // move the memory of all other anims to the combined anim and erase them from the source anims - for ( size_t b = 0; b < collectedAnimIndices.size(); ++b) - { - aiAnimation* srcAnimation = mAnims[collectedAnimIndices[b]]; - combinedAnim->mChannels[1 + b] = srcAnimation->mChannels[0]; - srcAnimation->mChannels[0] = NULL; - delete srcAnimation; - } - - // in a second go, delete all the single-channel-anims that we've stripped from their channels - // back to front to preserve indices - you know, removing an element from a vector moves all elements behind the removed one - while ( !collectedAnimIndices.empty() ) - { - mAnims.erase( mAnims.begin() + collectedAnimIndices.back()); - collectedAnimIndices.pop_back(); - } - } - } - } - - // now store all anims in the scene - if ( !mAnims.empty()) - { - pScene->mNumAnimations = mAnims.size(); - pScene->mAnimations = new aiAnimation*[mAnims.size()]; - std::copy( mAnims.begin(), mAnims.end(), pScene->mAnimations); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructs the animations for the given source anim -void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string pPrefix) -{ - std::string animName = pPrefix.empty() ? pSrcAnim->mName : pPrefix + "_" + pSrcAnim->mName; - - // create nested animations, if given - for ( std::vector<Collada::Animation*>::const_iterator it = pSrcAnim->mSubAnims.begin(); it != pSrcAnim->mSubAnims.end(); ++it) - StoreAnimations( pScene, pParser, *it, animName); - - // create animation channels, if any - if ( !pSrcAnim->mChannels.empty()) - CreateAnimation( pScene, pParser, pSrcAnim, animName); -} - -// ------------------------------------------------------------------------------------------------ -// Constructs the animation for the given source anim -void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName) -{ - // collect a list of animatable nodes - std::vector<const aiNode*> nodes; - CollectNodes( pScene->mRootNode, nodes); - - std::vector<aiNodeAnim*> anims; - for ( std::vector<const aiNode*>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit) - { - // find all the collada anim channels which refer to the current node - std::vector<Collada::ChannelEntry> entries; - std::string nodeName = (*nit)->mName.data; - - // find the collada node corresponding to the aiNode - const Collada::Node* srcNode = FindNode( pParser.mRootNode, nodeName); -// ai_assert( srcNode != NULL); - if ( !srcNode) - continue; - - // now check all channels if they affect the current node - for ( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin(); - cit != pSrcAnim->mChannels.end(); ++cit) - { - const Collada::AnimationChannel& srcChannel = *cit; - Collada::ChannelEntry entry; - - // we except the animation target to be of type "nodeName/transformID.subElement". Ignore all others - // find the slash that separates the node name - there should be only one - std::string::size_type slashPos = srcChannel.mTarget.find( '/'); - if ( slashPos == std::string::npos) - continue; - if ( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos) - continue; - std::string targetID = srcChannel.mTarget.substr( 0, slashPos); - if ( targetID != srcNode->mID) - continue; - - // find the dot that separates the transformID - there should be only one or zero - std::string::size_type dotPos = srcChannel.mTarget.find( '.'); - if ( dotPos != std::string::npos) - { - if ( srcChannel.mTarget.find( '.', dotPos+1) != std::string::npos) - continue; - - entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1); - - std::string subElement = srcChannel.mTarget.substr( dotPos+1); - if ( subElement == "ANGLE") - entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle - else if ( subElement == "X") - entry.mSubElement = 0; - else if ( subElement == "Y") - entry.mSubElement = 1; - else if ( subElement == "Z") - entry.mSubElement = 2; - else - DefaultLogger::get()->warn( boost::str( boost::format( "Unknown anim subelement \"%s\". Ignoring") % subElement)); - } else - { - // no subelement following, transformId is remaining string - entry.mTransformId = srcChannel.mTarget.substr( slashPos+1); - } - - // determine which transform step is affected by this channel - entry.mTransformIndex = 0xffffffff; - for ( size_t a = 0; a < srcNode->mTransforms.size(); ++a) - if ( srcNode->mTransforms[a].mID == entry.mTransformId) - entry.mTransformIndex = a; - - if ( entry.mTransformIndex == 0xffffffff) - continue; - - entry.mChannel = &(*cit); - entries.push_back( entry); - } - - // if there's no channel affecting the current node, we skip it - if ( entries.empty()) - continue; - - // resolve the data pointers for all anim channels. Find the minimum time while we're at it - float startTime = 1e20f, endTime = -1e20f; - for ( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& e = *it; - e.mTimeAccessor = &pParser.ResolveLibraryReference( pParser.mAccessorLibrary, e.mChannel->mSourceTimes); - e.mTimeData = &pParser.ResolveLibraryReference( pParser.mDataLibrary, e.mTimeAccessor->mSource); - e.mValueAccessor = &pParser.ResolveLibraryReference( pParser.mAccessorLibrary, e.mChannel->mSourceValues); - e.mValueData = &pParser.ResolveLibraryReference( pParser.mDataLibrary, e.mValueAccessor->mSource); - - // time count and value count must match - if ( e.mTimeAccessor->mCount != e.mValueAccessor->mCount) - throw DeadlyImportError( boost::str( boost::format( "Time count / value count mismatch in animation channel \"%s\".") % e.mChannel->mTarget)); - - // find bounding times - startTime = std::min( startTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, 0, 0)); - endTime = std::max( endTime, ReadFloat( *e.mTimeAccessor, *e.mTimeData, e.mTimeAccessor->mCount-1, 0)); - } - - // create a local transformation chain of the node's transforms - std::vector<Collada::Transform> transforms = srcNode->mTransforms; - - // now for every unique point in time, find or interpolate the key values for that time - // and apply them to the transform chain. Then the node's present transformation can be calculated. - float time = startTime; - std::vector<aiMatrix4x4> resultTrafos; - while ( 1) - { - for ( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& e = *it; - - // find the keyframe behind the current point in time - size_t pos = 0; - float postTime = 0.f; - while ( 1) - { - if ( pos >= e.mTimeAccessor->mCount) - break; - postTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0); - if ( postTime >= time) - break; - ++pos; - } - - pos = std::min( pos, e.mTimeAccessor->mCount-1); - - // read values from there - float temp[16]; - for ( size_t c = 0; c < e.mValueAccessor->mSize; ++c) - temp[c] = ReadFloat( *e.mValueAccessor, *e.mValueData, pos, c); - - // if not exactly at the key time, interpolate with previous value set - if ( postTime > time && pos > 0) - { - float preTime = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos-1, 0); - float factor = (time - postTime) / (preTime - postTime); - - for ( size_t c = 0; c < e.mValueAccessor->mSize; ++c) - { - float v = ReadFloat( *e.mValueAccessor, *e.mValueData, pos-1, c); - temp[c] += (v - temp[c]) * factor; - } - } - - // Apply values to current transformation - std::copy( temp, temp + e.mValueAccessor->mSize, transforms[e.mTransformIndex].f + e.mSubElement); - } - - // Calculate resulting transformation - aiMatrix4x4 mat = pParser.CalculateResultTransform( transforms); - - // out of lazyness: we store the time in matrix.d4 - mat.d4 = time; - resultTrafos.push_back( mat); - - // find next point in time to evaluate. That's the closest frame larger than the current in any channel - float nextTime = 1e20f; - for ( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it) - { - Collada::ChannelEntry& e = *it; - - // find the next time value larger than the current - size_t pos = 0; - while ( pos < e.mTimeAccessor->mCount) - { - float t = ReadFloat( *e.mTimeAccessor, *e.mTimeData, pos, 0); - if ( t > time) - { - nextTime = std::min( nextTime, t); - break; - } - ++pos; - } - } - - // no more keys on any channel after the current time -> we're done - if ( nextTime > 1e19) - break; - - // else construct next keyframe at this following time point - time = nextTime; - } - - // there should be some keyframes - ai_assert( resultTrafos.size() > 0); - - // build an animation channel for the given node out of these trafo keys - aiNodeAnim* dstAnim = new aiNodeAnim; - dstAnim->mNodeName = nodeName; - dstAnim->mNumPositionKeys = resultTrafos.size(); - dstAnim->mNumRotationKeys= resultTrafos.size(); - dstAnim->mNumScalingKeys = resultTrafos.size(); - dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()]; - dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()]; - dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()]; - - for ( size_t a = 0; a < resultTrafos.size(); ++a) - { - const aiMatrix4x4& mat = resultTrafos[a]; - double time = double( mat.d4); // remember? time is stored in mat.d4 - - dstAnim->mPositionKeys[a].mTime = time; - dstAnim->mRotationKeys[a].mTime = time; - dstAnim->mScalingKeys[a].mTime = time; - mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue); - } - - anims.push_back( dstAnim); - } - - if ( !anims.empty()) - { - aiAnimation* anim = new aiAnimation; - anim->mName.Set( pName); - anim->mNumChannels = anims.size(); - anim->mChannels = new aiNodeAnim*[anims.size()]; - std::copy( anims.begin(), anims.end(), anim->mChannels); - anim->mDuration = 0.0f; - for ( size_t a = 0; a < anims.size(); ++a) - { - anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime); - anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime); - anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime); - } - anim->mTicksPerSecond = 1; - mAnims.push_back( anim); - } -} - -// ------------------------------------------------------------------------------------------------ -// Add a texture to a material structure -void ColladaLoader::AddTexture ( Assimp::MaterialHelper& mat, const ColladaParser& pParser, - const Collada::Effect& effect, - const Collada::Sampler& sampler, - aiTextureType type, unsigned int idx) -{ - // first of all, basic file name - const aiString name = FindFilenameForEffectTexture( pParser, effect, sampler.mName ); - mat.AddProperty( &name, _AI_MATKEY_TEXTURE_BASE, type, idx ); - - // mapping mode - int map = aiTextureMapMode_Clamp; - if (sampler.mWrapU) - map = aiTextureMapMode_Wrap; - if (sampler.mWrapU && sampler.mMirrorU) - map = aiTextureMapMode_Mirror; - - mat.AddProperty( &map, 1, _AI_MATKEY_MAPPINGMODE_U_BASE, type, idx); - - map = aiTextureMapMode_Clamp; - if (sampler.mWrapV) - map = aiTextureMapMode_Wrap; - if (sampler.mWrapV && sampler.mMirrorV) - map = aiTextureMapMode_Mirror; - - mat.AddProperty( &map, 1, _AI_MATKEY_MAPPINGMODE_V_BASE, type, idx); - - // UV transformation - mat.AddProperty(&sampler.mTransform, 1, - _AI_MATKEY_UVTRANSFORM_BASE, type, idx); - - // Blend mode - mat.AddProperty((int*)&sampler.mOp , 1, - _AI_MATKEY_TEXBLEND_BASE, type, idx); - - // Blend factor - mat.AddProperty((float*)&sampler.mWeighting , 1, - _AI_MATKEY_TEXBLEND_BASE, type, idx); - - // UV source index ... if we didn't resolve the mapping it is actually just - // a guess but it works in most cases. We search for the frst occurence of a - // number in the channel name. We assume it is the zero-based index into the - // UV channel array of all corresponding meshes. It could also be one-based - // for some exporters, but we won't care of it unless someone complains about. - if (sampler.mUVId != 0xffffffff) - map = sampler.mUVId; - else { - map = -1; - for (std::string::const_iterator it = sampler.mUVChannel.begin();it != sampler.mUVChannel.end(); ++it){ - if (IsNumeric(*it)) { - map = strtol10(&(*it)); - break; - } - } - if (-1 == map) { - DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture"); - map = 0; - } - } - mat.AddProperty(&map,1,_AI_MATKEY_UVWSRC_BASE,type,idx); -} - -// ------------------------------------------------------------------------------------------------ -// Fills materials from the collada material definitions -void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* pScene) -{ - for (std::vector<std::pair<Collada::Effect*, aiMaterial*> >::iterator it = newMats.begin(), - end = newMats.end(); it != end; ++it) - { - MaterialHelper& mat = (MaterialHelper&)*it->second; - Collada::Effect& effect = *it->first; - - // resolve shading mode - int shadeMode; - if (effect.mFaceted) /* fixme */ - shadeMode = aiShadingMode_Flat; - else { - switch( effect.mShadeType) - { - case Collada::Shade_Constant: - shadeMode = aiShadingMode_NoShading; - break; - case Collada::Shade_Lambert: - shadeMode = aiShadingMode_Gouraud; - break; - case Collada::Shade_Blinn: - shadeMode = aiShadingMode_Blinn; - break; - case Collada::Shade_Phong: - shadeMode = aiShadingMode_Phong; - break; - - default: - DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading"); - shadeMode = aiShadingMode_Gouraud; - break; - } - } - mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); - - // double-sided? - shadeMode = effect.mDoubleSided; - mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_TWOSIDED); - - // wireframe? - shadeMode = effect.mWireframe; - mat.AddProperty<int>( &shadeMode, 1, AI_MATKEY_ENABLE_WIREFRAME); - - // add material colors - mat.AddProperty( &effect.mAmbient, 1,AI_MATKEY_COLOR_AMBIENT); - mat.AddProperty( &effect.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat.AddProperty( &effect.mSpecular, 1,AI_MATKEY_COLOR_SPECULAR); - mat.AddProperty( &effect.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); - mat.AddProperty( &effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT); - mat.AddProperty( &effect.mReflective, 1, AI_MATKEY_COLOR_REFLECTIVE); - - // scalar properties - mat.AddProperty( &effect.mShininess, 1, AI_MATKEY_SHININESS); - mat.AddProperty( &effect.mReflectivity, 1, AI_MATKEY_REFLECTIVITY); - mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI); - - // transparency, a very hard one. seemingly not all files are following the - // specification here .. but we can trick. - if (effect.mTransparency > 0.f && effect.mTransparency < 1.f) { - effect.mTransparency = 1.f- effect.mTransparency; - mat.AddProperty( &effect.mTransparency, 1, AI_MATKEY_OPACITY ); - mat.AddProperty( &effect.mTransparent, 1, AI_MATKEY_COLOR_TRANSPARENT ); - } - - // add textures, if given - if ( !effect.mTexAmbient.mName.empty()) - /* It is merely a lightmap */ - AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP); - - if ( !effect.mTexEmissive.mName.empty()) - AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE); - - if ( !effect.mTexSpecular.mName.empty()) - AddTexture( mat, pParser, effect, effect.mTexSpecular, aiTextureType_SPECULAR); - - if ( !effect.mTexDiffuse.mName.empty()) - AddTexture( mat, pParser, effect, effect.mTexDiffuse, aiTextureType_DIFFUSE); - - if ( !effect.mTexBump.mName.empty()) - AddTexture( mat, pParser, effect, effect.mTexBump, aiTextureType_HEIGHT); - - if ( !effect.mTexTransparent.mName.empty()) - AddTexture( mat, pParser, effect, effect.mTexTransparent, aiTextureType_OPACITY); - - if ( !effect.mTexReflective.mName.empty()) - AddTexture( mat, pParser, effect, effect.mTexReflective, aiTextureType_REFLECTION); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructs materials from the collada material definitions -void ColladaLoader::BuildMaterials( const ColladaParser& pParser, aiScene* pScene) -{ - newMats.reserve(pParser.mMaterialLibrary.size()); - - for ( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt) - { - const Collada::Material& material = matIt->second; - // a material is only a reference to an effect - ColladaParser::EffectLibrary::const_iterator effIt = pParser.mEffectLibrary.find( material.mEffect); - if ( effIt == pParser.mEffectLibrary.end()) - continue; - const Collada::Effect& effect = effIt->second; - - // create material - Assimp::MaterialHelper* mat = new Assimp::MaterialHelper; - aiString name( matIt->first); - mat->AddProperty(&name,AI_MATKEY_NAME); - - // MEGA SUPER MONSTER HACK by Alex ... It's all my fault, yes. - // We store the reference to the effect in the material and - // return ... we'll add the actual material properties later - // after we processed all meshes. During mesh processing, - // we evaluate vertex input mappings. Afterwards we should be - // able to correctly setup source UV channels for textures. - - // ... moved to ColladaLoader::FillMaterials() - // *duck* - - // store the material - mMaterialIndexByName[matIt->first] = newMats.size(); - newMats.push_back( std::pair<Collada::Effect*, aiMaterial*>(const_cast<Collada::Effect*>(&effect),mat) ); - } - // ScenePreprocessor generates a default material automatically if none is there. - // All further code here in this loader works well without a valid material so - // we can safely let it to ScenePreprocessor. -#if 0 - if ( newMats.size() == 0) - { - Assimp::MaterialHelper* mat = new Assimp::MaterialHelper; - aiString name( AI_DEFAULT_MATERIAL_NAME ); - mat->AddProperty( &name, AI_MATKEY_NAME); - - const int shadeMode = aiShadingMode_Phong; - mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); - aiColor4D colAmbient( 0.2f, 0.2f, 0.2f, 1.0f), colDiffuse( 0.8f, 0.8f, 0.8f, 1.0f), colSpecular( 0.5f, 0.5f, 0.5f, 0.5f); - mat->AddProperty( &colAmbient, 1, AI_MATKEY_COLOR_AMBIENT); - mat->AddProperty( &colDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &colSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - const float specExp = 5.0f; - mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS); - } -#endif -} - -// ------------------------------------------------------------------------------------------------ -// Resolves the texture name for the given effect texture entry -aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser, - const Collada::Effect& pEffect, const std::string& pName) -{ - // recurse through the param references until we end up at an image - std::string name = pName; - while ( 1) - { - // the given string is a param entry. Find it - Collada::Effect::ParamLibrary::const_iterator it = pEffect.mParams.find( name); - // if not found, we're at the end of the recursion. The resulting string should be the image ID - if ( it == pEffect.mParams.end()) - break; - - // else recurse on - name = it->second.mReference; - } - - // find the image referred by this name in the image library of the scene - ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name); - if ( imIt == pParser.mImageLibrary.end()) - { - throw DeadlyImportError( boost::str( boost::format( - "Collada: Unable to resolve effect texture entry \"%s\", ended up at ID \"%s\".") % pName % name)); - } - - aiString result; - - // if this is an embedded texture image setup an aiTexture for it - if (imIt->second.mFileName.empty()) - { - if (imIt->second.mImageData.empty()) { - throw DeadlyImportError("Collada: Invalid texture, no data or file reference given"); - } - - aiTexture* tex = new aiTexture(); - - // setup format hint - if (imIt->second.mEmbeddedFormat.length() > 3) { - DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters"); - } - strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3); - - // and copy texture data - tex->mHeight = 0; - tex->mWidth = imIt->second.mImageData.size(); - tex->pcData = (aiTexel*)new char[tex->mWidth]; - memcpy(tex->pcData,&imIt->second.mImageData[0],tex->mWidth); - - // setup texture reference string - result.data[0] = '*'; - result.length = 1 + ASSIMP_itoa10(result.data+1,MAXLEN-1,mTextures.size()); - - // and add this texture to the list - mTextures.push_back(tex); - } - else - { - result.Set( imIt->second.mFileName ); - ConvertPath(result); - } - return result; -} - -// ------------------------------------------------------------------------------------------------ -// Convert a path read from a collada file to the usual representation -void ColladaLoader::ConvertPath (aiString& ss) -{ - // TODO: collada spec, p 22. Handle URI correctly. - // For the moment we're just stripping the file:// away to make it work. - // Windoes doesn't seem to be able to find stuff like - // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg' - if (0 == strncmp(ss.data,"file://",7)) - { - ss.length -= 7; - memmove(ss.data,ss.data+7,ss.length); - ss.data[ss.length] = '\0'; - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a float value from an accessor and its data array. -float ColladaLoader::ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const -{ - // FIXME: (thom) Test for data type here in every access? For the moment, I leave this to the caller - size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset + pOffset; - ai_assert( pos < pData.mValues.size()); - return pData.mValues[pos]; -} - -// ------------------------------------------------------------------------------------------------ -// Reads a string value from an accessor and its data array. -const std::string& ColladaLoader::ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const -{ - size_t pos = pAccessor.mStride * pIndex + pAccessor.mOffset; - ai_assert( pos < pData.mStrings.size()); - return pData.mStrings[pos]; -} - -// ------------------------------------------------------------------------------------------------ -// Collects all nodes into the given array -void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const -{ - poNodes.push_back( pNode); - - for ( size_t a = 0; a < pNode->mNumChildren; ++a) - CollectNodes( pNode->mChildren[a], poNodes); -} - -// ------------------------------------------------------------------------------------------------ -// Finds a node in the collada scene by the given name -const Collada::Node* ColladaLoader::FindNode( const Collada::Node* pNode, const std::string& pName) const -{ - if ( pNode->mName == pName || pNode->mID == pName) - return pNode; - - for ( size_t a = 0; a < pNode->mChildren.size(); ++a) - { - const Collada::Node* node = FindNode( pNode->mChildren[a], pName); - if ( node) - return node; - } - - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// Finds a node in the collada scene by the given SID -const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const -{ - if ( pNode->mSID == pSID) - return pNode; - - for ( size_t a = 0; a < pNode->mChildren.size(); ++a) - { - const Collada::Node* node = FindNodeBySID( pNode->mChildren[a], pSID); - if ( node) - return node; - } - - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// Finds a proper name for a node derived from the collada-node's properties -std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode) const -{ - // now setup the name of the node. We take the name if not empty, otherwise the collada ID - // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default. - if (!pNode->mName.empty() && pNode->mName != "untitled") - return pNode->mName; - else if (!pNode->mID.empty()) - return pNode->mID; - else if (!pNode->mSID.empty()) - return pNode->mSID; - else - { - // No need to worry. Unnamed nodes are no problem at all, except - // if cameras or lights need to be assigned to them. - return boost::str( boost::format( "$ColladaAutoName$_%d") % clock()); - } -} - -#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER diff --git a/3rdparty/assimp/code/ColladaLoader.h b/3rdparty/assimp/code/ColladaLoader.h deleted file mode 100644 index 72439eb9..00000000 --- a/3rdparty/assimp/code/ColladaLoader.h +++ /dev/null @@ -1,241 +0,0 @@ -/** Defines the collada loader class */ - -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef AI_COLLADALOADER_H_INC -#define AI_COLLADALOADER_H_INC - -#include "BaseImporter.h" -#include "ColladaParser.h" - -namespace Assimp -{ - -struct ColladaMeshIndex -{ - std::string mMeshID; - size_t mSubMesh; - std::string mMaterial; - ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial) - : mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial) - { } - - bool operator < (const ColladaMeshIndex& p) const - { - if ( mMeshID == p.mMeshID) - { - if ( mSubMesh == p.mSubMesh) - return mMaterial < p.mMaterial; - else - return mSubMesh < p.mSubMesh; - } else - { - return mMeshID < p.mMeshID; - } - } -}; - -/** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing - * more useless stuff, so I limited the data to what I think is useful for games. -*/ -class ColladaLoader : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - ColladaLoader(); - - /** Destructor, private as well */ - ~ColladaLoader(); - -public: - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; - -protected: - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList( std::set<std::string>& extensions); - - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - /** Recursively constructs a scene node for the given parser node and returns it. */ - aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode); - - /** Resolve node instances */ - void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode, - std::vector<const Collada::Node*>& resolved); - - /** Builds meshes for the given node and references them */ - void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, - aiNode* pTarget); - - /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */ - aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh, - const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace); - - /** Builds cameras for the given node and references them */ - void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, - aiNode* pTarget); - - /** Builds lights for the given node and references them */ - void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, - aiNode* pTarget); - - /** Stores all meshes in the given scene */ - void StoreSceneMeshes( aiScene* pScene); - - /** Stores all materials in the given scene */ - void StoreSceneMaterials( aiScene* pScene); - - /** Stores all lights in the given scene */ - void StoreSceneLights( aiScene* pScene); - - /** Stores all cameras in the given scene */ - void StoreSceneCameras( aiScene* pScene); - - /** Stores all textures in the given scene */ - void StoreSceneTextures( aiScene* pScene); - - /** Stores all animations - * @param pScene target scene to store the anims - */ - void StoreAnimations( aiScene* pScene, const ColladaParser& pParser); - - /** Stores all animations for the given source anim and its nested child animations - * @param pScene target scene to store the anims - * @param pSrcAnim the source animation to process - * @param pPrefix Prefix to the name in case of nested animations - */ - void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string pPrefix); - - /** Constructs the animation for the given source anim */ - void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName); - - /** Constructs materials from the collada material definitions */ - void BuildMaterials( const ColladaParser& pParser, aiScene* pScene); - - /** Fill materials from the collada material definitions */ - void FillMaterials( const ColladaParser& pParser, aiScene* pScene); - - /** Resolve UV channel mappings*/ - void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler, - const Collada::SemanticMappingTable& table); - - /** Add a texture and all of its sampling properties to a material*/ - void AddTexture ( Assimp::MaterialHelper& mat, const ColladaParser& pParser, - const Collada::Effect& effect, - const Collada::Sampler& sampler, - aiTextureType type, unsigned int idx = 0); - - /** Resolves the texture name for the given effect texture entry */ - aiString FindFilenameForEffectTexture( const ColladaParser& pParser, - const Collada::Effect& pEffect, const std::string& pName); - - /** Converts a path read from a collada file to the usual representation */ - void ConvertPath( aiString& ss); - - /** Reads a float value from an accessor and its data array. - * @param pAccessor The accessor to use for reading - * @param pData The data array to read from - * @param pIndex The index of the element to retrieve - * @param pOffset Offset into the element, for multipart elements such as vectors or matrices - * @return the specified value - */ - float ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const; - - /** Reads a string value from an accessor and its data array. - * @param pAccessor The accessor to use for reading - * @param pData The data array to read from - * @param pIndex The index of the element to retrieve - * @return the specified value - */ - const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const; - - /** Recursively collects all nodes into the given array */ - void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const; - - /** Finds a node in the collada scene by the given name */ - const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const; - /** Finds a node in the collada scene by the given SID */ - const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const; - - /** Finds a proper name for a node derived from the collada-node's properties */ - std::string FindNameForNode( const Collada::Node* pNode) const; - -protected: - /** Filename, for a verbose error message */ - std::string mFileName; - - /** Which mesh-material compound was stored under which mesh ID */ - std::map<ColladaMeshIndex, size_t> mMeshIndexByID; - - /** Which material was stored under which index in the scene */ - std::map<std::string, size_t> mMaterialIndexByName; - - /** Accumulated meshes for the target scene */ - std::vector<aiMesh*> mMeshes; - - /** Temporary material list */ - std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats; - - /** Temporary camera list */ - std::vector<aiCamera*> mCameras; - - /** Temporary light list */ - std::vector<aiLight*> mLights; - - /** Temporary texture list */ - std::vector<aiTexture*> mTextures; - - /** Accumulated animations for the target scene */ - std::vector<aiAnimation*> mAnims; -}; - -} // end of namespace Assimp - -#endif // AI_COLLADALOADER_H_INC diff --git a/3rdparty/assimp/code/ColladaParser.cpp b/3rdparty/assimp/code/ColladaParser.cpp deleted file mode 100644 index 2513b929..00000000 --- a/3rdparty/assimp/code/ColladaParser.cpp +++ /dev/null @@ -1,2801 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ColladaParser.cpp - * @brief Implementation of the Collada parser helper - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_DAE_IMPORTER - -#include "ColladaParser.h" -#include "fast_atof.h" -#include "ParsingUtils.h" - -using namespace Assimp; -using namespace Assimp::Collada; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile) - : mFileName( pFile) -{ - mRootNode = NULL; - mUnitSize = 1.0f; - mUpDirection = UP_Z; - - // We assume the newest file format by default - mFormat = FV_1_5_n; - - // open the file - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open file " + pFile + "."); - - // generate a XML reader for it - boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get())); - mReader = irr::io::createIrrXMLReader( mIOWrapper.get()); - if ( !mReader) - ThrowException( "Collada: Unable to open file."); - - // start reading - ReadContents(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ColladaParser::~ColladaParser() -{ - delete mReader; - for ( NodeLibrary::iterator it = mNodeLibrary.begin(); it != mNodeLibrary.end(); ++it) - delete it->second; - for ( MeshLibrary::iterator it = mMeshLibrary.begin(); it != mMeshLibrary.end(); ++it) - delete it->second; -} - -// ------------------------------------------------------------------------------------------------ -// Read bool from text contents of current element -bool ColladaParser::ReadBoolFromTextContent() -{ - const char* cur = GetTextContent(); - return (!ASSIMP_strincmp(cur,"true",4) || '0' != *cur); -} - -// ------------------------------------------------------------------------------------------------ -// Read float from text contents of current element -float ColladaParser::ReadFloatFromTextContent() -{ - const char* cur = GetTextContent(); - return fast_atof(cur); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the contents of the file -void ColladaParser::ReadContents() -{ - while ( mReader->read()) - { - // handle the root element "COLLADA" - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "COLLADA")) - { - // check for 'version' attribute - const int attrib = TestAttribute("version"); - if (attrib != -1) { - const char* version = mReader->getAttributeValue(attrib); - - if (!::strncmp(version,"1.5",3)) { - mFormat = FV_1_5_n; - DefaultLogger::get()->debug("Collada schema version is 1.5.n"); - } - else if (!::strncmp(version,"1.4",3)) { - mFormat = FV_1_4_n; - DefaultLogger::get()->debug("Collada schema version is 1.4.n"); - } - else if (!::strncmp(version,"1.3",3)) { - mFormat = FV_1_3_n; - DefaultLogger::get()->debug("Collada schema version is 1.3.n"); - } - } - - ReadStructure(); - } else - { - DefaultLogger::get()->debug( boost::str( boost::format( "Ignoring global element \"%s\".") % mReader->getNodeName())); - SkipElement(); - } - } else - { - // skip everything else silently - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the structure of the file -void ColladaParser::ReadStructure() -{ - while ( mReader->read()) - { - // beginning of elements - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "asset")) - ReadAssetInfo(); - else if ( IsElement( "library_animations")) - ReadAnimationLibrary(); - else if ( IsElement( "library_controllers")) - ReadControllerLibrary(); - else if ( IsElement( "library_images")) - ReadImageLibrary(); - else if ( IsElement( "library_materials")) - ReadMaterialLibrary(); - else if ( IsElement( "library_effects")) - ReadEffectLibrary(); - else if ( IsElement( "library_geometries")) - ReadGeometryLibrary(); - else if ( IsElement( "library_visual_scenes")) - ReadSceneLibrary(); - else if ( IsElement( "library_lights")) - ReadLightLibrary(); - else if ( IsElement( "library_cameras")) - ReadCameraLibrary(); - else if ( IsElement( "library_nodes")) - ReadSceneNode(NULL); /* some hacking to reuse this piece of code */ - else if ( IsElement( "scene")) - ReadScene(); - else - SkipElement(); - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads asset informations such as coordinate system informations and legal blah -void ColladaParser::ReadAssetInfo() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "unit")) - { - // read unit data from the element's attributes - const int attrIndex = TestAttribute( "meter"); - if (attrIndex == -1) { - mUnitSize = 1.f; - } - else { - mUnitSize = mReader->getAttributeValueAsFloat( attrIndex); - } - - // consume the trailing stuff - if ( !mReader->isEmptyElement()) - SkipElement(); - } - else if ( IsElement( "up_axis")) - { - // read content, strip whitespace, compare - const char* content = GetTextContent(); - if ( strncmp( content, "X_UP", 4) == 0) - mUpDirection = UP_X; - else if ( strncmp( content, "Y_UP", 4) == 0) - mUpDirection = UP_Y; - else - mUpDirection = UP_Z; - - // check element end - TestClosing( "up_axis"); - } else - { - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "asset") != 0) - ThrowException( "Expected end of \"asset\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the animation library -void ColladaParser::ReadAnimationLibrary() -{ - if (mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "animation")) - { - // delegate the reading. Depending on the inner elements it will be a container or a anim channel - ReadAnimation( &mAnims); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "library_animations") != 0) - ThrowException( "Expected end of \"library_animations\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an animation into the given parent structure -void ColladaParser::ReadAnimation( Collada::Animation* pParent) -{ - if ( mReader->isEmptyElement()) - return; - - // an <animation> element may be a container for grouping sub-elements or an animation channel - // this is the channel collection by ID, in case it has channels - typedef std::map<std::string, AnimationChannel> ChannelMap; - ChannelMap channels; - // this is the anim container in case we're a container - Animation* anim = NULL; - - // optional name given as an attribute - std::string animName; - int indexName = TestAttribute( "name"); - int indexID = TestAttribute( "id"); - if ( indexName >= 0) - animName = mReader->getAttributeValue( indexName); - else if ( indexID >= 0) - animName = mReader->getAttributeValue( indexID); - else - animName = "animation"; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - // we have subanimations - if ( IsElement( "animation")) - { - // create container from our element - if ( !anim) - { - anim = new Animation; - anim->mName = animName; - pParent->mSubAnims.push_back( anim); - } - - // recurse into the subelement - ReadAnimation( anim); - } - else if ( IsElement( "source")) - { - // possible animation data - we'll never know. Better store it - ReadSource(); - } - else if ( IsElement( "sampler")) - { - // read the ID to assign the corresponding collada channel afterwards. - int indexID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( indexID); - ChannelMap::iterator newChannel = channels.insert( std::make_pair( id, AnimationChannel())).first; - - // have it read into a channel - ReadAnimationSampler( newChannel->second); - } - else if ( IsElement( "channel")) - { - // the binding element whose whole purpose is to provide the target to animate - // Thanks, Collada! A directly posted information would have been too simple, I guess. - // Better add another indirection to that! Can't have enough of those. - int indexTarget = GetAttribute( "target"); - int indexSource = GetAttribute( "source"); - const char* sourceId = mReader->getAttributeValue( indexSource); - if ( sourceId[0] == '#') - sourceId++; - ChannelMap::iterator cit = channels.find( sourceId); - if ( cit != channels.end()) - cit->second.mTarget = mReader->getAttributeValue( indexTarget); - - if ( !mReader->isEmptyElement()) - SkipElement(); - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "animation") != 0) - ThrowException( "Expected end of \"animation\" element."); - - break; - } - } - - // it turned out to have channels - add them - if ( !channels.empty()) - { - // special filtering for stupid exporters packing each channel into a separate animation - if ( channels.size() == 1) - { - pParent->mChannels.push_back( channels.begin()->second); - } else - { - // else create the animation, if not done yet, and store the channels - if ( !anim) - { - anim = new Animation; - anim->mName = animName; - pParent->mSubAnims.push_back( anim); - } - for ( ChannelMap::const_iterator it = channels.begin(); it != channels.end(); ++it) - anim->mChannels.push_back( it->second); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an animation sampler into the given anim channel -void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "input")) - { - int indexSemantic = GetAttribute( "semantic"); - const char* semantic = mReader->getAttributeValue( indexSemantic); - int indexSource = GetAttribute( "source"); - const char* source = mReader->getAttributeValue( indexSource); - if ( source[0] != '#') - ThrowException( "Unsupported URL format"); - source++; - - if ( strcmp( semantic, "INPUT") == 0) - pChannel.mSourceTimes = source; - else if ( strcmp( semantic, "OUTPUT") == 0) - pChannel.mSourceValues = source; - - if ( !mReader->isEmptyElement()) - SkipElement(); - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "sampler") != 0) - ThrowException( "Expected end of \"sampler\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the skeleton controller library -void ColladaParser::ReadControllerLibrary() -{ - if (mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "controller")) - { - // read ID. Ask the spec if it's neccessary or optional... you might be surprised. - int attrID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( attrID); - - // create an entry and store it in the library under its ID - mControllerLibrary[id] = Controller(); - - // read on from there - ReadController( mControllerLibrary[id]); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "library_controllers") != 0) - ThrowException( "Expected end of \"library_controllers\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a controller into the given mesh structure -void ColladaParser::ReadController( Collada::Controller& pController) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other - if ( IsElement( "morph")) - { - // should skip everything inside, so there's no danger of catching elements inbetween - SkipElement(); - } - else if ( IsElement( "skin")) - { - // read the mesh it refers to. According to the spec this could also be another - // controller, but I refuse to implement every bullshit idea they've come up with - int sourceIndex = GetAttribute( "source"); - pController.mMeshId = mReader->getAttributeValue( sourceIndex) + 1; - } - else if ( IsElement( "bind_shape_matrix")) - { - // content is 16 floats to define a matrix... it seems to be important for some models - const char* content = GetTextContent(); - - // read the 16 floats - for ( unsigned int a = 0; a < 16; a++) - { - // read a number - content = fast_atof_move( content, pController.mBindShapeMatrix[a]); - // skip whitespace after it - SkipSpacesAndLineEnd( &content); - } - - TestClosing( "bind_shape_matrix"); - } - else if ( IsElement( "source")) - { - // data array - we have specialists to handle this - ReadSource(); - } - else if ( IsElement( "joints")) - { - ReadControllerJoints( pController); - } - else if ( IsElement( "vertex_weights")) - { - ReadControllerWeights( pController); - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "controller") == 0) - break; - else if ( strcmp( mReader->getNodeName(), "skin") != 0) - ThrowException( "Expected end of \"controller\" element."); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the joint definitions for the given controller -void ColladaParser::ReadControllerJoints( Collada::Controller& pController) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - // Input channels for joint data. Two possible semantics: "JOINT" and "INV_BIND_MATRIX" - if ( IsElement( "input")) - { - int indexSemantic = GetAttribute( "semantic"); - const char* attrSemantic = mReader->getAttributeValue( indexSemantic); - int indexSource = GetAttribute( "source"); - const char* attrSource = mReader->getAttributeValue( indexSource); - - // local URLS always start with a '#'. We don't support global URLs - if ( attrSource[0] != '#') - ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\"") % attrSource)); - attrSource++; - - // parse source URL to corresponding source - if ( strcmp( attrSemantic, "JOINT") == 0) - pController.mJointNameSource = attrSource; - else if ( strcmp( attrSemantic, "INV_BIND_MATRIX") == 0) - pController.mJointOffsetMatrixSource = attrSource; - else - ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in joint data") % attrSemantic)); - - // skip inner data, if present - if ( !mReader->isEmptyElement()) - SkipElement(); - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "joints") != 0) - ThrowException( "Expected end of \"joints\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the joint weights for the given controller -void ColladaParser::ReadControllerWeights( Collada::Controller& pController) -{ - // read vertex count from attributes and resize the array accordingly - int indexCount = GetAttribute( "count"); - size_t vertexCount = (size_t) mReader->getAttributeValueAsInt( indexCount); - pController.mWeightCounts.resize( vertexCount); - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - // Input channels for weight data. Two possible semantics: "JOINT" and "WEIGHT" - if ( IsElement( "input")) - { - InputChannel channel; - - int indexSemantic = GetAttribute( "semantic"); - const char* attrSemantic = mReader->getAttributeValue( indexSemantic); - int indexSource = GetAttribute( "source"); - const char* attrSource = mReader->getAttributeValue( indexSource); - int indexOffset = TestAttribute( "offset"); - if ( indexOffset >= 0) - channel.mOffset = mReader->getAttributeValueAsInt( indexOffset); - - // local URLS always start with a '#'. We don't support global URLs - if ( attrSource[0] != '#') - ThrowException( boost::str( boost::format( "Unsupported URL format in \"%s\"") % attrSource)); - channel.mAccessor = attrSource + 1; - - // parse source URL to corresponding source - if ( strcmp( attrSemantic, "JOINT") == 0) - pController.mWeightInputJoints = channel; - else if ( strcmp( attrSemantic, "WEIGHT") == 0) - pController.mWeightInputWeights = channel; - else - ThrowException( boost::str( boost::format( "Unknown semantic \"%s\" in vertex_weight data") % attrSemantic)); - - // skip inner data, if present - if ( !mReader->isEmptyElement()) - SkipElement(); - } - else if ( IsElement( "vcount")) - { - // read weight count per vertex - const char* text = GetTextContent(); - size_t numWeights = 0; - for ( std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) - { - if ( *text == 0) - ThrowException( "Out of data while reading vcount"); - - *it = strtol10( text, &text); - numWeights += *it; - SkipSpacesAndLineEnd( &text); - } - - TestClosing( "vcount"); - - // reserve weight count - pController.mWeights.resize( numWeights); - } - else if ( IsElement( "v")) - { - // read JointIndex - WeightIndex pairs - const char* text = GetTextContent(); - - for ( std::vector< std::pair<size_t, size_t> >::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) - { - if ( *text == 0) - ThrowException( "Out of data while reading vertex_weights"); - it->first = strtol10( text, &text); - SkipSpacesAndLineEnd( &text); - if ( *text == 0) - ThrowException( "Out of data while reading vertex_weights"); - it->second = strtol10( text, &text); - SkipSpacesAndLineEnd( &text); - } - - TestClosing( "v"); - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "vertex_weights") != 0) - ThrowException( "Expected end of \"vertex_weights\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the image library contents -void ColladaParser::ReadImageLibrary() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "image")) - { - // read ID. Another entry which is "optional" by design but obligatory in reality - int attrID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( attrID); - - // create an entry and store it in the library under its ID - mImageLibrary[id] = Image(); - - // read on from there - ReadImage( mImageLibrary[id]); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "library_images") != 0) - ThrowException( "Expected end of \"library_images\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an image entry into the given image -void ColladaParser::ReadImage( Collada::Image& pImage) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT){ - // Need to run different code paths here, depending on the Collada XSD version - if (IsElement("image")) { - SkipElement(); - } - else if ( IsElement( "init_from")) - { - if (mFormat == FV_1_4_n) - { - // FIX: C4D exporter writes empty <init_from/> tags - if (!mReader->isEmptyElement()) { - // element content is filename - hopefully - const char* sz = TestTextContent(); - if (sz)pImage.mFileName = sz; - TestClosing( "init_from"); - } - if (!pImage.mFileName.length()) { - pImage.mFileName = "unknown_texture"; - } - } - else if (mFormat == FV_1_5_n) - { - // make sure we skip over mip and array initializations, which - // we don't support, but which could confuse the loader if - // they're not skipped. - int attrib = TestAttribute("array_index"); - if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) { - DefaultLogger::get()->warn("Collada: Ignoring texture array index"); - continue; - } - - attrib = TestAttribute("mip_index"); - if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) { - DefaultLogger::get()->warn("Collada: Ignoring MIP map layer"); - continue; - } - - // TODO: correctly jump over cube and volume maps? - } - } - else if (mFormat == FV_1_5_n) - { - if ( IsElement( "ref")) - { - // element content is filename - hopefully - const char* sz = TestTextContent(); - if (sz)pImage.mFileName = sz; - TestClosing( "ref"); - } - else if ( IsElement( "hex") && !pImage.mFileName.length()) - { - // embedded image. get format - const int attrib = TestAttribute("format"); - if (-1 == attrib) - DefaultLogger::get()->warn("Collada: Unknown image file format"); - else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib); - - const char* data = GetTextContent(); - - // hexadecimal-encoded binary octets. First of all, find the - // required buffer size to reserve enough storage. - const char* cur = data; - while (!IsSpaceOrNewLine(*cur)) cur++; - - const unsigned int size = (unsigned int)(cur-data) * 2; - pImage.mImageData.resize(size); - for (unsigned int i = 0; i < size;++i) - pImage.mImageData[i] = HexOctetToDecimal(data+(i<<1)); - - TestClosing( "hex"); - } - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "image") == 0) - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the material library -void ColladaParser::ReadMaterialLibrary() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "material")) - { - // read ID. By now you propably know my opinion about this "specification" - int attrID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( attrID); - - // create an entry and store it in the library under its ID - ReadMaterial(mMaterialLibrary[id] = Material()); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "library_materials") != 0) - ThrowException( "Expected end of \"library_materials\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the light library -void ColladaParser::ReadLightLibrary() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "light")) - { - // read ID. By now you propably know my opinion about this "specification" - int attrID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( attrID); - - // create an entry and store it in the library under its ID - ReadLight(mLightLibrary[id] = Light()); - - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "library_lights") != 0) - ThrowException( "Expected end of \"library_lights\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the camera library -void ColladaParser::ReadCameraLibrary() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "camera")) - { - // read ID. By now you propably know my opinion about this "specification" - int attrID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( attrID); - - // create an entry and store it in the library under its ID - Camera& cam = mCameraLibrary[id]; - attrID = TestAttribute( "name"); - if (attrID != -1) - cam.mName = mReader->getAttributeValue( attrID); - - ReadCamera(cam); - - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "library_cameras") != 0) - ThrowException( "Expected end of \"library_cameras\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a material entry into the given material -void ColladaParser::ReadMaterial( Collada::Material& pMaterial) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("material")) { - SkipElement(); - } - else if ( IsElement( "instance_effect")) - { - // referred effect by URL - int attrUrl = GetAttribute( "url"); - const char* url = mReader->getAttributeValue( attrUrl); - if ( url[0] != '#') - ThrowException( "Unknown reference format"); - - pMaterial.mEffect = url+1; - - SkipElement(); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "material") != 0) - ThrowException( "Expected end of \"material\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a light entry into the given light -void ColladaParser::ReadLight( Collada::Light& pLight) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("light")) { - SkipElement(); - } - else if (IsElement("spot")) { - pLight.mType = aiLightSource_SPOT; - } - else if (IsElement("ambient")) { - pLight.mType = aiLightSource_AMBIENT; - } - else if (IsElement("directional")) { - pLight.mType = aiLightSource_DIRECTIONAL; - } - else if (IsElement("point")) { - pLight.mType = aiLightSource_POINT; - } - else if (IsElement("color")) { - // text content contains 3 floats - const char* content = GetTextContent(); - - content = fast_atof_move( content, (float&)pLight.mColor.r); - SkipSpacesAndLineEnd( &content); - - content = fast_atof_move( content, (float&)pLight.mColor.g); - SkipSpacesAndLineEnd( &content); - - content = fast_atof_move( content, (float&)pLight.mColor.b); - SkipSpacesAndLineEnd( &content); - - TestClosing( "color"); - } - else if (IsElement("constant_attenuation")) { - pLight.mAttConstant = ReadFloatFromTextContent(); - TestClosing("constant_attenuation"); - } - else if (IsElement("linear_attenuation")) { - pLight.mAttLinear = ReadFloatFromTextContent(); - TestClosing("linear_attenuation"); - } - else if (IsElement("quadratic_attenuation")) { - pLight.mAttQuadratic = ReadFloatFromTextContent(); - TestClosing("quadratic_attenuation"); - } - else if (IsElement("falloff_angle")) { - pLight.mFalloffAngle = ReadFloatFromTextContent(); - TestClosing("falloff_angle"); - } - else if (IsElement("falloff_exponent")) { - pLight.mFalloffExponent = ReadFloatFromTextContent(); - TestClosing("falloff_exponent"); - } - // FCOLLADA extensions - // ------------------------------------------------------- - else if (IsElement("outer_cone")) { - pLight.mOuterAngle = ReadFloatFromTextContent(); - TestClosing("outer_cone"); - } - // ... and this one is even deprecated - else if (IsElement("penumbra_angle")) { - pLight.mPenumbraAngle = ReadFloatFromTextContent(); - TestClosing("penumbra_angle"); - } - else if (IsElement("intensity")) { - pLight.mIntensity = ReadFloatFromTextContent(); - TestClosing("intensity"); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "light") == 0) - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a camera entry into the given light -void ColladaParser::ReadCamera( Collada::Camera& pCamera) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if (IsElement("camera")) { - SkipElement(); - } - else if (IsElement("orthographic")) { - pCamera.mOrtho = true; - } - else if (IsElement("xfov") || IsElement("xmag")) { - pCamera.mHorFov = ReadFloatFromTextContent(); - TestClosing((pCamera.mOrtho ? "xmag" : "xfov")); - } - else if (IsElement("yfov") || IsElement("ymag")) { - pCamera.mVerFov = ReadFloatFromTextContent(); - TestClosing((pCamera.mOrtho ? "ymag" : "yfov")); - } - else if (IsElement("aspect_ratio")) { - pCamera.mAspect = ReadFloatFromTextContent(); - TestClosing("aspect_ratio"); - } - else if (IsElement("znear")) { - pCamera.mZNear = ReadFloatFromTextContent(); - TestClosing("znear"); - } - else if (IsElement("zfar")) { - pCamera.mZFar = ReadFloatFromTextContent(); - TestClosing("zfar"); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "camera") == 0) - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the effect library -void ColladaParser::ReadEffectLibrary() -{ - if (mReader->isEmptyElement()) { - return; - } - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "effect")) - { - // read ID. Do I have to repeat my ranting about "optional" attributes? - // Alex: .... no, not necessary. Please shut up and leave more space for - // me to complain about the fucking Collada spec with its fucking - // 'optional' attributes ... - int attrID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( attrID); - - // create an entry and store it in the library under its ID - mEffectLibrary[id] = Effect(); - // read on from there - ReadEffect( mEffectLibrary[id]); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "library_effects") != 0) - ThrowException( "Expected end of \"library_effects\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an effect entry into the given effect -void ColladaParser::ReadEffect( Collada::Effect& pEffect) -{ - // for the moment we don't support any other type of effect. - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "profile_COMMON")) - ReadEffectProfileCommon( pEffect); - else - SkipElement(); - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "effect") != 0) - ThrowException( "Expected end of \"effect\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an COMMON effect profile -void ColladaParser::ReadEffectProfileCommon( Collada::Effect& pEffect) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "newparam")) { - // save ID - int attrSID = GetAttribute( "sid"); - std::string sid = mReader->getAttributeValue( attrSID); - pEffect.mParams[sid] = EffectParam(); - ReadEffectParam( pEffect.mParams[sid]); - } - else if ( IsElement( "technique") || IsElement( "extra")) - { - // just syntactic sugar - } - - /* Shading modes */ - else if ( IsElement( "phong")) - pEffect.mShadeType = Shade_Phong; - else if ( IsElement( "constant")) - pEffect.mShadeType = Shade_Constant; - else if ( IsElement( "lambert")) - pEffect.mShadeType = Shade_Lambert; - else if ( IsElement( "blinn")) - pEffect.mShadeType = Shade_Blinn; - - /* Color + texture properties */ - else if ( IsElement( "emission")) - ReadEffectColor( pEffect.mEmissive, pEffect.mTexEmissive); - else if ( IsElement( "ambient")) - ReadEffectColor( pEffect.mAmbient, pEffect.mTexAmbient); - else if ( IsElement( "diffuse")) - ReadEffectColor( pEffect.mDiffuse, pEffect.mTexDiffuse); - else if ( IsElement( "specular")) - ReadEffectColor( pEffect.mSpecular, pEffect.mTexSpecular); - else if ( IsElement( "reflective")) { - ReadEffectColor( pEffect.mReflective, pEffect.mTexReflective); - } - else if ( IsElement( "transparent")) { - ReadEffectColor( pEffect.mTransparent,pEffect.mTexTransparent); - } - else if ( IsElement( "shininess")) - ReadEffectFloat( pEffect.mShininess); - else if ( IsElement( "reflectivity")) - ReadEffectFloat( pEffect.mReflectivity); - - /* Single scalar properties */ - else if ( IsElement( "transparency")) - ReadEffectFloat( pEffect.mTransparency); - else if ( IsElement( "index_of_refraction")) - ReadEffectFloat( pEffect.mRefractIndex); - - // GOOGLEEARTH/OKINO extensions - // ------------------------------------------------------- - else if ( IsElement( "double_sided")) - pEffect.mDoubleSided = ReadBoolFromTextContent(); - - // FCOLLADA extensions - // ------------------------------------------------------- - else if ( IsElement( "bump")) { - aiColor4D dummy; - ReadEffectColor( dummy,pEffect.mTexBump); - } - - // MAX3D extensions - // ------------------------------------------------------- - else if ( IsElement( "wireframe")) { - pEffect.mWireframe = ReadBoolFromTextContent(); - TestClosing( "wireframe"); - } - else if ( IsElement( "faceted")) { - pEffect.mFaceted = ReadBoolFromTextContent(); - TestClosing( "faceted"); - } - else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "profile_COMMON") == 0) - { - break; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Read texture wrapping + UV transform settings from a profile==Maya chunk -void ColladaParser::ReadSamplerProperties( Sampler& out ) -{ - if (mReader->isEmptyElement()) { - return; - } - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - - // MAYA extensions - // ------------------------------------------------------- - if ( IsElement( "wrapU")) { - out.mWrapU = ReadBoolFromTextContent(); - TestClosing( "wrapU"); - } - else if ( IsElement( "wrapV")) { - out.mWrapU = ReadBoolFromTextContent(); - TestClosing( "wrapV"); - } - else if ( IsElement( "mirrorU")) { - out.mMirrorU = ReadBoolFromTextContent(); - TestClosing( "mirrorU"); - } - else if ( IsElement( "mirrorV")) { - out.mMirrorU = ReadBoolFromTextContent(); - TestClosing( "mirrorV"); - } - else if ( IsElement( "repeatU")) { - out.mTransform.mScaling.x = ReadFloatFromTextContent(); - TestClosing( "repeatU"); - } - else if ( IsElement( "repeatV")) { - out.mTransform.mScaling.y = ReadFloatFromTextContent(); - TestClosing( "repeatV"); - } - else if ( IsElement( "offsetU")) { - out.mTransform.mTranslation.x = ReadFloatFromTextContent(); - TestClosing( "offsetU"); - } - else if ( IsElement( "offsetV")) { - out.mTransform.mTranslation.x = ReadFloatFromTextContent(); - TestClosing( "offsetV"); - } - else if ( IsElement( "rotateUV")) { - out.mTransform.mRotation = ReadFloatFromTextContent(); - TestClosing( "rotateUV"); - } - else if ( IsElement( "blend_mode")) { - - const char* sz = GetTextContent(); - // http://www.feelingsoftware.com/content/view/55/72/lang,en/ - // NONE, OVER, IN, OUT, ADD, SUBTRACT, MULTIPLY, DIFFERENCE, LIGHTEN, DARKEN, SATURATE, DESATURATE and ILLUMINATE - if (0 == ASSIMP_strincmp(sz,"ADD",3)) - out.mOp = aiTextureOp_Add; - - else if (0 == ASSIMP_strincmp(sz,"SUBTRACT",8)) - out.mOp = aiTextureOp_Subtract; - - else if (0 == ASSIMP_strincmp(sz,"MULTIPLY",8)) - out.mOp = aiTextureOp_Multiply; - - else { - DefaultLogger::get()->warn("Collada: Unsupported MAYA texture blend mode"); - } - TestClosing( "blend_mode"); - } - // OKINO extensions - // ------------------------------------------------------- - else if ( IsElement( "weighting")) { - out.mWeighting = ReadFloatFromTextContent(); - TestClosing( "weighting"); - } - else if ( IsElement( "mix_with_previous_layer")) { - out.mMixWithPrevious = ReadFloatFromTextContent(); - TestClosing( "mix_with_previous_layer"); - } - // MAX3D extensions - // ------------------------------------------------------- - else if ( IsElement( "amount")) { - out.mWeighting = ReadFloatFromTextContent(); - TestClosing( "amount"); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "technique") == 0) - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an effect entry containing a color or a texture defining that color -void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler) -{ - if (mReader->isEmptyElement()) - return; - - // Save current element name - const std::string curElem = mReader->getNodeName(); - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "color")) - { - // text content contains 4 floats - const char* content = GetTextContent(); - - content = fast_atof_move( content, (float&)pColor.r); - SkipSpacesAndLineEnd( &content); - - content = fast_atof_move( content, (float&)pColor.g); - SkipSpacesAndLineEnd( &content); - - content = fast_atof_move( content, (float&)pColor.b); - SkipSpacesAndLineEnd( &content); - - content = fast_atof_move( content, (float&)pColor.a); - SkipSpacesAndLineEnd( &content); - TestClosing( "color"); - } - else if ( IsElement( "texture")) - { - // get name of source textur/sampler - int attrTex = GetAttribute( "texture"); - pSampler.mName = mReader->getAttributeValue( attrTex); - - // get name of UV source channel - attrTex = GetAttribute( "texcoord"); - pSampler.mUVChannel = mReader->getAttributeValue( attrTex); - //SkipElement(); - } - else if ( IsElement( "technique")) - { - const int _profile = GetAttribute( "profile"); - const char* profile = mReader->getAttributeValue( _profile ); - - // Some extensions are quite useful ... ReadSamplerProperties processes - // several extensions in MAYA, OKINO and MAX3D profiles. - if (!::strcmp(profile,"MAYA") || !::strcmp(profile,"MAX3D") || !::strcmp(profile,"OKINO")) - { - // get more information on this sampler - ReadSamplerProperties(pSampler); - } - else SkipElement(); - } - else if ( !IsElement( "extra")) - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){ - if (mReader->getNodeName() == curElem) - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an effect entry containing a float -void ColladaParser::ReadEffectFloat( float& pFloat) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT){ - if ( IsElement( "float")) - { - // text content contains a single floats - const char* content = GetTextContent(); - content = fast_atof_move( content, pFloat); - SkipSpacesAndLineEnd( &content); - - TestClosing( "float"); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){ - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads an effect parameter specification of any kind -void ColladaParser::ReadEffectParam( Collada::EffectParam& pParam) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "surface")) - { - // image ID given inside <init_from> tags - TestOpening( "init_from"); - const char* content = GetTextContent(); - pParam.mType = Param_Surface; - pParam.mReference = content; - TestClosing( "init_from"); - - // don't care for remaining stuff - SkipElement( "surface"); - } - else if ( IsElement( "sampler2D")) - { - // surface ID is given inside <source> tags - TestOpening( "source"); - const char* content = GetTextContent(); - pParam.mType = Param_Sampler; - pParam.mReference = content; - TestClosing( "source"); - - // don't care for remaining stuff - SkipElement( "sampler2D"); - } else - { - // ignore unknown element - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the geometry library contents -void ColladaParser::ReadGeometryLibrary() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "geometry")) - { - // read ID. Another entry which is "optional" by design but obligatory in reality - int indexID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( indexID); - - // TODO: (thom) support SIDs - // ai_assert( TestAttribute( "sid") == -1); - - // create a mesh and store it in the library under its ID - Mesh* mesh = new Mesh; - mMeshLibrary[id] = mesh; - - // read on from there - ReadGeometry( mesh); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "library_geometries") != 0) - ThrowException( "Expected end of \"library_geometries\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a geometry from the geometry library. -void ColladaParser::ReadGeometry( Collada::Mesh* pMesh) -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "mesh")) - { - // read on from there - ReadMesh( pMesh); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "geometry") != 0) - ThrowException( "Expected end of \"geometry\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a mesh from the geometry library -void ColladaParser::ReadMesh( Mesh* pMesh) -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "source")) - { - // we have professionals dealing with this - ReadSource(); - } - else if ( IsElement( "vertices")) - { - // read per-vertex mesh data - ReadVertexData( pMesh); - } - else if ( IsElement( "triangles") || IsElement( "lines") || IsElement( "linestrips") - || IsElement( "polygons") || IsElement( "polylist") || IsElement( "trifans") || IsElement( "tristrips")) - { - // read per-index mesh data and faces setup - ReadIndexData( pMesh); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "technique_common") == 0) - { - // end of another meaningless element - read over it - } - else if ( strcmp( mReader->getNodeName(), "mesh") == 0) - { - // end of <mesh> element - we're done here - break; - } else - { - // everything else should be punished - ThrowException( "Expected end of \"mesh\" element."); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a source element -void ColladaParser::ReadSource() -{ - int indexID = GetAttribute( "id"); - std::string sourceID = mReader->getAttributeValue( indexID); - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "float_array") || IsElement( "IDREF_array") || IsElement( "Name_array")) - { - ReadDataArray(); - } - else if ( IsElement( "technique_common")) - { - // I don't fucking care for your profiles bullshit - } - else if ( IsElement( "accessor")) - { - ReadAccessor( sourceID); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "source") == 0) - { - // end of <source> - we're done - break; - } - else if ( strcmp( mReader->getNodeName(), "technique_common") == 0) - { - // end of another meaningless element - read over it - } else - { - // everything else should be punished - ThrowException( "Expected end of \"source\" element."); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a data array holding a number of floats, and stores it in the global library -void ColladaParser::ReadDataArray() -{ - std::string elmName = mReader->getNodeName(); - bool isStringArray = (elmName == "IDREF_array" || elmName == "Name_array"); - - // read attributes - int indexID = GetAttribute( "id"); - std::string id = mReader->getAttributeValue( indexID); - int indexCount = GetAttribute( "count"); - unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( indexCount); - const char* content = TestTextContent(); - if (content) { // some exporters write empty data arrays, silently skip over them - - // read values and store inside an array in the data library - mDataLibrary[id] = Data(); - Data& data = mDataLibrary[id]; - data.mIsStringArray = isStringArray; - - if ( isStringArray) - { - data.mStrings.reserve( count); - std::string s; - - for ( unsigned int a = 0; a < count; a++) - { - if ( *content == 0) - ThrowException( "Expected more values while reading IDREF_array contents."); - - s.clear(); - while ( !IsSpaceOrNewLine( *content)) - s += *content++; - data.mStrings.push_back( s); - - SkipSpacesAndLineEnd( &content); - } - } else - { - data.mValues.reserve( count); - - for ( unsigned int a = 0; a < count; a++) - { - if ( *content == 0) - ThrowException( "Expected more values while reading float_array contents."); - - float value; - // read a number - content = fast_atof_move( content, value); - data.mValues.push_back( value); - // skip whitespace after it - SkipSpacesAndLineEnd( &content); - } - } - } - - // test for closing tag - TestClosing( elmName.c_str()); -} - -// ------------------------------------------------------------------------------------------------ -// Reads an accessor and stores it in the global library -void ColladaParser::ReadAccessor( const std::string& pID) -{ - // read accessor attributes - int attrSource = GetAttribute( "source"); - const char* source = mReader->getAttributeValue( attrSource); - if ( source[0] != '#') - ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\".") % source)); - int attrCount = GetAttribute( "count"); - unsigned int count = (unsigned int) mReader->getAttributeValueAsInt( attrCount); - int attrOffset = TestAttribute( "offset"); - unsigned int offset = 0; - if ( attrOffset > -1) - offset = (unsigned int) mReader->getAttributeValueAsInt( attrOffset); - int attrStride = TestAttribute( "stride"); - unsigned int stride = 1; - if ( attrStride > -1) - stride = (unsigned int) mReader->getAttributeValueAsInt( attrStride); - - // store in the library under the given ID - mAccessorLibrary[pID] = Accessor(); - Accessor& acc = mAccessorLibrary[pID]; - acc.mCount = count; - acc.mOffset = offset; - acc.mStride = stride; - acc.mSource = source+1; // ignore the leading '#' - acc.mSize = 0; // gets incremented with every param - - // and read the components - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "param")) - { - // read data param - int attrName = TestAttribute( "name"); - std::string name; - if ( attrName > -1) - { - name = mReader->getAttributeValue( attrName); - - // analyse for common type components and store it's sub-offset in the corresponding field - - /* Cartesian coordinates */ - if ( name == "X") acc.mSubOffset[0] = acc.mParams.size(); - else if ( name == "Y") acc.mSubOffset[1] = acc.mParams.size(); - else if ( name == "Z") acc.mSubOffset[2] = acc.mParams.size(); - - /* RGBA colors */ - else if ( name == "R") acc.mSubOffset[0] = acc.mParams.size(); - else if ( name == "G") acc.mSubOffset[1] = acc.mParams.size(); - else if ( name == "B") acc.mSubOffset[2] = acc.mParams.size(); - else if ( name == "A") acc.mSubOffset[3] = acc.mParams.size(); - - /* UVWQ (STPQ) texture coordinates */ - else if ( name == "S") acc.mSubOffset[0] = acc.mParams.size(); - else if ( name == "T") acc.mSubOffset[1] = acc.mParams.size(); - else if ( name == "P") acc.mSubOffset[2] = acc.mParams.size(); - // else if ( name == "Q") acc.mSubOffset[3] = acc.mParams.size(); - /* 4D uv coordinates are not supported in Assimp */ - - /* Generic extra data, interpreted as UV data, too*/ - else if ( name == "U") acc.mSubOffset[0] = acc.mParams.size(); - else if ( name == "V") acc.mSubOffset[1] = acc.mParams.size(); - //else - // DefaultLogger::get()->warn( boost::str( boost::format( "Unknown accessor parameter \"%s\". Ignoring data channel.") % name)); - } - - // read data type - int attrType = TestAttribute( "type"); - if ( attrType > -1) - { - // for the moment we only distinguish between a 4x4 matrix and anything else. - // TODO: (thom) I don't have a spec here at work. Check if there are other multi-value types - // which should be tested for here. - std::string type = mReader->getAttributeValue( attrType); - if ( type == "float4x4") - acc.mSize += 16; - else - acc.mSize += 1; - } - - acc.mParams.push_back( name); - - // skip remaining stuff of this element, if any - SkipElement(); - } else - { - ThrowException( "Unexpected sub element in tag \"accessor\"."); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "accessor") != 0) - ThrowException( "Expected end of \"accessor\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads input declarations of per-vertex mesh data into the given mesh -void ColladaParser::ReadVertexData( Mesh* pMesh) -{ - // extract the ID of the <vertices> element. Not that we care, but to catch strange referencing schemes we should warn about - int attrID= GetAttribute( "id"); - pMesh->mVertexID = mReader->getAttributeValue( attrID); - - // a number of <input> elements - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "input")) - { - ReadInputChannel( pMesh->mPerVertexData); - } else - { - ThrowException( "Unexpected sub element in tag \"vertices\"."); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "vertices") != 0) - ThrowException( "Expected end of \"vertices\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads input declarations of per-index mesh data into the given mesh -void ColladaParser::ReadIndexData( Mesh* pMesh) -{ - std::vector<size_t> vcount; - std::vector<InputChannel> perIndexData; - - // read primitive count from the attribute - int attrCount = GetAttribute( "count"); - size_t numPrimitives = (size_t) mReader->getAttributeValueAsInt( attrCount); - - // material subgroup - int attrMaterial = TestAttribute( "material"); - SubMesh subgroup; - if ( attrMaterial > -1) - subgroup.mMaterial = mReader->getAttributeValue( attrMaterial); - subgroup.mNumFaces = numPrimitives; - pMesh->mSubMeshes.push_back( subgroup); - - // distinguish between polys and triangles - std::string elementName = mReader->getNodeName(); - PrimitiveType primType = Prim_Invalid; - if ( IsElement( "lines")) - primType = Prim_Lines; - else if ( IsElement( "linestrips")) - primType = Prim_LineStrip; - else if ( IsElement( "polygons")) - primType = Prim_Polygon; - else if ( IsElement( "polylist")) - primType = Prim_Polylist; - else if ( IsElement( "triangles")) - primType = Prim_Triangles; - else if ( IsElement( "trifans")) - primType = Prim_TriFans; - else if ( IsElement( "tristrips")) - primType = Prim_TriStrips; - - ai_assert( primType != Prim_Invalid); - - // also a number of <input> elements, but in addition a <p> primitive collection and propably index counts for all primitives - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "input")) - { - ReadInputChannel( perIndexData); - } - else if ( IsElement( "vcount")) - { - if ( !mReader->isEmptyElement()) - { - // case <polylist> - specifies the number of indices for each polygon - const char* content = GetTextContent(); - vcount.reserve( numPrimitives); - for ( unsigned int a = 0; a < numPrimitives; a++) - { - if ( *content == 0) - ThrowException( "Expected more values while reading vcount contents."); - // read a number - vcount.push_back( (size_t) strtol10( content, &content)); - // skip whitespace after it - SkipSpacesAndLineEnd( &content); - } - - TestClosing( "vcount"); - } - } - else if ( IsElement( "p")) - { - if ( !mReader->isEmptyElement()) - { - // now here the actual fun starts - these are the indices to construct the mesh data from - ReadPrimitives( pMesh, perIndexData, numPrimitives, vcount, primType); - } - } else - { - ThrowException( "Unexpected sub element in tag \"vertices\"."); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( mReader->getNodeName() != elementName) - ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % elementName)); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a single input channel element and stores it in the given array, if valid -void ColladaParser::ReadInputChannel( std::vector<InputChannel>& poChannels) -{ - InputChannel channel; - - // read semantic - int attrSemantic = GetAttribute( "semantic"); - std::string semantic = mReader->getAttributeValue( attrSemantic); - channel.mType = GetTypeForSemantic( semantic); - - // read source - int attrSource = GetAttribute( "source"); - const char* source = mReader->getAttributeValue( attrSource); - if ( source[0] != '#') - ThrowException( boost::str( boost::format( "Unknown reference format in url \"%s\".") % source)); - channel.mAccessor = source+1; // skipping the leading #, hopefully the remaining text is the accessor ID only - - // read index offset, if per-index <input> - int attrOffset = TestAttribute( "offset"); - if ( attrOffset > -1) - channel.mOffset = mReader->getAttributeValueAsInt( attrOffset); - - // read set if texture coordinates - if (channel.mType == IT_Texcoord || channel.mType == IT_Color){ - int attrSet = TestAttribute("set"); - if (attrSet > -1){ - attrSet = mReader->getAttributeValueAsInt( attrSet); - if (attrSet < 0) - ThrowException( boost::str( boost::format( "Invalid index \"%i\" for set attribute") % (attrSet))); - - channel.mIndex = attrSet; - } - } - - // store, if valid type - if ( channel.mType != IT_Invalid) - poChannels.push_back( channel); - - // skip remaining stuff of this element, if any - SkipElement(); -} - -// ------------------------------------------------------------------------------------------------ -// Reads a <p> primitive index list and assembles the mesh data into the given mesh -void ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, - size_t pNumPrimitives, const std::vector<size_t>& pVCount, PrimitiveType pPrimType) -{ - // determine number of indices coming per vertex - // find the offset index for all per-vertex channels - size_t numOffsets = 1; - size_t perVertexOffset = 0xffffffff; // invalid value - BOOST_FOREACH( const InputChannel& channel, pPerIndexChannels) - { - numOffsets = std::max( numOffsets, channel.mOffset+1); - if ( channel.mType == IT_Vertex) - perVertexOffset = channel.mOffset; - } - - // determine the expected number of indices - size_t expectedPointCount = 0; - switch( pPrimType) - { - case Prim_Polylist: - { - BOOST_FOREACH( size_t i, pVCount) - expectedPointCount += i; - break; - } - case Prim_Lines: - expectedPointCount = 2 * pNumPrimitives; - break; - case Prim_Triangles: - expectedPointCount = 3 * pNumPrimitives; - break; - default: - // other primitive types don't state the index count upfront... we need to guess - break; - } - - // and read all indices into a temporary array - std::vector<size_t> indices; - if ( expectedPointCount > 0) - indices.reserve( expectedPointCount * numOffsets); - - const char* content = GetTextContent(); - while ( *content != 0) - { - // read a value. - // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways. - int value = std::max( 0, strtol10s( content, &content)); - indices.push_back( size_t( value)); - // skip whitespace after it - SkipSpacesAndLineEnd( &content); - } - - // complain if the index count doesn't fit - if ( expectedPointCount > 0 && indices.size() != expectedPointCount * numOffsets) - ThrowException( "Expected different index count in <p> element."); - else if ( expectedPointCount == 0 && (indices.size() % numOffsets) != 0) - ThrowException( "Expected different index count in <p> element."); - - // find the data for all sources - for ( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) - { - InputChannel& input = *it; - if ( input.mResolved) - continue; - - // find accessor - input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor); - // resolve accessor's data pointer as well, if neccessary - const Accessor* acc = input.mResolved; - if ( !acc->mData) - acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); - } - // and the same for the per-index channels - for ( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) - { - InputChannel& input = *it; - if ( input.mResolved) - continue; - - // ignore vertex pointer, it doesn't refer to an accessor - if ( input.mType == IT_Vertex) - { - // warn if the vertex channel does not refer to the <vertices> element in the same mesh - if ( input.mAccessor != pMesh->mVertexID) - ThrowException( "Unsupported vertex referencing scheme. I fucking hate Collada."); - continue; - } - - // find accessor - input.mResolved = &ResolveLibraryReference( mAccessorLibrary, input.mAccessor); - // resolve accessor's data pointer as well, if neccessary - const Accessor* acc = input.mResolved; - if ( !acc->mData) - acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource); - } - - - // now assemble vertex data according to those indices - std::vector<size_t>::const_iterator idx = indices.begin(); - - // For continued primitives, the given count does not come all in one <p>, but only one primitive per <p> - size_t numPrimitives = pNumPrimitives; - if ( pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) - numPrimitives = 1; - - pMesh->mFaceSize.reserve( numPrimitives); - pMesh->mFacePosIndices.reserve( indices.size() / numOffsets); - - for ( size_t a = 0; a < numPrimitives; a++) - { - // determine number of points for this primitive - size_t numPoints = 0; - switch( pPrimType) - { - case Prim_Lines: - numPoints = 2; - break; - case Prim_Triangles: - numPoints = 3; - break; - case Prim_Polylist: - numPoints = pVCount[a]; - break; - case Prim_TriFans: - case Prim_Polygon: - numPoints = indices.size() / numOffsets; - break; - default: - // LineStrip and TriStrip not supported due to expected index unmangling - ThrowException( "Unsupported primitive type."); - break; - } - - // store the face size to later reconstruct the face from - pMesh->mFaceSize.push_back( numPoints); - - // gather that number of vertices - for ( size_t b = 0; b < numPoints; b++) - { - // read all indices for this vertex. Yes, in a hacky local array - assert( numOffsets < 20 && perVertexOffset < 20); - size_t vindex[20]; - for ( size_t offsets = 0; offsets < numOffsets; ++offsets) - vindex[offsets] = *idx++; - - // extract per-vertex channels using the global per-vertex offset - for ( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it) - ExtractDataObjectFromChannel( *it, vindex[perVertexOffset], pMesh); - // and extract per-index channels using there specified offset - for ( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it) - ExtractDataObjectFromChannel( *it, vindex[it->mOffset], pMesh); - - // store the vertex-data index for later assignment of bone vertex weights - pMesh->mFacePosIndices.push_back( vindex[perVertexOffset]); - } - } - - - // if I ever get my hands on that guy who invented this steaming pile of indirection... - TestClosing( "p"); -} - -// ------------------------------------------------------------------------------------------------ -// Extracts a single object from an input channel and stores it in the appropriate mesh data array -void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, size_t pLocalIndex, Mesh* pMesh) -{ - // ignore vertex referrer - we handle them that separate - if ( pInput.mType == IT_Vertex) - return; - - const Accessor& acc = *pInput.mResolved; - if ( pLocalIndex >= acc.mCount) - ThrowException( boost::str( boost::format( "Invalid data index (%d/%d) in primitive specification") % pLocalIndex % acc.mCount)); - - // get a pointer to the start of the data object referred to by the accessor and the local index - const float* dataObject = &(acc.mData->mValues[0]) + acc.mOffset + pLocalIndex* acc.mStride; - - // assemble according to the accessors component sub-offset list. We don't care, yet, - // what kind of object exactly we're extracting here - float obj[4]; - for ( size_t c = 0; c < 4; ++c) - obj[c] = dataObject[acc.mSubOffset[c]]; - - // now we reinterpret it according to the type we're reading here - switch( pInput.mType) - { - case IT_Position: // ignore all position streams except 0 - there can be only one position - if ( pInput.mIndex == 0) - pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2])); - else - DefaultLogger::get()->error("Collada: just one vertex position stream supported"); - break; - case IT_Normal: - // pad to current vertex count if necessary - if ( pMesh->mNormals.size() < pMesh->mPositions.size()-1) - pMesh->mNormals.insert( pMesh->mNormals.end(), pMesh->mPositions.size() - pMesh->mNormals.size() - 1, aiVector3D( 0, 1, 0)); - - // ignore all normal streams except 0 - there can be only one normal - if ( pInput.mIndex == 0) - pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2])); - else - DefaultLogger::get()->error("Collada: just one vertex normal stream supported"); - break; - case IT_Tangent: - // pad to current vertex count if necessary - if ( pMesh->mTangents.size() < pMesh->mPositions.size()-1) - pMesh->mTangents.insert( pMesh->mTangents.end(), pMesh->mPositions.size() - pMesh->mTangents.size() - 1, aiVector3D( 1, 0, 0)); - - // ignore all tangent streams except 0 - there can be only one tangent - if ( pInput.mIndex == 0) - pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2])); - else - DefaultLogger::get()->error("Collada: just one vertex tangent stream supported"); - break; - case IT_Bitangent: - // pad to current vertex count if necessary - if ( pMesh->mBitangents.size() < pMesh->mPositions.size()-1) - pMesh->mBitangents.insert( pMesh->mBitangents.end(), pMesh->mPositions.size() - pMesh->mBitangents.size() - 1, aiVector3D( 0, 0, 1)); - - // ignore all bitangent streams except 0 - there can be only one bitangent - if ( pInput.mIndex == 0) - pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2])); - else - DefaultLogger::get()->error("Collada: just one vertex bitangent stream supported"); - break; - case IT_Texcoord: - // up to 4 texture coord sets are fine, ignore the others - if ( pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) - { - // pad to current vertex count if necessary - if ( pMesh->mTexCoords[pInput.mIndex].size() < pMesh->mPositions.size()-1) - pMesh->mTexCoords[pInput.mIndex].insert( pMesh->mTexCoords[pInput.mIndex].end(), - pMesh->mPositions.size() - pMesh->mTexCoords[pInput.mIndex].size() - 1, aiVector3D( 0, 0, 0)); - - pMesh->mTexCoords[pInput.mIndex].push_back( aiVector3D( obj[0], obj[1], obj[2])); - if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) /* hack ... consider cleaner solution */ - pMesh->mNumUVComponents[pInput.mIndex]=3; - } else - { - DefaultLogger::get()->error("Collada: too many texture coordinate sets. Skipping."); - } - break; - case IT_Color: - // up to 4 color sets are fine, ignore the others - if ( pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) - { - // pad to current vertex count if necessary - if ( pMesh->mColors[pInput.mIndex].size() < pMesh->mPositions.size()-1) - pMesh->mColors[pInput.mIndex].insert( pMesh->mColors[pInput.mIndex].end(), - pMesh->mPositions.size() - pMesh->mColors[pInput.mIndex].size() - 1, aiColor4D( 0, 0, 0, 1)); - - pMesh->mColors[pInput.mIndex].push_back( aiColor4D( obj[0], obj[1], obj[2], obj[3])); - } else - { - DefaultLogger::get()->error("Collada: too many vertex color sets. Skipping."); - } - - break; - default: - // IT_Invalid and IT_Vertex - ai_assert(false && "shouldn't ever get here"); - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads the library of node hierarchies and scene parts -void ColladaParser::ReadSceneLibrary() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - // a visual scene - generate root node under its ID and let ReadNode() do the recursive work - if ( IsElement( "visual_scene")) - { - // read ID. Is optional according to the spec, but how on earth should a scene_instance refer to it then? - int indexID = GetAttribute( "id"); - const char* attrID = mReader->getAttributeValue( indexID); - - // read name if given. - int indexName = TestAttribute( "name"); - const char* attrName = "unnamed"; - if ( indexName > -1) - attrName = mReader->getAttributeValue( indexName); - - // create a node and store it in the library under its ID - Node* node = new Node; - node->mID = attrID; - node->mName = attrName; - mNodeLibrary[node->mID] = node; - - ReadSceneNode( node); - } else - { - // ignore the rest - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "library_visual_scenes") == 0) - //ThrowException( "Expected end of \"library_visual_scenes\" element."); - - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a scene node's contents including children and stores it in the given node -void ColladaParser::ReadSceneNode( Node* pNode) -{ - // quit immediately on <bla/> elements - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "node")) - { - Node* child = new Node; - int attrID = TestAttribute( "id"); - if ( attrID > -1) - child->mID = mReader->getAttributeValue( attrID); - int attrSID = TestAttribute( "sid"); - if ( attrSID > -1) - child->mSID = mReader->getAttributeValue( attrSID); - - int attrName = TestAttribute( "name"); - if ( attrName > -1) - child->mName = mReader->getAttributeValue( attrName); - - // TODO: (thom) support SIDs - // assert( TestAttribute( "sid") == -1); - - if (pNode) - { - pNode->mChildren.push_back( child); - child->mParent = pNode; - } - else - { - // no parent node given, probably called from <library_nodes> element. - // create new node in node library - mNodeLibrary[child->mID] = child; - } - - // read on recursively from there - ReadSceneNode( child); - continue; - } - // For any further stuff we need a valid node to work on - else if (!pNode) - continue; - - if ( IsElement( "lookat")) - ReadNodeTransformation( pNode, TF_LOOKAT); - else if ( IsElement( "matrix")) - ReadNodeTransformation( pNode, TF_MATRIX); - else if ( IsElement( "rotate")) - ReadNodeTransformation( pNode, TF_ROTATE); - else if ( IsElement( "scale")) - ReadNodeTransformation( pNode, TF_SCALE); - else if ( IsElement( "skew")) - ReadNodeTransformation( pNode, TF_SKEW); - else if ( IsElement( "translate")) - ReadNodeTransformation( pNode, TF_TRANSLATE); - else if ( IsElement( "render") && pNode->mParent == NULL && 0 == pNode->mPrimaryCamera.length()) - { - // ... scene evaluation or, in other words, postprocessing pipeline, - // or, again in other words, a turing-complete description how to - // render a Collada scene. The only thing that is interesting for - // us is the primary camera. - int attrId = TestAttribute("camera_node"); - if (-1 != attrId) - { - const char* s = mReader->getAttributeValue(attrId); - if (s[0] != '#') - DefaultLogger::get()->error("Collada: Unresolved reference format of camera"); - else - pNode->mPrimaryCamera = s+1; - } - } - else if ( IsElement( "instance_node")) - { - // find the node in the library - int attrID = TestAttribute( "url"); - if ( attrID != -1) - { - const char* s = mReader->getAttributeValue(attrID); - if (s[0] != '#') - DefaultLogger::get()->error("Collada: Unresolved reference format of node"); - else - { - pNode->mNodeInstances.push_back(NodeInstance()); - pNode->mNodeInstances.back().mNode = s+1; - } - } - } - else if ( IsElement( "instance_geometry") || IsElement( "instance_controller")) - { - // Reference to a mesh or controller, with possible material associations - ReadNodeGeometry( pNode); - } - else if ( IsElement( "instance_light")) - { - // Reference to a light, name given in 'url' attribute - int attrID = TestAttribute("url"); - if (-1 == attrID) - DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_light> element"); - else - { - const char* url = mReader->getAttributeValue( attrID); - if ( url[0] != '#') - ThrowException( "Unknown reference format in <instance_light> element"); - - pNode->mLights.push_back(LightInstance()); - pNode->mLights.back().mLight = url+1; - } - } - else if ( IsElement( "instance_camera")) - { - // Reference to a camera, name given in 'url' attribute - int attrID = TestAttribute("url"); - if (-1 == attrID) - DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_camera> element"); - else - { - const char* url = mReader->getAttributeValue( attrID); - if ( url[0] != '#') - ThrowException( "Unknown reference format in <instance_camera> element"); - - pNode->mCameras.push_back(CameraInstance()); - pNode->mCameras.back().mCamera = url+1; - } - } - else - { - // skip everything else for the moment - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a node transformation entry of the given type and adds it to the given node's transformation list. -void ColladaParser::ReadNodeTransformation( Node* pNode, TransformType pType) -{ - if ( mReader->isEmptyElement()) - return; - - std::string tagName = mReader->getNodeName(); - - Transform tf; - tf.mType = pType; - - // read SID - int indexSID = TestAttribute( "sid"); - if ( indexSID >= 0) - tf.mID = mReader->getAttributeValue( indexSID); - - // how many parameters to read per transformation type - static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 }; - const char* content = GetTextContent(); - - // read as many parameters and store in the transformation - for ( unsigned int a = 0; a < sNumParameters[pType]; a++) - { - // read a number - content = fast_atof_move( content, tf.f[a]); - // skip whitespace after it - SkipSpacesAndLineEnd( &content); - } - - // place the transformation at the queue of the node - pNode->mTransforms.push_back( tf); - - // and consume the closing tag - TestClosing( tagName.c_str()); -} - -// ------------------------------------------------------------------------------------------------ -// Processes bind_vertex_input and bind elements -void ColladaParser::ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl) -{ - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "bind_vertex_input")) - { - Collada::InputSemanticMapEntry vn; - - // effect semantic - int n = GetAttribute("semantic"); - std::string s = mReader->getAttributeValue(n); - - // input semantic - n = GetAttribute("input_semantic"); - vn.mType = GetTypeForSemantic( mReader->getAttributeValue(n) ); - - // index of input set - n = TestAttribute("input_set"); - if (-1 != n) - vn.mSet = mReader->getAttributeValueAsInt(n); - - tbl.mMap[s] = vn; - } - else if ( IsElement( "bind")) { - DefaultLogger::get()->warn("Collada: Found unsupported <bind> element"); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) { - if ( strcmp( mReader->getNodeName(), "instance_material") == 0) - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Reads a mesh reference in a node and adds it to the node's mesh list -void ColladaParser::ReadNodeGeometry( Node* pNode) -{ - // referred mesh is given as an attribute of the <instance_geometry> element - int attrUrl = GetAttribute( "url"); - const char* url = mReader->getAttributeValue( attrUrl); - if ( url[0] != '#') - ThrowException( "Unknown reference format"); - - Collada::MeshInstance instance; - instance.mMeshOrController = url+1; // skipping the leading # - - if ( !mReader->isEmptyElement()) - { - // read material associations. Ignore additional elements inbetween - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) - { - if ( IsElement( "instance_material")) - { - // read ID of the geometry subgroup and the target material - int attrGroup = GetAttribute( "symbol"); - std::string group = mReader->getAttributeValue( attrGroup); - int attrMaterial = GetAttribute( "target"); - const char* urlMat = mReader->getAttributeValue( attrMaterial); - Collada::SemanticMappingTable s; - if ( urlMat[0] == '#') - urlMat++; - - s.mMatName = urlMat; - - // resolve further material details + THIS UGLY AND NASTY semantic mapping stuff - if ( !mReader->isEmptyElement()) - ReadMaterialVertexInputBinding(s); - - // store the association - instance.mMaterials[group] = s; - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - { - if ( strcmp( mReader->getNodeName(), "instance_geometry") == 0 - || strcmp( mReader->getNodeName(), "instance_controller") == 0) - break; - } - } - } - - // store it - pNode->mMeshes.push_back( instance); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the collada scene -void ColladaParser::ReadScene() -{ - if ( mReader->isEmptyElement()) - return; - - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT) { - if ( IsElement( "instance_visual_scene")) - { - // should be the first and only occurence - if ( mRootNode) - ThrowException( "Invalid scene containing multiple root nodes"); - - // read the url of the scene to instance. Should be of format "#some_name" - int urlIndex = GetAttribute( "url"); - const char* url = mReader->getAttributeValue( urlIndex); - if ( url[0] != '#') - ThrowException( "Unknown reference format"); - - // find the referred scene, skip the leading # - NodeLibrary::const_iterator sit = mNodeLibrary.find( url+1); - if ( sit == mNodeLibrary.end()) - ThrowException( "Unable to resolve visual_scene reference \"" + std::string(url) + "\"."); - mRootNode = sit->second; - } else { - SkipElement(); - } - } - else if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END){ - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Aborts the file reading with an exception -void ColladaParser::ThrowException( const std::string& pError) const -{ - throw DeadlyImportError( boost::str( boost::format( "Collada: %s - %s") % mFileName % pError)); -} - -// ------------------------------------------------------------------------------------------------ -// Skips all data until the end node of the current element -void ColladaParser::SkipElement() -{ - // nothing to skip if it's an <element /> - if ( mReader->isEmptyElement()) - return; - - // reroute - SkipElement( mReader->getNodeName()); -} - -// ------------------------------------------------------------------------------------------------ -// Skips all data until the end node of the given element -void ColladaParser::SkipElement( const char* pElement) -{ - // copy the current node's name because it'a pointer to the reader's internal buffer, - // which is going to change with the upcoming parsing - std::string element = pElement; - while ( mReader->read()) - { - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) - if ( mReader->getNodeName() == element) - break; - } -} - -// ------------------------------------------------------------------------------------------------ -// Tests for an opening element of the given name, throws an exception if not found -void ColladaParser::TestOpening( const char* pName) -{ - // read element start - if ( !mReader->read()) - ThrowException( boost::str( boost::format( "Unexpected end of file while beginning of \"%s\" element.") % pName)); - // whitespace in front is ok, just read again if found - if ( mReader->getNodeType() == irr::io::EXN_TEXT) - if ( !mReader->read()) - ThrowException( boost::str( boost::format( "Unexpected end of file while reading beginning of \"%s\" element.") % pName)); - - if ( mReader->getNodeType() != irr::io::EXN_ELEMENT || strcmp( mReader->getNodeName(), pName) != 0) - ThrowException( boost::str( boost::format( "Expected start of \"%s\" element.") % pName)); -} - -// ------------------------------------------------------------------------------------------------ -// Tests for the closing tag of the given element, throws an exception if not found -void ColladaParser::TestClosing( const char* pName) -{ - // check if we're already on the closing tag and return right away - if ( mReader->getNodeType() == irr::io::EXN_ELEMENT_END && strcmp( mReader->getNodeName(), pName) == 0) - return; - - // if not, read some more - if ( !mReader->read()) - ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName)); - // whitespace in front is ok, just read again if found - if ( mReader->getNodeType() == irr::io::EXN_TEXT) - if ( !mReader->read()) - ThrowException( boost::str( boost::format( "Unexpected end of file while reading end of \"%s\" element.") % pName)); - - // but this has the be the closing tag, or we're lost - if ( mReader->getNodeType() != irr::io::EXN_ELEMENT_END || strcmp( mReader->getNodeName(), pName) != 0) - ThrowException( boost::str( boost::format( "Expected end of \"%s\" element.") % pName)); -} - -// ------------------------------------------------------------------------------------------------ -// Returns the index of the named attribute or -1 if not found. Does not throw, therefore useful for optional attributes -int ColladaParser::GetAttribute( const char* pAttr) const -{ - int index = TestAttribute( pAttr); - if ( index != -1) - return index; - - // attribute not found -> throw an exception - ThrowException( boost::str( boost::format( "Expected attribute \"%s\" at element \"%s\".") % pAttr % mReader->getNodeName())); - return -1; -} - -// ------------------------------------------------------------------------------------------------ -// Tests the present element for the presence of one attribute, returns its index or throws an exception if not found -int ColladaParser::TestAttribute( const char* pAttr) const -{ - for ( int a = 0; a < mReader->getAttributeCount(); a++) - if ( strcmp( mReader->getAttributeName( a), pAttr) == 0) - return a; - - return -1; -} - -// ------------------------------------------------------------------------------------------------ -// Reads the text contents of an element, throws an exception if not given. Skips leading whitespace. -const char* ColladaParser::GetTextContent() -{ - const char* sz = TestTextContent(); - if (!sz) { - ThrowException( "Invalid contents in element \"n\"."); - } - return sz; -} - -// ------------------------------------------------------------------------------------------------ -// Reads the text contents of an element, returns NULL if not given. Skips leading whitespace. -const char* ColladaParser::TestTextContent() -{ - // present node should be the beginning of an element - if ( mReader->getNodeType() != irr::io::EXN_ELEMENT || mReader->isEmptyElement()) - ThrowException( "Expected opening element"); - - // read contents of the element - if ( !mReader->read()) - ThrowException( "Unexpected end of file while reading n element."); - if ( mReader->getNodeType() != irr::io::EXN_TEXT) - return NULL; - - // skip leading whitespace - const char* text = mReader->getNodeData(); - SkipSpacesAndLineEnd( &text); - - return text; -} - -// ------------------------------------------------------------------------------------------------ -// Calculates the resulting transformation fromm all the given transform steps -aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform>& pTransforms) const -{ - aiMatrix4x4 res; - - for ( std::vector<Transform>::const_iterator it = pTransforms.begin(); it != pTransforms.end(); ++it) - { - const Transform& tf = *it; - switch( tf.mType) - { - case TF_LOOKAT: - { - aiVector3D pos( tf.f[0], tf.f[1], tf.f[2]); - aiVector3D dstPos( tf.f[3], tf.f[4], tf.f[5]); - aiVector3D up = aiVector3D( tf.f[6], tf.f[7], tf.f[8]).Normalize(); - aiVector3D dir = aiVector3D( dstPos - pos).Normalize(); - aiVector3D right = (dir ^ up).Normalize(); - - res *= aiMatrix4x4( - right.x, up.x, -dir.x, pos.x, - right.y, up.y, -dir.y, pos.y, - right.z, up.z, -dir.z, pos.z, - 0, 0, 0, 1); - break; - } - case TF_ROTATE: - { - aiMatrix4x4 rot; - float angle = tf.f[3] * float( AI_MATH_PI) / 180.0f; - aiVector3D axis( tf.f[0], tf.f[1], tf.f[2]); - aiMatrix4x4::Rotation( angle, axis, rot); - res *= rot; - break; - } - case TF_TRANSLATE: - { - aiMatrix4x4 trans; - aiMatrix4x4::Translation( aiVector3D( tf.f[0], tf.f[1], tf.f[2]), trans); - res *= trans; - break; - } - case TF_SCALE: - { - aiMatrix4x4 scale( tf.f[0], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[1], 0.0f, 0.0f, 0.0f, 0.0f, tf.f[2], 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); - res *= scale; - break; - } - case TF_SKEW: - // TODO: (thom) - ai_assert( false); - break; - case TF_MATRIX: - { - aiMatrix4x4 mat( tf.f[0], tf.f[1], tf.f[2], tf.f[3], tf.f[4], tf.f[5], tf.f[6], tf.f[7], - tf.f[8], tf.f[9], tf.f[10], tf.f[11], tf.f[12], tf.f[13], tf.f[14], tf.f[15]); - res *= mat; - break; - } - default: - assert( false); - break; - } - } - - return res; -} - -// ------------------------------------------------------------------------------------------------ -// Determines the input data type for the given semantic string -Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& pSemantic) -{ - if ( pSemantic == "POSITION") - return IT_Position; - else if ( pSemantic == "TEXCOORD") - return IT_Texcoord; - else if ( pSemantic == "NORMAL") - return IT_Normal; - else if ( pSemantic == "COLOR") - return IT_Color; - else if ( pSemantic == "VERTEX") - return IT_Vertex; - else if ( pSemantic == "BINORMAL" || pSemantic == "TEXBINORMAL") - return IT_Bitangent; - else if ( pSemantic == "TANGENT" || pSemantic == "TEXTANGENT") - return IT_Tangent; - - DefaultLogger::get()->warn( boost::str( boost::format( "Unknown vertex input type \"%s\". Ignoring.") % pSemantic)); - return IT_Invalid; -} - -#endif // !! ASSIMP_BUILD_NO_DAE_IMPORTER diff --git a/3rdparty/assimp/code/ColladaParser.h b/3rdparty/assimp/code/ColladaParser.h deleted file mode 100644 index cba18474..00000000 --- a/3rdparty/assimp/code/ColladaParser.h +++ /dev/null @@ -1,341 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ColladaParser.h - * @brief Defines the parser helper class for the collada loader - */ - -#ifndef AI_COLLADAPARSER_H_INC -#define AI_COLLADAPARSER_H_INC - -#include "irrXMLWrapper.h" -#include "ColladaHelper.h" - -namespace Assimp -{ - -// ------------------------------------------------------------------------------------------ -/** Parser helper class for the Collada loader. - * - * Does all the XML reading and builds internal data structures from it, - * but leaves the resolving of all the references to the loader. -*/ -class ColladaParser -{ - friend class ColladaLoader; - -protected: - /** Constructor from XML file */ - ColladaParser( IOSystem* pIOHandler, const std::string& pFile); - - /** Destructor */ - ~ColladaParser(); - - /** Reads the contents of the file */ - void ReadContents(); - - /** Reads the structure of the file */ - void ReadStructure(); - - /** Reads asset informations such as coordinate system informations and legal blah */ - void ReadAssetInfo(); - - /** Reads the animation library */ - void ReadAnimationLibrary(); - - /** Reads an animation into the given parent structure */ - void ReadAnimation( Collada::Animation* pParent); - - /** Reads an animation sampler into the given anim channel */ - void ReadAnimationSampler( Collada::AnimationChannel& pChannel); - - /** Reads the skeleton controller library */ - void ReadControllerLibrary(); - - /** Reads a controller into the given mesh structure */ - void ReadController( Collada::Controller& pController); - - /** Reads the joint definitions for the given controller */ - void ReadControllerJoints( Collada::Controller& pController); - - /** Reads the joint weights for the given controller */ - void ReadControllerWeights( Collada::Controller& pController); - - /** Reads the image library contents */ - void ReadImageLibrary(); - - /** Reads an image entry into the given image */ - void ReadImage( Collada::Image& pImage); - - /** Reads the material library */ - void ReadMaterialLibrary(); - - /** Reads a material entry into the given material */ - void ReadMaterial( Collada::Material& pMaterial); - - /** Reads the camera library */ - void ReadCameraLibrary(); - - /** Reads a camera entry into the given camera */ - void ReadCamera( Collada::Camera& pCamera); - - /** Reads the light library */ - void ReadLightLibrary(); - - /** Reads a light entry into the given light */ - void ReadLight( Collada::Light& pLight); - - /** Reads the effect library */ - void ReadEffectLibrary(); - - /** Reads an effect entry into the given effect*/ - void ReadEffect( Collada::Effect& pEffect); - - /** Reads an COMMON effect profile */ - void ReadEffectProfileCommon( Collada::Effect& pEffect); - - /** Read sampler properties */ - void ReadSamplerProperties( Collada::Sampler& pSampler); - - /** Reads an effect entry containing a color or a texture defining that color */ - void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler); - - /** Reads an effect entry containing a float */ - void ReadEffectFloat( float& pFloat); - - /** Reads an effect parameter specification of any kind */ - void ReadEffectParam( Collada::EffectParam& pParam); - - /** Reads the geometry library contents */ - void ReadGeometryLibrary(); - - /** Reads a geometry from the geometry library. */ - void ReadGeometry( Collada::Mesh* pMesh); - - /** Reads a mesh from the geometry library */ - void ReadMesh( Collada::Mesh* pMesh); - - /** Reads a source element - a combination of raw data and an accessor defining - * things that should not be redefinable. Yes, that's another rant. - */ - void ReadSource(); - - /** Reads a data array holding a number of elements, and stores it in the global library. - * Currently supported are array of floats and arrays of strings. - */ - void ReadDataArray(); - - /** Reads an accessor and stores it in the global library under the given ID - - * accessors use the ID of the parent <source> element - */ - void ReadAccessor( const std::string& pID); - - /** Reads input declarations of per-vertex mesh data into the given mesh */ - void ReadVertexData( Collada::Mesh* pMesh); - - /** Reads input declarations of per-index mesh data into the given mesh */ - void ReadIndexData( Collada::Mesh* pMesh); - - /** Reads a single input channel element and stores it in the given array, if valid */ - void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels); - - /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */ - void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, - size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType); - - /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */ - void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh); - - /** Reads the library of node hierarchies and scene parts */ - void ReadSceneLibrary(); - - /** Reads a scene node's contents including children and stores it in the given node */ - void ReadSceneNode( Collada::Node* pNode); - - /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */ - void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType); - - /** Reads a mesh reference in a node and adds it to the node's mesh list */ - void ReadNodeGeometry( Collada::Node* pNode); - - /** Reads the collada scene */ - void ReadScene(); - - // Processes bind_vertex_input and bind elements - void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl); - -protected: - /** Aborts the file reading with an exception */ - void ThrowException( const std::string& pError) const; - - /** Skips all data until the end node of the current element */ - void SkipElement(); - - /** Skips all data until the end node of the given element */ - void SkipElement( const char* pElement); - - /** Compares the current xml element name to the given string and returns true if equal */ - bool IsElement( const char* pName) const; - - /** Tests for the opening tag of the given element, throws an exception if not found */ - void TestOpening( const char* pName); - - /** Tests for the closing tag of the given element, throws an exception if not found */ - void TestClosing( const char* pName); - - /** Checks the present element for the presence of the attribute, returns its index - or throws an exception if not found */ - int GetAttribute( const char* pAttr) const; - - /** Returns the index of the named attribute or -1 if not found. Does not throw, - therefore useful for optional attributes */ - int TestAttribute( const char* pAttr) const; - - /** Reads the text contents of an element, throws an exception if not given. - Skips leading whitespace. */ - const char* GetTextContent(); - - /** Reads the text contents of an element, returns NULL if not given. - Skips leading whitespace. */ - const char* TestTextContent(); - - /** Reads a single bool from current text content */ - bool ReadBoolFromTextContent(); - - /** Reads a single float from current text content */ - float ReadFloatFromTextContent(); - - /** Calculates the resulting transformation from all the given transform steps */ - aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const; - - /** Determines the input data type for the given semantic string */ - Collada::InputType GetTypeForSemantic( const std::string& pSemantic); - - /** Finds the item in the given library by its reference, throws if not found */ - template <typename Type> const Type& ResolveLibraryReference( - const std::map<std::string, Type>& pLibrary, const std::string& pURL) const; - -protected: - /** Filename, for a verbose error message */ - std::string mFileName; - - /** XML reader, member for everyday use */ - irr::io::IrrXMLReader* mReader; - - /** All data arrays found in the file by ID. Might be referred to by actually - everyone. Collada, you are a steaming pile of indirection. */ - typedef std::map<std::string, Collada::Data> DataLibrary; - DataLibrary mDataLibrary; - - /** Same for accessors which define how the data in a data array is accessed. */ - typedef std::map<std::string, Collada::Accessor> AccessorLibrary; - AccessorLibrary mAccessorLibrary; - - /** Mesh library: mesh by ID */ - typedef std::map<std::string, Collada::Mesh*> MeshLibrary; - MeshLibrary mMeshLibrary; - - /** node library: root node of the hierarchy part by ID */ - typedef std::map<std::string, Collada::Node*> NodeLibrary; - NodeLibrary mNodeLibrary; - - /** Image library: stores texture properties by ID */ - typedef std::map<std::string, Collada::Image> ImageLibrary; - ImageLibrary mImageLibrary; - - /** Effect library: surface attributes by ID */ - typedef std::map<std::string, Collada::Effect> EffectLibrary; - EffectLibrary mEffectLibrary; - - /** Material library: surface material by ID */ - typedef std::map<std::string, Collada::Material> MaterialLibrary; - MaterialLibrary mMaterialLibrary; - - /** Light library: surface light by ID */ - typedef std::map<std::string, Collada::Light> LightLibrary; - LightLibrary mLightLibrary; - - /** Camera library: surface material by ID */ - typedef std::map<std::string, Collada::Camera> CameraLibrary; - CameraLibrary mCameraLibrary; - - /** Controller library: joint controllers by ID */ - typedef std::map<std::string, Collada::Controller> ControllerLibrary; - ControllerLibrary mControllerLibrary; - - /** Pointer to the root node. Don't delete, it just points to one of - the nodes in the node library. */ - Collada::Node* mRootNode; - - /** Root animation container */ - Collada::Animation mAnims; - - /** Size unit: how large compared to a meter */ - float mUnitSize; - - /** Which is the up vector */ - enum { UP_X, UP_Y, UP_Z } mUpDirection; - - /** Collada file format version */ - Collada::FormatVersion mFormat; -}; - -// ------------------------------------------------------------------------------------------------ -// Check for element match -inline bool ColladaParser::IsElement( const char* pName) const -{ - ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); - return ::strcmp( mReader->getNodeName(), pName) == 0; -} - -// ------------------------------------------------------------------------------------------------ -// Finds the item in the given library by its reference, throws if not found -template <typename Type> -const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const -{ - typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL); - if ( it == pLibrary.end()) - ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL)); - return it->second; -} - -} // end of namespace Assimp - -#endif // AI_COLLADAPARSER_H_INC diff --git a/3rdparty/assimp/code/ComputeUVMappingProcess.cpp b/3rdparty/assimp/code/ComputeUVMappingProcess.cpp deleted file mode 100644 index 68b75bae..00000000 --- a/3rdparty/assimp/code/ComputeUVMappingProcess.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 GenUVCoords step */ - - -#include "AssimpPCH.h" -#include "ComputeUVMappingProcess.h" -#include "ProcessHelper.h" - -using namespace Assimp; - -namespace { - - const static aiVector3D base_axis_y(0.f,1.f,0.f); - const static aiVector3D base_axis_x(1.f,0.f,0.f); - const static aiVector3D base_axis_z(0.f,0.f,1.f); - const static float angle_epsilon = 0.95f; -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -ComputeUVMappingProcess::ComputeUVMappingProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ComputeUVMappingProcess::~ComputeUVMappingProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_GenUVCoords) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Check whether a ray intersects a plane and find the intersection point -inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos, - const aiVector3D& planeNormal, aiVector3D& pos) -{ - const float b = planeNormal * (planePos - ray.pos); - float h = ray.dir * planeNormal; - if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0) - return false; - - pos = ray.pos + (ray.dir * h); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Find the first empty UV channel in a mesh -inline unsigned int FindEmptyUVChannel (aiMesh* mesh) -{ - for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m) - if (!mesh->mTextureCoords[m])return m; - - DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found"); - return 0xffffffff; -} - -// ------------------------------------------------------------------------------------------------ -// Try to remove UV seams -void RemoveUVSeams (aiMesh* mesh, aiVector3D* out) -{ - // TODO: just a very rough algorithm. I think it could be done - // much easier, but I don't know how and am currently too tired to - // to think about a better solution. - - const static float LOWER_LIMIT = 0.1f; - const static float UPPER_LIMIT = 0.9f; - - const static float LOWER_EPSILON = 10e-3f; - const static float UPPER_EPSILON = 1.f-10e-3f; - - for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx) - { - const aiFace& face = mesh->mFaces[fidx]; - if (face.mNumIndices < 3) continue; // triangles and polygons only, please - - unsigned int small = face.mNumIndices, large = small; - bool zero = false, one = false, round_to_zero = false; - - // Check whether this face lies on a UV seam. We can just guess, - // but the assumption that a face with at least one very small - // on the one side and one very large U coord on the other side - // lies on a UV seam should work for most cases. - for (unsigned int n = 0; n < face.mNumIndices;++n) - { - if (out[face.mIndices[n]].x < LOWER_LIMIT) - { - small = n; - - // If we have a U value very close to 0 we can't - // round the others to 0, too. - if (out[face.mIndices[n]].x <= LOWER_EPSILON) - zero = true; - else round_to_zero = true; - } - if (out[face.mIndices[n]].x > UPPER_LIMIT) - { - large = n; - - // If we have a U value very close to 1 we can't - // round the others to 1, too. - if (out[face.mIndices[n]].x >= UPPER_EPSILON) - one = true; - } - } - if (small != face.mNumIndices && large != face.mNumIndices) - { - for (unsigned int n = 0; n < face.mNumIndices;++n) - { - // If the u value is over the upper limit and no other u - // value of that face is 0, round it to 0 - if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero) - out[face.mIndices[n]].x = 0.f; - - // If the u value is below the lower limit and no other u - // value of that face is 1, round it to 1 - else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one) - out[face.mIndices[n]].x = 1.f; - - // The face contains both 0 and 1 as UV coords. This can occur - // for faces which have an edge that lies directly on the seam. - // Due to numerical inaccuracies one U coord becomes 0, the - // other 1. But we do still have a third UV coord to determine - // to which side we must round to. - else if (one && zero) - { - if (round_to_zero && out[face.mIndices[n]].x >= UPPER_EPSILON) - out[face.mIndices[n]].x = 0.f; - else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON) - out[face.mIndices[n]].x = 1.f; - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ - aiVector3D center, min, max; - FindMeshCenter(mesh, center, min, max); - - // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... - // currently the mapping axis will always be one of x,y,z, except if the - // PretransformVertices step is used (it transforms the meshes into worldspace, - // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { - - // For each point get a normalized projection vector in the sphere, - // get its longitude and latitude and map them to their respective - // UV axes. Problems occur around the poles ... unsolvable. - // - // The spherical coordinate system looks like this: - // x = cos(lon)*cos(lat) - // y = sin(lon)*cos(lat) - // z = sin(lat) - // - // Thus we can derive: - // lat = arcsin (z) - // lon = arctan (y/x) - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (asin (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); - } - } - else if (axis * base_axis_y >= angle_epsilon) { - // ... just the same again - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (asin (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); - } - } - else if (axis * base_axis_z >= angle_epsilon) { - // ... just the same again - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize(); - out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); - } - } - // slower code path in case the mapping axis is not one of the coordinate system axes - else { - aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - - // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize(); - out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F, - (asin (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f); - } - } - - - // Now find and remove UV seams. A seam occurs if a face has a tcoord - // close to zero on the one side, and a tcoord close to one on the - // other side. - RemoveUVSeams(mesh,out); -} - -// ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ - aiVector3D center, min, max; - - // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... - // currently the mapping axis will always be one of x,y,z, except if the - // PretransformVertices step is used (it transforms the meshes into worldspace, - // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { - FindMeshCenter(mesh, center, min, max); - const float diff = max.x - min.x; - - // If the main axis is 'z', the z coordinate of a point 'p' is mapped - // directly to the texture V axis. The other axis is derived from - // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where - // 'c' is the center point of the mesh. - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; - - uv.y = (pos.x - min.x) / diff; - uv.x = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; - } - } - else if (axis * base_axis_y >= angle_epsilon) { - FindMeshCenter(mesh, center, min, max); - const float diff = max.y - min.y; - - // just the same ... - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; - - uv.y = (pos.y - min.y) / diff; - uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; - } - } - else if (axis * base_axis_z >= angle_epsilon) { - FindMeshCenter(mesh, center, min, max); - const float diff = max.z - min.z; - - // just the same ... - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; - - uv.y = (pos.z - min.z) / diff; - uv.x = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; - } - } - // slower code path in case the mapping axis is not one of the coordinate system axes - else { - aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - FindMeshCenterTransformed(mesh, center, min, max,mTrafo); - const float diff = max.y - min.y; - - // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){ - const aiVector3D pos = mTrafo* mesh->mVertices[pnt]; - aiVector3D& uv = out[pnt]; - - uv.y = (pos.y - min.y) / diff; - uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI; - } - } - - // Now find and remove UV seams. A seam occurs if a face has a tcoord - // close to zero on the one side, and a tcoord close to one on the - // other side. - RemoveUVSeams(mesh,out); -} - -// ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out) -{ - float diffu,diffv; - aiVector3D center, min, max; - - // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ... - // currently the mapping axis will always be one of x,y,z, except if the - // PretransformVertices step is used (it transforms the meshes into worldspace, - // thus changing the mapping axis) - if (axis * base_axis_x >= angle_epsilon) { - FindMeshCenter(mesh, center, min, max); - diffu = max.z - min.z; - diffv = max.y - min.y; - - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv); - } - } - else if (axis * base_axis_y >= angle_epsilon) { - FindMeshCenter(mesh, center, min, max); - diffu = max.x - min.x; - diffv = max.z - min.z; - - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv); - } - } - else if (axis * base_axis_z >= angle_epsilon) { - FindMeshCenter(mesh, center, min, max); - diffu = max.y - min.y; - diffv = max.z - min.z; - - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D& pos = mesh->mVertices[pnt]; - out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv); - } - } - // slower code path in case the mapping axis is not one of the coordinate system axes - else - { - aiMatrix4x4 mTrafo; - aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo); - FindMeshCenterTransformed(mesh, center, min, max,mTrafo); - diffu = max.x - min.x; - diffv = max.z - min.z; - - // again the same, except we're applying a transformation now - for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt) { - const aiVector3D pos = mTrafo * mesh->mVertices[pnt]; - out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv); - } - } - - // shouldn't be necessary to remove UV seams ... -} - -// ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::ComputeBoxMapping(aiMesh* mesh, aiVector3D* out) -{ - DefaultLogger::get()->error("Mapping type currently not implemented"); -} - -// ------------------------------------------------------------------------------------------------ -void ComputeUVMappingProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("GenUVCoordsProcess begin"); - char buffer[1024]; - - if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) - throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); - - std::list<MappingInfo> mappingStack; - - /* Iterate through all materials and search for non-UV mapped textures - */ - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { - mappingStack.clear(); - aiMaterial* mat = pScene->mMaterials[i]; - for (unsigned int a = 0; a < mat->mNumProperties;++a) - { - aiMaterialProperty* prop = mat->mProperties[a]; - if (!::strcmp( prop->mKey.data, "$tex.mapping")) - { - aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData); - if (aiTextureMapping_UV != mapping) - { - if (!DefaultLogger::isNullLogger()) - { - sprintf(buffer, "Found non-UV mapped texture (%s,%i). Mapping type: %s", - TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex, - MappingTypeToString(mapping)); - - DefaultLogger::get()->info(buffer); - } - - if (aiTextureMapping_OTHER == mapping) - continue; - - MappingInfo info (mapping); - - // Get further properties - currently only the major axis - for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2) - { - aiMaterialProperty* prop2 = mat->mProperties[a2]; - if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex) - continue; - - if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis")) { - info.axis = *((aiVector3D*)prop2->mData); - break; - } - } - - unsigned int idx; - - // Check whether we have this mapping mode already - std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info); - if (mappingStack.end() != it) - { - idx = (*it).uv; - } - else - { - /* We have found a non-UV mapped texture. Now - * we need to find all meshes using this material - * that we can compute UV channels for them. - */ - for (unsigned int m = 0; m < pScene->mNumMeshes;++m) - { - aiMesh* mesh = pScene->mMeshes[m]; - unsigned int outIdx; - if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == 0xffffffff || - !mesh->mNumVertices) - { - continue; - } - - // Allocate output storage - aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices]; - - switch (mapping) - { - case aiTextureMapping_SPHERE: - ComputeSphereMapping(mesh,info.axis,p); - break; - case aiTextureMapping_CYLINDER: - ComputeCylinderMapping(mesh,info.axis,p); - break; - case aiTextureMapping_PLANE: - ComputePlaneMapping(mesh,info.axis,p); - break; - case aiTextureMapping_BOX: - ComputeBoxMapping(mesh,p); - break; - default: - ai_assert(false); - } - if (m && idx != outIdx) - { - DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to " - "this material have equal numbers of UV channels. The UV index stored in " - "the material structure does therefore not apply for all meshes. "); - } - idx = outIdx; - } - info.uv = idx; - mappingStack.push_back(info); - } - - // Update the material property list - mapping = aiTextureMapping_UV; - ((MaterialHelper*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex)); - } - } - } - } - DefaultLogger::get()->debug("GenUVCoordsProcess finished"); -} diff --git a/3rdparty/assimp/code/ComputeUVMappingProcess.h b/3rdparty/assimp/code/ComputeUVMappingProcess.h deleted file mode 100644 index 412c641a..00000000 --- a/3rdparty/assimp/code/ComputeUVMappingProcess.h +++ /dev/null @@ -1,149 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to compute UV coordinates - from abstract mappings, such as box or spherical*/ -#ifndef AI_COMPUTEUVMAPPING_H_INC -#define AI_COMPUTEUVMAPPING_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class ComputeUVMappingTest; -namespace Assimp - { - -// --------------------------------------------------------------------------- -/** ComputeUVMappingProcess - converts special mappings, such as spherical, - * cylindrical or boxed to proper UV coordinates for rendering. -*/ -class ASSIMP_API ComputeUVMappingProcess : public BaseProcess -{ - friend class Importer; - friend class ::ComputeUVMappingTest; // grant the unit test full access to us - -protected: - /** Constructor to be privately used by Importer */ - ComputeUVMappingProcess(); - - /** Destructor, private as well */ - ~ComputeUVMappingProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - -protected: - - // ------------------------------------------------------------------- - /** Computes spherical UV coordinates for a mesh - * - * @param mesh Mesh to be processed - * @param axis Main axis - * @param out Receives output UV coordinates - */ - void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, - aiVector3D* out); - - // ------------------------------------------------------------------- - /** Computes cylindrical UV coordinates for a mesh - * - * @param mesh Mesh to be processed - * @param axis Main axis - * @param out Receives output UV coordinates - */ - void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, - aiVector3D* out); - - // ------------------------------------------------------------------- - /** Computes planar UV coordinates for a mesh - * - * @param mesh Mesh to be processed - * @param axis Main axis - * @param out Receives output UV coordinates - */ - void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, - aiVector3D* out); - - // ------------------------------------------------------------------- - /** Computes cubic UV coordinates for a mesh - * - * @param mesh Mesh to be processed - * @param out Receives output UV coordinates - */ - void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out); - -private: - - // temporary structure to describe a mapping - struct MappingInfo - { - MappingInfo(aiTextureMapping _type) - : type (_type) - , axis (0.f,1.f,0.f) - , uv (0u) - {} - - aiTextureMapping type; - aiVector3D axis; - unsigned int uv; - - bool operator== (const MappingInfo& other) - { - return type == other.type && axis == other.axis; - } - }; -}; - -} // end of namespace Assimp - -#endif // AI_COMPUTEUVMAPPING_H_INC diff --git a/3rdparty/assimp/code/ConvertToLHProcess.cpp b/3rdparty/assimp/code/ConvertToLHProcess.cpp deleted file mode 100644 index f4c72245..00000000 --- a/3rdparty/assimp/code/ConvertToLHProcess.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MakeLeftHandedProcess.cpp - * @brief Implementation of the post processing step to convert all - * imported data to a left-handed coordinate system. - * - * Face order & UV flip are also implemented here, for the sake of a - * better location. - */ - -#include "AssimpPCH.h" -#include "ConvertToLHProcess.h" - -using namespace Assimp; - -#ifndef ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MakeLeftHandedProcess::MakeLeftHandedProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MakeLeftHandedProcess::~MakeLeftHandedProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const -{ - return 0 != (pFlags & aiProcess_MakeLeftHanded); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void MakeLeftHandedProcess::Execute( aiScene* pScene) -{ - // Check for an existent root node to proceed - ai_assert(pScene->mRootNode != NULL); - DefaultLogger::get()->debug("MakeLeftHandedProcess begin"); - - // recursively convert all the nodes - ProcessNode( pScene->mRootNode, aiMatrix4x4()); - - // process the meshes accordingly - for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a) - ProcessMesh( pScene->mMeshes[a]); - - // process the materials accordingly - for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a) - ProcessMaterial( pScene->mMaterials[a]); - - // transform all animation channels as well - for ( unsigned int a = 0; a < pScene->mNumAnimations; a++) - { - aiAnimation* anim = pScene->mAnimations[a]; - for ( unsigned int b = 0; b < anim->mNumChannels; b++) - { - aiNodeAnim* nodeAnim = anim->mChannels[b]; - ProcessAnimation( nodeAnim); - } - } - DefaultLogger::get()->debug("MakeLeftHandedProcess finished"); -} - -// ------------------------------------------------------------------------------------------------ -// Recursively converts a node, all of its children and all of its meshes -void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation) -{ - // mirror all base vectors at the local Z axis - pNode->mTransformation.c1 = -pNode->mTransformation.c1; - pNode->mTransformation.c2 = -pNode->mTransformation.c2; - pNode->mTransformation.c3 = -pNode->mTransformation.c3; - pNode->mTransformation.c4 = -pNode->mTransformation.c4; - - // now invert the Z axis again to keep the matrix determinant positive. - // The local meshes will be inverted accordingly so that the result should look just fine again. - pNode->mTransformation.a3 = -pNode->mTransformation.a3; - pNode->mTransformation.b3 = -pNode->mTransformation.b3; - pNode->mTransformation.c3 = -pNode->mTransformation.c3; - pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways... - - // continue for all children - for ( size_t a = 0; a < pNode->mNumChildren; ++a) - ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation); -} - -// ------------------------------------------------------------------------------------------------ -// Converts a single mesh to left handed coordinates. -void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) -{ - // mirror positions, normals and stuff along the Z axis - for ( size_t a = 0; a < pMesh->mNumVertices; ++a) - { - pMesh->mVertices[a].z *= -1.0f; - if ( pMesh->HasNormals()) - pMesh->mNormals[a].z *= -1.0f; - if ( pMesh->HasTangentsAndBitangents()) - { - pMesh->mTangents[a].z *= -1.0f; - pMesh->mBitangents[a].z *= -1.0f; - } - } - - // mirror offset matrices of all bones - for ( size_t a = 0; a < pMesh->mNumBones; ++a) - { - aiBone* bone = pMesh->mBones[a]; - bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3; - bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3; - bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3; - bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1; - bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2; - bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4; - } - - // mirror bitangents as well as they're derived from the texture coords - if ( pMesh->HasTangentsAndBitangents()) - { - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) - pMesh->mBitangents[a] *= -1.0f; - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts a single material to left handed coordinates. -void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) -{ - MaterialHelper* mat = (MaterialHelper*)_mat; - for (unsigned int a = 0; a < mat->mNumProperties;++a) { - aiMaterialProperty* prop = mat->mProperties[a]; - - // Mapping axis for UV mappings? - if (!::strcmp( prop->mKey.data, "$tex.mapaxis")) { - ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */ - aiVector3D* pff = (aiVector3D*)prop->mData; - - pff->z *= -1.f; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts the given animation to LH coordinates. -void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim) -{ - // position keys - for ( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++) - pAnim->mPositionKeys[a].mValue.z *= -1.0f; - - // rotation keys - for ( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) - { - /* That's the safe version, but the float errors add up. So we try the short version instead - aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix(); - rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3; - rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2; - aiQuaternion rotquat( rotmat); - pAnim->mRotationKeys[a].mValue = rotquat; - */ - pAnim->mRotationKeys[a].mValue.x *= -1.0f; - pAnim->mRotationKeys[a].mValue.y *= -1.0f; - } -} - -#endif // !! ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS -#ifndef ASSIMP_BUILD_NO_FLIPUVS_PROCESS -// # FlipUVsProcess - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -FlipUVsProcess::FlipUVsProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FlipUVsProcess::~FlipUVsProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool FlipUVsProcess::IsActive( unsigned int pFlags) const -{ - return 0 != (pFlags & aiProcess_FlipUVs); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void FlipUVsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("FlipUVsProcess begin"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - ProcessMesh(pScene->mMeshes[i]); - - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - ProcessMaterial(pScene->mMaterials[i]); - DefaultLogger::get()->debug("FlipUVsProcess finished"); -} - -// ------------------------------------------------------------------------------------------------ -// Converts a single material -void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat) -{ - MaterialHelper* mat = (MaterialHelper*)_mat; - for (unsigned int a = 0; a < mat->mNumProperties;++a) { - aiMaterialProperty* prop = mat->mProperties[a]; - - // UV transformation key? - if (!::strcmp( prop->mKey.data, "$tex.uvtrafo")) { - ai_assert( prop->mDataLength >= sizeof(aiUVTransform)); /* something is wrong with the validation if we end up here */ - aiUVTransform* uv = (aiUVTransform*)prop->mData; - - // just flip it, that's everything - uv->mTranslation.y *= -1.f; - uv->mRotation *= -1.f; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts a single mesh -void FlipUVsProcess::ProcessMesh( aiMesh* pMesh) -{ - // mirror texture y coordinate - for ( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++) { - if ( !pMesh->HasTextureCoords( a)) - break; - - for ( unsigned int b = 0; b < pMesh->mNumVertices; b++) - pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y; - } -} - -#endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS -#ifndef ASSIMP_BUILD_NO_FLIPWINDING_PROCESS -// # FlipWindingOrderProcess - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -FlipWindingOrderProcess::FlipWindingOrderProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FlipWindingOrderProcess::~FlipWindingOrderProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const -{ - return 0 != (pFlags & aiProcess_FlipWindingOrder); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void FlipWindingOrderProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("FlipWindingOrderProcess begin"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - ProcessMesh(pScene->mMeshes[i]); - DefaultLogger::get()->debug("FlipWindingOrderProcess finished"); -} - -// ------------------------------------------------------------------------------------------------ -// Converts a single mesh -void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh) -{ - // invert the order of all faces in this mesh - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - aiFace& face = pMesh->mFaces[a]; - for ( unsigned int b = 0; b < face.mNumIndices / 2; b++) - std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]); - } -} - -#endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS diff --git a/3rdparty/assimp/code/ConvertToLHProcess.h b/3rdparty/assimp/code/ConvertToLHProcess.h deleted file mode 100644 index 25bf178b..00000000 --- a/3rdparty/assimp/code/ConvertToLHProcess.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MakeLeftHandedProcess.h - * @brief Defines a bunch of post-processing steps to handle - * coordinate system conversions. - * - * - LH to RH - * - UV origin upper-left to lower-left - * - face order cw to ccw - */ -#ifndef AI_CONVERTTOLHPROCESS_H_INC -#define AI_CONVERTTOLHPROCESS_H_INC - -#include "../include/aiTypes.h" -#include "BaseProcess.h" - -struct aiMesh; -struct aiNodeAnim; - -namespace Assimp { - -// ----------------------------------------------------------------------------------- -/** @brief The MakeLeftHandedProcess converts all imported data to a left-handed - * coordinate system. - * - * This implies a mirroring of the Z axis of the coordinate system. But to keep - * transformation matrices free from reflections we shift the reflection to other - * places. We mirror the meshes and adapt the rotations. - * - * @note RH-LH and LH-RH is the same, so this class can be used for both - */ -class ASSIMP_API MakeLeftHandedProcess : public BaseProcess -{ - friend class Importer; - -public: - /** Constructor to be privately used by Importer */ - MakeLeftHandedProcess(); - - /** Destructor, private as well */ - ~MakeLeftHandedProcess(); - - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - -protected: - - // ------------------------------------------------------------------- - /** Recursively converts a node and all of its children - */ - void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation); - - // ------------------------------------------------------------------- - /** Converts a single mesh to left handed coordinates. - * This means that positions, normals and tangents are mirrored at - * the local Z axis and the order of all faces are inverted. - * @param pMesh The mesh to convert. - */ - void ProcessMesh( aiMesh* pMesh); - - // ------------------------------------------------------------------- - /** Converts a single material to left-handed coordinates - * @param pMat Material to convert - */ - void ProcessMaterial( aiMaterial* pMat); - - // ------------------------------------------------------------------- - /** Converts the given animation to LH coordinates. - * The rotation and translation keys are transformed, the scale keys - * work in local space and can therefore be left untouched. - * @param pAnim The bone animation to transform - */ - void ProcessAnimation( aiNodeAnim* pAnim); -}; - - -// --------------------------------------------------------------------------- -/** Postprocessing step to flip the face order of the imported data - */ -class ASSIMP_API FlipWindingOrderProcess : public BaseProcess -{ - friend class Importer; - -public: - /** Constructor to be privately used by Importer */ - FlipWindingOrderProcess(); - - /** Destructor, private as well */ - ~FlipWindingOrderProcess(); - - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - -protected: - void ProcessMesh( aiMesh* pMesh); -}; - -// --------------------------------------------------------------------------- -/** Postprocessing step to flip the UV coordinate system of the import data - */ -class ASSIMP_API FlipUVsProcess : public BaseProcess -{ - friend class Importer; - -public: - /** Constructor to be privately used by Importer */ - FlipUVsProcess(); - - /** Destructor, private as well */ - ~FlipUVsProcess(); - - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - -protected: - void ProcessMesh( aiMesh* pMesh); - void ProcessMaterial( aiMaterial* mat); -}; - -} // end of namespace Assimp - -#endif // AI_CONVERTTOLHPROCESS_H_INC diff --git a/3rdparty/assimp/code/DXFLoader.cpp b/3rdparty/assimp/code/DXFLoader.cpp deleted file mode 100644 index fc68ee88..00000000 --- a/3rdparty/assimp/code/DXFLoader.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 DXFLoader.cpp - * @brief Implementation of the DXF importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER - -#include "DXFLoader.h" -#include "ParsingUtils.h" -#include "ConvertToLHProcess.h" -#include "fast_atof.h" - -using namespace Assimp; - -// AutoCAD Binary DXF<CR><LF><SUB><NULL> -#define AI_DXF_BINARY_IDENT ("AutoCAD Binary DXF\r\n\x1a\0") -#define AI_DXF_BINARY_IDENT_LEN (24) - -// color indices for DXF - 16 are supported -static aiColor4D g_aclrDxfIndexColors[] = -{ - aiColor4D (0.6f, 0.6f, 0.6f, 1.0f), - aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red - aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green - aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue - aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green - aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue - aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red - aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink - aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange - aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange - aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow - aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray - aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray - aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black - aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white - aiColor4D (0.6f, 0.0f, 1.0f, 1.0f) // violet -}; -#define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0])) - -// invalid/unassigned color value -aiColor4D g_clrInvalid = aiColor4D(get_qnan(),0.f,0.f,1.f); - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -DXFImporter::DXFImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -DXFImporter::~DXFImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - return SimpleExtensionCheck(pFile,"dxf"); -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all supported file extensions -void DXFImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("dxf"); -} - -// ------------------------------------------------------------------------------------------------ -// Get a copy of the next data line, skip strange data -bool DXFImporter::GetNextLine() -{ - if (!SkipLine(&buffer)) - return false; - if (!SkipSpaces(&buffer)) - return GetNextLine(); - else if (*buffer == '{') { - // some strange meta data ... - while (true) - { - if (!SkipLine(&buffer)) - return false; - - if (SkipSpaces(&buffer) && *buffer == '}') - break; - } - return GetNextLine(); - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Get the next token in the file -bool DXFImporter::GetNextToken() -{ - if (bRepeat) { - bRepeat = false; - return true; - } - - SkipSpaces(&buffer); - groupCode = strtol10s(buffer,&buffer); - if (!GetNextLine()) - return false; - - // copy the data line to a separate buffer - char* m = cursor, *end = &cursor[4096]; - while (!IsSpaceOrNewLine( *buffer ) && m < end) - *m++ = *buffer++; - - *m = '\0'; - GetNextLine(); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void DXFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open DXF file " + pFile + ""); - } - - // read the contents of the file in a buffer - std::vector<char> buffer2; - TextFileToBuffer(file.get(),buffer2); - buffer = &buffer2[0]; - - bRepeat = false; - mDefaultLayer = NULL; - - // check whether this is a binaray DXF file - we can't read binary DXF files :-( - if (!strncmp(AI_DXF_BINARY_IDENT,buffer,AI_DXF_BINARY_IDENT_LEN)) - throw DeadlyImportError("DXF: Binary files are not supported at the moment"); - - // now get all lines of the file - while (GetNextToken()) { - - if (2 == groupCode) { - - // ENTITIES and BLOCKS sections - skip the whole rest, no need to waste our time with them - if (!::strcmp(cursor,"ENTITIES") || !::strcmp(cursor,"BLOCKS")) { - if (!ParseEntities()) - break; - else bRepeat = true; - } - - // other sections - skip them to make sure there will be no name conflicts - else { - while ( GetNextToken()) { - if (!::strcmp(cursor,"ENDSEC")) - break; - } - } - } - // print comment strings - else if (999 == groupCode) { - DefaultLogger::get()->info(std::string( cursor )); - } - else if (!groupCode && !::strcmp(cursor,"EOF")) - break; - } - - // find out how many valud layers we have - for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end(); it != end;++it) { - if (!(*it).vPositions.empty()) - ++pScene->mNumMeshes; - } - - if (!pScene->mNumMeshes) - throw DeadlyImportError("DXF: this file contains no 3d data"); - - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; - unsigned int m = 0; - for (std::vector<LayerInfo>::const_iterator it = mLayers.begin(),end = mLayers.end();it != end;++it) { - if ((*it).vPositions.empty()) { - continue; - } - // generate the output mesh - aiMesh* pMesh = pScene->mMeshes[m++] = new aiMesh(); - const std::vector<aiVector3D>& vPositions = (*it).vPositions; - const std::vector<aiColor4D>& vColors = (*it).vColors; - - // check whether we need vertex colors here - aiColor4D* clrOut = NULL; - const aiColor4D* clr = NULL; - for (std::vector<aiColor4D>::const_iterator it2 = (*it).vColors.begin(), end2 = (*it).vColors.end();it2 != end2; ++it2) { - - if ((*it2).r == (*it2).r) /* qnan? */ { - clrOut = pMesh->mColors[0] = new aiColor4D[vPositions.size()]; - for (unsigned int i = 0; i < vPositions.size();++i) - clrOut[i] = aiColor4D(0.6f,0.6f,0.6f,1.0f); - - clr = &vColors[0]; - break; - } - } - - pMesh->mNumFaces = (unsigned int)vPositions.size() / 4u; - pMesh->mFaces = new aiFace[pMesh->mNumFaces]; - - aiVector3D* vpOut = pMesh->mVertices = new aiVector3D[vPositions.size()]; - const aiVector3D* vp = &vPositions[0]; - - for (unsigned int i = 0; i < pMesh->mNumFaces;++i) { - aiFace& face = pMesh->mFaces[i]; - - // check whether we need four, three or two indices here - if (vp[1] == vp[2]) { - face.mNumIndices = 2; - } - else if (vp[3] == vp[2]) { - face.mNumIndices = 3; - } - else face.mNumIndices = 4; - face.mIndices = new unsigned int[face.mNumIndices]; - - for (unsigned int a = 0; a < face.mNumIndices;++a) { - *vpOut++ = vp[a]; - if (clr) { - if (is_not_qnan( clr[a].r )) { - *clrOut = clr[a]; - } - ++clrOut; - } - face.mIndices[a] = pMesh->mNumVertices++; - } - vp += 4; - } - } - - // generate the output scene graph - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("<DXF_ROOT>"); - - if (1 == pScene->mNumMeshes) { - pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ]; - pScene->mRootNode->mMeshes[0] = 0; - } - else - { - pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ]; - for (m = 0; m < pScene->mRootNode->mNumChildren;++m) { - aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode(); - p->mName.length = ::strlen( mLayers[m].name ); - strcpy(p->mName.data, mLayers[m].name); - - p->mMeshes = new unsigned int[p->mNumMeshes = 1]; - p->mMeshes[0] = m; - p->mParent = pScene->mRootNode; - } - } - - // generate a default material - MaterialHelper* pcMat = new MaterialHelper(); - aiString s; - s.Set(AI_DEFAULT_MATERIAL_NAME); - pcMat->AddProperty(&s, AI_MATKEY_NAME); - - aiColor4D clrDiffuse(0.6f,0.6f,0.6f,1.0f); - pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE); - - clrDiffuse = aiColor4D(1.0f,1.0f,1.0f,1.0f); - pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR); - - clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f); - pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT); - - pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = pcMat; - - // flip winding order to be ccw - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); - - // --- everything destructs automatically --- -} - -// ------------------------------------------------------------------------------------------------ -bool DXFImporter::ParseEntities() -{ - while (GetNextToken()) { - if (!groupCode) { - if (!::strcmp(cursor,"3DFACE") || !::strcmp(cursor,"LINE") || !::strcmp(cursor,"3DLINE")){ - //http://sourceforge.net/tracker/index.php?func=detail&aid=2970566&group_id=226462&atid=1067632 - Parse3DFace(); - bRepeat = true; - } - if (!::strcmp(cursor,"POLYLINE") || !::strcmp(cursor,"LWPOLYLINE")){ - ParsePolyLine(); - bRepeat = true; - } - if (!::strcmp(cursor,"ENDSEC")) { - return true; - } - } - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void DXFImporter::SetLayer(LayerInfo*& out) -{ - for (std::vector<LayerInfo>::iterator it = mLayers.begin(),end = mLayers.end();it != end;++it) { - if (!::strcmp( (*it).name, cursor )) { - out = &(*it); - break; - } - } - if (!out) { - // we don't have this layer yet - mLayers.push_back(LayerInfo()); - out = &mLayers.back(); - ::strcpy(out->name,cursor); - } -} - -// ------------------------------------------------------------------------------------------------ -void DXFImporter::SetDefaultLayer(LayerInfo*& out) -{ - if (!mDefaultLayer) { - mLayers.push_back(LayerInfo()); - mDefaultLayer = &mLayers.back(); - } - out = mDefaultLayer; -} - -// ------------------------------------------------------------------------------------------------ -bool DXFImporter::ParsePolyLine() -{ - bool ret = false; - LayerInfo* out = NULL; - - std::vector<aiVector3D> positions; - std::vector<aiColor4D> colors; - std::vector<unsigned int> indices; - unsigned int flags = 0; - - while (GetNextToken()) { - switch (groupCode) - { - case 0: - { - if (!::strcmp(cursor,"VERTEX")) { - aiVector3D v;aiColor4D clr(g_clrInvalid); - unsigned int idx[4] = {0xffffffff,0xffffffff,0xffffffff,0xffffffff}; - ParsePolyLineVertex(v, clr, idx); - if (0xffffffff == idx[0]) { - positions.push_back(v); - colors.push_back(clr); - } - else { - // check whether we have a fourth coordinate - if (0xffffffff == idx[3]) { - idx[3] = idx[2]; - } - - indices.reserve(indices.size()+4); - for (unsigned int m = 0; m < 4;++m) - indices.push_back(idx[m]); - } - bRepeat = true; - } - else if (!::strcmp(cursor,"ENDSEQ")) { - ret = true; - } - break; - } - - // flags --- important that we know whether it is a polyface mesh - case 70: - { - if (!flags) { - flags = strtol10(cursor); - } - break; - }; - - // optional number of vertices - case 71: - { - positions.reserve(strtol10(cursor)); - break; - } - - // optional number of faces - case 72: - { - indices.reserve(strtol10(cursor)); - break; - } - - // 8 specifies the layer - case 8: - { - SetLayer(out); - break; - } - } - } - if (!(flags & 64)) { - DefaultLogger::get()->warn("DXF: Only polyface meshes are currently supported"); - return ret; - } - - if (positions.size() < 3 || indices.size() < 3) { - DefaultLogger::get()->warn("DXF: Unable to parse POLYLINE element - not enough vertices"); - return ret; - } - - // use a default layer if necessary - if (!out) { - SetDefaultLayer(out); - } - - flags = (unsigned int)(out->vPositions.size()+indices.size()); - out->vPositions.reserve(flags); - out->vColors.reserve(flags); - - // generate unique vertices - for (std::vector<unsigned int>::const_iterator it = indices.begin(), end = indices.end();it != end; ++it) { - unsigned int idx = *it; - if (idx > positions.size() || !idx) { - DefaultLogger::get()->error("DXF: Polyface mesh index os out of range"); - idx = (unsigned int) positions.size(); - } - out->vPositions.push_back(positions[idx-1]); // indices are one-based. - out->vColors.push_back(colors[idx-1]); // indices are one-based. - } - - return ret; -} - -// ------------------------------------------------------------------------------------------------ -bool DXFImporter::ParsePolyLineVertex(aiVector3D& out,aiColor4D& clr, unsigned int* outIdx) -{ - bool ret = false; - while (GetNextToken()) { - switch (groupCode) - { - case 0: ret = true; - break; - - // todo - handle the correct layer for the vertex. At the moment it is assumed that all vertices of - // a polyline are placed on the same global layer. - - // x position of the first corner - case 10: out.x = fast_atof(cursor);break; - - // y position of the first corner - case 20: out.y = -fast_atof(cursor);break; - - // z position of the first corner - case 30: out.z = fast_atof(cursor);break; - - // POLYFACE vertex indices - case 71: outIdx[0] = strtol10(cursor);break; - case 72: outIdx[1] = strtol10(cursor);break; - case 73: outIdx[2] = strtol10(cursor);break; - // case 74: outIdx[3] = strtol10(cursor);break; - - // color - case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break; - }; - if (ret) { - break; - } - } - return ret; -} - -// ------------------------------------------------------------------------------------------------ -bool DXFImporter::Parse3DFace() -{ - bool ret = false; - LayerInfo* out = NULL; - - aiVector3D vip[4]; // -- vectors are initialized to zero - aiColor4D clr(g_clrInvalid); - - // this is also used for for parsing line entities - bool bThird = false; - - while (GetNextToken()) { - switch (groupCode) { - case 0: - ret = true; - break; - - // 8 specifies the layer - case 8: { - SetLayer(out); - break; - } - - // x position of the first corner - case 10: vip[0].x = fast_atof(cursor);break; - - // y position of the first corner - case 20: vip[0].y = -fast_atof(cursor);break; - - // z position of the first corner - case 30: vip[0].z = fast_atof(cursor);break; - - // x position of the second corner - case 11: vip[1].x = fast_atof(cursor);break; - - // y position of the second corner - case 21: vip[1].y = -fast_atof(cursor);break; - - // z position of the second corner - case 31: vip[1].z = fast_atof(cursor);break; - - // x position of the third corner - case 12: vip[2].x = fast_atof(cursor); - bThird = true;break; - - // y position of the third corner - case 22: vip[2].y = -fast_atof(cursor); - bThird = true;break; - - // z position of the third corner - case 32: vip[2].z = fast_atof(cursor); - bThird = true;break; - - // x position of the fourth corner - case 13: vip[3].x = fast_atof(cursor); - bThird = true;break; - - // y position of the fourth corner - case 23: vip[3].y = -fast_atof(cursor); - bThird = true;break; - - // z position of the fourth corner - case 33: vip[3].z = fast_atof(cursor); - bThird = true;break; - - // color - case 62: clr = g_aclrDxfIndexColors[strtol10(cursor) % AI_DXF_NUM_INDEX_COLORS]; break; - }; - if (ret) - break; - } - - if (!bThird) - vip[2] = vip[1]; - - // use a default layer if necessary - if (!out) { - SetDefaultLayer(out); - } - // add the faces to the face list for this layer - out->vPositions.push_back(vip[0]); - out->vPositions.push_back(vip[1]); - out->vPositions.push_back(vip[2]); - out->vPositions.push_back(vip[3]); // might be equal to the third - - for (unsigned int i = 0; i < 4;++i) - out->vColors.push_back(clr); - return ret; -} - -#endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER - diff --git a/3rdparty/assimp/code/DXFLoader.h b/3rdparty/assimp/code/DXFLoader.h deleted file mode 100644 index 9ae16ed5..00000000 --- a/3rdparty/assimp/code/DXFLoader.h +++ /dev/null @@ -1,184 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 DXFLoader.h - * @brief Declaration of the .dxf importer class. - */ -#ifndef AI_DXFLOADER_H_INCLUDED -#define AI_DXFLOADER_H_INCLUDED - -#include "BaseImporter.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** DXF importer class -*/ -class DXFImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - DXFImporter(); - - /** Destructor, private as well */ - ~DXFImporter(); - - - // describes a single layer in the DXF file - struct LayerInfo - { - LayerInfo() - { - name[0] = '\0'; - } - - char name[4096]; - - // face buffer - order is x,y,z v1,v2,v3,v4 - // if v2 = v3: line - // elsif v3 = v2: triangle - // else: polygon - std::vector<aiVector3D> vPositions; - std::vector<aiColor4D> vColors; - }; - - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Get the next line from the file. - * @return false if the end of the file was reached - */ - bool GetNextLine(); - - // ------------------------------------------------------------------- - /** Get the next token (group code + data line) from the file. - * @return false if the end of the file was reached - */ - bool GetNextToken(); - - // ------------------------------------------------------------------- - /** Parses the ENTITIES section in the file - * @return false if the end of the file was reached - */ - bool ParseEntities(); - - // ------------------------------------------------------------------- - /** Parses a 3DFACE section in the file - * @return false if the end of the file was reached - */ - bool Parse3DFace(); - - // ------------------------------------------------------------------- - /** Parses a POLYLINE section in the file - * @return false if the end of the file was reached - */ - bool ParsePolyLine(); - - // ------------------------------------------------------------------- - /** Sets the current layer - cursor must point to the name of it. - * @param out Receives a handle to the layer - */ - void SetLayer(LayerInfo*& out); - - // ------------------------------------------------------------------- - /** Creates a default layer. - * @param out Receives a handle to the default layer - */ - void SetDefaultLayer(LayerInfo*& out); - - // ------------------------------------------------------------------- - /** Parses a VERTEX element in a POLYLINE/POLYFACE - * @param out Receives the output vertex. - * @param clr Receives the output vertex color - won't be modified - * if it is not existing. - * @param outIdx Receives the output vertex indices, if present. - * Wont't be modified otherwise. Size must be at least 4. - * @return false if the end of the file was reached - */ - bool ParsePolyLineVertex(aiVector3D& out, aiColor4D& clr, - unsigned int* outIdx); - -private: - - // points to the next section - const char* buffer; - - // specifies the current group code - int groupCode; - - // contains the current data line - char cursor[4096]; - - // specifies whether the next call to GetNextToken() - // should return the current token a second time - bool bRepeat; - - // list of all loaded layers - std::vector<LayerInfo> mLayers; - LayerInfo* mDefaultLayer; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/DefaultIOStream.cpp b/3rdparty/assimp/code/DefaultIOStream.cpp deleted file mode 100644 index f68ad384..00000000 --- a/3rdparty/assimp/code/DefaultIOStream.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 DefaultIOStream.cpp - * @brief Default File I/O implementation for #Importer - */ - -#include "AssimpPCH.h" - -#include "DefaultIOStream.h" -#include <sys/types.h> -#include <sys/stat.h> - -using namespace Assimp; - -// ---------------------------------------------------------------------------------- -DefaultIOStream::~DefaultIOStream() -{ - if (mFile) { - ::fclose(mFile); - } -} - -// ---------------------------------------------------------------------------------- -size_t DefaultIOStream::Read(void* pvBuffer, - size_t pSize, - size_t pCount) -{ - ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); - return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0); -} - -// ---------------------------------------------------------------------------------- -size_t DefaultIOStream::Write(const void* pvBuffer, - size_t pSize, - size_t pCount) -{ - ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount); - return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0); -} - -// ---------------------------------------------------------------------------------- -aiReturn DefaultIOStream::Seek(size_t pOffset, - aiOrigin pOrigin) -{ - if (!mFile) { - return AI_FAILURE; - } - - // Just to check whether our enum maps one to one with the CRT constants - BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR && - aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET); - - // do the seek - return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE); -} - -// ---------------------------------------------------------------------------------- -size_t DefaultIOStream::Tell() const -{ - if (!mFile) { - return 0; - } - return ::ftell(mFile); -} - -// ---------------------------------------------------------------------------------- -size_t DefaultIOStream::FileSize() const -{ - if (! mFile || mFilename.empty()) { - return 0; - } - - if (0xffffffff == cachedSize) { - - // TODO: Is that really faster if we're already owning a handle to the file? -#if defined _WIN32 && !defined __GNUC__ - struct __stat64 fileStat; - int err = _stat64( mFilename.c_str(), &fileStat ); - if (0 != err) - return 0; - cachedSize = (size_t) (fileStat.st_size); -#else - struct stat fileStat; - int err = stat(mFilename.c_str(), &fileStat ); - if (0 != err) - return 0; - cachedSize = (size_t) (fileStat.st_size); -#endif - } - return cachedSize; -} - -// ---------------------------------------------------------------------------------- -void DefaultIOStream::Flush() -{ - if (mFile) { - ::fflush(mFile); - } -} - -// ---------------------------------------------------------------------------------- diff --git a/3rdparty/assimp/code/DefaultIOStream.h b/3rdparty/assimp/code/DefaultIOStream.h deleted file mode 100644 index 1fdaa33b..00000000 --- a/3rdparty/assimp/code/DefaultIOStream.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Default file I/O using fXXX()-family of functions */ -#ifndef AI_DEFAULTIOSTREAM_H_INC -#define AI_DEFAULTIOSTREAM_H_INC - -#include <stdio.h> -#include "../include/IOStream.h" - -namespace Assimp { - -// ---------------------------------------------------------------------------------- -//! @class DefaultIOStream -//! @brief Default IO implementation, use standard IO operations -//! @note An instance of this class can exist without a valid file handle -//! attached to it. All calls fail, but the instance can nevertheless be -//! used with no restrictions. -class DefaultIOStream : public IOStream -{ - friend class DefaultIOSystem; - -protected: - DefaultIOStream (); - DefaultIOStream (FILE* pFile, const std::string &strFilename); - -public: - /** Destructor public to allow simple deletion to close the file. */ - ~DefaultIOStream (); - - // ------------------------------------------------------------------- - // Read from stream - size_t Read(void* pvBuffer, - size_t pSize, - size_t pCount); - - - // ------------------------------------------------------------------- - // Write to stream - size_t Write(const void* pvBuffer, - size_t pSize, - size_t pCount); - - // ------------------------------------------------------------------- - // Seek specific position - aiReturn Seek(size_t pOffset, - aiOrigin pOrigin); - - // ------------------------------------------------------------------- - // Get current seek position - size_t Tell() const; - - // ------------------------------------------------------------------- - // Get size of file - size_t FileSize() const; - - // ------------------------------------------------------------------- - // Flush file contents - void Flush(); - -private: - //! File datastructure, using clib - FILE* mFile; - //! Filename - std::string mFilename; - - //! Cached file size - mutable size_t cachedSize; -}; - - -// ---------------------------------------------------------------------------------- -inline DefaultIOStream::DefaultIOStream () : - mFile (NULL), - mFilename (""), - cachedSize (0xffffffff) -{ - // empty -} - - -// ---------------------------------------------------------------------------------- -inline DefaultIOStream::DefaultIOStream (FILE* pFile, - const std::string &strFilename) : - mFile(pFile), - mFilename(strFilename), - cachedSize (0xffffffff) -{ - // empty -} -// ---------------------------------------------------------------------------------- - -} // ns assimp - -#endif //!!AI_DEFAULTIOSTREAM_H_INC - diff --git a/3rdparty/assimp/code/DefaultIOSystem.cpp b/3rdparty/assimp/code/DefaultIOSystem.cpp deleted file mode 100644 index f09f710b..00000000 --- a/3rdparty/assimp/code/DefaultIOSystem.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Default implementation of IOSystem using the standard C file functions */ - -#include "AssimpPCH.h" - -#include <stdlib.h> -#include "DefaultIOSystem.h" -#include "DefaultIOStream.h" - -#ifdef __unix__ -#include <sys/param.h> -#include <stdlib.h> -#endif - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor. -DefaultIOSystem::DefaultIOSystem() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -DefaultIOSystem::~DefaultIOSystem() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Tests for the existence of a file at the given path. -bool DefaultIOSystem::Exists( const char* pFile) const -{ - FILE* file = ::fopen( pFile, "rb"); - if ( !file) - return false; - - ::fclose( file); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Open a new file with a given path. -IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) -{ - ai_assert(NULL != strFile); - ai_assert(NULL != strMode); - - FILE* file = ::fopen( strFile, strMode); - if ( NULL == file) - return NULL; - - return new DefaultIOStream(file, (std::string) strFile); -} - -// ------------------------------------------------------------------------------------------------ -// Closes the given file and releases all resources associated with it. -void DefaultIOSystem::Close( IOStream* pFile) -{ - delete pFile; -} - -// ------------------------------------------------------------------------------------------------ -// Returns the operation specific directory separator -char DefaultIOSystem::getOsSeparator() const -{ -#ifndef _WIN32 - return '/'; -#else - return '\\'; -#endif -} - -// ------------------------------------------------------------------------------------------------ -// IOSystem default implementation (ComparePaths isn't a pure virtual function) -bool IOSystem::ComparePaths (const char* one, const char* second) const -{ - return !ASSIMP_stricmp(one,second); -} - -// maximum path length -// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html -#ifdef PATH_MAX -# define PATHLIMIT PATH_MAX -#else -# define PATHLIMIT 4096 -#endif - -// ------------------------------------------------------------------------------------------------ -// Convert a relative path into an absolute path -inline void MakeAbsolutePath (const char* in, char* _out) -{ - ai_assert(in && _out); - char* ret; -#ifdef _WIN32 - ret = ::_fullpath(_out, in,PATHLIMIT); -#else - // use realpath - ret = realpath(in, _out); -#endif - if (!ret) { - // preserve the input path, maybe someone else is able to fix - // the path before it is accessed (e.g. our file system filter) - DefaultLogger::get()->warn("Invalid path: "+std::string(in)); - strcpy(_out,in); - } -} - -// ------------------------------------------------------------------------------------------------ -// DefaultIOSystem's more specialized implementation -bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const -{ - // chances are quite good both paths are formatted identically, - // so we can hopefully return here already - if ( !ASSIMP_stricmp(one,second) ) - return true; - - char temp1[PATHLIMIT]; - char temp2[PATHLIMIT]; - - MakeAbsolutePath (one, temp1); - MakeAbsolutePath (second, temp2); - - return !ASSIMP_stricmp(temp1,temp2); -} - -#undef PATHLIMIT diff --git a/3rdparty/assimp/code/DefaultIOSystem.h b/3rdparty/assimp/code/DefaultIOSystem.h deleted file mode 100644 index 3c360175..00000000 --- a/3rdparty/assimp/code/DefaultIOSystem.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Default implementation of IOSystem using the standard C file functions */ -#ifndef AI_DEFAULTIOSYSTEM_H_INC -#define AI_DEFAULTIOSYSTEM_H_INC - -#include "../include/IOSystem.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Default implementation of IOSystem using the standard C file functions */ -class DefaultIOSystem : public IOSystem -{ -public: - /** Constructor. */ - DefaultIOSystem(); - - /** Destructor. */ - ~DefaultIOSystem(); - - // ------------------------------------------------------------------- - /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const; - - // ------------------------------------------------------------------- - /** Returns the directory separator. */ - char getOsSeparator() const; - - // ------------------------------------------------------------------- - /** Open a new file with a given path. */ - IOStream* Open( const char* pFile, const char* pMode = "rb"); - - // ------------------------------------------------------------------- - /** Closes the given file and releases all resources associated with it. */ - void Close( IOStream* pFile); - - // ------------------------------------------------------------------- - /** Compare two paths */ - bool ComparePaths (const char* one, const char* second) const; -}; - -} //!ns Assimp - -#endif //AI_DEFAULTIOSYSTEM_H_INC diff --git a/3rdparty/assimp/code/DefaultLogger.cpp b/3rdparty/assimp/code/DefaultLogger.cpp deleted file mode 100644 index 7951468e..00000000 --- a/3rdparty/assimp/code/DefaultLogger.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 DefaultLogger.cpp - * @brief Implementation of DefaultLogger (and Logger) - */ - -#include "AssimpPCH.h" -#include "DefaultIOSystem.h" - -// Default log streams -#include "Win32DebugLogStream.h" -#include "StdOStreamLogStream.h" -#include "FileLogStream.h" - -#ifndef ASSIMP_BUILD_SINGLETHREADED -# include <boost/thread/thread.hpp> -# include <boost/thread/mutex.hpp> - -boost::mutex loggerMutex; -#endif - -namespace Assimp { - -// ---------------------------------------------------------------------------------- -NullLogger DefaultLogger::s_pNullLogger; -Logger *DefaultLogger::m_pLogger = &DefaultLogger::s_pNullLogger; - -// ---------------------------------------------------------------------------------- -// Represents a logstream + its error severity -struct LogStreamInfo -{ - unsigned int m_uiErrorSeverity; - LogStream *m_pStream; - - // Constructor - LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : - m_uiErrorSeverity( uiErrorSev ), - m_pStream( pStream ) - { - // empty - } - - // Destructor - ~LogStreamInfo() - { - delete m_pStream; - } -}; - -// ---------------------------------------------------------------------------------- -// Construct a default log stream -LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, - const char* name /*= "AssimpLog.txt"*/, - IOSystem* io /*= NULL*/) -{ - switch (streams) - { - // This is a platform-specific feature - case aiDefaultLogStream_DEBUGGER: -#ifdef WIN32 - return new Win32DebugLogStream(); -#else - return NULL; -#endif - - // Platform-independent default streams - case aiDefaultLogStream_STDERR: - return new StdOStreamLogStream(std::cerr); - case aiDefaultLogStream_STDOUT: - return new StdOStreamLogStream(std::cout); - case aiDefaultLogStream_FILE: - return (name && *name ? new FileLogStream(name,io) : NULL); - default: - // We don't know this default log stream, so raise an assertion - ai_assert(false); - - }; - - // For compilers without dead code path detection - return NULL; -} - -// ---------------------------------------------------------------------------------- -// Creates the only singleton instance -Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, - LogSeverity severity /*= NORMAL*/, - unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, - IOSystem* io /*= NULL*/) -{ - // enter the mutex here to avoid concurrency problems -#ifndef ASSIMP_BUILD_SINGLETHREADED - boost::mutex::scoped_lock lock(loggerMutex); -#endif - - if (m_pLogger && !isNullLogger() ) - delete m_pLogger; - - m_pLogger = new DefaultLogger( severity ); - - // Attach default log streams - // Stream the log to the MSVC debugger? - if (defStreams & aiDefaultLogStream_DEBUGGER) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); - - // Stream the log to COUT? - if (defStreams & aiDefaultLogStream_STDOUT) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); - - // Stream the log to CERR? - if (defStreams & aiDefaultLogStream_STDERR) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); - - // Stream the log to a file - if (defStreams & aiDefaultLogStream_FILE && name && *name) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); - - return m_pLogger; -} - -// ---------------------------------------------------------------------------------- -void Logger::debug(const std::string &message) { - - // SECURITY FIX: otherwise it's easy to produce overruns ... - if (message.length()>MAX_LOG_MESSAGE_LENGTH) { - ai_assert(false); - return; - } - return OnDebug(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -void Logger::info(const std::string &message) { - - // SECURITY FIX: otherwise it's easy to produce overruns ... - if (message.length()>MAX_LOG_MESSAGE_LENGTH) { - ai_assert(false); - return; - } - return OnInfo(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -void Logger::warn(const std::string &message) { - - // SECURITY FIX: otherwise it's easy to produce overruns ... - if (message.length()>MAX_LOG_MESSAGE_LENGTH) { - ai_assert(false); - return; - } - return OnWarn(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -void Logger::error(const std::string &message) { - - // SECURITY FIX: otherwise it's easy to produce overruns ... - if (message.length()>MAX_LOG_MESSAGE_LENGTH) { - ai_assert(false); - return; - } - return OnError(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -void DefaultLogger::set( Logger *logger ) -{ - // enter the mutex here to avoid concurrency problems -#ifndef ASSIMP_BUILD_SINGLETHREADED - boost::mutex::scoped_lock lock(loggerMutex); -#endif - - if (!logger)logger = &s_pNullLogger; - if (m_pLogger && !isNullLogger() ) - delete m_pLogger; - - DefaultLogger::m_pLogger = logger; -} - -// ---------------------------------------------------------------------------------- -bool DefaultLogger::isNullLogger() -{ - return m_pLogger == &s_pNullLogger; -} - -// ---------------------------------------------------------------------------------- -// Singleton getter -Logger *DefaultLogger::get() -{ - return m_pLogger; -} - -// ---------------------------------------------------------------------------------- -// Kills the only instance -void DefaultLogger::kill() -{ - // enter the mutex here to avoid concurrency problems -#ifndef ASSIMP_BUILD_SINGLETHREADED - boost::mutex::scoped_lock lock(loggerMutex); -#endif - - if (m_pLogger == &s_pNullLogger)return; - delete m_pLogger; - m_pLogger = &s_pNullLogger; -} - -// ---------------------------------------------------------------------------------- -// Debug message -void DefaultLogger::OnDebug( const char* message ) -{ - if ( m_Severity == Logger::NORMAL ) - return; - - char msg[MAX_LOG_MESSAGE_LENGTH*2]; - ::sprintf(msg,"Debug, T%i: %s", GetThreadID(), message ); - - WriteToStreams( msg, Logger::DEBUGGING ); -} - -// ---------------------------------------------------------------------------------- -// Logs an info -void DefaultLogger::OnInfo( const char* message ) -{ - char msg[MAX_LOG_MESSAGE_LENGTH*2]; - ::sprintf(msg,"Info, T%i: %s", GetThreadID(), message ); - - WriteToStreams( msg , Logger::INFO ); -} - -// ---------------------------------------------------------------------------------- -// Logs a warning -void DefaultLogger::OnWarn( const char* message ) -{ - char msg[MAX_LOG_MESSAGE_LENGTH*2]; - ::sprintf(msg,"Warn, T%i: %s", GetThreadID(), message ); - - WriteToStreams( msg, Logger::WARN ); -} - -// ---------------------------------------------------------------------------------- -// Logs an error -void DefaultLogger::OnError( const char* message ) -{ - char msg[MAX_LOG_MESSAGE_LENGTH*2]; - ::sprintf(msg,"Error, T%i: %s", GetThreadID(), message ); - - WriteToStreams( msg, Logger::ERR ); -} - -// ---------------------------------------------------------------------------------- -// Attachs a new stream -bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) -{ - if (!pStream) - return false; - - if (0 == severity) { - severity = Logger::INFO | Logger::ERR | Logger::WARN | Logger::DEBUGGING; - } - - for ( StreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it ) - { - if ( (*it)->m_pStream == pStream ) - { - (*it)->m_uiErrorSeverity |= severity; - return true; - } - } - - LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream ); - m_StreamArray.push_back( pInfo ); - return true; -} - -// ---------------------------------------------------------------------------------- -// Detatch a stream -bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) -{ - if (!pStream) - return false; - - if (0 == severity) { - severity = Logger::INFO | Logger::ERR | Logger::WARN | Logger::DEBUGGING; - } - - for ( StreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it ) - { - if ( (*it)->m_pStream == pStream ) - { - (*it)->m_uiErrorSeverity &= ~severity; - if ( (*it)->m_uiErrorSeverity == 0 ) - { - // don't delete the underlying stream 'cause the caller gains ownership again - (**it).m_pStream = NULL; - delete *it; - m_StreamArray.erase( it ); - break; - } - return true; - } - } - return false; -} - -// ---------------------------------------------------------------------------------- -// Constructor -DefaultLogger::DefaultLogger(LogSeverity severity) - - : Logger ( severity ) - , noRepeatMsg (false) - , lastLen( 0 ) -{ - lastMsg[0] = '\0'; -} - -// ---------------------------------------------------------------------------------- -// Destructor -DefaultLogger::~DefaultLogger() -{ - for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { - // also frees the underlying stream, we are its owner. - delete *it; - } -} - -// ---------------------------------------------------------------------------------- -// Writes message to stream -void DefaultLogger::WriteToStreams(const char *message, - ErrorSeverity ErrorSev ) -{ - ai_assert(NULL != message); - - // Check whether this is a repeated message - if (! ::strncmp( message,lastMsg, lastLen-1)) - { - if (!noRepeatMsg) - { - noRepeatMsg = true; - message = "Skipping one or more lines with the same contents\n"; - } - else return; - } - else - { - // append a new-line character to the message to be printed - lastLen = ::strlen(message); - ::memcpy(lastMsg,message,lastLen+1); - ::strcat(lastMsg+lastLen,"\n"); - - message = lastMsg; - noRepeatMsg = false; - ++lastLen; - } - for ( ConstStreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it) - { - if ( ErrorSev & (*it)->m_uiErrorSeverity ) - (*it)->m_pStream->write( message); - } -} - -// ---------------------------------------------------------------------------------- -// Returns thread id, if not supported only a zero will be returned. -unsigned int DefaultLogger::GetThreadID() -{ - // fixme: we can get this value via boost::threads -#ifdef WIN32 - return (unsigned int)::GetCurrentThreadId(); -#else - return 0; // not supported -#endif -} - -// ---------------------------------------------------------------------------------- - -} // !namespace Assimp diff --git a/3rdparty/assimp/code/DefaultProgressHandler.h b/3rdparty/assimp/code/DefaultProgressHandler.h deleted file mode 100644 index 9b379dfa..00000000 --- a/3rdparty/assimp/code/DefaultProgressHandler.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ProgressHandler.h - * @brief Abstract base class 'ProgressHandler'. - */ -#ifndef INCLUDED_AI_DEFAULTPROGRESSHANDLER_H -#define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H - -#include "../include/ProgressHandler.h" -namespace Assimp { - -// ------------------------------------------------------------------------------------ -/** @brief Internal default implementation of the #ProgressHandler interface. */ -class ASSIMP_API DefaultProgressHandler - : public ProgressHandler { - - - virtual bool Update(float percentage) { - return false; - } - - -}; // !class DefaultProgressHandler -} // Namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/Exceptional.h b/3rdparty/assimp/code/Exceptional.h deleted file mode 100644 index ab9c2875..00000000 --- a/3rdparty/assimp/code/Exceptional.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef INCLUDED_EXCEPTIONAL_H -#define INCLUDED_EXCEPTIONAL_H - -#include <stdexcept> -using std::runtime_error; - -#ifdef _MSC_VER -# pragma warning(disable : 4275) -#endif - -// --------------------------------------------------------------------------- -/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an - * unrecoverable error occurs while importing. Loading APIs return - * NULL instead of a valid aiScene then. */ -class ASSIMP_API DeadlyImportError - : public runtime_error -{ -public: - /** Constructor with arguments */ - explicit DeadlyImportError( const std::string& pErrorText) - : runtime_error(pErrorText) - { - } - -private: -}; - -#ifdef _MSC_VER -# pragma warning(default : 4275) -#endif - -// --------------------------------------------------------------------------- -template <typename T> -struct ExceptionSwallower { - T operator ()() const { - return T(); - } -}; - -// --------------------------------------------------------------------------- -template <typename T> -struct ExceptionSwallower<T*> { - T* operator ()() const { - return NULL; - } -}; - -// --------------------------------------------------------------------------- -template <> -struct ExceptionSwallower<aiReturn> { - aiReturn operator ()() const { - try { - throw; - } - catch (std::bad_alloc&) { - return aiReturn_OUTOFMEMORY; - } - catch (...) { - return aiReturn_FAILURE; - } - } -}; - -// --------------------------------------------------------------------------- -template <> -struct ExceptionSwallower<void> { - void operator ()() const { - return; - } -}; - -#define ASSIMP_BEGIN_EXCEPTION_REGION()\ -{\ - try { - -#define ASSIMP_END_EXCEPTION_REGION(type)\ - } catch(...) {\ - return ExceptionSwallower<type>()();\ - }\ -} - -#endif // INCLUDED_EXCEPTIONAL_H diff --git a/3rdparty/assimp/code/FileLogStream.h b/3rdparty/assimp/code/FileLogStream.h deleted file mode 100644 index 15b8da7b..00000000 --- a/3rdparty/assimp/code/FileLogStream.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef ASSIMP_FILELOGSTREAM_H_INC -#define ASSIMP_FILELOGSTREAM_H_INC - -#include "../include/LogStream.h" -#include "../include/IOStream.h" - -namespace Assimp { - -// ---------------------------------------------------------------------------------- -/** @class FileLogStream - * @brief Logstream to write into a file. - */ -class FileLogStream : - public LogStream -{ -public: - FileLogStream( const char* file, IOSystem* io = NULL ); - ~FileLogStream(); - void write( const char* message ); - -private: - IOStream *m_pStream; -}; - -// ---------------------------------------------------------------------------------- -// Constructor -inline FileLogStream::FileLogStream( const char* file, IOSystem* io ) : - m_pStream(NULL) -{ - if ( !file || 0 == *file ) - return; - - // If no IOSystem is specified: take a default one - if (!io) - { - DefaultIOSystem FileSystem; - m_pStream = FileSystem.Open( file, "wt"); - } - else m_pStream = io->Open( file, "wt" ); -} - -// ---------------------------------------------------------------------------------- -// Destructor -inline FileLogStream::~FileLogStream() -{ - // The virtual d'tor should destroy the underlying file - delete m_pStream; -} - -// ---------------------------------------------------------------------------------- -// Write method -inline void FileLogStream::write( const char* message ) -{ - if (m_pStream != NULL) - { - m_pStream->Write(message, sizeof(char), ::strlen(message)); - m_pStream->Flush(); - } -} - -// ---------------------------------------------------------------------------------- -} // !Namespace Assimp - -#endif // !! ASSIMP_FILELOGSTREAM_H_INC diff --git a/3rdparty/assimp/code/FileSystemFilter.h b/3rdparty/assimp/code/FileSystemFilter.h deleted file mode 100644 index cc3b4a68..00000000 --- a/3rdparty/assimp/code/FileSystemFilter.h +++ /dev/null @@ -1,244 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 FileSystemFilter.h - * Implements a filter system to filter calls to Exists() and Open() - * in order to improve the sucess rate of file opening ... - */ -#ifndef AI_FILESYSTEMFILTER_H_INC -#define AI_FILESYSTEMFILTER_H_INC - -#include "../include/IOSystem.h" -#include "fast_atof.h" -#include "ParsingUtils.h" -namespace Assimp { - -// --------------------------------------------------------------------------- -/** File system filter - */ -class FileSystemFilter : public IOSystem -{ -public: - /** Constructor. */ - FileSystemFilter(const std::string& file, IOSystem* old) - : wrapped (old) - , src_file (file) - { - ai_assert(NULL != wrapped); - - // Determine base directory - base = src_file; - std::string::size_type ss2; - if (std::string::npos != (ss2 = base.find_last_of("\\/"))) { - base.erase(ss2,base.length()-ss2); - } - else { - base = ""; - // return; - } - - // make sure the directory is terminated properly - char s; - - if (base.length() == 0) { - base = "."; - base += getOsSeparator(); - } - else if ((s = *(base.end()-1)) != '\\' && s != '/') - base += getOsSeparator(); - - DefaultLogger::get()->info("Import root directory is \'" + base + "\'"); - } - - /** Destructor. */ - ~FileSystemFilter() - { - // haha - } - - // ------------------------------------------------------------------- - /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const - { - std::string tmp = pFile; - - // Currently this IOSystem is also used to open THE ONE FILE. - if (tmp != src_file) { - BuildPath(tmp); - Cleanup(tmp); - } - - return wrapped->Exists(tmp); - } - - // ------------------------------------------------------------------- - /** Returns the directory separator. */ - char getOsSeparator() const - { - return wrapped->getOsSeparator(); - } - - // ------------------------------------------------------------------- - /** Open a new file with a given path. */ - IOStream* Open( const char* pFile, const char* pMode = "rb") - { - ai_assert(pFile); - ai_assert(pMode); - - // First try the unchanged path - IOStream* s = wrapped->Open(pFile,pMode); - - if (!s) { - std::string tmp = pFile; - - // Try to convert between absolute and relative paths - BuildPath(tmp); - s = wrapped->Open(tmp,pMode); - - if (!s) { - // Finally, look for typical issues with paths - // and try to correct them. This is our last - // resort. - Cleanup(tmp); - s = wrapped->Open(tmp,pMode); - } - } - - return s; - } - - // ------------------------------------------------------------------- - /** Closes the given file and releases all resources associated with it. */ - void Close( IOStream* pFile) - { - return wrapped->Close(pFile); - } - - // ------------------------------------------------------------------- - /** Compare two paths */ - bool ComparePaths (const char* one, const char* second) const - { - return wrapped->ComparePaths (one,second); - } - -private: - IOSystem* wrapped; - std::string src_file, base; - - // ------------------------------------------------------------------- - /** Build a valid path from a given relative or absolute path. - */ - void BuildPath (std::string& in) const - { - // if we can already access the file, great. - if (in.length() < 3 || wrapped->Exists(in.c_str())) { - return; - } - - // Determine whether this is a relative path (Windows-specific - most assets are packaged on Windows). - if (in[1] != ':') { - - // append base path and try - in = base + in; - if (wrapped->Exists(in.c_str())) { - return; - } - } - - // hopefully the underyling file system has another few tricks to access this file ... - } - - // ------------------------------------------------------------------- - /** Cleanup the given path - */ - void Cleanup (std::string& in) const - { - char last = 0; - - // Remove a very common issue when we're parsing file names: spaces at the - // beginning of the path. - std::string::iterator it = in.begin(); - while (IsSpaceOrNewLine( *it ))++it; - if (it != in.begin()) - in.erase(in.begin(),it+1); - - const char sep = getOsSeparator(); - for (it = in.begin(); it != in.end(); ++it) { - // Exclude :// and \\, which remain untouched. - // https://sourceforge.net/tracker/?func=detail&aid=3031725&group_id=226462&atid=1067632 - if ( !strncmp(&*it, "://", 3 )) { - it += 3; - continue; - } - if (it == in.begin() && !strncmp(&*it, "\\\\", 2)) { - it += 2; - continue; - } - - // Cleanup path delimiters - if (*it == '/' || (*it) == '\\') { - *it = sep; - - // And we're removing double delimiters, frequent issue with - // incorrectly composited paths ... - if (last == *it) { - it = in.erase(it); - --it; - } - } - else if (*it == '%' && in.end() - it > 2) { - - // Hex sequence in URIs - uint32_t tmp; - if ( 0xffffffff != (tmp = HexOctetToDecimal(&*it))) { - *it = (char)tmp; - it = in.erase(it+1,it+2); - --it; - } - } - - last = *it; - } - } -}; - -} //!ns Assimp - -#endif //AI_DEFAULTIOSYSTEM_H_INC diff --git a/3rdparty/assimp/code/FindDegenerates.cpp b/3rdparty/assimp/code/FindDegenerates.cpp deleted file mode 100644 index 3cdd325d..00000000 --- a/3rdparty/assimp/code/FindDegenerates.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 FindDegenerates.cpp - * @brief Implementation of the FindDegenerates post-process step. -*/ - -#include "AssimpPCH.h" - -// internal headers -#include "ProcessHelper.h" -#include "FindDegenerates.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -FindDegeneratesProcess::FindDegeneratesProcess() -: configRemoveDegenerates (false) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FindDegeneratesProcess::~FindDegeneratesProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool FindDegeneratesProcess::IsActive( unsigned int pFlags) const -{ - return 0 != (pFlags & aiProcess_FindDegenerates); -} - -// ------------------------------------------------------------------------------------------------ -// Setup import configuration -void FindDegeneratesProcess::SetupProperties(const Importer* pImp) -{ - // Get the current value of AI_CONFIG_PP_FD_REMOVE - configRemoveDegenerates = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_FD_REMOVE,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void FindDegeneratesProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("FindDegeneratesProcess begin"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i){ - ExecuteOnMesh( pScene->mMeshes[i]); - } - DefaultLogger::get()->debug("FindDegeneratesProcess finished"); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported mesh -void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) -{ - mesh->mPrimitiveTypes = 0; - - std::vector<bool> remove_me; - if (configRemoveDegenerates) - remove_me.resize(mesh->mNumFaces,false); - - unsigned int deg = 0, limit; - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { - aiFace& face = mesh->mFaces[a]; - bool first = true; - - // check whether the face contains degenerated entries - for (register unsigned int i = 0; i < face.mNumIndices; ++i) - { - // Polygons with more than 4 points are allowed to have double points, that is - // simulating polygons with holes just with concave polygons. However, - // double points may not come directly after another. - limit = face.mNumIndices; - if (face.mNumIndices > 4) - limit = std::min(limit,i+2); - - for (register unsigned int t = i+1; t < limit; ++t) - { - if (mesh->mVertices[face.mIndices[i]] == mesh->mVertices[face.mIndices[t]]) - { - // we have found a matching vertex position - // remove the corresponding index from the array - --face.mNumIndices;--limit; - for (unsigned int m = t; m < face.mNumIndices; ++m) - { - face.mIndices[m] = face.mIndices[m+1]; - } - --t; - - // NOTE: we set the removed vertex index to an unique value - // to make sure the developer gets notified when his - // application attemps to access this data. - face.mIndices[face.mNumIndices] = 0xdeadbeef; - - if (first) - { - ++deg; - first = false; - } - - if (configRemoveDegenerates) { - remove_me[a] = true; - goto evil_jump_outside; // hrhrhrh ... yeah, this rocks baby! - } - } - } - } - - // We need to update the primitive flags array of the mesh. - switch (face.mNumIndices) - { - case 1u: - mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2u: - mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3u: - mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - }; -evil_jump_outside: - continue; - } - - // If AI_CONFIG_PP_FD_REMOVE is true, remove degenerated faces from the import - if (configRemoveDegenerates && deg) { - unsigned int n = 0; - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) - { - aiFace& face_src = mesh->mFaces[a]; - if (!remove_me[a]) { - aiFace& face_dest = mesh->mFaces[n++]; - - // Do a manual copy, keep the index array - face_dest.mNumIndices = face_src.mNumIndices; - face_dest.mIndices = face_src.mIndices; - - if (&face_src != &face_dest) { - // clear source - face_src.mNumIndices = 0; - face_src.mIndices = NULL; - } - } - else { - // Otherwise delete it if we don't need this face - delete[] face_src.mIndices; - face_src.mIndices = NULL; - face_src.mNumIndices = 0; - } - } - // Just leave the rest of the array unreferenced, we don't care for now - mesh->mNumFaces = n; - if (!mesh->mNumFaces) { - // WTF!? - // OK ... for completeness and because I'm not yet tired, - // let's write code that willl hopefully never be called - // (famous last words) - - // OK ... bad idea. - throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?"); - } - } - - if (deg && !DefaultLogger::isNullLogger()) - { - char s[64]; - ASSIMP_itoa10(s,deg); - DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives"); - } -} diff --git a/3rdparty/assimp/code/FindDegenerates.h b/3rdparty/assimp/code/FindDegenerates.h deleted file mode 100644 index daa5cf93..00000000 --- a/3rdparty/assimp/code/FindDegenerates.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to search all meshes for - degenerated faces */ -#ifndef AI_FINDDEGENERATESPROCESS_H_INC -#define AI_FINDDEGENERATESPROCESS_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class FindDegeneratesProcessTest; -namespace Assimp { - - -// --------------------------------------------------------------------------- -/** FindDegeneratesProcess: Searches a mesh for degenerated triangles. -*/ -class ASSIMP_API FindDegeneratesProcess : public BaseProcess -{ - friend class Importer; - friend class ::FindDegeneratesProcessTest; // grant the unit test full access to us - -protected: - /** Constructor to be privately used by Importer */ - FindDegeneratesProcess(); - - /** Destructor, private as well */ - ~FindDegeneratesProcess(); - -public: - - // ------------------------------------------------------------------- - // Check whether step is active - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - // Execute step on a given scene - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - // Setup import settings - void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - // Execute step on a given mesh - void ExecuteOnMesh( aiMesh* mesh); - - - // ------------------------------------------------------------------- - /** @brief Enable the instant removal of degenerated primitives - * @param d hm ... difficult to guess what this means, hu!? - */ - void EnableInstantRemoval(bool d) { - configRemoveDegenerates = d; - } - - // ------------------------------------------------------------------- - /** @brief Check whether instant removal is currently enabled - * @return ... - */ - bool IsInstantRemoval() const { - return configRemoveDegenerates; - } - -private: - - //! Configuration option: remove degenerates faces immediately - bool configRemoveDegenerates; -}; -} - -#endif // !! AI_FINDDEGENERATESPROCESS_H_INC diff --git a/3rdparty/assimp/code/FindInstancesProcess.cpp b/3rdparty/assimp/code/FindInstancesProcess.cpp deleted file mode 100644 index f5956891..00000000 --- a/3rdparty/assimp/code/FindInstancesProcess.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 FindInstancesProcess.cpp - * @brief Implementation of the aiProcess_FindInstances postprocessing step -*/ - -#include "AssimpPCH.h" -#include "FindInstancesProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -FindInstancesProcess::FindInstancesProcess() -: configSpeedFlag (false) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FindInstancesProcess::~FindInstancesProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool FindInstancesProcess::IsActive( unsigned int pFlags) const -{ - // FindInstances makes absolutely no sense together with PreTransformVertices - // fixme: spawn error message somewhere else? - return 0 != (pFlags & aiProcess_FindInstances) && 0 == (pFlags & aiProcess_PreTransformVertices); -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties for the step -void FindInstancesProcess::SetupProperties(const Importer* pImp) -{ - // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Compare the bones of two meshes -bool CompareBones(const aiMesh* orig, const aiMesh* inst) -{ - for (unsigned int i = 0; i < orig->mNumBones;++i) { - aiBone* aha = orig->mBones[i]; - aiBone* oha = inst->mBones[i]; - - if (aha->mNumWeights != oha->mNumWeights || - aha->mOffsetMatrix != oha->mOffsetMatrix || - aha->mNumWeights != oha->mNumWeights) { - return false; - } - - // compare weight per weight --- - for (unsigned int n = 0; n < aha->mNumWeights;++n) { - if (aha->mWeights[n].mVertexId != oha->mWeights[n].mVertexId || - (aha->mWeights[n].mWeight - oha->mWeights[n].mWeight) < 10e-3f) { - return false; - } - } - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Update mesh indices in the node graph -void UpdateMeshIndices(aiNode* node, unsigned int* lookup) -{ - for (unsigned int n = 0; n < node->mNumMeshes;++n) - node->mMeshes[n] = lookup[node->mMeshes[n]]; - - for (unsigned int n = 0; n < node->mNumChildren;++n) - UpdateMeshIndices(node->mChildren[n],lookup); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void FindInstancesProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("FindInstancesProcess begin"); - if (pScene->mNumMeshes) { - - // use a pseudo hash for all meshes in the scene to quickly find - // the ones which are possibly equal. This step is executed early - // in the pipeline, so we could, depending on the file format, - // have several thousand small meshes. That's too much for a brute - // everyone-against-everyone check involving up to 10 comparisons - // each. - boost::scoped_array<uint64_t> hashes (new uint64_t[pScene->mNumMeshes]); - boost::scoped_array<unsigned int> remapping (new unsigned int[pScene->mNumMeshes]); - - unsigned int numMeshesOut = 0; - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - - aiMesh* inst = pScene->mMeshes[i]; - hashes[i] = GetMeshHash(inst); - - for (int a = i-1; a >= 0; --a) { - if (hashes[i] == hashes[a]) - { - aiMesh* orig = pScene->mMeshes[a]; - if (!orig) - continue; - - // check for hash collision .. we needn't check - // the vertex format, it *must* match due to the - // (brilliant) construction of the hash - if (orig->mNumBones != inst->mNumBones || - orig->mNumFaces != inst->mNumFaces || - orig->mNumVertices != inst->mNumVertices || - orig->mMaterialIndex != inst->mMaterialIndex || - orig->mPrimitiveTypes != inst->mPrimitiveTypes) - continue; - - // up to now the meshes are equal. find an appropriate - // epsilon to compare position differences against - float epsilon = ComputePositionEpsilon(inst); - epsilon *= epsilon; - - // now compare vertex positions, normals, - // tangents and bitangents using this epsilon. - if (orig->HasPositions()) { - if (!CompareArrays(orig->mVertices,inst->mVertices,orig->mNumVertices,epsilon)) - continue; - } - if (orig->HasNormals()) { - if (!CompareArrays(orig->mNormals,inst->mNormals,orig->mNumVertices,epsilon)) - continue; - } - if (orig->HasTangentsAndBitangents()) { - if (!CompareArrays(orig->mTangents,inst->mTangents,orig->mNumVertices,epsilon) || - !CompareArrays(orig->mBitangents,inst->mBitangents,orig->mNumVertices,epsilon)) - continue; - } - - // use a constant epsilon for colors and UV coordinates - static const float uvEpsilon = 10e-4f; - - BOOST_STATIC_ASSERT(4 == AI_MAX_NUMBER_OF_COLOR_SETS); - - // as in JIV: manually unrolled as continue wouldn't work as desired in inner loops - if (orig->mTextureCoords[0]) { - if (!CompareArrays(orig->mTextureCoords[0],inst->mTextureCoords[0],orig->mNumVertices,uvEpsilon)) - continue; - if (orig->mTextureCoords[1]) { - if (!CompareArrays(orig->mTextureCoords[1],inst->mTextureCoords[1],orig->mNumVertices,uvEpsilon)) - continue; - if (orig->mTextureCoords[2]) { - if (!CompareArrays(orig->mTextureCoords[2],inst->mTextureCoords[2],orig->mNumVertices,uvEpsilon)) - continue; - if (orig->mTextureCoords[3]) { - if (!CompareArrays(orig->mTextureCoords[3],inst->mTextureCoords[3],orig->mNumVertices,uvEpsilon)) - continue; - } - } - } - } - - BOOST_STATIC_ASSERT(4 == AI_MAX_NUMBER_OF_COLOR_SETS); - - // and the same nasty stuff for vertex colors ... - if (orig->mColors[0]) { - if (!CompareArrays(orig->mColors[0],inst->mColors[0],orig->mNumVertices,uvEpsilon)) - continue; - if (orig->mTextureCoords[1]) { - if (!CompareArrays(orig->mColors[1],inst->mColors[1],orig->mNumVertices,uvEpsilon)) - continue; - if (orig->mTextureCoords[2]) { - if (!CompareArrays(orig->mColors[2],inst->mColors[2],orig->mNumVertices,uvEpsilon)) - continue; - if (orig->mTextureCoords[3]) { - if (!CompareArrays(orig->mColors[3],inst->mColors[3],orig->mNumVertices,uvEpsilon)) - continue; - } - } - } - } - - // These two checks are actually quite expensive and almost *never* required. - // Almost. That's why they're still here. But there's no reason to do them - // in speed-targeted imports. - if (!configSpeedFlag) { - - // It seems to be strange, but we really need to check whether the - // bones are identical too. Although it's extremely unprobable - // that they're not if control reaches here, we need to deal - // with unprobable cases, too. It could still be that there are - // equal shapes which are deformed differently. - if (!CompareBones(orig,inst)) - continue; - - // For completeness ... compare even the index buffers for equality - // face order & winding order doesn't care. Input data is in verbose format. - boost::scoped_array<unsigned int> ftbl_orig(new unsigned int[orig->mNumVertices]); - boost::scoped_array<unsigned int> ftbl_inst(new unsigned int[orig->mNumVertices]); - - for (unsigned int tt = 0; tt < orig->mNumFaces;++tt) { - aiFace& f = orig->mFaces[tt]; - for (unsigned int nn = 0; nn < f.mNumIndices;++nn) - ftbl_orig[f.mIndices[nn]] = tt; - - aiFace& f2 = inst->mFaces[tt]; - for (unsigned int nn = 0; nn < f2.mNumIndices;++nn) - ftbl_inst[f2.mIndices[nn]] = tt; - } - if (0 != ::memcmp(ftbl_inst.get(),ftbl_orig.get(),orig->mNumVertices*sizeof(unsigned int))) - continue; - } - - // We're still here. Or in other words: 'inst' is an instance of 'orig'. - // Place a marker in our list that we can easily update mesh indices. - remapping[i] = remapping[a]; - - // Delete the instanced mesh, we don't need it anymore - delete inst; - pScene->mMeshes[i] = NULL; - break; - } - } - - // If we didn't find a match for the current mesh: keep it - if (pScene->mMeshes[i]) { - remapping[i] = numMeshesOut++; - } - } - ai_assert(0 != numMeshesOut); - if (numMeshesOut != pScene->mNumMeshes) { - - // Collapse the meshes array by removing all NULL entries - for (unsigned int real = 0, i = 0; real < numMeshesOut; ++i) { - if (pScene->mMeshes[i]) - pScene->mMeshes[real++] = pScene->mMeshes[i]; - } - - // And update the nodegraph with our nice lookup table - UpdateMeshIndices(pScene->mRootNode,remapping.get()); - - // write to log - if (!DefaultLogger::isNullLogger()) { - - char buffer[512]; - ::sprintf(buffer,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut); - DefaultLogger::get()->info(buffer); - } - pScene->mNumMeshes = numMeshesOut; - } - else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found"); - } -} diff --git a/3rdparty/assimp/code/FindInstancesProcess.h b/3rdparty/assimp/code/FindInstancesProcess.h deleted file mode 100644 index 3b329a15..00000000 --- a/3rdparty/assimp/code/FindInstancesProcess.h +++ /dev/null @@ -1,140 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 FindInstancesProcess.h - * @brief Declares the aiProcess_FindInstances post-process step - */ -#ifndef AI_FINDINSTANCES_H_INC -#define AI_FINDINSTANCES_H_INC - -#include "BaseProcess.h" -#include "ProcessHelper.h" - -class FindInstancesProcessTest; -namespace Assimp { - -// ------------------------------------------------------------------------------- -/** @brief Get a pseudo(!)-hash representing a mesh. - * - * The hash is built from number of vertices, faces, primitive types, - * .... but *not* from the real mesh data. It isn't absolutely unique. - * @param in Input mesh - * @return Hash. - */ -inline uint64_t GetMeshHash(aiMesh* in) -{ - ai_assert(NULL != in); - - // ... get an unique value representing the vertex format of the mesh - const unsigned int fhash = GetMeshVFormatUnique(in); - - // and bake it with number of vertices/faces/bones/matidx/ptypes - return ((uint64_t)fhash << 32u) | (( - (in->mNumBones << 16u) ^ (in->mNumVertices) ^ - (in->mNumFaces<<4u) ^ (in->mMaterialIndex<<15) ^ - (in->mPrimitiveTypes<<28)) & 0xffffffff ); -} - -// ------------------------------------------------------------------------------- -/** @brief Perform a component-wise comparison of two arrays - * - * @param first First array - * @param second Second aray - * @param size Size of both arrays - * @param e Epsilon - * @return true if the arrays are identical - */ -inline bool CompareArrays(const aiVector3D* first, const aiVector3D* second, - unsigned int size, float e) -{ - for (const aiVector3D* end = first+size; first != end; ++first,++second) { - if ( (*first - *second).SquareLength() >= e) - return false; - } - return true; -} - -// and the same for colors ... -inline bool CompareArrays(const aiColor4D* first, const aiColor4D* second, - unsigned int size, float e) -{ - for (const aiColor4D* end = first+size; first != end; ++first,++second) { - if ( GetColorDifference(*first,*second) >= e) - return false; - } - return true; -} - -// --------------------------------------------------------------------------- -/** @brief A post-processing steps to search for instanced meshes -*/ -class ASSIMP_API FindInstancesProcess : public BaseProcess -{ - friend class Importer; - friend class ::FindInstancesProcessTest; - -protected: - /** Constructor to be privately used by Importer */ - FindInstancesProcess(); - - /** Destructor, private as well */ - ~FindInstancesProcess(); - -public: - // ------------------------------------------------------------------- - // Check whether step is active in given flags combination - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - // Execute step on a given scene - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - // Setup properties prior to executing the process - void SetupProperties(const Importer* pImp); - -private: - - bool configSpeedFlag; - -}; // ! end class FindInstancesProcess -} // ! end namespace Assimp - -#endif // !! AI_FINDINSTANCES_H_INC diff --git a/3rdparty/assimp/code/FindInvalidDataProcess.cpp b/3rdparty/assimp/code/FindInvalidDataProcess.cpp deleted file mode 100644 index ad4ab75e..00000000 --- a/3rdparty/assimp/code/FindInvalidDataProcess.cpp +++ /dev/null @@ -1,419 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to search an importer's output - for data that is obviously invalid */ - -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS - -// internal headers -#include "FindInvalidDataProcess.h" -#include "ProcessHelper.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -FindInvalidDataProcess::FindInvalidDataProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FindInvalidDataProcess::~FindInvalidDataProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool FindInvalidDataProcess::IsActive( unsigned int pFlags) const -{ - return 0 != (pFlags & aiProcess_FindInvalidData); -} - -// ------------------------------------------------------------------------------------------------ -// Setup import configuration -void FindInvalidDataProcess::SetupProperties(const Importer* pImp) -{ - // Get the current value of AI_CONFIG_PP_FID_ANIM_ACCURACY - configEpsilon = (0 != pImp->GetPropertyFloat(AI_CONFIG_PP_FID_ANIM_ACCURACY,0.f)); -} - -// ------------------------------------------------------------------------------------------------ -// Update mesh references in the node graph -void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMapping) -{ - if (node->mNumMeshes) { - unsigned int out = 0; - for (unsigned int a = 0; a < node->mNumMeshes;++a) { - - register unsigned int ref = node->mMeshes[a]; - if (0xffffffff != (ref = meshMapping[ref])) { - node->mMeshes[out++] = ref; - } - } - // just let the members that are unused, that's much cheaper - // than a full array realloc'n'copy party ... - if (!(node->mNumMeshes = out)) { - - delete[] node->mMeshes; - node->mMeshes = NULL; - } - } - // recursively update all children - for (unsigned int i = 0; i < node->mNumChildren;++i) { - UpdateMeshReferences(node->mChildren[i],meshMapping); - } -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void FindInvalidDataProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("FindInvalidDataProcess begin"); - - bool out = false; - std::vector<unsigned int> meshMapping(pScene->mNumMeshes); - unsigned int real = 0; - - // Process meshes - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - - int result; - if ((result = ProcessMesh( pScene->mMeshes[a]))) { - out = true; - - if (2 == result) { - // remove this mesh - delete pScene->mMeshes[a]; - AI_DEBUG_INVALIDATE_PTR(pScene->mMeshes[a]); - - meshMapping[a] = 0xffffffff; - continue; - } - } - pScene->mMeshes[real] = pScene->mMeshes[a]; - meshMapping[a] = real++; - } - - // Process animations - for (unsigned int a = 0; a < pScene->mNumAnimations;++a) { - ProcessAnimation( pScene->mAnimations[a]); - } - - - if (out) { - if ( real != pScene->mNumMeshes) { - if (!real) { - throw DeadlyImportError("No meshes remaining"); - } - - // we need to remove some meshes. - // therefore we'll also need to remove all references - // to them from the scenegraph - UpdateMeshReferences(pScene->mRootNode,meshMapping); - pScene->mNumMeshes = real; - } - - DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ..."); - } - else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK."); -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -inline const char* ValidateArrayContents(const T* arr, unsigned int size, - const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) -{ - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -template <> -inline const char* ValidateArrayContents<aiVector3D>(const aiVector3D* arr, unsigned int size, - const std::vector<bool>& dirtyMask, bool mayBeIdentical , bool mayBeZero ) -{ - bool b = false; - unsigned int cnt = 0; - for (unsigned int i = 0; i < size;++i) { - - if (dirtyMask.size() && dirtyMask[i]) { - continue; - } - ++cnt; - - const aiVector3D& v = arr[i]; - if (is_special_float(v.x) || is_special_float(v.y) || is_special_float(v.z)) { - return "INF/NAN was found in a vector component"; - } - if (!mayBeZero && !v.x && !v.y && !v.z ) { - return "Found zero-length vector"; - } - if (i && v != arr[i-1])b = true; - } - if (cnt > 1 && !b && !mayBeIdentical) { - return "All vectors are identical"; - } - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -inline bool ProcessArray(T*& in, unsigned int num,const char* name, - const std::vector<bool>& dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) -{ - const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero); - if (err) { - DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err); - - delete[] in; - in = NULL; - return true; - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -AI_FORCE_INLINE bool EpsilonCompare(const T& n, const T& s, float epsilon); - -// ------------------------------------------------------------------------------------------------ -AI_FORCE_INLINE bool EpsilonCompare(float n, float s, float epsilon) { - return fabs(n-s)>epsilon; -} - -// ------------------------------------------------------------------------------------------------ -template <> -bool EpsilonCompare<aiVectorKey>(const aiVectorKey& n, const aiVectorKey& s, float epsilon) { - return - EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) && - EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) && - EpsilonCompare(n.mValue.z,s.mValue.z,epsilon); -} - -// ------------------------------------------------------------------------------------------------ -template <> -bool EpsilonCompare<aiQuatKey>(const aiQuatKey& n, const aiQuatKey& s, float epsilon) { - return - EpsilonCompare(n.mValue.x,s.mValue.x,epsilon) && - EpsilonCompare(n.mValue.y,s.mValue.y,epsilon) && - EpsilonCompare(n.mValue.z,s.mValue.z,epsilon) && - EpsilonCompare(n.mValue.w,s.mValue.w,epsilon); -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -inline bool AllIdentical(T* in, unsigned int num, float epsilon) -{ - if (num <= 1) { - return true; - } - - if (epsilon > 0.f) { - for (unsigned int i = 0; i < num-1;++i) { - - if (!EpsilonCompare(in[i],in[i+1],epsilon)) { - return false; - } - } - } - else { - for (unsigned int i = 0; i < num-1;++i) { - - if (in[i] != in[i+1]) { - return false; - } - } - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Search an animation for invalid content -void FindInvalidDataProcess::ProcessAnimation (aiAnimation* anim) -{ - // Process all animation channels - for (unsigned int a = 0; a < anim->mNumChannels;++a) { - ProcessAnimationChannel( anim->mChannels[a]); - } -} - -// ------------------------------------------------------------------------------------------------ -void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim) -{ - int i = 0; - - // ScenePreprocessor's work ... - ai_assert((0 != anim->mPositionKeys && 0 != anim->mRotationKeys && 0 != anim->mScalingKeys)); - - // Check whether all values in a tracks are identical - in this case - // we can remove al keys except one. - // POSITIONS - if (anim->mNumPositionKeys > 1 && AllIdentical(anim->mPositionKeys,anim->mNumPositionKeys,configEpsilon)) - { - aiVectorKey v = anim->mPositionKeys[0]; - - // Reallocate ... we need just ONE element, it makes no sense to reuse the array - delete[] anim->mPositionKeys; - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys = 1]; - anim->mPositionKeys[0] = v; - i = 1; - } - - // ROTATIONS - if (anim->mNumRotationKeys > 1 && AllIdentical(anim->mRotationKeys,anim->mNumRotationKeys,configEpsilon)) - { - aiQuatKey v = anim->mRotationKeys[0]; - - // Reallocate ... we need just ONE element, it makes no sense to reuse the array - delete[] anim->mRotationKeys; - anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys = 1]; - anim->mRotationKeys[0] = v; - i = 1; - } - - // SCALINGS - if (anim->mNumScalingKeys > 1 && AllIdentical(anim->mScalingKeys,anim->mNumScalingKeys,configEpsilon)) - { - aiVectorKey v = anim->mScalingKeys[0]; - - // Reallocate ... we need just ONE element, it makes no sense to reuse the array - delete[] anim->mScalingKeys; - anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys = 1]; - anim->mScalingKeys[0] = v; - i = 1; - } - if (1 == i) - DefaultLogger::get()->warn("Simplified dummy tracks with just one key"); -} - -// ------------------------------------------------------------------------------------------------ -// Search a mesh for invalid contents -int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh) -{ - bool ret = false; - std::vector<bool> dirtyMask(pMesh->mNumVertices,(pMesh->mNumFaces ? true : false)); - - // Ignore elements that are not referenced by vertices. - // (they are, for example, caused by the FindDegenerates step) - for (unsigned int m = 0; m < pMesh->mNumFaces;++m) { - const aiFace& f = pMesh->mFaces[m]; - - for (unsigned int i = 0; i < f.mNumIndices;++i) { - dirtyMask[f.mIndices[i]] = false; - } - } - - // Process vertex positions - if (pMesh->mVertices && ProcessArray(pMesh->mVertices,pMesh->mNumVertices,"positions",dirtyMask)) { - DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions"); - return 2; - } - - // process texture coordinates - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS && pMesh->mTextureCoords[i];++i) { - if (ProcessArray(pMesh->mTextureCoords[i],pMesh->mNumVertices,"uvcoords",dirtyMask)) { - - // delete all subsequent texture coordinate sets. - for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { - delete[] pMesh->mTextureCoords[a]; pMesh->mTextureCoords[a] = NULL; - } - ret = true; - } - } - - // -- we don't validate vertex colors, it's difficult to say whether - // they are invalid or not. - - // Normals and tangents are undefined for point and line faces. - if (pMesh->mNormals || pMesh->mTangents) { - - if (aiPrimitiveType_POINT & pMesh->mPrimitiveTypes || - aiPrimitiveType_LINE & pMesh->mPrimitiveTypes) - { - if (aiPrimitiveType_TRIANGLE & pMesh->mPrimitiveTypes || - aiPrimitiveType_POLYGON & pMesh->mPrimitiveTypes) - { - // We need to update the lookup-table - for (unsigned int m = 0; m < pMesh->mNumFaces;++m) - { - const aiFace& f = pMesh->mFaces[m]; - - if (f.mNumIndices < 3) { - dirtyMask[f.mIndices[0]] = true; - - if (f.mNumIndices == 2) { - dirtyMask[f.mIndices[1]] = true; - } - } - } - } - // Normals, tangents and bitangents are undefined for - // the whole mesh (and should not even be there) - else return ret; - } - - // Process mesh normals - if (pMesh->mNormals && ProcessArray(pMesh->mNormals,pMesh->mNumVertices, - "normals",dirtyMask,true,false)) - ret = true; - - // Process mesh tangents - if (pMesh->mTangents && ProcessArray(pMesh->mTangents,pMesh->mNumVertices,"tangents",dirtyMask)) { - delete[] pMesh->mBitangents; pMesh->mBitangents = NULL; - ret = true; - } - - // Process mesh bitangents - if (pMesh->mBitangents && ProcessArray(pMesh->mBitangents,pMesh->mNumVertices,"bitangents",dirtyMask)) { - delete[] pMesh->mTangents; pMesh->mTangents = NULL; - ret = true; - } - } - return ret ? 1 : 0; -} - - -#endif // !! ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS diff --git a/3rdparty/assimp/code/FindInvalidDataProcess.h b/3rdparty/assimp/code/FindInvalidDataProcess.h deleted file mode 100644 index 0cdf1587..00000000 --- a/3rdparty/assimp/code/FindInvalidDataProcess.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to search an importer's output - for data that is obviously invalid */ -#ifndef AI_FINDINVALIDDATA_H_INC -#define AI_FINDINVALIDDATA_H_INC - -#include "BaseProcess.h" -#include "../include/aiTypes.h" - -struct aiMesh; -class FindInvalidDataProcessTest; -namespace Assimp { - -// --------------------------------------------------------------------------- -/** The FindInvalidData postprocessing step. It searches the mesh data - * for parts that are obviously invalid and removes them. - * - * Originally this was a workaround for some models written by Blender - * which have zero normal vectors. */ -class ASSIMP_API FindInvalidDataProcess - : public BaseProcess -{ - friend class Importer; - friend class ::FindInvalidDataProcessTest; - -protected: - - /** Constructor to be privately used by Importer */ - FindInvalidDataProcess(); - - /** Destructor, private as well */ - ~FindInvalidDataProcess(); - -public: - - // ------------------------------------------------------------------- - // - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - // Setup import settings - void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - // Run the step - void Execute( aiScene* pScene); - -protected: - - // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given mesh - * @param pMesh The mesh to process. - * @return 0 - nothing, 1 - removed sth, 2 - please delete me */ - int ProcessMesh( aiMesh* pMesh); - - // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given animation - * @param anim The animation to process. */ - void ProcessAnimation (aiAnimation* anim); - - // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given anim channel - * @param anim The animation channel to process.*/ - void ProcessAnimationChannel (aiNodeAnim* anim); - -private: - float configEpsilon; -}; - -} // end of namespace Assimp - -#endif // AI_AI_FINDINVALIDDATA_H_INC diff --git a/3rdparty/assimp/code/FixNormalsStep.cpp b/3rdparty/assimp/code/FixNormalsStep.cpp deleted file mode 100644 index fd10f4d1..00000000 --- a/3rdparty/assimp/code/FixNormalsStep.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to invert - * all normals in meshes with infacing normals. - */ - -#include "AssimpPCH.h" - -// internal headers -#include "FixNormalsStep.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -FixInfacingNormalsProcess::FixInfacingNormalsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -FixInfacingNormalsProcess::~FixInfacingNormalsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_FixInfacingNormals) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void FixInfacingNormalsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("FixInfacingNormalsProcess begin"); - - bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - if (ProcessMesh( pScene->mMeshes[a],a))bHas = true; - - if (bHas) - DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues."); - else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene."); -} - -// ------------------------------------------------------------------------------------------------ -// Apply the step to the mesh -bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index) -{ - ai_assert(NULL != pcMesh); - - // Nothing to do if there are no model normals - if (!pcMesh->HasNormals())return false; - - // Compute the bounding box of both the model vertices + normals and - // the umodified model vertices. Then check whether the first BB - // is smaller than the second. In this case we can assume that the - // normals need to be flipped, although there are a few special cases .. - // convex, concave, planar models ... - - aiVector3D vMin0 (1e10f,1e10f,1e10f); - aiVector3D vMin1 (1e10f,1e10f,1e10f); - aiVector3D vMax0 (-1e10f,-1e10f,-1e10f); - aiVector3D vMax1 (-1e10f,-1e10f,-1e10f); - - for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) - { - vMin1.x = std::min(vMin1.x,pcMesh->mVertices[i].x); - vMin1.y = std::min(vMin1.y,pcMesh->mVertices[i].y); - vMin1.z = std::min(vMin1.z,pcMesh->mVertices[i].z); - - vMax1.x = std::max(vMax1.x,pcMesh->mVertices[i].x); - vMax1.y = std::max(vMax1.y,pcMesh->mVertices[i].y); - vMax1.z = std::max(vMax1.z,pcMesh->mVertices[i].z); - - const aiVector3D vWithNormal = pcMesh->mVertices[i] + pcMesh->mNormals[i]; - - vMin0.x = std::min(vMin0.x,vWithNormal.x); - vMin0.y = std::min(vMin0.y,vWithNormal.y); - vMin0.z = std::min(vMin0.z,vWithNormal.z); - - vMax0.x = std::max(vMax0.x,vWithNormal.x); - vMax0.y = std::max(vMax0.y,vWithNormal.y); - vMax0.z = std::max(vMax0.z,vWithNormal.z); - } - - const float fDelta0_x = (vMax0.x - vMin0.x); - const float fDelta0_y = (vMax0.y - vMin0.y); - const float fDelta0_z = (vMax0.z - vMin0.z); - - const float fDelta1_x = (vMax1.x - vMin1.x); - const float fDelta1_y = (vMax1.y - vMin1.y); - const float fDelta1_z = (vMax1.z - vMin1.z); - - // Check whether the boxes are overlapping - if ((fDelta0_x > 0.0f) != (fDelta1_x > 0.0f))return false; - if ((fDelta0_y > 0.0f) != (fDelta1_y > 0.0f))return false; - if ((fDelta0_z > 0.0f) != (fDelta1_z > 0.0f))return false; - - // Check whether this is a planar surface - const float fDelta1_yz = fDelta1_y * fDelta1_z; - - if (fDelta1_x < 0.05f * sqrtf( fDelta1_yz ))return false; - if (fDelta1_y < 0.05f * sqrtf( fDelta1_z * fDelta1_x ))return false; - if (fDelta1_z < 0.05f * sqrtf( fDelta1_y * fDelta1_x ))return false; - - // now compare the volumes of the bounding boxes - if (::fabsf(fDelta0_x * fDelta1_yz) < - ::fabsf(fDelta1_x * fDelta1_y * fDelta1_z)) - { - if (!DefaultLogger::isNullLogger()) - { - char buffer[128]; // should be sufficiently large - ::sprintf(buffer,"Mesh %i: Normals are facing inwards (or the mesh is planar)",index); - DefaultLogger::get()->info(buffer); - } - - // Invert normals - for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) - pcMesh->mNormals[i] *= -1.0f; - - // ... and flip faces - for (unsigned int i = 0; i < pcMesh->mNumFaces;++i) - { - aiFace& face = pcMesh->mFaces[i]; - for ( unsigned int b = 0; b < face.mNumIndices / 2; b++) - std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]); - } - return true; - } - return false; -} diff --git a/3rdparty/assimp/code/FixNormalsStep.h b/3rdparty/assimp/code/FixNormalsStep.h deleted file mode 100644 index 972001e8..00000000 --- a/3rdparty/assimp/code/FixNormalsStep.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to fix infacing normals */ -#ifndef AI_FIXNORMALSPROCESS_H_INC -#define AI_FIXNORMALSPROCESS_H_INC - -#include "BaseProcess.h" - -struct aiMesh; - -namespace Assimp -{ - -// --------------------------------------------------------------------------- -/** The FixInfacingNormalsProcess tries to deteermine whether the normal - * vectors of an object are facing inwards. In this case they will be - * flipped. - */ - class ASSIMP_API FixInfacingNormalsProcess : public BaseProcess -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - FixInfacingNormalsProcess(); - - /** Destructor, private as well */ - ~FixInfacingNormalsProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - -protected: - - // ------------------------------------------------------------------- - /** Executes the step on the given mesh - * @param pMesh The mesh to process. - */ - bool ProcessMesh( aiMesh* pMesh, unsigned int index); -}; - -} // end of namespace Assimp - -#endif // AI_FIXNORMALSPROCESS_H_INC diff --git a/3rdparty/assimp/code/GenFaceNormalsProcess.cpp b/3rdparty/assimp/code/GenFaceNormalsProcess.cpp deleted file mode 100644 index f4baca6a..00000000 --- a/3rdparty/assimp/code/GenFaceNormalsProcess.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to generate face -* normals for all imported faces. -*/ - -#include "AssimpPCH.h" -#include "GenFaceNormalsProcess.h" - - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -GenFaceNormalsProcess::GenFaceNormalsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -GenFaceNormalsProcess::~GenFaceNormalsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_GenNormals) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void GenFaceNormalsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("GenFaceNormalsProcess begin"); - - if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { - throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); - } - - bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - if (this->GenMeshFaceNormals( pScene->mMeshes[a])) { - bHas = true; - } - } - if (bHas) { - DefaultLogger::get()->info("GenFaceNormalsProcess finished. " - "Face normals have been calculated"); - } - else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. " - "Normals are already there"); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh) -{ - if (NULL != pMesh->mNormals) { - return false; - } - - // If the mesh consists of lines and/or points but not of - // triangles or higher-order polygons the normal vectors - // are undefined. - if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) { - DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes"); - return false; - } - - // allocate an array to hold the output normals - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - const float qnan = get_qnan(); - - // iterate through all faces and compute per-face normals but store them per-vertex. - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) { - const aiFace& face = pMesh->mFaces[a]; - if (face.mNumIndices < 3) { - // either a point or a line -> no well-defined normal vector - for (unsigned int i = 0;i < face.mNumIndices;++i) { - pMesh->mNormals[face.mIndices[i]] = qnan; - } - continue; - } - - const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; - const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; - const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; - aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); - - for (unsigned int i = 0;i < face.mNumIndices;++i) { - pMesh->mNormals[face.mIndices[i]] = vNor; - } - } - return true; -} diff --git a/3rdparty/assimp/code/GenFaceNormalsProcess.h b/3rdparty/assimp/code/GenFaceNormalsProcess.h deleted file mode 100644 index 87ca6f22..00000000 --- a/3rdparty/assimp/code/GenFaceNormalsProcess.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to compute face normals for all loaded faces*/ -#ifndef AI_GENFACENORMALPROCESS_H_INC -#define AI_GENFACENORMALPROCESS_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -namespace Assimp -{ - -// --------------------------------------------------------------------------- -/** The GenFaceNormalsProcess computes face normals for all faces of all meshes -*/ -class ASSIMP_API GenFaceNormalsProcess : public BaseProcess -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - GenFaceNormalsProcess(); - - /** Destructor, private as well */ - ~GenFaceNormalsProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - -private: - bool GenMeshFaceNormals (aiMesh* pcMesh); -}; - -} // end of namespace Assimp - -#endif // !!AI_GENFACENORMALPROCESS_H_INC diff --git a/3rdparty/assimp/code/GenVertexNormalsProcess.cpp b/3rdparty/assimp/code/GenVertexNormalsProcess.cpp deleted file mode 100644 index e8be8709..00000000 --- a/3rdparty/assimp/code/GenVertexNormalsProcess.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to generate face -* normals for all imported faces. -*/ - -#include "AssimpPCH.h" - -// internal headers -#include "GenVertexNormalsProcess.h" -#include "ProcessHelper.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -GenVertexNormalsProcess::GenVertexNormalsProcess() -{ - this->configMaxAngle = AI_DEG_TO_RAD(175.f); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -GenVertexNormalsProcess::~GenVertexNormalsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_GenSmoothNormals) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void GenVertexNormalsProcess::SetupProperties(const Importer* pImp) -{ - // Get the current value of the AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE property - configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_GSN_MAX_SMOOTHING_ANGLE,175.f); - configMaxAngle = AI_DEG_TO_RAD(std::max(std::min(configMaxAngle,175.0f),0.0f)); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void GenVertexNormalsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("GenVertexNormalsProcess begin"); - - if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) - throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here"); - - bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { - if (GenMeshVertexNormals( pScene->mMeshes[a],a)) - bHas = true; - } - - if (bHas) { - DefaultLogger::get()->info("GenVertexNormalsProcess finished. " - "Vertex normals have been calculated"); - } - else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. " - "Normals are already there"); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex) -{ - if (NULL != pMesh->mNormals) - return false; - - // If the mesh consists of lines and/or points but not of - // triangles or higher-order polygons the normal vectors - // are undefined. - if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON))) - { - DefaultLogger::get()->info("Normal vectors are undefined for line and point meshes"); - return false; - } - - // Allocate the array to hold the output normals - const float qnan = std::numeric_limits<float>::quiet_NaN(); - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - - // Compute per-face normals but store them per-vertex - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - const aiFace& face = pMesh->mFaces[a]; - if (face.mNumIndices < 3) - { - // either a point or a line -> no normal vector - for (unsigned int i = 0;i < face.mNumIndices;++i) - pMesh->mNormals[face.mIndices[i]] = qnan; - continue; - } - - aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]]; - aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]]; - aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]]; - aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize(); - - for (unsigned int i = 0;i < face.mNumIndices;++i) - pMesh->mNormals[face.mIndices[i]] = vNor; - } - - // Set up a SpatialSort to quickly find all vertices close to a given position - // check whether we can reuse the SpatialSort of a previous step. - SpatialSort* vertexFinder = NULL; - SpatialSort _vertexFinder; - float posEpsilon = 1e-5f; - if (shared) { - std::vector<std::pair<SpatialSort,float> >* avf; - shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); - if (avf) - { - std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex); - vertexFinder = &blubb.first; - posEpsilon = blubb.second; - } - } - if (!vertexFinder) { - _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); - vertexFinder = &_vertexFinder; - posEpsilon = ComputePositionEpsilon(pMesh); - } - std::vector<unsigned int> verticesFound; - aiVector3D* pcNew = new aiVector3D[pMesh->mNumVertices]; - - if (configMaxAngle >= AI_DEG_TO_RAD( 175.f )) { - // There is no angle limit. Thus all vertices with positions close - // to each other will receive the same vertex normal. This allows us - // to optimize the whole algorithm a little bit ... - std::vector<bool> abHad(pMesh->mNumVertices,false); - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { - if (abHad[i])continue; - - // Get all vertices that share this one ... - vertexFinder->FindPositions( pMesh->mVertices[i], posEpsilon, verticesFound); - - aiVector3D pcNor; - for (unsigned int a = 0; a < verticesFound.size(); ++a) { - const aiVector3D& v = pMesh->mNormals[verticesFound[a]]; - if (is_not_qnan(v.x))pcNor += v; - } - pcNor.Normalize(); - - // Write the smoothed normal back to all affected normals - for (unsigned int a = 0; a < verticesFound.size(); ++a) - { - register unsigned int vidx = verticesFound[a]; - pcNew[vidx] = pcNor; - abHad[vidx] = true; - } - } - } - // Slower code path if a smooth angle is set. There are many ways to achieve - // the effect, this one is the most straightforward one. - else { - const float fLimit = ::cos(configMaxAngle); - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { - // Get all vertices that share this one ... - vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound); - - aiVector3D pcNor; - for (unsigned int a = 0; a < verticesFound.size(); ++a) { - const aiVector3D& v = pMesh->mNormals[verticesFound[a]]; - - // check whether the angle between the two normals is not too large - // HACK: if v.x is qnan the dot product will become qnan, too - // therefore the comparison against fLimit should be false - // in every case. - if (v * pMesh->mNormals[i] < fLimit) - continue; - - pcNor += v; - } - pcNew[i] = pcNor.Normalize(); - } - } - - delete[] pMesh->mNormals; - pMesh->mNormals = pcNew; - - return true; -} diff --git a/3rdparty/assimp/code/GenVertexNormalsProcess.h b/3rdparty/assimp/code/GenVertexNormalsProcess.h deleted file mode 100644 index 294cb7ef..00000000 --- a/3rdparty/assimp/code/GenVertexNormalsProcess.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to compute vertex normals - for all loaded vertizes */ -#ifndef AI_GENVERTEXNORMALPROCESS_H_INC -#define AI_GENVERTEXNORMALPROCESS_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class GenNormalsTest; - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** The GenFaceNormalsProcess computes vertex normals for all vertizes -*/ -class ASSIMP_API GenVertexNormalsProcess : public BaseProcess -{ - friend class Importer; - friend class ::GenNormalsTest; - -protected: - /** Constructor to be privately used by Importer */ - GenVertexNormalsProcess(); - - /** Destructor, private as well */ - ~GenVertexNormalsProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. - * @param pFlags The processing flags the importer was called with. - * A bitwise combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, - * false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - - // setter for configMaxAngle - inline void SetMaxSmoothAngle(float f) - { - configMaxAngle =f; - } - -protected: - - // ------------------------------------------------------------------- - /** Computes normals for a specific mesh - * @param pcMesh Mesh - * @param meshIndex Index of the mesh - * @return true if vertex normals have been computed - */ - bool GenMeshVertexNormals (aiMesh* pcMesh, unsigned int meshIndex); - -private: - - /** Configuration option: maximum smoothing angle, in radians*/ - float configMaxAngle; -}; - -} // end of namespace Assimp - -#endif // !!AI_GENVERTEXNORMALPROCESS_H_INC - diff --git a/3rdparty/assimp/code/GenericProperty.h b/3rdparty/assimp/code/GenericProperty.h deleted file mode 100644 index ccc504a6..00000000 --- a/3rdparty/assimp/code/GenericProperty.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef AI_GENERIC_PROPERTY_H_INCLUDED -#define AI_GENERIC_PROPERTY_H_INCLUDED - -#include "./../include/assimp.hpp" -#include "Hash.h" - -// ------------------------------------------------------------------------------------------------ -template <class T> -inline void SetGenericProperty(std::map< unsigned int, T >& list, - const char* szName, const T& value, bool* bWasExisting = NULL) -{ - ai_assert(NULL != szName); - const uint32_t hash = SuperFastHash(szName); - - typename std::map<unsigned int, T>::iterator it = list.find(hash); - if (it == list.end()) { - if (bWasExisting) - *bWasExisting = false; - list.insert(std::pair<unsigned int, T>( hash, value )); - return; - } - (*it).second = value; - if (bWasExisting) - *bWasExisting = true; -} - -// ------------------------------------------------------------------------------------------------ -template <class T> -inline const T& GetGenericProperty(const std::map< unsigned int, T >& list, - const char* szName, const T& errorReturn) -{ - ai_assert(NULL != szName); - const uint32_t hash = SuperFastHash(szName); - - typename std::map<unsigned int, T>::const_iterator it = list.find(hash); - if (it == list.end()) - return errorReturn; - - return (*it).second; -} - -// ------------------------------------------------------------------------------------------------ -// Special version for pointer types - they will be deleted when replaced with another value -// passing NULL removes the whole property -template <class T> -inline void SetGenericPropertyPtr(std::map< unsigned int, T* >& list, - const char* szName, T* value, bool* bWasExisting = NULL) -{ - ai_assert(NULL != szName); - const uint32_t hash = SuperFastHash(szName); - - typename std::map<unsigned int, T*>::iterator it = list.find(hash); - if (it == list.end()) { - if (bWasExisting) - *bWasExisting = false; - - list.insert(std::pair<unsigned int,T*>( hash, value )); - return; - } - if ((*it).second != value) { - delete (*it).second; - (*it).second = value; - } - if (!value) { - list.erase(it); - } - if (bWasExisting) - *bWasExisting = true; -} - - -#endif // !! AI_GENERIC_PROPERTY_H_INCLUDED diff --git a/3rdparty/assimp/code/HMPFileData.h b/3rdparty/assimp/code/HMPFileData.h deleted file mode 100644 index 2d372a06..00000000 --- a/3rdparty/assimp/code/HMPFileData.h +++ /dev/null @@ -1,134 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Data structures for the 3D Game Studio Heightmap format (HMP) -//! - -namespace Assimp { -namespace HMP { - -#include "./../include/Compiler/pushpack1.h" - -// to make it easier for us, we test the magic word against both "endianesses" -#define AI_HMP_MAGIC_NUMBER_BE_4 AI_MAKE_MAGIC("HMP4") -#define AI_HMP_MAGIC_NUMBER_LE_4 AI_MAKE_MAGIC("4PMH") - -#define AI_HMP_MAGIC_NUMBER_BE_5 AI_MAKE_MAGIC("HMP5") -#define AI_HMP_MAGIC_NUMBER_LE_5 AI_MAKE_MAGIC("5PMH") - -#define AI_HMP_MAGIC_NUMBER_BE_7 AI_MAKE_MAGIC("HMP7") -#define AI_HMP_MAGIC_NUMBER_LE_7 AI_MAKE_MAGIC("7PMH") - -// --------------------------------------------------------------------------- -/** Data structure for the header of a HMP5 file. - * This is also used by HMP4 and HMP7, but with modifications -*/ -struct Header_HMP5 -{ - int8_t ident[4]; // "HMP5" - int32_t version; - - // ignored - float scale[3]; - float scale_origin[3]; - float boundingradius; - - //! Size of one triangle in x direction - float ftrisize_x; - //! Size of one triangle in y direction - float ftrisize_y; - //! Number of vertices in x direction - float fnumverts_x; - - //! Number of skins in the file - int32_t numskins; - - // can ignore this? - int32_t skinwidth; - int32_t skinheight; - - //!Number of vertices in the file - int32_t numverts; - - // ignored and zero - int32_t numtris; - - //! only one supported ... - int32_t numframes; - - //! Always 0 ... - int32_t num_stverts; - int32_t flags; - float size; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** Data structure for a terrain vertex in a HMP4 file -*/ -struct Vertex_HMP4 -{ - uint16_t p_pos[3]; - uint8_t normals162index; - uint8_t pad; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** Data structure for a terrain vertex in a HMP5 file -*/ -struct Vertex_HMP5 -{ - uint16_t z; - uint8_t normals162index; - uint8_t pad; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** Data structure for a terrain vertex in a HMP7 file -*/ -struct Vertex_HMP7 -{ - uint16_t z; - int8_t normal_x,normal_y; -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - -} //! namespace HMP -} //! namespace Assimp diff --git a/3rdparty/assimp/code/HMPLoader.cpp b/3rdparty/assimp/code/HMPLoader.cpp deleted file mode 100644 index dc4dea15..00000000 --- a/3rdparty/assimp/code/HMPLoader.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MDL importer class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER - -// internal headers -#include "MaterialSystem.h" -#include "HMPLoader.h" -#include "MD2FileData.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -HMPImporter::HMPImporter() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -HMPImporter::~HMPImporter() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "hmp" ) - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || cs) { - uint32_t tokens[3]; - tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4; - tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5; - tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7; - return CheckMagicToken(pIOHandler,pFile,tokens,3,0); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get list of all file extensions that are handled by this loader -void HMPImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("hmp"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void HMPImporter::InternReadFile( const std::string& pFile, - aiScene* _pScene, IOSystem* _pIOHandler) -{ - pScene = _pScene; - pIOHandler = _pIOHandler; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open HMP file " + pFile + "."); - - // Check whether the HMP file is large enough to contain - // at least the file header - const size_t fileSize = file->FileSize(); - if ( fileSize < 50) - throw DeadlyImportError( "HMP File is too small."); - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector<uint8_t> buffer(fileSize); - mBuffer = &buffer[0]; - file->Read( (void*)mBuffer, 1, fileSize); - iFileSize = (unsigned int)fileSize; - - // Determine the file subtype and call the appropriate member function - const uint32_t iMagic = *((uint32_t*)this->mBuffer); - - // HMP4 format - if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic || - AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) - { - DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4"); - InternReadFile_HMP4(); - } - // HMP5 format - else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic || - AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) - { - DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5"); - InternReadFile_HMP5(); - } - // HMP7 format - else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic || - AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) - { - DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7"); - InternReadFile_HMP7(); - } - else - { - // Print the magic word to the logger - char szBuffer[5]; - szBuffer[0] = ((char*)&iMagic)[0]; - szBuffer[1] = ((char*)&iMagic)[1]; - szBuffer[2] = ((char*)&iMagic)[2]; - szBuffer[3] = ((char*)&iMagic)[3]; - szBuffer[4] = '\0'; - - // We're definitely unable to load this file - throw DeadlyImportError( "Unknown HMP subformat " + pFile + - ". Magic word (" + szBuffer + ") is not known"); - } - - // Set the AI_SCENE_FLAGS_TERRAIN bit - pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN; - - // File buffer destructs automatically now -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::ValidateHeader_HMP457( ) -{ - const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; - - if (120 > iFileSize) - { - throw DeadlyImportError("HMP file is too small (header size is " - "120 bytes, this file is smaller)"); - } - - if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y) - throw DeadlyImportError("Size of triangles in either x or y direction is zero"); - - if (pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f) - throw DeadlyImportError("Number of triangles in either x or y direction is zero"); - - if (!pcHeader->numframes) - throw DeadlyImportError("There are no frames. At least one should be there"); - -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::InternReadFile_HMP4( ) -{ - throw DeadlyImportError("HMP4 is currently not supported"); -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::InternReadFile_HMP5( ) -{ - // read the file header and skip everything to byte 84 - const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer; - const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84); - ValidateHeader_HMP457(); - - // generate an output mesh - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); - - pcMesh->mMaterialIndex = 0; - pcMesh->mVertices = new aiVector3D[pcHeader->numverts]; - pcMesh->mNormals = new aiVector3D[pcHeader->numverts]; - - const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x); - const unsigned int width = (unsigned int)pcHeader->fnumverts_x; - - // generate/load a material for the terrain - CreateMaterial(szCurrent,&szCurrent); - - // goto offset 120, I don't know why ... - // (fixme) is this the frame header? I assume yes since it starts with 2. - szCurrent += 36; - SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width); - - // now load all vertices from the file - aiVector3D* pcVertOut = pcMesh->mVertices; - aiVector3D* pcNorOut = pcMesh->mNormals; - const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent; - for (unsigned int y = 0; y < height;++y) - { - for (unsigned int x = 0; x < width;++x) - { - pcVertOut->x = x * pcHeader->ftrisize_x; - pcVertOut->y = y * pcHeader->ftrisize_y; - pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f; - MD2::LookupNormalIndex(src->normals162index, *pcNorOut ); - ++pcVertOut;++pcNorOut;++src; - } - } - - // generate texture coordinates if necessary - if (pcHeader->numskins) - GenerateTextureCoords(width,height); - - // now build a list of faces - CreateOutputFaceList(width,height); - - // there is no nodegraph in HMP files. Simply assign the one mesh - // (no, not the one ring) to the root node - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("terrain_root"); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::InternReadFile_HMP7( ) -{ - // read the file header and skip everything to byte 84 - const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; - const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84); - ValidateHeader_HMP457(); - - // generate an output mesh - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); - - pcMesh->mMaterialIndex = 0; - pcMesh->mVertices = new aiVector3D[pcHeader->numverts]; - pcMesh->mNormals = new aiVector3D[pcHeader->numverts]; - - const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x); - const unsigned int width = (unsigned int)pcHeader->fnumverts_x; - - // generate/load a material for the terrain - CreateMaterial(szCurrent,&szCurrent); - - // goto offset 120, I don't know why ... - // (fixme) is this the frame header? I assume yes since it starts with 2. - szCurrent += 36; - - SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width); - - // now load all vertices from the file - aiVector3D* pcVertOut = pcMesh->mVertices; - aiVector3D* pcNorOut = pcMesh->mNormals; - const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent; - for (unsigned int y = 0; y < height;++y) - { - for (unsigned int x = 0; x < width;++x) - { - pcVertOut->x = x * pcHeader->ftrisize_x; - pcVertOut->y = y * pcHeader->ftrisize_y; - - // FIXME: What exctly is the correct scaling factor to use? - // possibly pcHeader->scale_origin[2] in combination with a - // signed interpretation of src->z? - pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f; - - pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0]; - pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1]; - pcNorOut->z = 1.0f; - pcNorOut->Normalize(); - - ++pcVertOut;++pcNorOut;++src; - } - } - - // generate texture coordinates if necessary - if (pcHeader->numskins)GenerateTextureCoords(width,height); - - // now build a list of faces - CreateOutputFaceList(width,height); - - // there is no nodegraph in HMP files. Simply assign the one mesh - // (no, not the One Ring) to the root node - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("terrain_root"); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::CreateMaterial(const unsigned char* szCurrent, - const unsigned char** szCurrentOut) -{ - aiMesh* const pcMesh = pScene->mMeshes[0]; - const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer; - - // we don't need to generate texture coordinates if - // we have no textures in the file ... - if (pcHeader->numskins) - { - pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts]; - pcMesh->mNumUVComponents[0] = 2; - - // now read the first skin and skip all others - ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent); - } - else - { - // generate a default material - const int iMode = (int)aiShadingMode_Gouraud; - MaterialHelper* pcHelper = new MaterialHelper(); - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor3D clr; - clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - aiString szName; - szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); - - // add the material to the scene - pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = pcHelper; - } - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height) -{ - aiMesh* const pcMesh = this->pScene->mMeshes[0]; - - // Allocate enough storage - pcMesh->mNumFaces = (width-1) * (height-1); - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - - pcMesh->mNumVertices = pcMesh->mNumFaces*4; - aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcNormals = new aiVector3D[pcMesh->mNumVertices]; - - aiFace* pcFaceOut(pcMesh->mFaces); - aiVector3D* pcVertOut = pcVertices; - aiVector3D* pcNorOut = pcNormals; - - aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL; - aiVector3D* pcUVOut(pcUVs); - - // Build the terrain square - unsigned int iCurrent = 0; - for (unsigned int y = 0; y < height-1;++y) { - for (unsigned int x = 0; x < width-1;++x,++pcFaceOut) { - pcFaceOut->mNumIndices = 4; - pcFaceOut->mIndices = new unsigned int[4]; - - *pcVertOut++ = pcMesh->mVertices[y*width+x]; - *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x]; - *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1]; - *pcVertOut++ = pcMesh->mVertices[y*width+x+1]; - - - *pcNorOut++ = pcMesh->mNormals[y*width+x]; - *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x]; - *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1]; - *pcNorOut++ = pcMesh->mNormals[y*width+x+1]; - - if (pcMesh->mTextureCoords[0]) - { - *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x]; - *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x]; - *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1]; - *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1]; - } - - for (unsigned int i = 0; i < 4;++i) - pcFaceOut->mIndices[i] = iCurrent++; - } - } - delete[] pcMesh->mVertices; - pcMesh->mVertices = pcVertices; - - delete[] pcMesh->mNormals; - pcMesh->mNormals = pcNormals; - - if (pcMesh->mTextureCoords[0]) - { - delete[] pcMesh->mTextureCoords[0]; - pcMesh->mTextureCoords[0] = pcUVs; - } -} - -// ------------------------------------------------------------------------------------------------ -void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor, - const unsigned char** szCursorOut) -{ - ai_assert(0 != iNumSkins && NULL != szCursor); - - // read the type of the skin ... - // sometimes we need to skip 12 bytes here, I don't know why ... - uint32_t iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t); - if (0 == iType) - { - szCursor += sizeof(uint32_t) * 2; - iType = *((uint32_t*)szCursor);szCursor += sizeof(uint32_t); - if (!iType) - throw DeadlyImportError("Unable to read HMP7 skin chunk"); - - } - // read width and height - uint32_t iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - - // allocate an output material - MaterialHelper* pcMat = new MaterialHelper(); - - // read the skin, this works exactly as for MDL7 - ParseSkinLump_3DGS_MDL7(szCursor,&szCursor, - pcMat,iType,iWidth,iHeight); - - // now we need to skip any other skins ... - for (unsigned int i = 1; i< iNumSkins;++i) - { - iType = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - iWidth = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t); - - SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight); - SizeCheck(szCursor); - } - - // setup the material ... - pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = pcMat; - - *szCursorOut = szCursor; -} - -// ------------------------------------------------------------------------------------------------ -// Generate proepr texture coords -void HMPImporter::GenerateTextureCoords( - const unsigned int width, const unsigned int height) -{ - ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] && - NULL != pScene->mMeshes[0]->mTextureCoords[0]); - - aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0]; - - const float fY = (1.0f / height) + (1.0f / height) / (height-1); - const float fX = (1.0f / width) + (1.0f / width) / (width-1); - - for (unsigned int y = 0; y < height;++y) { - for (unsigned int x = 0; x < width;++x,++uv) { - uv->y = fY*y; - uv->x = fX*x; - uv->z = 0.0f; - } - } -} - -#endif // !! ASSIMP_BUILD_NO_HMP_IMPORTER diff --git a/3rdparty/assimp/code/HMPLoader.h b/3rdparty/assimp/code/HMPLoader.h deleted file mode 100644 index fdf84baa..00000000 --- a/3rdparty/assimp/code/HMPLoader.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 HMPLoader.h - * @brief Declaration of the HMP importer class - */ - -#ifndef AI_HMPLOADER_H_INCLUDED -#define AI_HMPLOADER_H_INCLUDED - -// public ASSIMP headers -#include "../include/aiTypes.h" -#include "../include/aiTexture.h" -#include "../include/aiMaterial.h" - -// internal headers -#include "BaseImporter.h" -#include "MDLLoader.h" -#include "HMPFileData.h" - -namespace Assimp { -using namespace HMP; - -// --------------------------------------------------------------------------- -/** Used to load 3D GameStudio HMP files (terrains) -*/ -class HMPImporter : public MDLImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - HMPImporter(); - - /** Destructor, private as well */ - ~HMPImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - - // ------------------------------------------------------------------- - /** Import a HMP4 file - */ - void InternReadFile_HMP4( ); - - // ------------------------------------------------------------------- - /** Import a HMP5 file - */ - void InternReadFile_HMP5( ); - - // ------------------------------------------------------------------- - /** Import a HMP7 file - */ - void InternReadFile_HMP7( ); - - // ------------------------------------------------------------------- - /** Validate a HMP 5,4,7 file header - */ - void ValidateHeader_HMP457( ); - - // ------------------------------------------------------------------- - /** Try to load one material from the file, if this fails create - * a default material - */ - void CreateMaterial(const unsigned char* szCurrent, - const unsigned char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Build a list of output faces and vertices. The function - * triangulates the height map read from the file - * \param width Width of the height field - * \param width Height of the height field - */ - void CreateOutputFaceList(unsigned int width,unsigned int height); - - // ------------------------------------------------------------------- - /** Generate planar texture coordinates for a terrain - * \param width Width of the terrain, in vertices - * \param height Height of the terrain, in vertices - */ - void GenerateTextureCoords(const unsigned int width, - const unsigned int height); - - // ------------------------------------------------------------------- - /** Read the first skin from the file and skip all others ... - * \param iNumSkins Number of skins in the file - * \param szCursor Position of the first skin (offset 84) - */ - void ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor, - const unsigned char** szCursorOut); - -private: - -}; - -} // end of namespace Assimp - -#endif // AI_HMPIMPORTER_H_INC - diff --git a/3rdparty/assimp/code/HalfLifeFileData.h b/3rdparty/assimp/code/HalfLifeFileData.h deleted file mode 100644 index b12adf6a..00000000 --- a/3rdparty/assimp/code/HalfLifeFileData.h +++ /dev/null @@ -1,150 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Definition of in-memory structures for the HL2 MDL file format -// and for the HalfLife text format (SMD) -// -// The specification has been taken from various sources on the internet. - - -#ifndef AI_MDLFILEHELPER2_H_INC -#define AI_MDLFILEHELPER2_H_INC - -#include "./../include/Compiler/pushpack1.h" - -#include "MDLFileData.h" - -namespace Assimp { -namespace MDL { - -// magic bytes used in Half Life 2 MDL models -#define AI_MDL_MAGIC_NUMBER_BE_HL2a AI_MAKE_MAGIC("IDST") -#define AI_MDL_MAGIC_NUMBER_LE_HL2a AI_MAKE_MAGIC("TSDI") -#define AI_MDL_MAGIC_NUMBER_BE_HL2b AI_MAKE_MAGIC("IDSQ") -#define AI_MDL_MAGIC_NUMBER_LE_HL2b AI_MAKE_MAGIC("QSDI") - -// --------------------------------------------------------------------------- -/** \struct Header_HL2 - * \brief Data structure for the HL2 main header - */ -// --------------------------------------------------------------------------- -struct Header_HL2 -{ - //! magic number: "IDST"/"IDSQ" - char ident[4]; - - //! Version number - int32_t version; - - //! Original file name in pak ? - char name[64]; - - //! Length of file name/length of file? - int32_t length; - - //! For viewer, ignored - aiVector3D eyeposition; - aiVector3D min; - aiVector3D max; - - //! AABB of the model - aiVector3D bbmin; - aiVector3D bbmax; - - // File flags - int32_t flags; - - //! NUmber of bones contained in the file - int32_t numbones; - int32_t boneindex; - - //! Number of bone controllers for bone animation - int32_t numbonecontrollers; - int32_t bonecontrollerindex; - - //! More bounding boxes ... - int32_t numhitboxes; - int32_t hitboxindex; - - //! Animation sequences in the file - int32_t numseq; - int32_t seqindex; - - //! Loaded sequences. Ignored - int32_t numseqgroups; - int32_t seqgroupindex; - - //! Raw texture data - int32_t numtextures; - int32_t textureindex; - int32_t texturedataindex; - - //! Number of skins (=textures?) - int32_t numskinref; - int32_t numskinfamilies; - int32_t skinindex; - - //! Number of parts - int32_t numbodyparts; - int32_t bodypartindex; - - //! attachable points for gameplay and physics - int32_t numattachments; - int32_t attachmentindex; - - //! Table of sound effects associated with the model - int32_t soundtable; - int32_t soundindex; - int32_t soundgroups; - int32_t soundgroupindex; - - //! Number of animation transitions - int32_t numtransitions; - int32_t transitionindex; -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - -} -} // end namespaces - -#endif // ! AI_MDLFILEHELPER2_H_INC diff --git a/3rdparty/assimp/code/Hash.h b/3rdparty/assimp/code/Hash.h deleted file mode 100644 index 9ba79c51..00000000 --- a/3rdparty/assimp/code/Hash.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef AI_HASH_H_INCLUDED -#define AI_HASH_H_INCLUDED - -// ------------------------------------------------------------------------------------------------ -// hashing function taken from -// http://www.azillionmonkeys.com/qed/hash.html -// (incremental version of the hashing function) -// (stdint.h should have been been included here) -// ------------------------------------------------------------------------------------------------ -#undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ - || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) -#define get16bits(d) (*((const uint16_t *) (d))) -#endif - -#if !defined (get16bits) -#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ - +(uint32_t)(((const uint8_t *)(d))[0]) ) -#endif - -// ------------------------------------------------------------------------------------------------ -inline unsigned int SuperFastHash (const char * data, unsigned int len = 0, unsigned int hash = 0) { -unsigned int tmp; -int rem; - - if (!data) return 0; - if (!len)len = (unsigned int)::strlen(data); - - rem = len & 3; - len >>= 2; - - /* Main loop */ - for (;len > 0; len--) { - hash += get16bits (data); - tmp = (get16bits (data+2) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - data += 2*sizeof (uint16_t); - hash += hash >> 11; - } - - /* Handle end cases */ - switch (rem) { - case 3: hash += get16bits (data); - hash ^= hash << 16; - hash ^= data[sizeof (uint16_t)] << 18; - hash += hash >> 11; - break; - case 2: hash += get16bits (data); - hash ^= hash << 11; - hash += hash >> 17; - break; - case 1: hash += *data; - hash ^= hash << 10; - hash += hash >> 1; - } - - /* Force "avalanching" of final 127 bits */ - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 4; - hash += hash >> 17; - hash ^= hash << 25; - hash += hash >> 6; - - return hash; -} - -#endif // !! AI_HASH_H_INCLUDED diff --git a/3rdparty/assimp/code/IFF.h b/3rdparty/assimp/code/IFF.h deleted file mode 100644 index 91d56b34..00000000 --- a/3rdparty/assimp/code/IFF.h +++ /dev/null @@ -1,102 +0,0 @@ - - -// Definitions for the Interchange File Format (IFF) -// Alexander Gessler, 2006 -// Adapted to Assimp August 2008 - -#ifndef AI_IFF_H_INCLUDED -#define AI_IFF_H_INCLUDED - -#include "ByteSwap.h" - -namespace Assimp { -namespace IFF { - -#include "./../include/Compiler/pushpack1.h" - -///////////////////////////////////////////////////////////////////////////////// -//! Describes an IFF chunk header -///////////////////////////////////////////////////////////////////////////////// -struct ChunkHeader -{ - //! Type of the chunk header - FourCC - uint32_t type; - - //! Length of the chunk data, in bytes - uint32_t length; -} PACK_STRUCT; - - -///////////////////////////////////////////////////////////////////////////////// -//! Describes an IFF sub chunk header -///////////////////////////////////////////////////////////////////////////////// -struct SubChunkHeader -{ - //! Type of the chunk header - FourCC - uint32_t type; - - //! Length of the chunk data, in bytes - uint16_t length; -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - - -#define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \ - ((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d))) - - -#define AI_IFF_FOURCC_FORM AI_IFF_FOURCC('F','O','R','M') - - -///////////////////////////////////////////////////////////////////////////////// -//! Load a chunk header -//! @param outFile Pointer to the file data - points to the chunk data afterwards -//! @return Pointer to the chunk header -///////////////////////////////////////////////////////////////////////////////// -inline ChunkHeader* LoadChunk(uint8_t*& outFile) -{ - ChunkHeader* head = (ChunkHeader*) outFile; - AI_LSWAP4(head->length); - AI_LSWAP4(head->type); - outFile += sizeof(ChunkHeader); - return head; -} - -///////////////////////////////////////////////////////////////////////////////// -//! Load a sub chunk header -//! @param outFile Pointer to the file data - points to the chunk data afterwards -//! @return Pointer to the sub chunk header -///////////////////////////////////////////////////////////////////////////////// -inline SubChunkHeader* LoadSubChunk(uint8_t*& outFile) -{ - SubChunkHeader* head = (SubChunkHeader*) outFile; - AI_LSWAP2(head->length); - AI_LSWAP4(head->type); - outFile += sizeof(SubChunkHeader); - return head; -} - -///////////////////////////////////////////////////////////////////////////////// -//! Read the file header and return the type of the file and its size -//! @param outFile Pointer to the file data. The buffer must at -//! least be 12 bytes large. -//! @param fileType Receives the type of the file -//! @return 0 if everything was OK, otherwise an error message -///////////////////////////////////////////////////////////////////////////////// -inline const char* ReadHeader(uint8_t* outFile,uint32_t& fileType) -{ - ChunkHeader* head = LoadChunk(outFile); - if (AI_IFF_FOURCC_FORM != head->type) - { - return "The file is not an IFF file: FORM chunk is missing"; - } - fileType = *((uint32_t*)(head+1)); - AI_LSWAP4(fileType); - return 0; -} - - -}} - -#endif // !! AI_IFF_H_INCLUDED diff --git a/3rdparty/assimp/code/IRRLoader.cpp b/3rdparty/assimp/code/IRRLoader.cpp deleted file mode 100644 index 1498c9ee..00000000 --- a/3rdparty/assimp/code/IRRLoader.cpp +++ /dev/null @@ -1,1462 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 IRRLoader.cpp - * @brief Implementation of the Irr importer class - */ - -#include "AssimpPCH.h" - -#include "IRRLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" -#include "GenericProperty.h" - -#include "SceneCombiner.h" -#include "StandardShapes.h" - - -// We need boost::common_factor to compute the lcm/gcd of a number -#include <boost/math/common_factor_rt.hpp> - -using namespace Assimp; -using namespace irr; -using namespace irr::io; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -IRRImporter::IRRImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -IRRImporter::~IRRImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool IRRImporter::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 == "irr")return true; - else if (extension == "xml" || checkSig) - { - /* If CanRead() is called in order to check whether we - * support a specific file extension in general pIOHandler - * might be NULL and it's our duty to return true here. - */ - if (!pIOHandler)return true; - const char* tokens[] = {"irr_scene"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void IRRImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("irr"); - extensions.insert("xml"); -} - -// ------------------------------------------------------------------------------------------------ -void IRRImporter::SetupProperties(const Importer* pImp) -{ - // read the output frame rate of all node animation channels - fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100); - if (fps < 10.) { - DefaultLogger::get()->error("IRR: Invalid FPS configuration"); - fps = 100; - } - - // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Build a mesh tha consists of a single squad (a side of a skybox) -aiMesh* IRRImporter::BuildSingleQuadMesh(const SkyboxVertex& v1, - const SkyboxVertex& v2, - const SkyboxVertex& v3, - const SkyboxVertex& v4) -{ - // allocate and prepare the mesh - aiMesh* out = new aiMesh(); - - out->mPrimitiveTypes = aiPrimitiveType_POLYGON; - out->mNumFaces = 1; - - // build the face - out->mFaces = new aiFace[1]; - aiFace& face = out->mFaces[0]; - - face.mNumIndices = 4; - face.mIndices = new unsigned int[4]; - for (unsigned int i = 0; i < 4;++i) - face.mIndices[i] = i; - - out->mNumVertices = 4; - - // copy vertex positions - aiVector3D* vec = out->mVertices = new aiVector3D[4]; - *vec++ = v1.position; - *vec++ = v2.position; - *vec++ = v3.position; - *vec = v4.position; - - // copy vertex normals - vec = out->mNormals = new aiVector3D[4]; - *vec++ = v1.normal; - *vec++ = v2.normal; - *vec++ = v3.normal; - *vec = v4.normal; - - // copy texture coordinates - vec = out->mTextureCoords[0] = new aiVector3D[4]; - *vec++ = v1.uv; - *vec++ = v2.uv; - *vec++ = v3.uv; - *vec = v4.uv; - return out; -} - -// ------------------------------------------------------------------------------------------------ -void IRRImporter::BuildSkybox(std::vector<aiMesh*>& meshes, std::vector<aiMaterial*> materials) -{ - // Update the material of the skybox - replace the name and disable shading for skyboxes. - for (unsigned int i = 0; i < 6;++i) { - MaterialHelper* out = ( MaterialHelper* ) (*(materials.end()-(6-i))); - - aiString s; - s.length = ::sprintf( s.data, "SkyboxSide_%i",i ); - out->AddProperty(&s,AI_MATKEY_NAME); - - int shading = aiShadingMode_NoShading; - out->AddProperty(&shading,1,AI_MATKEY_SHADING_MODEL); - } - - // Skyboxes are much more difficult. They are represented - // by six single planes with different textures, so we'll - // need to build six meshes. - - const float l = 10.f; // the size used by Irrlicht - - // FRONT SIDE - meshes.push_back( BuildSingleQuadMesh( - SkyboxVertex(-l,-l,-l, 0, 0, 1, 1.f,1.f), - SkyboxVertex( l,-l,-l, 0, 0, 1, 0.f,1.f), - SkyboxVertex( l, l,-l, 0, 0, 1, 0.f,0.f), - SkyboxVertex(-l, l,-l, 0, 0, 1, 1.f,0.f)) ); - meshes.back()->mMaterialIndex = materials.size()-6u; - - // LEFT SIDE - meshes.push_back( BuildSingleQuadMesh( - SkyboxVertex( l,-l,-l, -1, 0, 0, 1.f,1.f), - SkyboxVertex( l,-l, l, -1, 0, 0, 0.f,1.f), - SkyboxVertex( l, l, l, -1, 0, 0, 0.f,0.f), - SkyboxVertex( l, l,-l, -1, 0, 0, 1.f,0.f)) ); - meshes.back()->mMaterialIndex = materials.size()-5u; - - // BACK SIDE - meshes.push_back( BuildSingleQuadMesh( - SkyboxVertex( l,-l, l, 0, 0, -1, 1.f,1.f), - SkyboxVertex(-l,-l, l, 0, 0, -1, 0.f,1.f), - SkyboxVertex(-l, l, l, 0, 0, -1, 0.f,0.f), - SkyboxVertex( l, l, l, 0, 0, -1, 1.f,0.f)) ); - meshes.back()->mMaterialIndex = materials.size()-4u; - - // RIGHT SIDE - meshes.push_back( BuildSingleQuadMesh( - SkyboxVertex(-l,-l, l, 1, 0, 0, 1.f,1.f), - SkyboxVertex(-l,-l,-l, 1, 0, 0, 0.f,1.f), - SkyboxVertex(-l, l,-l, 1, 0, 0, 0.f,0.f), - SkyboxVertex(-l, l, l, 1, 0, 0, 1.f,0.f)) ); - meshes.back()->mMaterialIndex = materials.size()-3u; - - // TOP SIDE - meshes.push_back( BuildSingleQuadMesh( - SkyboxVertex( l, l,-l, 0, -1, 0, 1.f,1.f), - SkyboxVertex( l, l, l, 0, -1, 0, 0.f,1.f), - SkyboxVertex(-l, l, l, 0, -1, 0, 0.f,0.f), - SkyboxVertex(-l, l,-l, 0, -1, 0, 1.f,0.f)) ); - meshes.back()->mMaterialIndex = materials.size()-2u; - - // BOTTOM SIDE - meshes.push_back( BuildSingleQuadMesh( - SkyboxVertex( l,-l, l, 0, 1, 0, 0.f,0.f), - SkyboxVertex( l,-l,-l, 0, 1, 0, 1.f,0.f), - SkyboxVertex(-l,-l,-l, 0, 1, 0, 1.f,1.f), - SkyboxVertex(-l,-l, l, 0, 1, 0, 0.f,1.f)) ); - meshes.back()->mMaterialIndex = materials.size()-1u; -} - -// ------------------------------------------------------------------------------------------------ -void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials, - std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials, - unsigned int& defMatIdx, - aiMesh* mesh) -{ - if (inmaterials.empty()) { - // Do we have a default material? If not we need to create one - if (0xffffffff == defMatIdx) - { - defMatIdx = (unsigned int)materials.size(); - MaterialHelper* mat = new MaterialHelper(); - - aiString s; - s.Set(AI_DEFAULT_MATERIAL_NAME); - mat->AddProperty(&s,AI_MATKEY_NAME); - - aiColor3D c(0.6f,0.6f,0.6f); - mat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE); - } - mesh->mMaterialIndex = defMatIdx; - return; - } - else if (inmaterials.size() > 1) { - DefaultLogger::get()->info("IRR: Skipping additional materials"); - } - - mesh->mMaterialIndex = (unsigned int)materials.size(); - materials.push_back(inmaterials[0].first); -} - - -// ------------------------------------------------------------------------------------------------ -inline int ClampSpline(int idx, int size) -{ - return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) ); -} - -// ------------------------------------------------------------------------------------------------ -inline void FindSuitableMultiple(int& angle) -{ - if (angle < 3)angle = 3; - else if (angle < 10) angle = 10; - else if (angle < 20) angle = 20; - else if (angle < 30) angle = 30; - else - { - } -} - -// ------------------------------------------------------------------------------------------------ -void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNodeAnim*>& anims) -{ - ai_assert(NULL != root && NULL != real); - - // XXX totally WIP - doesn't produce proper results, need to evaluate - // whether there's any use for Irrlicht's proprietary scene format - // outside Irrlicht ... - - if (root->animators.empty()) { - return; - } - unsigned int total = 0; - for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it) { - if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER) { - DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator"); - continue; - } - ++total; - } - if (!total)return; - else if (1 == total) { - DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators"); - } - - // NOTE: 1 tick == i millisecond - - unsigned int cur = 0; - for (std::list<Animator>::iterator it = root->animators.begin(); - it != root->animators.end(); ++it) - { - if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)continue; - - Animator& in = *it ; - aiNodeAnim* anim = new aiNodeAnim(); - - if (cur != total-1) { - // Build a new name - a prefix instead of a suffix because it is - // easier to check against - anim->mNodeName.length = ::sprintf(anim->mNodeName.data, - "$INST_DUMMY_%i_%s",total-1, - (root->name.length() ? root->name.c_str() : "")); - - // we'll also need to insert a dummy in the node hierarchy. - aiNode* dummy = new aiNode(); - - for (unsigned int i = 0; i < real->mParent->mNumChildren;++i) - if (real->mParent->mChildren[i] == real) - real->mParent->mChildren[i] = dummy; - - dummy->mParent = real->mParent; - dummy->mName = anim->mNodeName; - - dummy->mNumChildren = 1; - dummy->mChildren = new aiNode*[dummy->mNumChildren]; - dummy->mChildren[0] = real; - - // the transformation matrix of the dummy node is the identity - - real->mParent = dummy; - } - else anim->mNodeName.Set(root->name); - ++cur; - - switch (in.type) { - case Animator::ROTATION: - { - // ----------------------------------------------------- - // find out how long a full rotation will take - // This is the least common multiple of 360.f and all - // three euler angles. Although we'll surely find a - // possible multiple (haha) it could be somewhat large - // for our purposes. So we need to modify the angles - // here in order to get good results. - // ----------------------------------------------------- - int angles[3]; - angles[0] = (int)(in.direction.x*100); - angles[1] = (int)(in.direction.y*100); - angles[2] = (int)(in.direction.z*100); - - angles[0] %= 360; - angles[1] %= 360; - angles[2] %= 360; - - if ((angles[0]*angles[1]) && (angles[1]*angles[2])) - { - FindSuitableMultiple(angles[0]); - FindSuitableMultiple(angles[1]); - FindSuitableMultiple(angles[2]); - } - - int lcm = 360; - - if (angles[0]) - lcm = boost::math::lcm(lcm,angles[0]); - - if (angles[1]) - lcm = boost::math::lcm(lcm,angles[1]); - - if (angles[2]) - lcm = boost::math::lcm(lcm,angles[2]); - - if (360 == lcm) - break; - -#if 0 - // This can be a division through zero, but we don't care - float f1 = (float)lcm / angles[0]; - float f2 = (float)lcm / angles[1]; - float f3 = (float)lcm / angles[2]; -#endif - - // find out how many time units we'll need for the finest - // track (in seconds) - this defines the number of output - // keys (fps * seconds) - float max = 0.f; - if (angles[0]) - max = (float)lcm / angles[0]; - if (angles[1]) - max = std::max(max, (float)lcm / angles[1]); - if (angles[2]) - max = std::max(max, (float)lcm / angles[2]); - - anim->mNumRotationKeys = (unsigned int)(max*fps); - anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys]; - - // begin with a zero angle - aiVector3D angle; - for (unsigned int i = 0; i < anim->mNumRotationKeys;++i) - { - // build the quaternion for the given euler angles - aiQuatKey& q = anim->mRotationKeys[i]; - - q.mValue = aiQuaternion(angle.x, angle.y, angle.z); - q.mTime = (double)i; - - // increase the angle - angle += in.direction; - } - - // This animation is repeated and repeated ... - anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; - } - break; - - case Animator::FLY_CIRCLE: - { - // ----------------------------------------------------- - // Find out how much time we'll need to perform a - // full circle. - // ----------------------------------------------------- - const double seconds = (1. / in.speed) / 1000.; - const double tdelta = 1000. / fps; - - anim->mNumPositionKeys = (unsigned int) (fps * seconds); - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; - - // from Irrlicht, what else should we do than copying it? - aiVector3D vecU,vecV; - if (in.direction.y) { - vecV = aiVector3D(50,0,0) ^ in.direction; - } - else vecV = aiVector3D(0,50,00) ^ in.direction; - vecV.Normalize(); - vecU = (vecV ^ in.direction).Normalize(); - - // build the output keys - for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) { - aiVectorKey& key = anim->mPositionKeys[i]; - key.mTime = i * tdelta; - - const float t = (float) ( in.speed * key.mTime ); - key.mValue = in.circleCenter + in.circleRadius * ((vecU*::cos(t)) + (vecV*::sin(t))); - } - - // This animation is repeated and repeated ... - anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; - } - break; - - case Animator::FLY_STRAIGHT: - { - anim->mPostState = anim->mPreState = (in.loop ? aiAnimBehaviour_REPEAT : aiAnimBehaviour_CONSTANT); - const double seconds = in.timeForWay / 1000.; - const double tdelta = 1000. / fps; - - anim->mNumPositionKeys = (unsigned int) (fps * seconds); - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; - - aiVector3D diff = in.direction - in.circleCenter; - const float lengthOfWay = diff.Length(); - diff.Normalize(); - - const double timeFactor = lengthOfWay / in.timeForWay; - - // build the output keys - for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) { - aiVectorKey& key = anim->mPositionKeys[i]; - key.mTime = i * tdelta; - key.mValue = in.circleCenter + diff * float(timeFactor * key.mTime); - } - } - break; - - case Animator::FOLLOW_SPLINE: - { - // repeat outside the defined time range - anim->mPostState = anim->mPreState = aiAnimBehaviour_REPEAT; - const int size = (int)in.splineKeys.size(); - if (!size) { - // We have no point in the spline. That's bad. Really bad. - DefaultLogger::get()->warn("IRR: Spline animators with no points defined"); - - delete anim;anim = NULL; - break; - } - else if (size == 1) { - // We have just one point in the spline so we don't need the full calculation - anim->mNumPositionKeys = 1; - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; - - anim->mPositionKeys[0].mValue = in.splineKeys[0].mValue; - anim->mPositionKeys[0].mTime = 0.f; - break; - } - - unsigned int ticksPerFull = 15; - anim->mNumPositionKeys = (unsigned int) ( ticksPerFull * fps ); - anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys]; - - for (unsigned int i = 0; i < anim->mNumPositionKeys;++i) - { - aiVectorKey& key = anim->mPositionKeys[i]; - - const float dt = (i * in.speed * 0.001f ); - const float u = dt - floor(dt); - const int idx = (int)floor(dt) % size; - - // get the 4 current points to evaluate the spline - const aiVector3D& p0 = in.splineKeys[ ClampSpline( idx - 1, size ) ].mValue; - const aiVector3D& p1 = in.splineKeys[ ClampSpline( idx + 0, size ) ].mValue; - const aiVector3D& p2 = in.splineKeys[ ClampSpline( idx + 1, size ) ].mValue; - const aiVector3D& p3 = in.splineKeys[ ClampSpline( idx + 2, size ) ].mValue; - - // compute polynomials - const float u2 = u*u; - const float u3 = u2*2; - - const float h1 = 2.0f * u3 - 3.0f * u2 + 1.0f; - const float h2 = -2.0f * u3 + 3.0f * u3; - const float h3 = u3 - 2.0f * u3; - const float h4 = u3 - u2; - - // compute the spline tangents - const aiVector3D t1 = ( p2 - p0 ) * in.tightness; - aiVector3D t2 = ( p3 - p1 ) * in.tightness; - - // and use them to get the interpolated point - t2 = (h1 * p1 + p2 * h2 + t1 * h3 + h4 * t2); - - // build a simple translation matrix from it - key.mValue = t2.x; - key.mTime = (double) i; - } - } - break; - default: - // UNKNOWN , OTHER - break; - }; - if (anim) { - anims.push_back(anim); - ++total; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// This function is maybe more generic than we'd need it here -void SetupMapping (MaterialHelper* mat, aiTextureMapping mode, const aiVector3D& axis = aiVector3D(0.f,0.f,-1.f)) -{ - // Check whether there are texture properties defined - setup - // the desired texture mapping mode for all of them and ignore - // all UV settings we might encounter. WE HAVE NO UVS! - - std::vector<aiMaterialProperty*> p; - p.reserve(mat->mNumProperties+1); - - for (unsigned int i = 0; i < mat->mNumProperties;++i) - { - aiMaterialProperty* prop = mat->mProperties[i]; - if (!::strcmp( prop->mKey.data, "$tex.file")) { - // Setup the mapping key - aiMaterialProperty* m = new aiMaterialProperty(); - m->mKey.Set("$tex.mapping"); - m->mIndex = prop->mIndex; - m->mSemantic = prop->mSemantic; - m->mType = aiPTI_Integer; - - m->mDataLength = 4; - m->mData = new char[4]; - *((int*)m->mData) = mode; - - p.push_back(prop); - p.push_back(m); - - // Setup the mapping axis - if (mode == aiTextureMapping_CYLINDER || mode == aiTextureMapping_PLANE || mode == aiTextureMapping_SPHERE) { - m = new aiMaterialProperty(); - m->mKey.Set("$tex.mapaxis"); - m->mIndex = prop->mIndex; - m->mSemantic = prop->mSemantic; - m->mType = aiPTI_Float; - - m->mDataLength = 12; - m->mData = new char[12]; - *((aiVector3D*)m->mData) = axis; - p.push_back(m); - } - } - else if (! ::strcmp( prop->mKey.data, "$tex.uvwsrc")) { - delete mat->mProperties[i]; - } - else p.push_back(prop); - } - - if (p.empty())return; - - // rebuild the output array - if (p.size() > mat->mNumAllocated) { - delete[] mat->mProperties; - mat->mProperties = new aiMaterialProperty*[p.size()*2]; - - mat->mNumAllocated = p.size()*2; - } - mat->mNumProperties = (unsigned int)p.size(); - ::memcpy(mat->mProperties,&p[0],sizeof(void*)*mat->mNumProperties); -} - -// ------------------------------------------------------------------------------------------------ -void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, - BatchLoader& batch, - std::vector<aiMesh*>& meshes, - std::vector<aiNodeAnim*>& anims, - std::vector<AttachmentInfo>& attach, - std::vector<aiMaterial*>& materials, - unsigned int& defMatIdx) -{ - unsigned int oldMeshSize = (unsigned int)meshes.size(); - //unsigned int meshTrafoAssign = 0; - - // Now determine the type of the node - switch (root->type) - { - case Node::ANIMMESH: - case Node::MESH: - { - if (!root->meshPath.length()) - break; - - // Get the loaded mesh from the scene and add it to - // the list of all scenes to be attached to the - // graph we're currently building - aiScene* scene = batch.GetImport(root->id); - if (!scene) { - DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath); - break; - } - attach.push_back(AttachmentInfo(scene,rootOut)); - - // Now combine the material we've loaded for this mesh - // with the real materials we got from the file. As we - // don't execute any pp-steps on the file, the numbers - // should be equal. If they are not, we can impossibly - // do this ... - if (root->materials.size() != (unsigned int)scene->mNumMaterials) { - DefaultLogger::get()->warn("IRR: Failed to match imported materials " - "with the materials found in the IRR scene file"); - - break; - } - for (unsigned int i = 0; i < scene->mNumMaterials;++i) { - // Delete the old material, we don't need it anymore - delete scene->mMaterials[i]; - - std::pair<aiMaterial*, unsigned int>& src = root->materials[i]; - scene->mMaterials[i] = src.first; - } - - // NOTE: Each mesh should have exactly one material assigned, - // but we do it in a separate loop if this behaviour changes - // in future. - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - // Process material flags - aiMesh* mesh = scene->mMeshes[i]; - - - // If "trans_vertex_alpha" mode is enabled, search all vertex colors - // and check whether they have a common alpha value. This is quite - // often the case so we can simply extract it to a shared oacity - // value. - std::pair<aiMaterial*, unsigned int>& src = root->materials[mesh->mMaterialIndex]; - MaterialHelper* mat = (MaterialHelper*)src.first; - - if (mesh->HasVertexColors(0) && src.second & AI_IRRMESH_MAT_trans_vertex_alpha) - { - bool bdo = true; - for (unsigned int a = 1; a < mesh->mNumVertices;++a) { - - if (mesh->mColors[0][a].a != mesh->mColors[0][a-1].a) { - bdo = false; - break; - } - } - if (bdo) { - DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity"); - - for (unsigned int a = 0; a < mesh->mNumVertices;++a) - mesh->mColors[0][a].a = 1.f; - - mat->AddProperty(& mesh->mColors[0][0].a, 1, AI_MATKEY_OPACITY); - } - } - - // If we have a second texture coordinate set and a second texture - // (either lightmap, normalmap, 2layered material) we need to - // setup the correct UV index for it. The texture can either - // be diffuse (lightmap & 2layer) or a normal map (normal & parallax) - if (mesh->HasTextureCoords(1)) { - - int idx = 1; - if (src.second & (AI_IRRMESH_MAT_solid_2layer | AI_IRRMESH_MAT_lightmap)) { - mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_DIFFUSE(0)); - } - else if (src.second & AI_IRRMESH_MAT_normalmap_solid) { - mat->AddProperty(&idx,1,AI_MATKEY_UVWSRC_NORMALS(0)); - } - } - } - } - break; - - case Node::LIGHT: - case Node::CAMERA: - - // We're already finished with lights and cameras - break; - - - case Node::SPHERE: - { - // Generate the sphere model. Our input parameter to - // the sphere generation algorithm is the number of - // subdivisions of each triangle - but here we have - // the number of poylgons on a specific axis. Just - // use some hardcoded limits to approximate this ... - unsigned int mul = root->spherePolyCountX*root->spherePolyCountY; - if (mul < 100)mul = 2; - else if (mul < 300)mul = 3; - else mul = 4; - - meshes.push_back(StandardShapes::MakeMesh(mul, - &StandardShapes::MakeSphere)); - - // Adjust scaling - root->scaling *= root->sphereRadius/2; - - // Copy one output material - CopyMaterial(materials, root->materials, defMatIdx, meshes.back()); - - // Now adjust this output material - if there is a first texture - // set, setup spherical UV mapping around the Y axis. - SetupMapping ( (MaterialHelper*) materials.back(), aiTextureMapping_SPHERE); - } - break; - - case Node::CUBE: - { - // Generate an unit cube first - meshes.push_back(StandardShapes::MakeMesh( - &StandardShapes::MakeHexahedron)); - - // Adjust scaling - root->scaling *= root->sphereRadius; - - // Copy one output material - CopyMaterial(materials, root->materials, defMatIdx, meshes.back()); - - // Now adjust this output material - if there is a first texture - // set, setup cubic UV mapping - SetupMapping ( (MaterialHelper*) materials.back(), aiTextureMapping_BOX ); - } - break; - - - case Node::SKYBOX: - { - // A skybox is defined by six materials - if (root->materials.size() < 6) { - DefaultLogger::get()->error("IRR: There should be six materials for a skybox"); - break; - } - - // copy those materials and generate 6 meshes for our new skybox - materials.reserve(materials.size() + 6); - for (unsigned int i = 0; i < 6;++i) - materials.insert(materials.end(),root->materials[i].first); - - BuildSkybox(meshes,materials); - - // ************************************************************* - // Skyboxes will require a different code path for rendering, - // so there must be a way for the user to add special support - // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node. - // ************************************************************* - root->name = "IRR.SkyBox_" + root->name; - DefaultLogger::get()->info("IRR: Loading skybox, this will " - "require special handling to be displayed correctly"); - } - break; - - case Node::TERRAIN: - { - // to support terrains, we'd need to have a texture decoder - DefaultLogger::get()->error("IRR: Unsupported node - TERRAIN"); - } - break; - default: - // DUMMY - break; - }; - - // Check whether we added a mesh (or more than one ...). In this case - // we'll also need to attach it to the node - if (oldMeshSize != (unsigned int) meshes.size()) { - - rootOut->mNumMeshes = (unsigned int)meshes.size() - oldMeshSize; - rootOut->mMeshes = new unsigned int[rootOut->mNumMeshes]; - - for (unsigned int a = 0; a < rootOut->mNumMeshes;++a) { - rootOut->mMeshes[a] = oldMeshSize+a; - } - } - - // Setup the name of this node - rootOut->mName.Set(root->name); - - // Now compute the final local transformation matrix of the - // node from the given translation, rotation and scaling values. - // (the rotation is given in Euler angles, XYZ order) - //std::swap((float&)root->rotation.z,(float&)root->rotation.y); - rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation) ); - - // apply scaling - aiMatrix4x4& mat = rootOut->mTransformation; - mat.a1 *= root->scaling.x; - mat.b1 *= root->scaling.x; - mat.c1 *= root->scaling.x; - mat.a2 *= root->scaling.y; - mat.b2 *= root->scaling.y; - mat.c2 *= root->scaling.y; - mat.a3 *= root->scaling.z; - mat.b3 *= root->scaling.z; - mat.c3 *= root->scaling.z; - - // apply translation - mat.a4 += root->position.x; - mat.b4 += root->position.y; - mat.c4 += root->position.z; - - // now compute animations for the node - ComputeAnimations(root,rootOut, anims); - - // Add all children recursively. First allocate enough storage - // for them, then call us again - rootOut->mNumChildren = (unsigned int)root->children.size(); - if (rootOut->mNumChildren) { - - rootOut->mChildren = new aiNode*[rootOut->mNumChildren]; - for (unsigned int i = 0; i < rootOut->mNumChildren;++i) { - - aiNode* node = rootOut->mChildren[i] = new aiNode(); - node->mParent = rootOut; - GenerateGraph(root->children[i],node,scene,batch,meshes, - anims,attach,materials,defMatIdx); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void IRRImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open IRR file " + pFile + ""); - - // Construct the irrXML parser - CIrrXML_IOStreamReader st(file.get()); - reader = createIrrXMLReader((IFileReadCallBack*) &st); - - // The root node of the scene - Node* root = new Node(Node::DUMMY); - root->parent = NULL; - root->name = "<IRRSceneRoot>"; - - // Current node parent - Node* curParent = root; - - // Scenegraph node we're currently working on - Node* curNode = NULL; - - // List of output cameras - std::vector<aiCamera*> cameras; - - // List of output lights - std::vector<aiLight*> lights; - - // Batch loader used to load external models - BatchLoader batch(pIOHandler); -// batch.SetBasePath(pFile); - - cameras.reserve(5); - lights.reserve(5); - - bool inMaterials = false, inAnimator = false; - unsigned int guessedAnimCnt = 0, guessedMeshCnt = 0, guessedMatCnt = 0; - - // Parse the XML file - while (reader->read()) { - switch (reader->getNodeType()) { - case EXN_ELEMENT: - - if (!ASSIMP_stricmp(reader->getNodeName(),"node")) { - // *********************************************************************** - /* What we're going to do with the node depends - * on its type: - * - * "mesh" - Load a mesh from an external file - * "cube" - Generate a cube - * "skybox" - Generate a skybox - * "light" - A light source - * "sphere" - Generate a sphere mesh - * "animatedMesh" - Load an animated mesh from an external file - * and join its animation channels with ours. - * "empty" - A dummy node - * "camera" - A camera - * "terrain" - a terrain node (data comes from a heightmap) - * "billboard", "" - * - * Each of these nodes can be animated and all can have multiple - * materials assigned (except lights, cameras and dummies, of course). - */ - // *********************************************************************** - const char* sz = reader->getAttributeValueSafe("type"); - Node* nd; - if (!ASSIMP_stricmp(sz,"mesh") || !ASSIMP_stricmp(sz,"octTree")) { - // OctTree's and meshes are treated equally - nd = new Node(Node::MESH); - } - else if (!ASSIMP_stricmp(sz,"cube")) { - nd = new Node(Node::CUBE); - ++guessedMeshCnt; - // meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron)); - } - else if (!ASSIMP_stricmp(sz,"skybox")) { - nd = new Node(Node::SKYBOX); - guessedMeshCnt += 6; - } - else if (!ASSIMP_stricmp(sz,"camera")) { - nd = new Node(Node::CAMERA); - - // Setup a temporary name for the camera - aiCamera* cam = new aiCamera(); - cam->mName.Set( nd->name ); - cameras.push_back(cam); - } - else if (!ASSIMP_stricmp(sz,"light")) { - nd = new Node(Node::LIGHT); - - // Setup a temporary name for the light - aiLight* cam = new aiLight(); - cam->mName.Set( nd->name ); - lights.push_back(cam); - } - else if (!ASSIMP_stricmp(sz,"sphere")) { - nd = new Node(Node::SPHERE); - ++guessedMeshCnt; - } - else if (!ASSIMP_stricmp(sz,"animatedMesh")) { - nd = new Node(Node::ANIMMESH); - } - else if (!ASSIMP_stricmp(sz,"empty")) { - nd = new Node(Node::DUMMY); - } - else if (!ASSIMP_stricmp(sz,"terrain")) { - nd = new Node(Node::TERRAIN); - } - else if (!ASSIMP_stricmp(sz,"billBoard")) { - // We don't support billboards, so ignore them - DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp"); - nd = new Node(Node::DUMMY); - } - else { - DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz)); - - /* We skip the contents of nodes we don't know. - * We parse the transformation and all animators - * and skip the rest. - */ - nd = new Node(Node::DUMMY); - } - - /* Attach the newly created node to the scenegraph - */ - curNode = nd; - nd->parent = curParent; - curParent->children.push_back(nd); - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) { - inMaterials = true; - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) { - inAnimator = true; - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"attributes")) { - /* We should have a valid node here - * FIX: no ... the scene root node is also contained in an attributes block - */ - if (!curNode) { -#if 0 - DefaultLogger::get()->error("IRR: Encountered <attributes> element, but " - "there is no node active"); -#endif - continue; - } - - Animator* curAnim = NULL; - - // Materials can occur for nearly any type of node - if (inMaterials && curNode->type != Node::DUMMY) { - /* This is a material description - parse it! - */ - curNode->materials.push_back(std::pair< aiMaterial*, unsigned int > () ); - std::pair< aiMaterial*, unsigned int >& p = curNode->materials.back(); - - p.first = ParseMaterial(p.second); - - ++guessedMatCnt; - continue; - } - else if (inAnimator) { - /* This is an animation path - add a new animator - * to the list. - */ - curNode->animators.push_back(Animator()); - curAnim = & curNode->animators.back(); - - ++guessedAnimCnt; - } - - /* Parse all elements in the attributes block - * and process them. - */ - while (reader->read()) { - if (reader->getNodeType() == EXN_ELEMENT) { - if (!ASSIMP_stricmp(reader->getNodeName(),"vector3d")) { - VectorProperty prop; - ReadVectorProperty(prop); - - if (inAnimator) { - if (curAnim->type == Animator::ROTATION && prop.name == "Rotation") { - // We store the rotation euler angles in 'direction' - curAnim->direction = prop.value; - } - else if (curAnim->type == Animator::FOLLOW_SPLINE) { - // Check whether the vector follows the PointN naming scheme, - // here N is the ONE-based index of the point - if (prop.name.length() >= 6 && prop.name.substr(0,5) == "Point") { - // Add a new key to the list - curAnim->splineKeys.push_back(aiVectorKey()); - aiVectorKey& key = curAnim->splineKeys.back(); - - // and parse its properties - key.mValue = prop.value; - key.mTime = strtol10(&prop.name[5]); - } - } - else if (curAnim->type == Animator::FLY_CIRCLE) { - if (prop.name == "Center") { - curAnim->circleCenter = prop.value; - } - else if (prop.name == "Direction") { - curAnim->direction = prop.value; - - // From Irrlicht's source - a workaround for backward compatibility with Irrlicht 1.1 - if (curAnim->direction == aiVector3D()) { - curAnim->direction = aiVector3D(0.f,1.f,0.f); - } - else curAnim->direction.Normalize(); - } - } - else if (curAnim->type == Animator::FLY_STRAIGHT) { - if (prop.name == "Start") { - // We reuse the field here - curAnim->circleCenter = prop.value; - } - else if (prop.name == "End") { - // We reuse the field here - curAnim->direction = prop.value; - } - } - } - else { - if (prop.name == "Position") { - curNode->position = prop.value; - } - else if (prop.name == "Rotation") { - curNode->rotation = prop.value; - } - else if (prop.name == "Scale") { - curNode->scaling = prop.value; - } - else if (Node::CAMERA == curNode->type) - { - aiCamera* cam = cameras.back(); - if (prop.name == "Target") { - cam->mLookAt = prop.value; - } - else if (prop.name == "UpVector") { - cam->mUp = prop.value; - } - } - } - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) { - BoolProperty prop; - ReadBoolProperty(prop); - - if (inAnimator && curAnim->type == Animator::FLY_CIRCLE && prop.name == "Loop") { - curAnim->loop = prop.value; - } - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) { - FloatProperty prop; - ReadFloatProperty(prop); - - if (inAnimator) { - // The speed property exists for several animators - if (prop.name == "Speed") { - curAnim->speed = prop.value; - } - else if (curAnim->type == Animator::FLY_CIRCLE && prop.name == "Radius") { - curAnim->circleRadius = prop.value; - } - else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness") { - curAnim->tightness = prop.value; - } - } - else { - if (prop.name == "FramesPerSecond" && Node::ANIMMESH == curNode->type) { - curNode->framesPerSecond = prop.value; - } - else if (Node::CAMERA == curNode->type) { - /* This is the vertical, not the horizontal FOV. - * We need to compute the right FOV from the - * screen aspect which we don't know yet. - */ - if (prop.name == "Fovy") { - cameras.back()->mHorizontalFOV = prop.value; - } - else if (prop.name == "Aspect") { - cameras.back()->mAspect = prop.value; - } - else if (prop.name == "ZNear") { - cameras.back()->mClipPlaneNear = prop.value; - } - else if (prop.name == "ZFar") { - cameras.back()->mClipPlaneFar = prop.value; - } - } - else if (Node::LIGHT == curNode->type) { - /* Additional light information - */ - if (prop.name == "Attenuation") { - lights.back()->mAttenuationLinear = prop.value; - } - else if (prop.name == "OuterCone") { - lights.back()->mAngleOuterCone = AI_DEG_TO_RAD( prop.value ); - } - else if (prop.name == "InnerCone") { - lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value ); - } - } - // radius of the sphere to be generated - - // or alternatively, size of the cube - else if ((Node::SPHERE == curNode->type && prop.name == "Radius") - || (Node::CUBE == curNode->type && prop.name == "Size" )) { - - curNode->sphereRadius = prop.value; - } - } - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"int")) { - IntProperty prop; - ReadIntProperty(prop); - - if (inAnimator) { - if (curAnim->type == Animator::FLY_STRAIGHT && prop.name == "TimeForWay") { - curAnim->timeForWay = prop.value; - } - } - else { - // sphere polgon numbers in each direction - if (Node::SPHERE == curNode->type) { - - if (prop.name == "PolyCountX") { - curNode->spherePolyCountX = prop.value; - } - else if (prop.name == "PolyCountY") { - curNode->spherePolyCountY = prop.value; - } - } - } - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"string") ||!ASSIMP_stricmp(reader->getNodeName(),"enum")) { - StringProperty prop; - ReadStringProperty(prop); - if (prop.value.length()) { - if (prop.name == "Name") { - curNode->name = prop.value; - - /* If we're either a camera or a light source - * we need to update the name in the aiLight/ - * aiCamera structure, too. - */ - if (Node::CAMERA == curNode->type) { - cameras.back()->mName.Set(prop.value); - } - else if (Node::LIGHT == curNode->type) { - lights.back()->mName.Set(prop.value); - } - } - else if (Node::LIGHT == curNode->type && "LightType" == prop.name) - { - if (prop.value == "Spot") - lights.back()->mType = aiLightSource_SPOT; - else if (prop.value == "Point") - lights.back()->mType = aiLightSource_POINT; - else if (prop.value == "Directional") - lights.back()->mType = aiLightSource_DIRECTIONAL; - else - { - // We won't pass the validation with aiLightSourceType_UNDEFINED, - // so we remove the light and replace it with a silly dummy node - delete lights.back(); - lights.pop_back(); - curNode->type = Node::DUMMY; - - DefaultLogger::get()->error("Ignoring light of unknown type: " + prop.value); - } - } - else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || - Node::ANIMMESH == curNode->type) - { - /* This is the file name of the mesh - either - * animated or not. We need to make sure we setup - * the correct postprocessing settings here. - */ - unsigned int pp = 0; - BatchLoader::PropertyMap map; - - /* If the mesh is a static one remove all animations from the impor data - */ - if (Node::ANIMMESH != curNode->type) { - pp |= aiProcess_RemoveComponent; - SetGenericProperty<int>(map.ints,AI_CONFIG_PP_RVC_FLAGS, - aiComponent_ANIMATIONS | aiComponent_BONEWEIGHTS); - } - - /* TODO: maybe implement the protection against recursive - * loading calls directly in BatchLoader? The current - * implementation is not absolutely safe. A LWS and an IRR - * file referencing each other *could* cause the system to - * recurse forever. - */ - - const std::string extension = GetExtension(prop.value); - if ("irr" == extension) { - DefaultLogger::get()->error("IRR: Can't load another IRR file recursively"); - } - else - { - curNode->id = batch.AddLoadRequest(prop.value,pp,&map); - curNode->meshPath = prop.value; - } - } - else if (inAnimator && prop.name == "Type") - { - // type of the animator - if (prop.value == "rotation") { - curAnim->type = Animator::ROTATION; - } - else if (prop.value == "flyCircle") { - curAnim->type = Animator::FLY_CIRCLE; - } - else if (prop.value == "flyStraight") { - curAnim->type = Animator::FLY_CIRCLE; - } - else if (prop.value == "followSpline") { - curAnim->type = Animator::FOLLOW_SPLINE; - } - else { - DefaultLogger::get()->warn("IRR: Ignoring unknown animator: " - + prop.value); - - curAnim->type = Animator::UNKNOWN; - } - } - } - } - } - else if (reader->getNodeType() == EXN_ELEMENT_END && !ASSIMP_stricmp(reader->getNodeName(),"attributes")) { - break; - } - } - } - break; - - case EXN_ELEMENT_END: - - // If we reached the end of a node, we need to continue processing its parent - if (!ASSIMP_stricmp(reader->getNodeName(),"node")) { - if (!curNode) { - // currently is no node set. We need to go - // back in the node hierarchy - if (!curParent) { - curParent = root; - DefaultLogger::get()->error("IRR: Too many closing <node> elements"); - } - else curParent = curParent->parent; - } - else curNode = NULL; - } - // clear all flags - else if (!ASSIMP_stricmp(reader->getNodeName(),"materials")) { - inMaterials = false; - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"animators")) { - inAnimator = false; - } - break; - - default: - // GCC complains that not all enumeration values are handled - break; - } - } - - /* Now iterate through all cameras and compute their final (horizontal) FOV - */ - for (std::vector<aiCamera*>::iterator it = cameras.begin(), end = cameras.end();it != end; ++it) { - aiCamera* cam = *it; - - // screen aspect could be missing - if (cam->mAspect) { - cam->mHorizontalFOV *= cam->mAspect; - } - else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV"); - } - - batch.LoadAll(); - - /* Allocate a tempoary scene data structure - */ - aiScene* tempScene = new aiScene(); - tempScene->mRootNode = new aiNode(); - tempScene->mRootNode->mName.Set("<IRRRoot>"); - - /* Copy the cameras to the output array - */ - if (!cameras.empty()) { - tempScene->mNumCameras = (unsigned int)cameras.size(); - tempScene->mCameras = new aiCamera*[tempScene->mNumCameras]; - ::memcpy(tempScene->mCameras,&cameras[0],sizeof(void*)*tempScene->mNumCameras); - } - - /* Copy the light sources to the output array - */ - if (!lights.empty()) { - tempScene->mNumLights = (unsigned int)lights.size(); - tempScene->mLights = new aiLight*[tempScene->mNumLights]; - ::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights); - } - - // temporary data - std::vector< aiNodeAnim*> anims; - std::vector< aiMaterial*> materials; - std::vector< AttachmentInfo > attach; - std::vector<aiMesh*> meshes; - - // try to guess how much storage we'll need - anims.reserve (guessedAnimCnt + (guessedAnimCnt >> 2)); - meshes.reserve (guessedMeshCnt + (guessedMeshCnt >> 2)); - materials.reserve (guessedMatCnt + (guessedMatCnt >> 2)); - - /* Now process our scenegraph recursively: generate final - * meshes and generate animation channels for all nodes. - */ - unsigned int defMatIdx = 0xffffffff; - GenerateGraph(root,tempScene->mRootNode, tempScene, - batch, meshes, anims, attach, materials, defMatIdx); - - if (!anims.empty()) - { - tempScene->mNumAnimations = 1; - tempScene->mAnimations = new aiAnimation*[tempScene->mNumAnimations]; - aiAnimation* an = tempScene->mAnimations[0] = new aiAnimation(); - - // *********************************************************** - // This is only the global animation channel of the scene. - // If there are animated models, they will have separate - // animation channels in the scene. To display IRR scenes - // correctly, users will need to combine the global anim - // channel with all the local animations they want to play - // *********************************************************** - an->mName.Set("Irr_GlobalAnimChannel"); - - // copy all node animation channels to the global channel - an->mNumChannels = (unsigned int)anims.size(); - an->mChannels = new aiNodeAnim*[an->mNumChannels]; - ::memcpy(an->mChannels, & anims [0], sizeof(void*)*an->mNumChannels); - } - if (!meshes.empty()) { - // copy all meshes to the temporary scene - tempScene->mNumMeshes = (unsigned int)meshes.size(); - tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes]; - ::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes* - sizeof(void*)); - } - - /* Copy all materials to the output array - */ - if (!materials.empty()) { - tempScene->mNumMaterials = (unsigned int)materials.size(); - tempScene->mMaterials = new aiMaterial*[tempScene->mNumMaterials]; - ::memcpy(tempScene->mMaterials,&materials[0],sizeof(void*)* - tempScene->mNumMaterials); - } - - /* Now merge all sub scenes and attach them to the correct - * attachment points in the scenegraph. - */ - SceneCombiner::MergeScenes(&pScene,tempScene,attach, - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0)); - - - /* If we have no meshes | no materials now set the INCOMPLETE - * scene flag. This is necessary if we failed to load all - * models from external files - */ - if (!pScene->mNumMeshes || !pScene->mNumMaterials) { - DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE"); - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - - /* Finished ... everything destructs automatically and all - * temporary scenes have already been deleted by MergeScenes() - */ - return; -} diff --git a/3rdparty/assimp/code/IRRLoader.h b/3rdparty/assimp/code/IRRLoader.h deleted file mode 100644 index bfe40ec7..00000000 --- a/3rdparty/assimp/code/IRRLoader.h +++ /dev/null @@ -1,312 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 IRRLoader.h - * @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format) - * importer class. - */ -#ifndef AI_IRRLOADER_H_INCLUDED -#define AI_IRRLOADER_H_INCLUDED - -#include "IRRShared.h" -#include "SceneCombiner.h" - -namespace Assimp { - - -// --------------------------------------------------------------------------- -/** Irr importer class. - * - * Irr is the native scene file format of the Irrlight engine and its editor - * irrEdit. As IrrEdit itself is capable of importing quite many file formats, - * it might be a good file format for data exchange. - */ -class IRRImporter : public BaseImporter, public IrrlichtBase -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - IRRImporter(); - - /** Destructor, private as well */ - ~IRRImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** - */ - void SetupProperties(const Importer* pImp); - -private: - - /** Data structure for a scenegraph node animator - */ - struct Animator - { - // Type of the animator - enum AT - { - UNKNOWN = 0x0, - ROTATION = 0x1, - FLY_CIRCLE = 0x2, - FLY_STRAIGHT = 0x3, - FOLLOW_SPLINE = 0x4, - OTHER = 0x5 - - } type; - - Animator(AT t = UNKNOWN) - : type (t) - , speed (0.001f) - , direction (0.f,1.f,0.f) - , circleRadius (1.f) - , tightness (0.5f) - , loop (true) - , timeForWay (100) - { - } - - - // common parameters - float speed; - aiVector3D direction; - - // FLY_CIRCLE - aiVector3D circleCenter; - float circleRadius; - - // FOLLOW_SPLINE - float tightness; - std::vector<aiVectorKey> splineKeys; - - // ROTATION (angles given in direction) - - // FLY STRAIGHT - // circleCenter = start, direction = end - bool loop; - int timeForWay; - }; - - /** Data structure for a scenegraph node in an IRR file - */ - struct Node - { - // Type of the node - enum ET - { - LIGHT, - CUBE, - MESH, - SKYBOX, - DUMMY, - CAMERA, - TERRAIN, - SPHERE, - ANIMMESH - } type; - - Node(ET t) - : type (t) - , scaling (1.f,1.f,1.f) // assume uniform scaling by default - , framesPerSecond (0.f) - , sphereRadius (1.f) - , spherePolyCountX (100) - , spherePolyCountY (100) - { - - // Generate a default name for the node - char buffer[128]; - static int cnt; - ::sprintf(buffer,"IrrNode_%i",cnt++); - name = std::string(buffer); - - // reserve space for up to 5 materials - materials.reserve(5); - - // reserve space for up to 5 children - children.reserve(5); - } - - // Transformation of the node - aiVector3D position, rotation, scaling; - - // Name of the node - std::string name; - - // List of all child nodes - std::vector<Node*> children; - - // Parent node - Node* parent; - - // Animated meshes: frames per second - // 0.f if not specified - float framesPerSecond; - - // Meshes: path to the mesh to be loaded - std::string meshPath; - unsigned int id; - - // Meshes: List of materials to be assigned - // along with their corresponding material flags - std::vector< std::pair<aiMaterial*, unsigned int> > materials; - - // Spheres: radius of the sphere to be generates - float sphereRadius; - - // Spheres: Number of polygons in the x,y direction - unsigned int spherePolyCountX,spherePolyCountY; - - // List of all animators assigned to the node - std::list<Animator> animators; - }; - - /** Data structure for a vertex in an IRR skybox - */ - struct SkyboxVertex - { - SkyboxVertex() - {} - - //! Construction from single vertex components - SkyboxVertex(float px, float py, float pz, - float nx, float ny, float nz, - float uvx, float uvy) - - : position (px,py,pz) - , normal (nx,ny,nz) - , uv (uvx,uvy,0.f) - {} - - aiVector3D position, normal, uv; - }; - - - // ------------------------------------------------------------------- - /** Fill the scenegraph recursively - */ - void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene, - BatchLoader& batch, - std::vector<aiMesh*>& meshes, - std::vector<aiNodeAnim*>& anims, - std::vector<AttachmentInfo>& attach, - std::vector<aiMaterial*>& materials, - unsigned int& defaultMatIdx); - - - // ------------------------------------------------------------------- - /** Generate a mesh that consists of just a single quad - */ - aiMesh* BuildSingleQuadMesh(const SkyboxVertex& v1, - const SkyboxVertex& v2, - const SkyboxVertex& v3, - const SkyboxVertex& v4); - - - // ------------------------------------------------------------------- - /** Build a skybox - * - * @param meshes Receives 6 output meshes - * @param materials The last 6 materials are assigned to the newly - * created meshes. The names of the materials are adjusted. - */ - void BuildSkybox(std::vector<aiMesh*>& meshes, - std::vector<aiMaterial*> materials); - - - // ------------------------------------------------------------------- - /** Copy a material for a mesh to the output material list - * - * @param materials Receives an output material - * @param inmaterials List of input materials - * @param defMatIdx Default material index - 0xffffffff if not there - * @param mesh Mesh to work on - */ - void CopyMaterial(std::vector<aiMaterial*>& materials, - std::vector< std::pair<aiMaterial*, unsigned int> >& inmaterials, - unsigned int& defMatIdx, - aiMesh* mesh); - - - // ------------------------------------------------------------------- - /** Compute animations for a specific node - * - * @param root Node to be processed - * @param anims The list of output animations - */ - void ComputeAnimations(Node* root, aiNode* real, - std::vector<aiNodeAnim*>& anims); - - -private: - - /** Configuration option: desired output FPS */ - double fps; - - /** Configuration option: speed flag was set? */ - bool configSpeedFlag; -}; - -} // end of namespace Assimp - -#endif // AI_IRRIMPORTER_H_INC diff --git a/3rdparty/assimp/code/IRRMeshLoader.cpp b/3rdparty/assimp/code/IRRMeshLoader.cpp deleted file mode 100644 index 6d67e225..00000000 --- a/3rdparty/assimp/code/IRRMeshLoader.cpp +++ /dev/null @@ -1,499 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 */ - -#include "AssimpPCH.h" - -#include "IRRMeshLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -using namespace Assimp; -using namespace irr; -using namespace irr::io; - -// ------------------------------------------------------------------------------------------------ -// 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 -void IRRMeshImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("xml"); - extensions.insert("irrmesh"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void IRRMeshImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_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 = NULL; - aiMesh* curMesh = NULL; - unsigned int curMatFlags; - - 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"); - delete curMat; - delete curMesh; - } - else { - materials.push_back(curMat); - meshes.push_back(curMesh); - } - curMat = NULL; - curMesh = NULL; - - 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"); - delete curMat;curMat = NULL; - } - 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"); - - delete curMat;curMat = NULL; - - curMesh = NULL; - 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; - MaterialHelper* mat = ( MaterialHelper* ) 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)) { - delete curMat; - DefaultLogger::get()->warn("IRRMESH: Unknown vertex format"); - } - else vertexFormat = 0; - textMeaning = 1; - } - else if (!ASSIMP_stricmp(reader->getNodeName(),"indices")) { - if (curVertices.empty() && curMat) { - delete 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 - delete curMesh; curMesh = NULL; - - // material - away - delete curMat;curMat = NULL; - - 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_atof_move(sz,(float&)temp.x); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.y); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.z); - SkipSpaces(&sz); - curVertices.push_back(temp); - - // Read the vertex normals - sz = fast_atof_move(sz,(float&)temp.x); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.y); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.z); - SkipSpaces(&sz); - curNormals.push_back(temp); - - // read the vertex colors - uint32_t clr = strtol16(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_atof_move(sz,(float&)temp.x); - SkipSpaces(&sz); - - sz = fast_atof_move(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_atof_move(sz,(float&)temp.x); - SkipSpaces(&sz); - - sz = fast_atof_move(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_atof_move(sz,(float&)temp.x); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.z); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.y); - SkipSpaces(&sz); - temp.y *= -1.0f; - curTangents.push_back(temp); - - // bitangents - sz = fast_atof_move(sz,(float&)temp.x); - SkipSpaces(&sz); - - sz = fast_atof_move(sz,(float&)temp.z); - SkipSpaces(&sz); - - sz = fast_atof_move(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 = strtol10(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 - MaterialHelper* mat = (MaterialHelper*)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"); - delete curMat; - delete 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); -} diff --git a/3rdparty/assimp/code/IRRMeshLoader.h b/3rdparty/assimp/code/IRRMeshLoader.h deleted file mode 100644 index e5a94dff..00000000 --- a/3rdparty/assimp/code/IRRMeshLoader.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 IRRMeshLoader.h - * @brief Declaration of the .irrMesh (Irrlight Engine Mesh Format) - * importer class. - */ -#ifndef AI_IRRMESHLOADER_H_INCLUDED -#define AI_IRRMESHLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "IRRShared.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** IrrMesh importer class. - * - * IrrMesh is the native file format of the Irrlight engine and its editor - * irrEdit. As IrrEdit itself is capable of importing quite many file formats, - * it might be a good file format for data exchange. - */ -class IRRMeshImporter : public BaseImporter, public IrrlichtBase -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - IRRMeshImporter(); - - /** Destructor, private as well */ - ~IRRMeshImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -}; - -} // end of namespace Assimp - -#endif // AI_IRRMESHIMPORTER_H_INC diff --git a/3rdparty/assimp/code/IRRShared.cpp b/3rdparty/assimp/code/IRRShared.cpp deleted file mode 100644 index d3010705..00000000 --- a/3rdparty/assimp/code/IRRShared.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 IRRShared.cpp - * @brief Shared utilities for the IRR and IRRMESH loaders - */ - -#include "AssimpPCH.h" - -#include "IRRShared.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -using namespace Assimp; -using namespace irr; -using namespace irr::io; - -// Transformation matrix to convert from Assimp to IRR space -const aiMatrix4x4 Assimp::AI_TO_IRR_MATRIX = aiMatrix4x4 ( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); - -// ------------------------------------------------------------------------------------------------ -// read a property in hexadecimal format (i.e. ffffffff) -void IrrlichtBase::ReadHexProperty (HexProperty& out) -{ - for (int i = 0; i < reader->getAttributeCount();++i) - { - if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) - { - out.name = std::string( reader->getAttributeValue(i) ); - } - else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) - { - // parse the hexadecimal value - out.value = strtol16(reader->getAttributeValue(i)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// read a decimal property -void IrrlichtBase::ReadIntProperty (IntProperty& out) -{ - for (int i = 0; i < reader->getAttributeCount();++i) - { - if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) - { - out.name = std::string( reader->getAttributeValue(i) ); - } - else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) - { - // parse the ecimal value - out.value = strtol10s(reader->getAttributeValue(i)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// read a string property -void IrrlichtBase::ReadStringProperty (StringProperty& out) -{ - for (int i = 0; i < reader->getAttributeCount();++i) - { - if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) - { - out.name = std::string( reader->getAttributeValue(i) ); - } - else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) - { - // simple copy the string - out.value = std::string (reader->getAttributeValue(i)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// read a boolean property -void IrrlichtBase::ReadBoolProperty (BoolProperty& out) -{ - for (int i = 0; i < reader->getAttributeCount();++i) - { - if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) - { - out.name = std::string( reader->getAttributeValue(i) ); - } - else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) - { - // true or false, case insensitive - out.value = (ASSIMP_stricmp( reader->getAttributeValue(i), - "true") ? false : true); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// read a float property -void IrrlichtBase::ReadFloatProperty (FloatProperty& out) -{ - for (int i = 0; i < reader->getAttributeCount();++i) - { - if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) - { - out.name = std::string( reader->getAttributeValue(i) ); - } - else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) - { - // just parse the float - out.value = fast_atof( reader->getAttributeValue(i) ); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// read a vector property -void IrrlichtBase::ReadVectorProperty (VectorProperty& out) -{ - for (int i = 0; i < reader->getAttributeCount();++i) - { - if (!ASSIMP_stricmp(reader->getAttributeName(i),"name")) - { - out.name = std::string( reader->getAttributeValue(i) ); - } - else if (!ASSIMP_stricmp(reader->getAttributeName(i),"value")) - { - // three floats, separated with commas - const char* ptr = reader->getAttributeValue(i); - - SkipSpaces(&ptr); - ptr = fast_atof_move( ptr,(float&)out.value.x ); - SkipSpaces(&ptr); - if (',' != *ptr) - { - DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition"); - } - else SkipSpaces(ptr+1,&ptr); - ptr = fast_atof_move( ptr,(float&)out.value.y ); - SkipSpaces(&ptr); - if (',' != *ptr) - { - DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition"); - } - else SkipSpaces(ptr+1,&ptr); - ptr = fast_atof_move( ptr,(float&)out.value.z ); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Convert a string to a proper aiMappingMode -int ConvertMappingMode(const std::string& mode) -{ - if (mode == "texture_clamp_repeat") - { - return aiTextureMapMode_Wrap; - } - else if (mode == "texture_clamp_mirror") - return aiTextureMapMode_Mirror; - - return aiTextureMapMode_Clamp; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a material from the XML file -aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) -{ - MaterialHelper* mat = new MaterialHelper(); - aiColor4D clr; - aiString s; - - matFlags = 0; // zero output flags - int cnt = 0; // number of used texture channels - unsigned int nd = 0; - - // Continue reading from the file - while (reader->read()) - { - switch (reader->getNodeType()) - { - case EXN_ELEMENT: - - // Hex properties - if (!ASSIMP_stricmp(reader->getNodeName(),"color")) - { - HexProperty prop; - ReadHexProperty(prop); - if (prop.name == "Diffuse") - { - ColorFromARGBPacked(prop.value,clr); - mat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - } - else if (prop.name == "Ambient") - { - ColorFromARGBPacked(prop.value,clr); - mat->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT); - } - else if (prop.name == "Specular") - { - ColorFromARGBPacked(prop.value,clr); - mat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR); - } - - // NOTE: The 'emissive' property causes problems. It is - // often != 0, even if there is obviously no light - // emitted by the described surface. In fact I think - // IRRLICHT ignores this property, too. -#if 0 - else if (prop.name == "Emissive") - { - ColorFromARGBPacked(prop.value,clr); - mat->AddProperty(&clr,1,AI_MATKEY_COLOR_EMISSIVE); - } -#endif - } - // Float properties - else if (!ASSIMP_stricmp(reader->getNodeName(),"float")) - { - FloatProperty prop; - ReadFloatProperty(prop); - if (prop.name == "Shininess") - { - mat->AddProperty(&prop.value,1,AI_MATKEY_SHININESS); - } - } - // Bool properties - else if (!ASSIMP_stricmp(reader->getNodeName(),"bool")) - { - BoolProperty prop; - ReadBoolProperty(prop); - if (prop.name == "Wireframe") - { - int val = (prop.value ? true : false); - mat->AddProperty(&val,1,AI_MATKEY_ENABLE_WIREFRAME); - } - else if (prop.name == "GouraudShading") - { - int val = (prop.value ? aiShadingMode_Gouraud - : aiShadingMode_NoShading); - mat->AddProperty(&val,1,AI_MATKEY_SHADING_MODEL); - } - else if (prop.name == "BackfaceCulling") - { - int val = (!prop.value); - mat->AddProperty(&val,1,AI_MATKEY_TWOSIDED); - } - } - // String properties - textures and texture related properties - else if (!ASSIMP_stricmp(reader->getNodeName(),"texture") || - !ASSIMP_stricmp(reader->getNodeName(),"enum")) - { - StringProperty prop; - ReadStringProperty(prop); - if (prop.value.length()) - { - // material type (shader) - if (prop.name == "Type") - { - if (prop.value == "solid") - { - // default material ... - } - else if (prop.value == "trans_vertex_alpha") - { - matFlags = AI_IRRMESH_MAT_trans_vertex_alpha; - } - else if (prop.value == "lightmap") - { - matFlags = AI_IRRMESH_MAT_lightmap; - } - else if (prop.value == "solid_2layer") - { - matFlags = AI_IRRMESH_MAT_solid_2layer; - } - else if (prop.value == "lightmap_m2") - { - matFlags = AI_IRRMESH_MAT_lightmap_m2; - } - else if (prop.value == "lightmap_m4") - { - matFlags = AI_IRRMESH_MAT_lightmap_m4; - } - else if (prop.value == "lightmap_light") - { - matFlags = AI_IRRMESH_MAT_lightmap_light; - } - else if (prop.value == "lightmap_light_m2") - { - matFlags = AI_IRRMESH_MAT_lightmap_light_m2; - } - else if (prop.value == "lightmap_light_m4") - { - matFlags = AI_IRRMESH_MAT_lightmap_light_m4; - } - else if (prop.value == "lightmap_add") - { - matFlags = AI_IRRMESH_MAT_lightmap_add; - } - // Normal and parallax maps are treated equally - else if (prop.value == "normalmap_solid" || - prop.value == "parallaxmap_solid") - { - matFlags = AI_IRRMESH_MAT_normalmap_solid; - } - else if (prop.value == "normalmap_trans_vertex_alpha" || - prop.value == "parallaxmap_trans_vertex_alpha") - { - matFlags = AI_IRRMESH_MAT_normalmap_tva; - } - else if (prop.value == "normalmap_trans_add" || - prop.value == "parallaxmap_trans_add") - { - matFlags = AI_IRRMESH_MAT_normalmap_ta; - } - else { - DefaultLogger::get()->warn("IRRMat: Unrecognized material type: " + prop.value); - } - } - - // Up to 4 texture channels are supported - if (prop.name == "Texture1") - { - // Always accept the primary texture channel - ++cnt; - s.Set(prop.value); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - else if (prop.name == "Texture2" && cnt == 1) - { - // 2-layer material lightmapped? - if (matFlags & AI_IRRMESH_MAT_lightmap) { - ++cnt; - s.Set(prop.value); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_LIGHTMAP(0)); - - // set the corresponding material flag - matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE; - } - // alternatively: normal or parallax mapping - else if (matFlags & AI_IRRMESH_MAT_normalmap_solid) { - ++cnt; - s.Set(prop.value); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_NORMALS(0)); - - // set the corresponding material flag - matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE; - } - // or just as second diffuse texture - else if (matFlags & AI_IRRMESH_MAT_solid_2layer) { - ++cnt; - s.Set(prop.value); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1)); - ++nd; - - // set the corresponding material flag - matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE; - } - else DefaultLogger::get()->warn("IRRmat: Skipping second texture"); - } - - else if (prop.name == "Texture3" && cnt == 2) - { - // Irrlicht does not seem to use these channels. - ++cnt; - s.Set(prop.value); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1)); - } - else if (prop.name == "Texture4" && cnt == 3) - { - // Irrlicht does not seem to use these channels. - ++cnt; - s.Set(prop.value); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+2)); - } - - // Texture mapping options - if (prop.name == "TextureWrap1" && cnt >= 1) - { - int map = ConvertMappingMode(prop.value); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(0)); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(0)); - } - else if (prop.name == "TextureWrap2" && cnt >= 2) - { - int map = ConvertMappingMode(prop.value); - if (matFlags & AI_IRRMESH_MAT_lightmap) { - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_LIGHTMAP(0)); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_LIGHTMAP(0)); - } - else if (matFlags & (AI_IRRMESH_MAT_normalmap_solid)) { - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_NORMALS(0)); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_NORMALS(0)); - } - else if (matFlags & AI_IRRMESH_MAT_solid_2layer) { - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(1)); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(1)); - } - } - else if (prop.name == "TextureWrap3" && cnt >= 3) - { - int map = ConvertMappingMode(prop.value); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+1)); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+1)); - } - else if (prop.name == "TextureWrap4" && cnt >= 4) - { - int map = ConvertMappingMode(prop.value); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_U_DIFFUSE(nd+2)); - mat->AddProperty(&map,1,AI_MATKEY_MAPPINGMODE_V_DIFFUSE(nd+2)); - } - } - } - break; - case EXN_ELEMENT_END: - - /* Assume there are no further nested nodes in <material> elements - */ - if (/* IRRMESH */ !ASSIMP_stricmp(reader->getNodeName(),"material") || - /* IRR */ !ASSIMP_stricmp(reader->getNodeName(),"attributes")) - { - // Now process lightmapping flags - // We should have at least one textur to do that .. - if (cnt && matFlags & AI_IRRMESH_MAT_lightmap) - { - float f = 1.f; - unsigned int unmasked = matFlags&~AI_IRRMESH_MAT_lightmap; - - // Additive lightmap? - int op = (unmasked & AI_IRRMESH_MAT_lightmap_add - ? aiTextureOp_Add : aiTextureOp_Multiply); - - // Handle Irrlicht's lightmapping scaling factor - if (unmasked & AI_IRRMESH_MAT_lightmap_m2 || - unmasked & AI_IRRMESH_MAT_lightmap_light_m2) - { - f = 2.f; - } - else if (unmasked & AI_IRRMESH_MAT_lightmap_m4 || - unmasked & AI_IRRMESH_MAT_lightmap_light_m4) - { - f = 4.f; - } - mat->AddProperty( &f, 1, AI_MATKEY_TEXBLEND_LIGHTMAP(0)); - mat->AddProperty( &op,1, AI_MATKEY_TEXOP_LIGHTMAP(0)); - } - - return mat; - } - default: - - // GCC complains here ... - break; - } - } - DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete"); - return mat; -} diff --git a/3rdparty/assimp/code/IRRShared.h b/3rdparty/assimp/code/IRRShared.h deleted file mode 100644 index e4081336..00000000 --- a/3rdparty/assimp/code/IRRShared.h +++ /dev/null @@ -1,115 +0,0 @@ - - -/** @file IRRShared.h - * @brief Shared utilities for the IRR and IRRMESH loaders - */ - -#ifndef INCLUDED_AI_IRRSHARED_H -#define INCLUDED_AI_IRRSHARED_H - -#include "irrXMLWrapper.h" -#include "BaseImporter.h" - -namespace Assimp { - - -/** @brief Matrix to convert from Assimp to IRR and backwards - */ -extern const aiMatrix4x4 AI_TO_IRR_MATRIX; - - -// Default: 0 = solid, one texture -#define AI_IRRMESH_MAT_solid_2layer 0x10000 - -// Transparency flags -#define AI_IRRMESH_MAT_trans_vertex_alpha 0x1 -#define AI_IRRMESH_MAT_trans_add 0x2 - -// Lightmapping flags -#define AI_IRRMESH_MAT_lightmap 0x2 -#define AI_IRRMESH_MAT_lightmap_m2 (AI_IRRMESH_MAT_lightmap|0x4) -#define AI_IRRMESH_MAT_lightmap_m4 (AI_IRRMESH_MAT_lightmap|0x8) -#define AI_IRRMESH_MAT_lightmap_light (AI_IRRMESH_MAT_lightmap|0x10) -#define AI_IRRMESH_MAT_lightmap_light_m2 (AI_IRRMESH_MAT_lightmap|0x20) -#define AI_IRRMESH_MAT_lightmap_light_m4 (AI_IRRMESH_MAT_lightmap|0x40) -#define AI_IRRMESH_MAT_lightmap_add (AI_IRRMESH_MAT_lightmap|0x80) - -// Standard NormalMap (or Parallax map, they're treated equally) -#define AI_IRRMESH_MAT_normalmap_solid (0x100) - -// Normal map combined with vertex alpha -#define AI_IRRMESH_MAT_normalmap_tva \ - (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_vertex_alpha) - -// Normal map combined with additive transparency -#define AI_IRRMESH_MAT_normalmap_ta \ - (AI_IRRMESH_MAT_normalmap_solid | AI_IRRMESH_MAT_trans_add) - -// Special flag. It indicates a second texture has been found -// Its type depends ... either a normal textue or a normal map -#define AI_IRRMESH_EXTRA_2ND_TEXTURE 0x100000 - -// --------------------------------------------------------------------------- -/** Base class for the Irr and IrrMesh importers. - * - * Declares some irrlight-related xml parsing utilities and provides tools - * to load materials from IRR and IRRMESH files. - */ -class IrrlichtBase -{ -protected: - - /** @brief Data structure for a simple name-value property - */ - template <class T> - struct Property - { - std::string name; - T value; - }; - - typedef Property<uint32_t> HexProperty; - typedef Property<std::string> StringProperty; - typedef Property<bool> BoolProperty; - typedef Property<float> FloatProperty; - typedef Property<aiVector3D> VectorProperty; - typedef Property<int> IntProperty; - - /** XML reader instance - */ - irr::io::IrrXMLReader* reader; - - // ------------------------------------------------------------------- - /** Parse a material description from the XML - * @return The created material - * @param matFlags Receives AI_IRRMESH_MAT_XX flags - */ - aiMaterial* ParseMaterial(unsigned int& matFlags); - - // ------------------------------------------------------------------- - /** Read a property of the specified type from the current XML element. - * @param out Recives output data - */ - void ReadHexProperty (HexProperty& out); - void ReadStringProperty (StringProperty& out); - void ReadBoolProperty (BoolProperty& out); - void ReadFloatProperty (FloatProperty& out); - void ReadVectorProperty (VectorProperty& out); - void ReadIntProperty (IntProperty& out); -}; - - -// ------------------------------------------------------------------------------------------------ -// Unpack a hex color, e.g. 0xdcdedfff -inline void ColorFromARGBPacked(uint32_t in, aiColor4D& clr) -{ - clr.a = ((in >> 24) & 0xff) / 255.f; - clr.r = ((in >> 16) & 0xff) / 255.f; - clr.g = ((in >> 8) & 0xff) / 255.f; - clr.b = ((in ) & 0xff) / 255.f; -} - - -} // end namespace Assimp - -#endif // !! INCLUDED_AI_IRRSHARED_H diff --git a/3rdparty/assimp/code/Importer.cpp b/3rdparty/assimp/code/Importer.cpp deleted file mode 100644 index 3f158360..00000000 --- a/3rdparty/assimp/code/Importer.cpp +++ /dev/null @@ -1,1415 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Importer.cpp - * @brief Implementation of the CPP-API class #Importer - */ - -#include "AssimpPCH.h" -#include "../include/aiVersion.h" - -// ------------------------------------------------------------------------------------------------ -/* Uncomment this line to prevent Assimp from catching unknown exceptions. - * - * Note that any Exception except DeadlyImportError may lead to - * undefined behaviour -> loaders could remain in an unusable state and - * further imports with the same Importer instance could fail/crash/burn ... - */ -// ------------------------------------------------------------------------------------------------ -#define ASSIMP_CATCH_GLOBAL_EXCEPTIONS - - -// ------------------------------------------------------------------------------------------------ -// Internal headers -// ------------------------------------------------------------------------------------------------ -#include "BaseImporter.h" -#include "BaseProcess.h" -#include "DefaultIOStream.h" -#include "DefaultIOSystem.h" -#include "DefaultProgressHandler.h" -#include "GenericProperty.h" -#include "ProcessHelper.h" -#include "ScenePreprocessor.h" -#include "MemoryIOWrapper.h" -#include "Profiler.h" -#include "TinyFormatter.h" - -using namespace Assimp::Profiling; -using namespace Assimp::Formatter; - -// ------------------------------------------------------------------------------------------------ -// Importers -// (include_new_importers_here) -// ------------------------------------------------------------------------------------------------ -#ifndef ASSIMP_BUILD_NO_X_IMPORTER -# include "XFileImporter.h" -#endif -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER -# include "3DSLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER -# include "MD3Loader.h" -#endif -#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER -# include "MDLLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER -# include "MD2Loader.h" -#endif -#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER -# include "PlyLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_ASE_IMPORTER -# include "ASELoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER -# include "ObjFileImporter.h" -#endif -#ifndef ASSIMP_BUILD_NO_HMP_IMPORTER -# include "HMPLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER -# include "SMDLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER -# include "MDCLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER -# include "MD5Loader.h" -#endif -#ifndef ASSIMP_BUILD_NO_STL_IMPORTER -# include "STLLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER -# include "LWOLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_DXF_IMPORTER -# include "DXFLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER -# include "NFFLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER -# include "RawLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER -# include "OFFLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_AC_IMPORTER -# include "ACLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_BVH_IMPORTER -# include "BVHLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_IRRMESH_IMPORTER -# include "IRRMeshLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_IRR_IMPORTER -# include "IRRLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_Q3D_IMPORTER -# include "Q3DLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_B3D_IMPORTER -# include "B3DImporter.h" -#endif -#ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER -# include "ColladaLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER -# include "TerragenLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER -# include "CSMLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_3D_IMPORTER -# include "UnrealLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_LWS_IMPORTER -# include "LWSLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER -# include "OgreImporter.h" -#endif -#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER -# include "MS3DLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_COB_IMPORTER -# include "COBLoader.h" -#endif -#ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER -# include "BlenderLoader.h" -#endif -//#ifndef ASSIMP_BUILD_NO_SWORDOFMOONLIGHT_IMPORTER -//# include "SomLoader.h" -//#endif -#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER -# include "Q3BSPFileImporter.h" -#endif -#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER -# include "NDOLoader.h" -#endif - -// ------------------------------------------------------------------------------------------------ -// Post processing-Steps -// ------------------------------------------------------------------------------------------------ -#ifndef ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS -# include "CalcTangentsProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS -# include "JoinVerticesProcess.h" -#endif -#if !(defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS && defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS && defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) -# include "ConvertToLHProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS -# include "TriangulateProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS -# include "GenFaceNormalsProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS -# include "GenVertexNormalsProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_REMOVEVC_PROCESS -# include "RemoveVCProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS -# include "SplitLargeMeshes.h" -#endif -#ifndef ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS -# include "PretransformVertices.h" -#endif -#ifndef ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS -# include "LimitBoneWeightsProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS -# include "ValidateDataStructure.h" -#endif -#ifndef ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS -# include "ImproveCacheLocality.h" -#endif -#ifndef ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS -# include "FixNormalsStep.h" -#endif -#ifndef ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS -# include "RemoveRedundantMaterials.h" -#endif -#ifndef ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS -# include "FindInvalidDataProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS -# include "FindDegenerates.h" -#endif -#ifndef ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS -# include "SortByPTypeProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS -# include "ComputeUVMappingProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS -# include "TextureTransform.h" -#endif -#ifndef ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS -# include "FindInstancesProcess.h" -#endif -#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS -# include "OptimizeMeshes.h" -#endif -#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS -# include "OptimizeGraph.h" -#endif - -using namespace Assimp; -using namespace Assimp::Intern; - -// ------------------------------------------------------------------------------------------------ -// Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides -// new and delete (and their array counterparts) of public API classes (e.g. Logger) to -// utilize our DLL heap. -// See http://www.gotw.ca/publications/mill15.htm -// ------------------------------------------------------------------------------------------------ -void* AllocateFromAssimpHeap::operator new ( size_t num_bytes) { - return ::operator new(num_bytes); -} - -void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw() { - try { - return AllocateFromAssimpHeap::operator new( num_bytes ); - } - catch( ... ) { - return NULL; - } -} - -void AllocateFromAssimpHeap::operator delete ( void* data) { - return ::operator delete(data); -} - -void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) { - return ::operator new[](num_bytes); -} - -void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() { - try { - return AllocateFromAssimpHeap::operator new[]( num_bytes ); - } - catch( ... ) { - return NULL; - } -} - -void AllocateFromAssimpHeap::operator delete[] ( void* data) { - return ::operator delete[](data); -} - -// ------------------------------------------------------------------------------------------------ -// Importer constructor. -Importer::Importer() -{ - // allocate the pimpl first - pimpl = new ImporterPimpl(); - - pimpl->mScene = NULL; - pimpl->mErrorString = ""; - - // Allocate a default IO handler - pimpl->mIOHandler = new DefaultIOSystem; - pimpl->mIsDefaultHandler = true; - pimpl->bExtraVerbose = false; // disable extra verbose mode by default - - pimpl->mProgressHandler = new DefaultProgressHandler(); - pimpl->mIsDefaultProgressHandler = true; - - // ---------------------------------------------------------------------------- - // Add an instance of each worker class here - // (register_new_importers_here) - // ---------------------------------------------------------------------------- - pimpl->mImporter.reserve(64); -#if (!defined ASSIMP_BUILD_NO_X_IMPORTER) - pimpl->mImporter.push_back( new XFileImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_OBJ_IMPORTER) - pimpl->mImporter.push_back( new ObjFileImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_3DS_IMPORTER) - pimpl->mImporter.push_back( new Discreet3DSImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_MD3_IMPORTER) - pimpl->mImporter.push_back( new MD3Importer()); -#endif -#if (!defined ASSIMP_BUILD_NO_MD2_IMPORTER) - pimpl->mImporter.push_back( new MD2Importer()); -#endif -#if (!defined ASSIMP_BUILD_NO_PLY_IMPORTER) - pimpl->mImporter.push_back( new PLYImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_MDL_IMPORTER) - pimpl->mImporter.push_back( new MDLImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_ASE_IMPORTER) - pimpl->mImporter.push_back( new ASEImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_HMP_IMPORTER) - pimpl->mImporter.push_back( new HMPImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_SMD_IMPORTER) - pimpl->mImporter.push_back( new SMDImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_MDC_IMPORTER) - pimpl->mImporter.push_back( new MDCImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_MD5_IMPORTER) - pimpl->mImporter.push_back( new MD5Importer()); -#endif -#if (!defined ASSIMP_BUILD_NO_STL_IMPORTER) - pimpl->mImporter.push_back( new STLImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER) - pimpl->mImporter.push_back( new LWOImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_DXF_IMPORTER) - pimpl->mImporter.push_back( new DXFImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_NFF_IMPORTER) - pimpl->mImporter.push_back( new NFFImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_RAW_IMPORTER) - pimpl->mImporter.push_back( new RAWImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_OFF_IMPORTER) - pimpl->mImporter.push_back( new OFFImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_AC_IMPORTER) - pimpl->mImporter.push_back( new AC3DImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_BVH_IMPORTER) - pimpl->mImporter.push_back( new BVHLoader()); -#endif -#if (!defined ASSIMP_BUILD_NO_IRRMESH_IMPORTER) - pimpl->mImporter.push_back( new IRRMeshImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_IRR_IMPORTER) - pimpl->mImporter.push_back( new IRRImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_Q3D_IMPORTER) - pimpl->mImporter.push_back( new Q3DImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_B3D_IMPORTER) - pimpl->mImporter.push_back( new B3DImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_COLLADA_IMPORTER) - pimpl->mImporter.push_back( new ColladaLoader()); -#endif -#if (!defined ASSIMP_BUILD_NO_TERRAGEN_IMPORTER) - pimpl->mImporter.push_back( new TerragenImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_CSM_IMPORTER) - pimpl->mImporter.push_back( new CSMImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_3D_IMPORTER) - pimpl->mImporter.push_back( new UnrealImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_LWS_IMPORTER) - pimpl->mImporter.push_back( new LWSImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_OGRE_IMPORTER) - pimpl->mImporter.push_back( new Ogre::OgreImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_MS3D_IMPORTER) - pimpl->mImporter.push_back( new MS3DImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_COB_IMPORTER) - pimpl->mImporter.push_back( new COBImporter()); -#endif -#if (!defined ASSIMP_BUILD_NO_BLEND_IMPORTER) - pimpl->mImporter.push_back( new BlenderImporter()); -#endif -//#if (!defined ASSIMP_BUILD_NO_SWORDOFMOONLIGHT_IMPORTER) -// pimpl->mImporter.push_back( new SomImporter()); -//#endif -#if (!defined ASSIMP_BUILD_NO_Q3BSP_IMPORTER) - pimpl->mImporter.push_back( new Q3BSPFileImporter() ); -#endif -#if (!defined ASSIMP_BUILD_NO_NDO_IMPORTER) - pimpl->mImporter.push_back( new NDOImporter() ); -#endif - - // ---------------------------------------------------------------------------- - // Add an instance of each post processing step here in the order - // of sequence it is executed. Steps that are added here are not - // validated - as RegisterPPStep() does - all dependencies must be given. - // ---------------------------------------------------------------------------- - pimpl->mPostProcessingSteps.reserve(25); -#if (!defined ASSIMP_BUILD_NO_REMOVEVC_PROCESS) - pimpl->mPostProcessingSteps.push_back( new RemoveVCProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_REMOVE_REDUNDANTMATERIALS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new RemoveRedundantMatsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FINDINSTANCES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new FindInstancesProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS) - pimpl->mPostProcessingSteps.push_back( new OptimizeGraphProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new OptimizeMeshesProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FINDDEGENERATES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new FindDegeneratesProcess()); -#endif -#ifndef ASSIMP_BUILD_NO_GENUVCOORDS_PROCESS - pimpl->mPostProcessingSteps.push_back( new ComputeUVMappingProcess()); -#endif -#ifndef ASSIMP_BUILD_NO_TRANSFORMTEXCOORDS_PROCESS - pimpl->mPostProcessingSteps.push_back( new TextureTransformStep()); -#endif -#if (!defined ASSIMP_BUILD_NO_PRETRANSFORMVERTICES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new PretransformVertices()); -#endif -#if (!defined ASSIMP_BUILD_NO_TRIANGULATE_PROCESS) - pimpl->mPostProcessingSteps.push_back( new TriangulateProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_SORTBYPTYPE_PROCESS) - pimpl->mPostProcessingSteps.push_back( new SortByPTypeProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FINDINVALIDDATA_PROCESS) - pimpl->mPostProcessingSteps.push_back( new FindInvalidDataProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FIXINFACINGNORMALS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new FixInfacingNormalsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Triangle()); -#endif -#if (!defined ASSIMP_BUILD_NO_GENFACENORMALS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new GenFaceNormalsProcess()); -#endif - - // ......................................................................... - // DON'T change the order of these five! - pimpl->mPostProcessingSteps.push_back( new ComputeSpatialSortProcess()); - // ......................................................................... - -#if (!defined ASSIMP_BUILD_NO_GENVERTEXNORMALS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new GenVertexNormalsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_CALCTANGENTS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new CalcTangentsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_JOINVERTICES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new JoinVerticesProcess()); -#endif - - // ......................................................................... - pimpl->mPostProcessingSteps.push_back( new DestroySpatialSortProcess()); - // ......................................................................... - -#if (!defined ASSIMP_BUILD_NO_SPLITLARGEMESHES_PROCESS) - pimpl->mPostProcessingSteps.push_back( new SplitLargeMeshesProcess_Vertex()); -#endif -#if (!defined ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS) - pimpl->mPostProcessingSteps.push_back( new MakeLeftHandedProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FLIPUVS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new FlipUVsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_FLIPWINDINGORDER_PROCESS) - pimpl->mPostProcessingSteps.push_back( new FlipWindingOrderProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_LIMITBONEWEIGHTS_PROCESS) - pimpl->mPostProcessingSteps.push_back( new LimitBoneWeightsProcess()); -#endif -#if (!defined ASSIMP_BUILD_NO_IMPROVECACHELOCALITY_PROCESS) - pimpl->mPostProcessingSteps.push_back( new ImproveCacheLocalityProcess()); -#endif - - // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list. - pimpl->mPPShared = new SharedPostProcessInfo(); - for (std::vector<BaseProcess*>::iterator it = pimpl->mPostProcessingSteps.begin(); - it != pimpl->mPostProcessingSteps.end(); - ++it) { - - (*it)->SetSharedData(pimpl->mPPShared); - } -} - -// ------------------------------------------------------------------------------------------------ -// Destructor of Importer -Importer::~Importer() -{ - // Delete all import plugins - for ( unsigned int a = 0; a < pimpl->mImporter.size(); a++) - delete pimpl->mImporter[a]; - - // Delete all post-processing plug-ins - for ( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) - delete pimpl->mPostProcessingSteps[a]; - - // Delete the assigned IO handler - delete pimpl->mIOHandler; - - // Kill imported scene. Destructors should do that recursivly - delete pimpl->mScene; - - // Delete shared post-processing data - delete pimpl->mPPShared; - - // and finally the pimpl itself - delete pimpl; -} - -// ------------------------------------------------------------------------------------------------ -// Copy constructor - copies the config of another Importer, not the scene -Importer::Importer(const Importer &other) -{ - new(this) Importer(); - - pimpl->mIntProperties = other.pimpl->mIntProperties; - pimpl->mFloatProperties = other.pimpl->mFloatProperties; - pimpl->mStringProperties = other.pimpl->mStringProperties; -} - -// ------------------------------------------------------------------------------------------------ -// Register a custom post-processing step -aiReturn Importer::RegisterPPStep(BaseProcess* pImp) -{ - ai_assert(NULL != pImp); - ASSIMP_BEGIN_EXCEPTION_REGION(); - - pimpl->mPostProcessingSteps.push_back(pImp); - DefaultLogger::get()->info("Registering custom post-processing step"); - - ASSIMP_END_EXCEPTION_REGION(aiReturn); - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -// Register a custom loader plugin -aiReturn Importer::RegisterLoader(BaseImporter* pImp) -{ - ai_assert(NULL != pImp); - ASSIMP_BEGIN_EXCEPTION_REGION(); - - // -------------------------------------------------------------------- - // Check whether we would have two loaders for the same file extension - // This is absolutely OK, but we should warn the developer of the new - // loader that his code will probably never be called if the first - // loader is a bit too lazy in his file checking. - // -------------------------------------------------------------------- - std::set<std::string> st; - std::string baked; - pImp->GetExtensionList(st); - - for (std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) { - -#ifdef _DEBUG - if (IsExtensionSupported(*it)) { - DefaultLogger::get()->warn("The file extension " + *it + " is already in use"); - } -#endif - baked += *it; - } - - // add the loader - pimpl->mImporter.push_back(pImp); - DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked); - ASSIMP_END_EXCEPTION_REGION(aiReturn); - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -// Unregister a custom loader plugin -aiReturn Importer::UnregisterLoader(BaseImporter* pImp) -{ - if (!pImp) { - // unregistering a NULL importer is no problem for us ... really! - return AI_SUCCESS; - } - - ASSIMP_BEGIN_EXCEPTION_REGION(); - std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(), - pimpl->mImporter.end(),pImp); - - if (it != pimpl->mImporter.end()) { - pimpl->mImporter.erase(it); - - std::set<std::string> st; - pImp->GetExtensionList(st); - - DefaultLogger::get()->info("Unregistering custom importer: "); - return AI_SUCCESS; - } - DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ..."); - ASSIMP_END_EXCEPTION_REGION(aiReturn); - return AI_FAILURE; -} - -// ------------------------------------------------------------------------------------------------ -// Unregister a custom loader plugin -aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) -{ - if (!pImp) { - // unregistering a NULL ppstep is no problem for us ... really! - return AI_SUCCESS; - } - - ASSIMP_BEGIN_EXCEPTION_REGION(); - std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(), - pimpl->mPostProcessingSteps.end(),pImp); - - if (it != pimpl->mPostProcessingSteps.end()) { - pimpl->mPostProcessingSteps.erase(it); - DefaultLogger::get()->info("Unregistering custom post-processing step"); - return AI_SUCCESS; - } - DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you .."); - ASSIMP_END_EXCEPTION_REGION(aiReturn); - return AI_FAILURE; -} - -// ------------------------------------------------------------------------------------------------ -// Supplies a custom IO handler to the importer to open and access files. -void Importer::SetIOHandler( IOSystem* pIOHandler) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - // If the new handler is zero, allocate a default IO implementation. - if (!pIOHandler) - { - // Release pointer in the possession of the caller - pimpl->mIOHandler = new DefaultIOSystem(); - pimpl->mIsDefaultHandler = true; - } - // Otherwise register the custom handler - else if (pimpl->mIOHandler != pIOHandler) - { - delete pimpl->mIOHandler; - pimpl->mIOHandler = pIOHandler; - pimpl->mIsDefaultHandler = false; - } - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Get the currently set IO handler -IOSystem* Importer::GetIOHandler() const -{ - return pimpl->mIOHandler; -} - -// ------------------------------------------------------------------------------------------------ -// Check whether a custom IO handler is currently set -bool Importer::IsDefaultIOHandler() const -{ - return pimpl->mIsDefaultHandler; -} - -// ------------------------------------------------------------------------------------------------ -// Supplies a custom progress handler to get regular callbacks during importing -void Importer::SetProgressHandler ( ProgressHandler* pHandler ) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - // If the new handler is zero, allocate a default implementation. - if (!pHandler) - { - // Release pointer in the possession of the caller - pimpl->mProgressHandler = new DefaultProgressHandler(); - pimpl->mIsDefaultProgressHandler = true; - } - // Otherwise register the custom handler - else if (pimpl->mProgressHandler != pHandler) - { - delete pimpl->mProgressHandler; - pimpl->mProgressHandler = pHandler; - pimpl->mIsDefaultProgressHandler = false; - } - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Get the currently set progress handler -ProgressHandler* Importer::GetProgressHandler() const -{ - return pimpl->mProgressHandler; -} - -// ------------------------------------------------------------------------------------------------ -// Check whether a custom progress handler is currently set -bool Importer::IsDefaultProgressHandler() const -{ - return pimpl->mIsDefaultProgressHandler; -} - -// ------------------------------------------------------------------------------------------------ -// Validate post process step flags -bool _ValidateFlags(unsigned int pFlags) -{ - if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) { - DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible"); - return false; - } - if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) { - DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible"); - return false; - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Free the current scene -void Importer::FreeScene( ) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - delete pimpl->mScene; - pimpl->mScene = NULL; - - pimpl->mErrorString = ""; - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Get the current error string, if any -const char* Importer::GetErrorString() const -{ - /* Must remain valid as long as ReadFile() or FreeFile() are not called */ - return pimpl->mErrorString.c_str(); -} - -// ------------------------------------------------------------------------------------------------ -// Enable extra-verbose mode -void Importer::SetExtraVerbose(bool bDo) -{ - pimpl->bExtraVerbose = bDo; -} - -// ------------------------------------------------------------------------------------------------ -// Get the current scene -const aiScene* Importer::GetScene() const -{ - return pimpl->mScene; -} - -// ------------------------------------------------------------------------------------------------ -// Orphan the current scene and return it. -aiScene* Importer::GetOrphanedScene() -{ - aiScene* s = pimpl->mScene; - - ASSIMP_BEGIN_EXCEPTION_REGION(); - pimpl->mScene = NULL; - - pimpl->mErrorString = ""; /* reset error string */ - ASSIMP_END_EXCEPTION_REGION(aiScene*); - return s; -} - -// ------------------------------------------------------------------------------------------------ -// Validate post-processing flags -bool Importer::ValidateFlags(unsigned int pFlags) const -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - // run basic checks for mutually exclusive flags - if (!_ValidateFlags(pFlags)) { - return false; - } - - // ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ... -#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - if (pFlags & aiProcess_ValidateDataStructure) { - return false; - } -#endif - pFlags &= ~aiProcess_ValidateDataStructure; - - // Now iterate through all bits which are set in the flags and check whether we find at least - // one pp plugin which handles it. - for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) { - - if (pFlags & mask) { - - bool have = false; - for ( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { - if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) { - - have = true; - break; - } - } - if (!have) { - return false; - } - } - } - ASSIMP_END_EXCEPTION_REGION(bool); - return true; -} - -// ------------------------------------------------------------------------------------------------ -const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, - size_t pLength, - unsigned int pFlags, - const char* pHint /*= ""*/) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - if (!pHint) { - pHint = ""; - } - - if (!pBuffer || !pLength || strlen(pHint) > 100) { - pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()"; - return NULL; - } - - // prevent deletion of the previous IOHandler - IOSystem* io = pimpl->mIOHandler; - pimpl->mIOHandler = NULL; - - SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength)); - - // read the file and recover the previous IOSystem - char fbuff[128]; - sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint); - - ReadFile(fbuff,pFlags); - SetIOHandler(io); - - ASSIMP_END_EXCEPTION_REGION(const aiScene*); - return pimpl->mScene; -} - -// ------------------------------------------------------------------------------------------------ -void WriteLogOpening(const std::string& file) -{ - Logger* l = DefaultLogger::get(); - if (!l) { - return; - } - l->info("Load " + file); - - // print a full version dump. This is nice because we don't - // need to ask the authors of incoming bug reports for - // the library version they're using - a log dump is - // sufficient. - const unsigned int flags = aiGetCompileFlags(); - l->debug(format() - << "Assimp " - << aiGetVersionMajor() - << "." - << aiGetVersionMinor() - << "." - << aiGetVersionRevision() - -#if defined(ASSIMP_BUILD_X86_32BIT_ARCHITECTURE) - << " x86" -#elif defined(ASSIMP_BUILD_X86_64BIT_ARCHITECTURE) - << " amd64" -#elif defined(ASSIMP_BUILD_IA_64BIT_ARCHITECTURE) - << " itanium" -#elif defined(ASSIMP_BUILD_PPC_32BIT_ARCHITECTURE) - << " ppc32" -#elif defined(ASSIMP_BUILD_ARM_32BIT_ARCHITECTURE) - << " arm32" -#else -# error unknown architecture -#endif - -#if defined(_MSC_VER) - << " msvc" -#elif defined(__GNUC__) - << " gcc" -#else -# warning unknown compiler -#endif - -#ifndef NDEBUG - << " debug" -#endif - - << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "") - << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "") - << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "") - ); -} - -// ------------------------------------------------------------------------------------------------ -// Reads the given file and returns its contents if successful. -const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - const std::string pFile(_pFile); - - // ---------------------------------------------------------------------- - // Put a large try block around everything to catch all std::exception's - // that might be thrown by STL containers or by new(). - // ImportErrorException's are throw by ourselves and caught elsewhere. - //----------------------------------------------------------------------- - - WriteLogOpening(pFile); - -#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS - try -#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS - { - // Check whether this Importer instance has already loaded - // a scene. In this case we need to delete the old one - if (pimpl->mScene) { - - DefaultLogger::get()->debug("(Deleting previous scene)"); - FreeScene(); - } - - // First check if the file is accessable at all - if ( !pimpl->mIOHandler->Exists( pFile)) { - - pimpl->mErrorString = "Unable to open file \"" + pFile + "\"."; - DefaultLogger::get()->error(pimpl->mErrorString); - return NULL; - } - - boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL); - if (profiler) { - profiler->BeginRegion("total"); - } - - // Find an worker class which can handle the file - BaseImporter* imp = NULL; - for ( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { - - if ( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) { - imp = pimpl->mImporter[a]; - break; - } - } - - if (!imp) { - // not so bad yet ... try format auto detection. - const std::string::size_type s = pFile.find_last_of('.'); - if (s != std::string::npos) { - DefaultLogger::get()->info("File extension now known, trying signature-based detection"); - for ( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { - - if ( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { - imp = pimpl->mImporter[a]; - break; - } - } - } - // Put a proper error message if no suitable importer was found - if ( !imp) { - pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\"."; - DefaultLogger::get()->error(pimpl->mErrorString); - return NULL; - } - } - - // Dispatch the reading to the worker class for this format - DefaultLogger::get()->info("Found a matching importer for this file format"); - pimpl->mProgressHandler->Update(); - - if (profiler) { - profiler->BeginRegion("import"); - } - - pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler); - pimpl->mProgressHandler->Update(); - - if (profiler) { - profiler->EndRegion("import"); - } - - // If successful, apply all active post processing steps to the imported data - if ( pimpl->mScene) { - -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called. - if (pFlags & aiProcess_ValidateDataStructure) - { - ValidateDSProcess ds; - ds.ExecuteOnScene (this); - if (!pimpl->mScene) { - return NULL; - } - } -#endif // no validation - - // Preprocess the scene and prepare it for post-processing - if (profiler) { - profiler->BeginRegion("preprocess"); - } - - ScenePreprocessor pre(pimpl->mScene); - pre.ProcessScene(); - - pimpl->mProgressHandler->Update(); - if (profiler) { - profiler->EndRegion("preprocess"); - } - - // Ensure that the validation process won't be called twice - ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure)); - } - // if failed, extract the error string - else if ( !pimpl->mScene) { - pimpl->mErrorString = imp->GetErrorText(); - } - - // clear any data allocated by post-process steps - pimpl->mPPShared->Clean(); - - if (profiler) { - profiler->EndRegion("total"); - } - } -#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS - catch (std::exception &e) - { -#if (defined _MSC_VER) && (defined _CPPRTTI) - // if we have RTTI get the full name of the exception that occured - pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what(); -#else - pimpl->mErrorString = std::string("std::exception: ") + e.what(); -#endif - - DefaultLogger::get()->error(pimpl->mErrorString); - delete pimpl->mScene; pimpl->mScene = NULL; - } -#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS - - // either successful or failure - the pointer expresses it anyways - ASSIMP_END_EXCEPTION_REGION(const aiScene*); - return pimpl->mScene; -} - - -// ------------------------------------------------------------------------------------------------ -// Apply post-processing to the currently bound scene -const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - // Return immediately if no scene is active - if (!pimpl->mScene) { - return NULL; - } - - // If no flags are given, return the current scene with no further action - if (!pFlags) { - return pimpl->mScene; - } - - // In debug builds: run basic flag validation - ai_assert(_ValidateFlags(pFlags)); - DefaultLogger::get()->info("Entering post processing pipeline"); - -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - // The ValidateDS process plays an exceptional role. It isn't contained in the global - // list of post-processing steps, so we need to call it manually. - if (pFlags & aiProcess_ValidateDataStructure) - { - ValidateDSProcess ds; - ds.ExecuteOnScene (this); - if (!pimpl->mScene) { - return NULL; - } - } -#endif // no validation -#ifdef _DEBUG - if (pimpl->bExtraVerbose) - { -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - DefaultLogger::get()->error("Verbose Import is not available due to build settings"); -#endif // no validation - pFlags |= aiProcess_ValidateDataStructure; - } -#else - if (pimpl->bExtraVerbose) { - DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting"); - } -#endif // ! DEBUG - - boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL); - for ( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { - - BaseProcess* process = pimpl->mPostProcessingSteps[a]; - if ( process->IsActive( pFlags)) { - - if (profiler) { - profiler->BeginRegion("postprocess"); - } - - process->ExecuteOnScene ( this ); - pimpl->mProgressHandler->Update(); - - if (profiler) { - profiler->EndRegion("postprocess"); - } - } - if ( !pimpl->mScene) { - break; - } -#ifdef _DEBUG - -#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS - continue; -#endif // no validation - - // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step - if (pimpl->bExtraVerbose) { - DefaultLogger::get()->debug("Verbose Import: revalidating data structures"); - - ValidateDSProcess ds; - ds.ExecuteOnScene (this); - if ( !pimpl->mScene) { - DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures"); - break; - } - } -#endif // ! DEBUG - } - - // clear any data allocated by post-process steps - pimpl->mPPShared->Clean(); - DefaultLogger::get()->info("Leaving post processing pipeline"); - - ASSIMP_END_EXCEPTION_REGION(const aiScene*); - return pimpl->mScene; -} - -// ------------------------------------------------------------------------------------------------ -// Helper function to check whether an extension is supported by ASSIMP -bool Importer::IsExtensionSupported(const char* szExtension) const -{ - return NULL != FindLoader(szExtension); -} - -// ------------------------------------------------------------------------------------------------ -// Find a loader plugin for a given file extension -BaseImporter* Importer::FindLoader (const char* szExtension) const -{ - ai_assert(szExtension); - ASSIMP_BEGIN_EXCEPTION_REGION(); - - // skip over wildcard and dot characters at string head -- - for (;*szExtension == '*' || *szExtension == '.'; ++szExtension); - - std::string ext(szExtension); - if (ext.empty()) { - return NULL; - } - std::transform(ext.begin(),ext.end(), ext.begin(), tolower); - - std::set<std::string> str; - for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) { - str.clear(); - - (*i)->GetExtensionList(str); - for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) { - if (ext == *it) { - return (*i); - } - } - } - ASSIMP_END_EXCEPTION_REGION(BaseImporter*); - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// Helper function to build a list of all file extensions supported by ASSIMP -void Importer::GetExtensionList(aiString& szOut) const -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - std::set<std::string> str; - for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) { - (*i)->GetExtensionList(str); - } - - for (std::set<std::string>::const_iterator it = str.begin();; ) { - szOut.Append("*."); - szOut.Append((*it).c_str()); - - if (++it == str.end()) { - break; - } - szOut.Append(";"); - } - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Set a configuration property -void Importer::SetPropertyInteger(const char* szName, int iValue, - bool* bWasExisting /*= NULL*/) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue,bWasExisting); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Set a configuration property -void Importer::SetPropertyFloat(const char* szName, float iValue, - bool* bWasExisting /*= NULL*/) -{ - ASSIMP_BEGIN_EXCEPTION_REGION(); - SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue,bWasExisting); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Set a configuration property -void Importer::SetPropertyString(const char* szName, const std::string& value, - bool* bWasExisting /*= NULL*/) -{ - try { - std::cout << ""; - } - catch (...) { - try { - throw; - } - catch(std::exception&) { - return; - } - } - - ASSIMP_BEGIN_EXCEPTION_REGION(); - SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value,bWasExisting); - ASSIMP_END_EXCEPTION_REGION(void); -} - -// ------------------------------------------------------------------------------------------------ -// Get a configuration property -int Importer::GetPropertyInteger(const char* szName, - int iErrorReturn /*= 0xffffffff*/) const -{ - return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn); -} - -// ------------------------------------------------------------------------------------------------ -// Get a configuration property -float Importer::GetPropertyFloat(const char* szName, - float iErrorReturn /*= 10e10*/) const -{ - return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn); -} - -// ------------------------------------------------------------------------------------------------ -// Get a configuration property -const std::string& Importer::GetPropertyString(const char* szName, - const std::string& iErrorReturn /*= ""*/) const -{ - return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn); -} - -// ------------------------------------------------------------------------------------------------ -// Get the memory requirements of a single node -inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) -{ - iScene += sizeof(aiNode); - iScene += sizeof(unsigned int) * pcNode->mNumMeshes; - iScene += sizeof(void*) * pcNode->mNumChildren; - - for (unsigned int i = 0; i < pcNode->mNumChildren;++i) { - AddNodeWeight(iScene,pcNode->mChildren[i]); - } -} - -// ------------------------------------------------------------------------------------------------ -// Get the memory requirements of the scene -void Importer::GetMemoryRequirements(aiMemoryInfo& in) const -{ - in = aiMemoryInfo(); - aiScene* mScene = pimpl->mScene; - - // return if we have no scene loaded - if (!pimpl->mScene) - return; - - - in.total = sizeof(aiScene); - - // add all meshes - for (unsigned int i = 0; i < mScene->mNumMeshes;++i) - { - in.meshes += sizeof(aiMesh); - if (mScene->mMeshes[i]->HasPositions()) { - in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices; - } - - if (mScene->mMeshes[i]->HasNormals()) { - in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices; - } - - if (mScene->mMeshes[i]->HasTangentsAndBitangents()) { - in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2; - } - - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) { - if (mScene->mMeshes[i]->HasVertexColors(a)) { - in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices; - } - else break; - } - for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) { - if (mScene->mMeshes[i]->HasTextureCoords(a)) { - in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices; - } - else break; - } - if (mScene->mMeshes[i]->HasBones()) { - in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones; - for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) { - in.meshes += sizeof(aiBone); - in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight); - } - } - in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces; - } - in.total += in.meshes; - - // add all embedded textures - for (unsigned int i = 0; i < mScene->mNumTextures;++i) { - const aiTexture* pc = mScene->mTextures[i]; - in.textures += sizeof(aiTexture); - if (pc->mHeight) { - in.textures += 4 * pc->mHeight * pc->mWidth; - } - else in.textures += pc->mWidth; - } - in.total += in.textures; - - // add all animations - for (unsigned int i = 0; i < mScene->mNumAnimations;++i) { - const aiAnimation* pc = mScene->mAnimations[i]; - in.animations += sizeof(aiAnimation); - - // add all bone anims - for (unsigned int a = 0; a < pc->mNumChannels; ++a) { - const aiNodeAnim* pc2 = pc->mChannels[i]; - in.animations += sizeof(aiNodeAnim); - in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey); - in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey); - in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey); - } - } - in.total += in.animations; - - // add all cameras and all lights - in.total += in.cameras = sizeof(aiCamera) * mScene->mNumCameras; - in.total += in.lights = sizeof(aiLight) * mScene->mNumLights; - - // add all nodes - AddNodeWeight(in.nodes,mScene->mRootNode); - in.total += in.nodes; - - // add all materials - for (unsigned int i = 0; i < mScene->mNumMaterials;++i) { - const aiMaterial* pc = mScene->mMaterials[i]; - in.materials += sizeof(aiMaterial); - in.materials += pc->mNumAllocated * sizeof(void*); - - for (unsigned int a = 0; a < pc->mNumProperties;++a) { - in.materials += pc->mProperties[a]->mDataLength; - } - } - in.total += in.materials; -} - diff --git a/3rdparty/assimp/code/ImproveCacheLocality.cpp b/3rdparty/assimp/code/ImproveCacheLocality.cpp deleted file mode 100644 index 26891407..00000000 --- a/3rdparty/assimp/code/ImproveCacheLocality.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to improve the cache locality of a mesh. - * <br> - * The algorithm is roughly basing on this paper: - * http://www.cs.princeton.edu/gfx/pubs/Sander_2007_%3ETR/tipsy.pdf - * .. although overdraw rduction isn't implemented yet ... - */ - -#include "AssimpPCH.h" - -// internal headers -#include "ImproveCacheLocality.h" -#include "VertexTriangleAdjacency.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() { - configCacheDepth = PP_ICL_PTCACHE_SIZE; -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ImproveCacheLocalityProcess::~ImproveCacheLocalityProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_ImproveCacheLocality) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration -void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) -{ - // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer - configCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void ImproveCacheLocalityProcess::Execute( aiScene* pScene) -{ - if (!pScene->mNumMeshes) { - DefaultLogger::get()->debug("ImproveCacheLocalityProcess skipped; there are no meshes"); - return; - } - - DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin"); - - float out = 0.f; - unsigned int numf = 0, numm = 0; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++){ - const float res = ProcessMesh( pScene->mMeshes[a],a); - if (res) { - numf += pScene->mMeshes[a]->mNumFaces; - out += res; - ++numm; - } - } - if (!DefaultLogger::isNullLogger()) { - char szBuff[128]; // should be sufficiently large in every case - ::sprintf(szBuff,"Cache relevant are %i meshes (%i faces). Average output ACMR is %f", - numm,numf,out/numf); - - DefaultLogger::get()->info(szBuff); - DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. "); - } -} - -// ------------------------------------------------------------------------------------------------ -// Improves the cache coherency of a specific mesh -float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum) -{ - // TODO: rewrite this to use std::vector or boost::shared_array - ai_assert(NULL != pMesh); - - // Check whether the input data is valid - // - there must be vertices and faces - // - all faces must be triangulated or we can't operate on them - if (!pMesh->HasFaces() || !pMesh->HasPositions()) - return 0.f; - - if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) { - DefaultLogger::get()->error("This algorithm works on triangle meshes only"); - return 0.f; - } - - float fACMR = 3.f; - const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces; - - // Input ACMR is for logging purposes only - if (!DefaultLogger::isNullLogger()) { - - unsigned int* piFIFOStack = new unsigned int[configCacheDepth]; - memset(piFIFOStack,0xff,configCacheDepth*sizeof(unsigned int)); - unsigned int* piCur = piFIFOStack; - const unsigned int* const piCurEnd = piFIFOStack + configCacheDepth; - - // count the number of cache misses - unsigned int iCacheMisses = 0; - for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) { - - for (unsigned int qq = 0; qq < 3;++qq) { - bool bInCache = false; - - for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) { - if (*pp == pcFace->mIndices[qq]) { - // the vertex is in cache - bInCache = true; - break; - } - } - if (!bInCache) { - ++iCacheMisses; - if (piCurEnd == piCur) { - piCur = piFIFOStack; - } - *piCur++ = pcFace->mIndices[qq]; - } - } - } - delete[] piFIFOStack; - fACMR = (float)iCacheMisses / pMesh->mNumFaces; - if (3.0 == fACMR) { - char szBuff[128]; // should be sufficiently large in every case - - // the JoinIdenticalVertices process has not been executed on this - // mesh, otherwise this value would normally be at least minimally - // smaller than 3.0 ... - sprintf(szBuff,"Mesh %i: Not suitable for vcache optimization",meshNum); - DefaultLogger::get()->warn(szBuff); - return 0.f; - } - } - - // first we need to build a vertex-triangle adjacency list - VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true); - - // build a list to store per-vertex caching time stamps - unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices]; - memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int)); - - // allocate an empty output index buffer. We store the output indices in one large array. - // Since the number of triangles won't change the input faces can be reused. This is how - // we save thousands of redundant mini allocations for aiFace::mIndices - const unsigned int iIdxCnt = pMesh->mNumFaces*3; - unsigned int* const piIBOutput = new unsigned int[iIdxCnt]; - unsigned int* piCSIter = piIBOutput; - - // allocate the flag array to hold the information - // whether a face has already been emitted or not - std::vector<bool> abEmitted(pMesh->mNumFaces,false); - - // dead-end vertex index stack - std::stack<unsigned int> sDeadEndVStack; - - // create a copy of the piNumTriPtr buffer - unsigned int* const piNumTriPtr = adj.mLiveTriangles; - const unsigned int* const piNumTriPtrNoModify = new unsigned int[pMesh->mNumVertices]; - memcpy(const_cast<unsigned int* const> (piNumTriPtrNoModify),piNumTriPtr, - pMesh->mNumVertices * sizeof(unsigned int)); - - // get the largest number of referenced triangles and allocate the "candidate buffer" - unsigned int iMaxRefTris = 0; { - const unsigned int* piCur = adj.mLiveTriangles; - const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices; - for (;piCur != piCurEnd;++piCur) { - iMaxRefTris = std::max(iMaxRefTris,*piCur); - } - } - unsigned int* piCandidates = new unsigned int[iMaxRefTris*3]; - unsigned int iCacheMisses = 0; - - // ................................................................................... - /** PSEUDOCODE for the algorithm - - A = Build-Adjacency(I) Vertex-triangle adjacency - L = Get-Triangle-Counts(A) Per-vertex live triangle counts - C = Zero(Vertex-Count(I)) Per-vertex caching time stamps - D = Empty-Stack() Dead-end vertex stack - E = False(Triangle-Count(I)) Per triangle emitted flag - O = Empty-Index-Buffer() Empty output buffer - f = 0 Arbitrary starting vertex - s = k+1, i = 1 Time stamp and cursor - while f >= 0 For all valid fanning vertices - N = Empty-Set() 1-ring of next candidates - for each Triangle t in Neighbors(A, f) - if !Emitted(E,t) - for each Vertex v in t - Append(O,v) Output vertex - Push(D,v) Add to dead-end stack - Insert(N,v) Register as candidate - L[v] = L[v]-1 Decrease live triangle count - if s-C[v] > k If not in cache - C[v] = s Set time stamp - s = s+1 Increment time stamp - E[t] = true Flag triangle as emitted - Select next fanning vertex - f = Get-Next-Vertex(I,i,k,N,C,s,L,D) - return O - */ - // ................................................................................... - - int ivdx = 0; - int ics = 1; - int iStampCnt = configCacheDepth+1; - while (ivdx >= 0) { - - unsigned int icnt = piNumTriPtrNoModify[ivdx]; - unsigned int* piList = adj.GetAdjacentTriangles(ivdx); - unsigned int* piCurCandidate = piCandidates; - - // get all triangles in the neighborhood - for (unsigned int tri = 0; tri < icnt;++tri) { - - // if they have not yet been emitted, add them to the output IB - const unsigned int fidx = *piList++; - if (!abEmitted[fidx]) { - - // so iterate through all vertices of the current triangle - const aiFace* pcFace = &pMesh->mFaces[ fidx ]; - for (unsigned int* p = pcFace->mIndices, *p2 = pcFace->mIndices+3;p != p2;++p) { - const unsigned int dp = *p; - - // the current vertex won't have any free triangles after this step - if (ivdx != (int)dp) { - // append the vertex to the dead-end stack - sDeadEndVStack.push(dp); - - // register as candidate for the next step - *piCurCandidate++ = dp; - - // decrease the per-vertex triangle counts - piNumTriPtr[dp]--; - } - - // append the vertex to the output index buffer - *piCSIter++ = dp; - - // if the vertex is not yet in cache, set its cache count - if (iStampCnt-piCachingStamps[dp] > configCacheDepth) { - piCachingStamps[dp] = iStampCnt++; - ++iCacheMisses; - } - } - // flag triangle as emitted - abEmitted[fidx] = true; - } - } - - // the vertex has now no living adjacent triangles anymore - piNumTriPtr[ivdx] = 0; - - // get next fanning vertex - ivdx = -1; - int max_priority = -1; - for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) { - register const unsigned int dp = *piCur; - - // must have live triangles - if (piNumTriPtr[dp] > 0) { - int priority = 0; - - // will the vertex be in cache, even after fanning occurs? - unsigned int tmp; - if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= configCacheDepth) { - priority = tmp; - } - - // keep best candidate - if (priority > max_priority) { - max_priority = priority; - ivdx = dp; - } - } - } - // did we reach a dead end? - if (-1 == ivdx) { - // need to get a non-local vertex for which we have a good chance that it is still - // in the cache ... - while (!sDeadEndVStack.empty()) { - unsigned int iCachedIdx = sDeadEndVStack.top(); - sDeadEndVStack.pop(); - if (piNumTriPtr[ iCachedIdx ] > 0) { - ivdx = iCachedIdx; - break; - } - } - - if (-1 == ivdx) { - // well, there isn't such a vertex. Simply get the next vertex in input order and - // hope it is not too bad ... - while (ics < (int)pMesh->mNumVertices) { - ++ics; - if (piNumTriPtr[ics] > 0) { - ivdx = ics; - break; - } - } - } - } - } - float fACMR2 = 0.0f; - if (!DefaultLogger::isNullLogger()) { - fACMR2 = (float)iCacheMisses / pMesh->mNumFaces; - - // very intense verbose logging ... prepare for much text if there are many meshes - if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - char szBuff[128]; // should be sufficiently large in every case - - ::sprintf(szBuff,"Mesh %i | ACMR in: %f out: %f | ~%.1f%%",meshNum,fACMR,fACMR2, - ((fACMR - fACMR2) / fACMR) * 100.f); - DefaultLogger::get()->debug(szBuff); - } - - fACMR2 *= pMesh->mNumFaces; - } - // sort the output index buffer back to the input array - piCSIter = piIBOutput; - for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) { - pcFace->mIndices[0] = *piCSIter++; - pcFace->mIndices[1] = *piCSIter++; - pcFace->mIndices[2] = *piCSIter++; - } - - // delete temporary storage - delete[] piCachingStamps; - delete[] piIBOutput; - delete[] piCandidates; - delete[] piNumTriPtrNoModify; - return fACMR2; -} diff --git a/3rdparty/assimp/code/ImproveCacheLocality.h b/3rdparty/assimp/code/ImproveCacheLocality.h deleted file mode 100644 index 58613e04..00000000 --- a/3rdparty/assimp/code/ImproveCacheLocality.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to reorder faces for - better cache locality*/ -#ifndef AI_IMPROVECACHELOCALITY_H_INC -#define AI_IMPROVECACHELOCALITY_H_INC - -#include "BaseProcess.h" -#include "../include/aiTypes.h" - -struct aiMesh; - -namespace Assimp -{ - -// --------------------------------------------------------------------------- -/** The ImproveCacheLocalityProcess reorders all faces for improved vertex - * cache locality. It tries to arrange all faces to fans and to render - * faces which share vertices directly one after the other. - * - * @note This step expects triagulated input data. - */ -class ASSIMP_API ImproveCacheLocalityProcess : public BaseProcess -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - ImproveCacheLocalityProcess(); - - /** Destructor, private as well */ - ~ImproveCacheLocalityProcess(); - -public: - - // ------------------------------------------------------------------- - // Check whether the pp step is active - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - // Executes the pp step on a given scene - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - // Configures the pp step - void SetupProperties(const Importer* pImp); - -protected: - // ------------------------------------------------------------------- - /** Executes the postprocessing step on the given mesh - * @param pMesh The mesh to process. - * @param meshNum Index of the mesh to process - */ - float ProcessMesh( aiMesh* pMesh, unsigned int meshNum); - -private: - //! Configuration parameter: specifies the size of the cache to - //! optimize the vertex data for. - unsigned int configCacheDepth; -}; - -} // end of namespace Assimp - -#endif // AI_IMPROVECACHELOCALITY_H_INC diff --git a/3rdparty/assimp/code/JoinVerticesProcess.cpp b/3rdparty/assimp/code/JoinVerticesProcess.cpp deleted file mode 100644 index acc98cb8..00000000 --- a/3rdparty/assimp/code/JoinVerticesProcess.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to join identical vertices - * for all imported meshes - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_JOINVERTICES_PROCESS - -#include "JoinVerticesProcess.h" -#include "ProcessHelper.h" -#include "Vertex.h" -#include "TinyFormatter.h" - -using namespace Assimp; -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -JoinVerticesProcess::JoinVerticesProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -JoinVerticesProcess::~JoinVerticesProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool JoinVerticesProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_JoinIdenticalVertices) != 0; -} -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void JoinVerticesProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("JoinVerticesProcess begin"); - - // get the total number of vertices BEFORE the step is executed - int iNumOldVertices = 0; - if (!DefaultLogger::isNullLogger()) { - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) { - iNumOldVertices += pScene->mMeshes[a]->mNumVertices; - } - } - - // execute the step - int iNumVertices = 0; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - iNumVertices += ProcessMesh( pScene->mMeshes[a],a); - - // if logging is active, print detailed statistics - if (!DefaultLogger::isNullLogger()) - { - if (iNumOldVertices == iNumVertices) - { - DefaultLogger::get()->debug("JoinVerticesProcess finished "); - } else - { - char szBuff[128]; // should be sufficiently large in every case - sprintf(szBuff,"JoinVerticesProcess finished | Verts in: %i out: %i | ~%.1f%%", - iNumOldVertices, - iNumVertices, - ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f); - DefaultLogger::get()->info(szBuff); - } - } - - pScene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; -} - -// ------------------------------------------------------------------------------------------------ -// Unites identical vertices in the given mesh -int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) -{ - BOOST_STATIC_ASSERT( AI_MAX_NUMBER_OF_COLOR_SETS == 4); - BOOST_STATIC_ASSERT( AI_MAX_NUMBER_OF_TEXTURECOORDS == 4); - - // Return early if we don't have any positions - if (!pMesh->HasPositions() || !pMesh->HasFaces()) { - return 0; - } - - // We'll never have more vertices afterwards. - std::vector<Vertex> uniqueVertices; - uniqueVertices.reserve( pMesh->mNumVertices); - - // For each vertex the index of the vertex it was replaced by. - // Since the maximal number of vertices is 2^31-1, the most significand bit can be used to mark - // whether a new vertex was created for the index (true) or if it was replaced by an existing - // unique vertex (false). This saves an additional std::vector<bool> and greatly enhances - // branching performance. - BOOST_STATIC_ASSERT(AI_MAX_VERTICES == 0x7fffffff); - std::vector<unsigned int> replaceIndex( pMesh->mNumVertices, 0xffffffff); - - // A little helper to find locally close vertices faster. - // Try to reuse the lookup table from the last step. - const static float epsilon = 1e-5f; - float posEpsilonSqr; - SpatialSort* vertexFinder = NULL; - SpatialSort _vertexFinder; - - typedef std::pair<SpatialSort,float> SpatPair; - if (shared) { - std::vector<SpatPair >* avf; - shared->GetProperty(AI_SPP_SPATIAL_SORT,avf); - if (avf) { - SpatPair& blubb = (*avf)[meshIndex]; - vertexFinder = &blubb.first; - posEpsilonSqr = blubb.second; - } - } - if (!vertexFinder) { - // bad, need to compute it. - _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D)); - vertexFinder = &_vertexFinder; - posEpsilonSqr = ComputePositionEpsilon(pMesh); - } - - // Squared because we check against squared length of the vector difference - static const float squareEpsilon = epsilon * epsilon; - - // Again, better waste some bytes than a realloc ... - std::vector<unsigned int> verticesFound; - verticesFound.reserve(10); - - // Run an optimized code path if we don't have multiple UVs or vertex colors. - // This should yield false in more than 99% of all imports ... - const bool complex = ( - pMesh->mTextureCoords[1] || - pMesh->mTextureCoords[2] || - pMesh->mTextureCoords[3] || - pMesh->mColors[0] || - pMesh->mColors[1] || - pMesh->mColors[2] || - pMesh->mColors[3] ); - - // Now check each vertex if it brings something new to the table - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - // collect the vertex data - Vertex v(pMesh,a); - - // collect all vertices that are close enough to the given position - vertexFinder->FindIdenticalPositions( v.position, verticesFound); - unsigned int matchIndex = 0xffffffff; - - // check all unique vertices close to the position if this vertex is already present among them - for ( unsigned int b = 0; b < verticesFound.size(); b++) { - - const unsigned int vidx = verticesFound[b]; - const unsigned int uidx = replaceIndex[ vidx]; - if ( uidx & 0x80000000) - continue; - - const Vertex& uv = uniqueVertices[ uidx]; - // Position mismatch is impossible - the vertex finder already discarded all non-matching positions - - // We just test the other attributes even if they're not present in the mesh. - // In this case they're initialized to 0 so the comparision succeeds. - // By this method the non-present attributes are effectively ignored in the comparision. - if ( (uv.normal - v.normal).SquareLength() > squareEpsilon) - continue; - if ( (uv.texcoords[0] - v.texcoords[0]).SquareLength() > squareEpsilon) - continue; - if ( (uv.tangent - v.tangent).SquareLength() > squareEpsilon) - continue; - if ( (uv.bitangent - v.bitangent).SquareLength() > squareEpsilon) - continue; - - // Usually we won't have vertex colors or multiple UVs, so we can skip from here - // Actually this increases runtime performance slightly, at least if branch - // prediction is on our side. - if (complex){ - // manually unrolled because continue wouldn't work as desired in an inner loop - if ( GetColorDifference( uv.colors[0], v.colors[0]) > squareEpsilon) - continue; - if ( GetColorDifference( uv.colors[1], v.colors[1]) > squareEpsilon) - continue; - if ( GetColorDifference( uv.colors[2], v.colors[2]) > squareEpsilon) - continue; - if ( GetColorDifference( uv.colors[3], v.colors[3]) > squareEpsilon) - continue; - - // texture coord matching manually unrolled as well - if ( (uv.texcoords[1] - v.texcoords[1]).SquareLength() > squareEpsilon) - continue; - if ( (uv.texcoords[2] - v.texcoords[2]).SquareLength() > squareEpsilon) - continue; - if ( (uv.texcoords[3] - v.texcoords[3]).SquareLength() > squareEpsilon) - continue; - } - - // we're still here -> this vertex perfectly matches our given vertex - matchIndex = uidx; - break; - } - - // found a replacement vertex among the uniques? - if ( matchIndex != 0xffffffff) - { - // store where to found the matching unique vertex - replaceIndex[a] = matchIndex | 0x80000000; - } - else - { - // no unique vertex matches it upto now -> so add it - replaceIndex[a] = (unsigned int)uniqueVertices.size(); - uniqueVertices.push_back( v); - } - } - - if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - DefaultLogger::get()->debug((Formatter::format(), - "Mesh ",meshIndex, - " (", - (pMesh->mName.length ? pMesh->mName.data : "unnamed"), - ") | Verts in: ",pMesh->mNumVertices, - " out: ", - uniqueVertices.size(), - " | ~", - ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f, - "%" - )); - } - - // replace vertex data with the unique data sets - pMesh->mNumVertices = (unsigned int)uniqueVertices.size(); - - // ---------------------------------------------------------------------------- - // NOTE - we're *not* calling Vertex::SortBack() because it would check for - // presence of every single vertex component once PER VERTEX. And our CPU - // dislikes branches, even if they're easily predictable. - // ---------------------------------------------------------------------------- - - // Position - delete [] pMesh->mVertices; - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) - pMesh->mVertices[a] = uniqueVertices[a].position; - - // Normals, if present - if ( pMesh->mNormals) - { - delete [] pMesh->mNormals; - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mNormals[a] = uniqueVertices[a].normal; - } - } - // Tangents, if present - if ( pMesh->mTangents) - { - delete [] pMesh->mTangents; - pMesh->mTangents = new aiVector3D[pMesh->mNumVertices]; - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mTangents[a] = uniqueVertices[a].tangent; - } - } - // Bitangents as well - if ( pMesh->mBitangents) - { - delete [] pMesh->mBitangents; - pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices]; - for ( unsigned int a = 0; a < pMesh->mNumVertices; a++) { - pMesh->mBitangents[a] = uniqueVertices[a].bitangent; - } - } - // Vertex colors - for ( unsigned int a = 0; pMesh->HasVertexColors(a); a++) - { - delete [] pMesh->mColors[a]; - pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices]; - for ( unsigned int b = 0; b < pMesh->mNumVertices; b++) { - pMesh->mColors[a][b] = uniqueVertices[b].colors[a]; - } - } - // Texture coords - for ( unsigned int a = 0; pMesh->HasTextureCoords(a); a++) - { - delete [] pMesh->mTextureCoords[a]; - pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices]; - for ( unsigned int b = 0; b < pMesh->mNumVertices; b++) { - pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a]; - } - } - - // adjust the indices in all faces - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) - { - aiFace& face = pMesh->mFaces[a]; - for ( unsigned int b = 0; b < face.mNumIndices; b++) { - face.mIndices[b] = replaceIndex[face.mIndices[b]] & ~0x80000000; - } - } - - // adjust bone vertex weights. - for ( int a = 0; a < (int)pMesh->mNumBones; a++) - { - aiBone* bone = pMesh->mBones[a]; - std::vector<aiVertexWeight> newWeights; - newWeights.reserve( bone->mNumWeights); - - for ( unsigned int b = 0; b < bone->mNumWeights; b++) - { - const aiVertexWeight& ow = bone->mWeights[b]; - // if the vertex is a unique one, translate it - if ( !(replaceIndex[ow.mVertexId] & 0x80000000)) - { - aiVertexWeight nw; - nw.mVertexId = replaceIndex[ow.mVertexId]; - nw.mWeight = ow.mWeight; - newWeights.push_back( nw); - } - } - - if (newWeights.size() > 0) { - // kill the old and replace them with the translated weights - delete [] bone->mWeights; - bone->mNumWeights = (unsigned int)newWeights.size(); - - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - memcpy( bone->mWeights, &newWeights[0], bone->mNumWeights * sizeof( aiVertexWeight)); - } - else { - - /* NOTE: - * - * In the algorithm above we're assuming that there are no vertices - * with a different bone weight setup at the same position. That wouldn't - * make sense, but it is not absolutely impossible. SkeletonMeshBuilder - * for example generates such input data if two skeleton points - * share the same position. Again this doesn't make sense but is - * reality for some model formats (MD5 for example uses these special - * nodes as attachment tags for its weapons). - * - * Then it is possible that a bone has no weights anymore .... as a quick - * workaround, we're just removing these bones. If they're animated, - * model geometry might be modified but at least there's no risk of a crash. - */ - delete bone; - --pMesh->mNumBones; - for (unsigned int n = a; n < pMesh->mNumBones; ++n) { - pMesh->mBones[n] = pMesh->mBones[n+1]; - } - - --a; - DefaultLogger::get()->warn("Removing bone -> no weights remaining"); - } - } - return pMesh->mNumVertices; -} - -#endif // !! ASSIMP_BUILD_NO_JOINVERTICES_PROCESS diff --git a/3rdparty/assimp/code/JoinVerticesProcess.h b/3rdparty/assimp/code/JoinVerticesProcess.h deleted file mode 100644 index 0ce00ab5..00000000 --- a/3rdparty/assimp/code/JoinVerticesProcess.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to join identical vertices - on all imported meshes.*/ -#ifndef AI_JOINVERTICESPROCESS_H_INC -#define AI_JOINVERTICESPROCESS_H_INC - -#include "BaseProcess.h" -#include "../include/aiTypes.h" - -struct aiMesh; - -namespace Assimp -{ - -class JoinVerticesTest; - -// --------------------------------------------------------------------------- -/** The JoinVerticesProcess unites identical vertices in all imported meshes. - * By default the importer returns meshes where each face addressed its own - * set of vertices even if that means that identical vertices are stored multiple - * times. The JoinVerticesProcess finds these identical vertices and - * erases all but one of the copies. This usually reduces the number of vertices - * in a mesh by a serious amount and is the standard form to render a mesh. - */ -class ASSIMP_API JoinVerticesProcess : public BaseProcess -{ - friend class Importer; - friend class JoinVerticesTest; - -protected: - /** Constructor to be privately used by Importer */ - JoinVerticesProcess(); - - /** Destructor, private as well */ - ~JoinVerticesProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - -protected: - // ------------------------------------------------------------------- - /** Unites identical vertices in the given mesh. - * @param pMesh The mesh to process. - * @param meshIndex Index of the mesh to process - */ - int ProcessMesh( aiMesh* pMesh, unsigned int meshIndex); - -private: -}; - -} // end of namespace Assimp - -#endif // AI_CALCTANGENTSPROCESS_H_INC diff --git a/3rdparty/assimp/code/LWOAnimation.cpp b/3rdparty/assimp/code/LWOAnimation.cpp deleted file mode 100644 index 128fd6d6..00000000 --- a/3rdparty/assimp/code/LWOAnimation.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWOAnimation.cpp - * @brief LWOAnimationResolver utility class - * - * It's a very generic implementation of LightWave's system of - * componentwise-animated stuff. The one and only fully free - * implementation of LightWave envelopes of which I know. -*/ - -#include "AssimpPCH.h" -#if (!defined ASSIMP_BUILD_NO_LWO_IMPORTER) && (!defined ASSIMP_BUILD_NO_LWS_IMPORTER) - -// internal headers -#include "LWOFileData.h" - -using namespace Assimp; -using namespace Assimp::LWO; - -// ------------------------------------------------------------------------------------------------ -// Construct an animation resolver from a given list of envelopes -AnimResolver::AnimResolver(std::list<Envelope>& _envelopes,double tick) - : envelopes (_envelopes) - , sample_rate (0.) -{ - trans_x = trans_y = trans_z = NULL; - rotat_x = rotat_y = rotat_z = NULL; - scale_x = scale_y = scale_z = NULL; - - first = last = 150392.; - - // find transformation envelopes - for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) { - - (*it).old_first = 0; - (*it).old_last = (*it).keys.size()-1; - - if ((*it).keys.empty()) continue; - switch ((*it).type) { - - // translation - case LWO::EnvelopeType_Position_X: - trans_x = &*it;break; - case LWO::EnvelopeType_Position_Y: - trans_y = &*it;break; - case LWO::EnvelopeType_Position_Z: - trans_z = &*it;break; - - // rotation - case LWO::EnvelopeType_Rotation_Heading: - rotat_x = &*it;break; - case LWO::EnvelopeType_Rotation_Pitch: - rotat_y = &*it;break; - case LWO::EnvelopeType_Rotation_Bank: - rotat_z = &*it;break; - - // scaling - case LWO::EnvelopeType_Scaling_X: - scale_x = &*it;break; - case LWO::EnvelopeType_Scaling_Y: - scale_y = &*it;break; - case LWO::EnvelopeType_Scaling_Z: - scale_z = &*it;break; - default: - continue; - }; - - // convert from seconds to ticks - for (std::vector<LWO::Key>::iterator d = (*it).keys.begin(); d != (*it).keys.end(); ++d) - (*d).time *= tick; - - // set default animation range (minimum and maximum time value for which we have a keyframe) - first = std::min(first, (*it).keys.front().time ); - last = std::max(last, (*it).keys.back().time ); - } - - // deferred setup of animation range to increase performance. - // typically the application will want to specify its own. - need_to_setup = true; -} - -// ------------------------------------------------------------------------------------------------ -// Reset all envelopes to their original contents -void AnimResolver::ClearAnimRangeSetup() -{ - for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) { - - (*it).keys.erase((*it).keys.begin(),(*it).keys.begin()+(*it).old_first); - (*it).keys.erase((*it).keys.begin()+(*it).old_last+1,(*it).keys.end()); - } -} - -// ------------------------------------------------------------------------------------------------ -// Insert additional keys to match LWO's pre& post behaviours. -void AnimResolver::UpdateAnimRangeSetup() -{ - // XXX doesn't work yet (hangs if more than one envelope channels needs to be interpolated) - - for (std::list<LWO::Envelope>::iterator it = envelopes.begin(); it != envelopes.end(); ++it) { - if ((*it).keys.empty()) continue; - - const double my_first = (*it).keys.front().time; - const double my_last = (*it).keys.back().time; - - const double delta = my_last-my_first; - const size_t old_size = (*it).keys.size(); - - const float value_delta = (*it).keys.back().value - (*it).keys.front().value; - - // NOTE: We won't handle reset, linear and constant here. - // See DoInterpolation() for their implementation. - - // process pre behaviour - switch ((*it).pre) { - case LWO::PrePostBehaviour_OffsetRepeat: - case LWO::PrePostBehaviour_Repeat: - case LWO::PrePostBehaviour_Oscillate: - { - const double start_time = delta - fmod(my_first-first,delta); - std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(),(*it).keys.end(), - std::bind1st(std::greater<double>(),start_time)),m; - - size_t ofs = 0; - if (n != (*it).keys.end()) { - // copy from here - don't use iterators, insert() would invalidate them - ofs = (*it).keys.end()-n; - (*it).keys.insert((*it).keys.begin(),ofs,LWO::Key()); - - std::copy((*it).keys.end()-ofs,(*it).keys.end(),(*it).keys.begin()); - } - - // do full copies. again, no iterators - const unsigned int num = (unsigned int)((my_first-first) / delta); - (*it).keys.resize((*it).keys.size() + num*old_size); - - n = (*it).keys.begin()+ofs; - bool reverse = false; - for (unsigned int i = 0; i < num; ++i) { - m = n+old_size*(i+1); - std::copy(n,n+old_size,m); - - if ((*it).pre == LWO::PrePostBehaviour_Oscillate && (reverse = !reverse)) - std::reverse(m,m+old_size-1); - } - - // update time values - n = (*it).keys.end() - (old_size+1); - double cur_minus = delta; - unsigned int tt = 1; - for (const double tmp = delta*(num+1);cur_minus <= tmp;cur_minus += delta,++tt) { - m = (delta == tmp ? (*it).keys.begin() : n - (old_size+1)); - for (;m != n; --n) { - (*n).time -= cur_minus; - - // offset repeat? add delta offset to key value - if ((*it).pre == LWO::PrePostBehaviour_OffsetRepeat) { - (*n).value += tt * value_delta; - } - } - } - break; - } - default: - // silence compiler warning - break; - } - - // process post behaviour - switch ((*it).post) { - - case LWO::PrePostBehaviour_OffsetRepeat: - case LWO::PrePostBehaviour_Repeat: - case LWO::PrePostBehaviour_Oscillate: - - break; - - default: - // silence compiler warning - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Extract bind pose matrix -void AnimResolver::ExtractBindPose(aiMatrix4x4& out) -{ - // If we have no envelopes, return identity - if (envelopes.empty()) { - out = aiMatrix4x4(); - return; - } - aiVector3D angles, scaling(1.f,1.f,1.f), translation; - - if (trans_x) translation.x = trans_x->keys[0].value; - if (trans_y) translation.y = trans_y->keys[0].value; - if (trans_z) translation.z = trans_z->keys[0].value; - - if (rotat_x) angles.x = rotat_x->keys[0].value; - if (rotat_y) angles.y = rotat_y->keys[0].value; - if (rotat_z) angles.z = rotat_z->keys[0].value; - - if (scale_x) scaling.x = scale_x->keys[0].value; - if (scale_y) scaling.y = scale_y->keys[0].value; - if (scale_z) scaling.z = scale_z->keys[0].value; - - // build the final matrix - aiMatrix4x4 s,r,t; - - r.FromEulerAnglesXYZ(angles); - //aiMatrix4x4::RotationY(angles.y,r); - // fixme: make FromEulerAngles static, too - aiMatrix4x4::Translation(translation,t); - aiMatrix4x4::Scaling(scaling,s); - out = s*r*t; -} - -// ------------------------------------------------------------------------------------------------ -// Do a single interpolation on a channel -void AnimResolver::DoInterpolation(std::vector<LWO::Key>::const_iterator cur, - LWO::Envelope* envl,double time, float& fill) -{ - if (envl->keys.size() == 1) { - fill = envl->keys[0].value; - return; - } - - // check whether we're at the beginning of the animation track - if (cur == envl->keys.begin()) { - - // ok ... this depends on pre behaviour now - // we don't need to handle repeat&offset repeat&oszillate here, see UpdateAnimRangeSetup() - switch (envl->pre) - { - case LWO::PrePostBehaviour_Linear: - DoInterpolation2(cur,cur+1,time,fill); - return; - - case LWO::PrePostBehaviour_Reset: - fill = 0.f; - return; - - default : //case LWO::PrePostBehaviour_Constant: - fill = (*cur).value; - return; - } - } - // check whether we're at the end of the animation track - else if (cur == envl->keys.end()-1 && time > envl->keys.rbegin()->time) { - // ok ... this depends on post behaviour now - switch (envl->post) - { - case LWO::PrePostBehaviour_Linear: - DoInterpolation2(cur,cur-1,time,fill); - return; - - case LWO::PrePostBehaviour_Reset: - fill = 0.f; - return; - - default : //case LWO::PrePostBehaviour_Constant: - fill = (*cur).value; - return; - } - } - - // Otherwise do a simple interpolation - DoInterpolation2(cur-1,cur,time,fill); -} - -// ------------------------------------------------------------------------------------------------ -// Almost the same, except we won't handle pre/post conditions here -void AnimResolver::DoInterpolation2(std::vector<LWO::Key>::const_iterator beg, - std::vector<LWO::Key>::const_iterator end,double time, float& fill) -{ - switch ((*end).inter) { - - case LWO::IT_STEP: - // no interpolation at all - take the value of the last key - fill = (*beg).value; - return; - default: - - // silence compiler warning - break; - } - // linear interpolation - default - fill = (*beg).value + ((*end).value - (*beg).value)*(float)(((time - (*beg).time) / ((*end).time - (*beg).time))); -} - -// ------------------------------------------------------------------------------------------------ -// Subsample animation track by given key values -void AnimResolver::SubsampleAnimTrack(std::vector<aiVectorKey>& /*out*/, - double /*time*/ ,double /*sample_delta*/ ) -{ - //ai_assert(out.empty() && sample_delta); - - //const double time_start = out.back().mTime; -// for () -} - -// ------------------------------------------------------------------------------------------------ -// Track interpolation -void AnimResolver::InterpolateTrack(std::vector<aiVectorKey>& out,aiVectorKey& fill,double time) -{ - // subsample animation track? - if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) { - SubsampleAnimTrack(out,time, sample_delta); - } - - fill.mTime = time; - - // get x - if ((*cur_x).time == time) { - fill.mValue.x = (*cur_x).value; - - if (cur_x != envl_x->keys.end()-1) /* increment x */ - ++cur_x; - else end_x = true; - } - else DoInterpolation(cur_x,envl_x,time,(float&)fill.mValue.x); - - // get y - if ((*cur_y).time == time) { - fill.mValue.y = (*cur_y).value; - - if (cur_y != envl_y->keys.end()-1) /* increment y */ - ++cur_y; - else end_y = true; - } - else DoInterpolation(cur_y,envl_y,time,(float&)fill.mValue.y); - - // get z - if ((*cur_z).time == time) { - fill.mValue.z = (*cur_z).value; - - if (cur_z != envl_z->keys.end()-1) /* increment z */ - ++cur_z; - else end_x = true; - } - else DoInterpolation(cur_z,envl_z,time,(float&)fill.mValue.z); -} - -// ------------------------------------------------------------------------------------------------ -// Build linearly subsampled keys from three single envelopes, one for each component (x,y,z) -void AnimResolver::GetKeys(std::vector<aiVectorKey>& out, - LWO::Envelope* _envl_x, - LWO::Envelope* _envl_y, - LWO::Envelope* _envl_z, - unsigned int _flags) -{ - envl_x = _envl_x; - envl_y = _envl_y; - envl_z = _envl_z; - flags = _flags; - - // generate default channels if none are given - LWO::Envelope def_x, def_y, def_z; - LWO::Key key_dummy; - key_dummy.time = 0.f; - if ((envl_x && envl_x->type == LWO::EnvelopeType_Scaling_X) || - (envl_y && envl_y->type == LWO::EnvelopeType_Scaling_Y) || - (envl_z && envl_z->type == LWO::EnvelopeType_Scaling_Z)) { - key_dummy.value = 1.f; - } - else key_dummy.value = 0.f; - - if (!envl_x) { - envl_x = &def_x; - envl_x->keys.push_back(key_dummy); - } - if (!envl_y) { - envl_y = &def_y; - envl_y->keys.push_back(key_dummy); - } - if (!envl_z) { - envl_z = &def_z; - envl_z->keys.push_back(key_dummy); - } - - // guess how many keys we'll get - size_t reserve; - double sr = 1.; - if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) { - if (!sample_rate) - sr = 100.f; - else sr = sample_rate; - sample_delta = 1.f / sr; - - reserve = (size_t)( - std::max( envl_x->keys.end()->time, - std::max( envl_y->keys.end()->time, envl_z->keys.end()->time )) * sr); - } - else reserve = std::max(envl_x->keys.size(),std::max(envl_x->keys.size(),envl_z->keys.size())); - out.reserve(reserve+(reserve>>1)); - - // Iterate through all three arrays at once - it's tricky, but - // rather interesting to implement. - double lasttime = std::min(envl_x->keys[0].time,std::min(envl_y->keys[0].time,envl_z->keys[0].time)); - - cur_x = envl_x->keys.begin(); - cur_y = envl_y->keys.begin(); - cur_z = envl_z->keys.begin(); - - end_x = end_y = end_z = false; - while (1) { - - aiVectorKey fill; - - if ((*cur_x).time == (*cur_y).time && (*cur_x).time == (*cur_z).time ) { - - // we have a keyframe for all of them defined .. great, - // we don't need to fucking interpolate here ... - fill.mTime = (*cur_x).time; - - fill.mValue.x = (*cur_x).value; - fill.mValue.y = (*cur_y).value; - fill.mValue.z = (*cur_z).value; - - // subsample animation track - if (flags & AI_LWO_ANIM_FLAG_SAMPLE_ANIMS) { - //SubsampleAnimTrack(out,cur_x, cur_y, cur_z, d, sample_delta); - } - - if (cur_x != envl_x->keys.end()-1) - ++cur_x; - else end_x = true; - if (cur_y != envl_y->keys.end()-1) - ++cur_y; - else end_y = true; - if (cur_z != envl_z->keys.end()-1) - ++cur_z; - else end_z = true; - } - - // Find key with lowest time value - else if ((*cur_x).time <= (*cur_y).time && !end_x) { - - if ((*cur_z).time <= (*cur_x).time && !end_z) { - InterpolateTrack(out,fill,(*cur_z).time); - } - else { - InterpolateTrack(out,fill,(*cur_x).time); - } - } - else if ((*cur_z).time <= (*cur_y).time && !end_z) { - InterpolateTrack(out,fill,(*cur_z).time); - } - else if (!end_y) { - // welcome on the server, y - InterpolateTrack(out,fill,(*cur_y).time); - } - else { - // we have reached the end of at least 2 channels, - // only one is remaining. Extrapolate the 2. - if (end_y) { - InterpolateTrack(out,fill,(end_x ? (*cur_z) : (*cur_x)).time); - } - else if (end_x) { - InterpolateTrack(out,fill,(end_z ? (*cur_y) : (*cur_z)).time); - } - else { // if (end_z) - InterpolateTrack(out,fill,(end_y ? (*cur_x) : (*cur_y)).time); - } - } - lasttime = fill.mTime; - out.push_back(fill); - - if ( end_x && end_y && end_z ) /* finished? */ - break; - } - - if (flags & AI_LWO_ANIM_FLAG_START_AT_ZERO) { - for (std::vector<aiVectorKey>::iterator it = out.begin(); it != out.end(); ++it) - (*it).mTime -= first; - } -} - -// ------------------------------------------------------------------------------------------------ -// Extract animation channel -void AnimResolver::ExtractAnimChannel(aiNodeAnim** out, unsigned int flags /*= 0*/) -{ - *out = NULL; - - - //FIXME: crashes if more than one component is animated at different timings, to be resolved. - return; - -#if 0 - // If we have no envelopes, return NULL - if (envelopes.empty()) { - return; - } - - // We won't spawn an animation channel if we don't have at least one envelope with more than one keyframe defined. - const bool trans = (trans_x && trans_x->keys.size() > 1 || trans_y && trans_y->keys.size() > 1 || trans_z && trans_z->keys.size() > 1); - const bool rotat = (rotat_x && rotat_x->keys.size() > 1 || rotat_y && rotat_y->keys.size() > 1 || rotat_z && rotat_z->keys.size() > 1); - const bool scale = (scale_x && scale_x->keys.size() > 1 || scale_y && scale_y->keys.size() > 1 || scale_z && scale_z->keys.size() > 1); - if (!trans && !rotat && !scale) - return; - - // Allocate the output animation - aiNodeAnim* anim = *out = new aiNodeAnim(); - - // Setup default animation setup if necessary - if (need_to_setup) { - UpdateAnimRangeSetup(); - need_to_setup = false; - } - - // copy translation keys - if (trans) { - std::vector<aiVectorKey> keys; - GetKeys(keys,trans_x,trans_y,trans_z,flags); - - anim->mPositionKeys = new aiVectorKey[ anim->mNumPositionKeys = keys.size() ]; - std::copy(keys.begin(),keys.end(),anim->mPositionKeys); - } - - // copy rotation keys - if (rotat) { - std::vector<aiVectorKey> keys; - GetKeys(keys,rotat_x,rotat_y,rotat_z,flags); - - anim->mRotationKeys = new aiQuatKey[ anim->mNumRotationKeys = keys.size() ]; - - // convert heading, pitch, bank to quaternion - for (unsigned int i = 0; i < anim->mNumRotationKeys; ++i) { - aiQuatKey& qk = anim->mRotationKeys[i]; - qk.mTime = keys[i].mTime; - qk.mValue = aiQuaternion( keys[i].mValue.x ,keys[i].mValue.z ,keys[i].mValue.y ); - } - } - - // copy scaling keys - if (scale) { - std::vector<aiVectorKey> keys; - GetKeys(keys,scale_x,scale_y,scale_z,flags); - - anim->mScalingKeys = new aiVectorKey[ anim->mNumScalingKeys = keys.size() ]; - std::copy(keys.begin(),keys.end(),anim->mScalingKeys); - } -#endif -} - - -#endif // no lwo or no lws diff --git a/3rdparty/assimp/code/LWOAnimation.h b/3rdparty/assimp/code/LWOAnimation.h deleted file mode 100644 index cb376f23..00000000 --- a/3rdparty/assimp/code/LWOAnimation.h +++ /dev/null @@ -1,336 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWOAnimation.h - * @brief LWOAnimationResolver utility class - * - * This is for all lightwave-related file format, not only LWO. - * LWS isthe main purpose. -*/ -#ifndef AI_LWO_ANIMATION_INCLUDED -#define AI_LWO_ANIMATION_INCLUDED - -namespace Assimp { -namespace LWO { - -// --------------------------------------------------------------------------- -/** \brief List of recognized LWO envelopes - */ -enum EnvelopeType -{ - EnvelopeType_Position_X = 0x1, - EnvelopeType_Position_Y = 0x2, - EnvelopeType_Position_Z = 0x3, - - EnvelopeType_Rotation_Heading = 0x4, - EnvelopeType_Rotation_Pitch = 0x5, - EnvelopeType_Rotation_Bank = 0x6, - - EnvelopeType_Scaling_X = 0x7, - EnvelopeType_Scaling_Y = 0x8, - EnvelopeType_Scaling_Z = 0x9, - - // -- currently not yet handled - EnvelopeType_Color_R = 0xa, - EnvelopeType_Color_G = 0xb, - EnvelopeType_Color_B = 0xc, - - EnvelopeType_Falloff_X = 0xd, - EnvelopeType_Falloff_Y = 0xe, - EnvelopeType_Falloff_Z = 0xf, - - EnvelopeType_Unknown -}; - -// --------------------------------------------------------------------------- -/** \brief List of recognized LWO interpolation modes - */ -enum InterpolationType -{ - IT_STEP, IT_LINE, IT_TCB, IT_HERM, IT_BEZI, IT_BEZ2 -}; - - -// --------------------------------------------------------------------------- -/** \brief List of recognized LWO pre or post range behaviours - */ -enum PrePostBehaviour -{ - PrePostBehaviour_Reset = 0x0, - PrePostBehaviour_Constant = 0x1, - PrePostBehaviour_Repeat = 0x2, - PrePostBehaviour_Oscillate = 0x3, - PrePostBehaviour_OffsetRepeat = 0x4, - PrePostBehaviour_Linear = 0x5 -}; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a LWO animation keyframe - */ -struct Key -{ - Key() - : inter (IT_LINE) - {} - - //! Current time - double time; - - //! Current value - float value; - - //! How to interpolate this key with previous key? - InterpolationType inter; - - //! Interpolation parameters - float params[5]; - - - // for std::find() - operator double () { - return time; - } -}; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a LWO animation envelope - */ -struct Envelope -{ - Envelope() - : type (EnvelopeType_Unknown) - , pre (PrePostBehaviour_Constant) - , post (PrePostBehaviour_Constant) - - , old_first (0) - , old_last (0) - {} - - //! Index of this envelope - unsigned int index; - - //! Type of envelope - EnvelopeType type; - - //! Pre and post-behaviour - PrePostBehaviour pre,post; - - //! Keyframes for this envelope - std::vector<Key> keys; - - - // temporary data for AnimResolver - size_t old_first,old_last; -}; - -// --------------------------------------------------------------------------- -//! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS -//! Flag for AnimResolver, subsamples the input data with the rate specified -//! by AnimResolver::SetSampleRate(). -#define AI_LWO_ANIM_FLAG_SAMPLE_ANIMS 0x1 - - -// --------------------------------------------------------------------------- -//! @def AI_LWO_ANIM_FLAG_START_AT_ZERO -//! Flag for AnimResolver, ensures that the animations starts at zero. -#define AI_LWO_ANIM_FLAG_START_AT_ZERO 0x2 - -// --------------------------------------------------------------------------- -/** @brief Utility class to build Assimp animations from LWO envelopes. - * - * Used for both LWO and LWS (MOT also). - */ -class AnimResolver -{ -public: - - // ------------------------------------------------------------------ - /** @brief Construct an AnimResolver from a given list of envelopes - * @param envelopes Input envelopes. May be empty. - * @param Output tick rate, per second - * @note The input envelopes are possibly modified. - */ - AnimResolver(std::list<Envelope>& envelopes, - double tick); - -public: - - // ------------------------------------------------------------------ - /** @brief Extract the bind-pose transformation matrix. - * @param out Receives bind-pose transformation matrix - */ - void ExtractBindPose(aiMatrix4x4& out); - - // ------------------------------------------------------------------ - /** @brief Extract a node animation channel - * @param out Receives a pointer to a newly allocated node anim. - * If there's just one keyframe defined, *out is set to NULL and - * no animation channel is computed. - * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. - */ - void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0); - - - // ------------------------------------------------------------------ - /** @brief Set the sampling rate for ExtractAnimChannel(). - * - * Non-linear interpolations are subsampled with this rate (keys - * per second). Closer sampling positions, if existent, are kept. - * The sampling rate defaults to 0, if this value is not changed and - * AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(), - * the class finds a suitable sample rate by itself. - */ - void SetSampleRate(double sr) { - sample_rate = sr; - } - - // ------------------------------------------------------------------ - /** @brief Getter for SetSampleRate() - */ - double GetSampleRate() const { - return sample_rate; - } - - // ------------------------------------------------------------------ - /** @brief Set the animation time range - * - * @param first Time where the animation starts, in ticks - * @param last Time where the animation ends, in ticks - */ - void SetAnimationRange(double _first, double _last) { - first = _first; - last = _last; - - ClearAnimRangeSetup(); - UpdateAnimRangeSetup(); - } - -protected: - - // ------------------------------------------------------------------ - /** @brief Build linearly subsampled keys from 3 single envelopes - * @param out Receives output keys - * @param envl_x X-component envelope - * @param envl_y Y-component envelope - * @param envl_z Z-component envelope - * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. - * @note Up to two input envelopes may be NULL - */ - void GetKeys(std::vector<aiVectorKey>& out, - LWO::Envelope* envl_x, - LWO::Envelope* envl_y, - LWO::Envelope* envl_z, - unsigned int flags); - - // ------------------------------------------------------------------ - /** @brief Resolve a single animation key by applying the right - * interpolation to it. - * @param cur Current key - * @param envl Envelope working on - * @param time time to be interpolated - * @param fill Receives the interpolated output value. - */ - void DoInterpolation(std::vector<LWO::Key>::const_iterator cur, - LWO::Envelope* envl,double time, float& fill); - - // ------------------------------------------------------------------ - /** @brief Almost the same, except we won't handle pre/post - * conditions here. - * @see DoInterpolation - */ - void DoInterpolation2(std::vector<LWO::Key>::const_iterator beg, - std::vector<LWO::Key>::const_iterator end,double time, float& fill); - - // ------------------------------------------------------------------ - /** @brief Interpolate 2 tracks if one is given - * - * @param out Receives extra output keys - * @param key_out Primary output key - * @param time Time to interpolate for - */ - void InterpolateTrack(std::vector<aiVectorKey>& out, - aiVectorKey& key_out,double time); - - // ------------------------------------------------------------------ - /** @brief Subsample an animation track by a given sampling rate - * - * @param out Receives output keys. Last key at input defines the - * time where subsampling starts. - * @param time Time to end subsampling at - * @param sample_delta Time delta between two samples - */ - void SubsampleAnimTrack(std::vector<aiVectorKey>& out, - double time,double sample_delta); - - // ------------------------------------------------------------------ - /** @brief Delete all keys which we inserted to match anim setup - */ - void ClearAnimRangeSetup(); - - // ------------------------------------------------------------------ - /** @brief Insert extra keys to match LWO's pre and post behaviours - * in a given time range [first...last] - */ - void UpdateAnimRangeSetup(); - -private: - std::list<Envelope>& envelopes; - double sample_rate; - - LWO::Envelope* trans_x, *trans_y, *trans_z; - LWO::Envelope* rotat_x, *rotat_y, *rotat_z; - LWO::Envelope* scale_x, *scale_y, *scale_z; - - double first, last; - bool need_to_setup; - - // temporary storage - LWO::Envelope* envl_x, * envl_y, * envl_z; - std::vector<LWO::Key>::const_iterator cur_x,cur_y,cur_z; - bool end_x, end_y, end_z; - - unsigned int flags; - double sample_delta; -}; - -} // end namespace LWO -} // end namespace Assimp - -#endif // !! AI_LWO_ANIMATION_INCLUDED diff --git a/3rdparty/assimp/code/LWOBLoader.cpp b/3rdparty/assimp/code/LWOBLoader.cpp deleted file mode 100644 index c4704ca7..00000000 --- a/3rdparty/assimp/code/LWOBLoader.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWO importer class for the older LWOB - file formats, including materials */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER - -// Internal headers -#include "LWOLoader.h" -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOBFile() -{ - LE_NCONST uint8_t* const end = mFileBuffer + fileSize; - bool running = true; - while (running) - { - if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; - LE_NCONST IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - { - throw DeadlyImportError("LWOB: Invalid chunk length"); - break; - } - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - // vertex list - case AI_LWO_PNTS: - { - if (!mCurLayer->mTempPoints.empty()) - DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice"); - else LoadLWOPoints(head->length); - break; - } - // face list - case AI_LWO_POLS: - { - if (!mCurLayer->mFaces.empty()) - DefaultLogger::get()->warn("LWO: POLS chunk encountered twice"); - else LoadLWOBPolygons(head->length); - break; - } - // list of tags - case AI_LWO_SRFS: - { - if (!mTags->empty()) - DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice"); - else LoadLWOTags(head->length); - break; - } - - // surface chunk - case AI_LWO_SURF: - { - LoadLWOBSurface(head->length); - break; - } - } - mFileBuffer = next; - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOBPolygons(unsigned int length) -{ - // first find out how many faces and vertices we'll finally need - LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); - LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer; - - // perform endianess conversions -#ifndef AI_BUILD_BIG_ENDIAN - while (cursor < end)ByteSwap::Swap2(cursor++); - cursor = (LE_NCONST uint16_t*)mFileBuffer; -#endif - - unsigned int iNumFaces = 0,iNumVertices = 0; - CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end); - - // allocate the output array and copy face indices - if (iNumFaces) - { - cursor = (LE_NCONST uint16_t*)mFileBuffer; - - mCurLayer->mFaces.resize(iNumFaces); - FaceList::iterator it = mCurLayer->mFaces.begin(); - CopyFaceIndicesLWOB(it,cursor,end); - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces, - LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) -{ - while (cursor < end && max--) - { - uint16_t numIndices = *cursor++; - verts += numIndices;faces++; - cursor += numIndices; - int16_t surface = *cursor++; - if (surface < 0) - { - // there are detail polygons - numIndices = *cursor++; - CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, - LE_NCONST uint16_t*& cursor, - const uint16_t* const end, - unsigned int max) -{ - while (cursor < end && max--) - { - LWO::Face& face = *it;++it; - if ((face.mNumIndices = *cursor++)) - { - if (cursor + face.mNumIndices >= end)break; - face.mIndices = new unsigned int[face.mNumIndices]; - for (unsigned int i = 0; i < face.mNumIndices;++i) - { - unsigned int & mi = face.mIndices[i] = *cursor++; - if (mi > mCurLayer->mTempPoints.size()) - { - DefaultLogger::get()->warn("LWOB: face index is out of range"); - mi = (unsigned int)mCurLayer->mTempPoints.size()-1; - } - } - } - else DefaultLogger::get()->warn("LWOB: Face has 0 indices"); - int16_t surface = *cursor++; - if (surface < 0) - { - surface = -surface; - - // there are detail polygons. - const uint16_t numPolygons = *cursor++; - if (cursor < end)CopyFaceIndicesLWOB(it,cursor,end,numPolygons); - } - face.surfaceIndex = surface-1; - } -} - -// ------------------------------------------------------------------------------------------------ -LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) -{ - list.push_back(LWO::Texture()); - LWO::Texture* tex = &list.back(); - - std::string type; - GetS0(type,size); - const char* s = type.c_str(); - - if (strstr(s, "Image Map")) - { - // Determine mapping type - if (strstr(s, "Planar")) - tex->mapMode = LWO::Texture::Planar; - else if (strstr(s, "Cylindrical")) - tex->mapMode = LWO::Texture::Cylindrical; - else if (strstr(s, "Spherical")) - tex->mapMode = LWO::Texture::Spherical; - else if (strstr(s, "Cubic")) - tex->mapMode = LWO::Texture::Cubic; - else if (strstr(s, "Front")) - tex->mapMode = LWO::Texture::FrontProjection; - } - else - { - // procedural or gradient, not supported - DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type); - } - - return tex; -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOBSurface(unsigned int size) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; - - mSurfaces->push_back( LWO::Surface () ); - LWO::Surface& surf = mSurfaces->back(); - LWO::Texture* pTex = NULL; - - GetS0(surf.mName,size); - bool runnning = true; - while (runnning) { - if (mFileBuffer + 6 >= end) - break; - - IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - - /* A single test file (sonycam.lwo) seems to have invalid surface chunks. - * I'm assuming it's the fault of a single, unknown exporter so there are - * probably THOUSANDS of them. Here's a dirty workaround: - * - * We don't break if the chunk limit is exceeded. Instead, we're computing - * how much storage is actually left and work with this value from now on. - */ - if (mFileBuffer + head->length > end) { - DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue."); - head->length = (uint16_t) (end - mFileBuffer); - } - - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - // diffuse color - case AI_LWO_COLR: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,3); - surf.mColor.r = GetU1() / 255.0f; - surf.mColor.g = GetU1() / 255.0f; - surf.mColor.b = GetU1() / 255.0f; - break; - } - // diffuse strength ... - case AI_LWO_DIFF: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,2); - surf.mDiffuseValue = GetU2() / 255.0f; - break; - } - // specular strength ... - case AI_LWO_SPEC: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,2); - surf.mSpecularValue = GetU2() / 255.0f; - break; - } - // luminosity ... - case AI_LWO_LUMI: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LUMI,2); - surf.mLuminosity = GetU2() / 255.0f; - break; - } - // transparency - case AI_LWO_TRAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,2); - surf.mTransparency = GetU2() / 255.0f; - break; - } - // surface flags - case AI_LWO_FLAG: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,FLAG,2); - uint16_t flag = GetU2(); - if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f; - if (flag & 0x8 ) surf.mColorHighlights = 1.f; - if (flag & 0x100) surf.bDoubleSided = true; - break; - } - // maximum smoothing angle - case AI_LWO_SMAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4); - surf.mMaximumSmoothAngle = fabs( GetF4() ); - break; - } - // glossiness - case AI_LWO_GLOS: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,2); - surf.mGlossiness = (float)GetU2(); - break; - } - // color texture - case AI_LWO_CTEX: - { - pTex = SetupNewTextureLWOB(surf.mColorTextures, - head->length); - break; - } - // diffuse texture - case AI_LWO_DTEX: - { - pTex = SetupNewTextureLWOB(surf.mDiffuseTextures, - head->length); - break; - } - // specular texture - case AI_LWO_STEX: - { - pTex = SetupNewTextureLWOB(surf.mSpecularTextures, - head->length); - break; - } - // bump texture - case AI_LWO_BTEX: - { - pTex = SetupNewTextureLWOB(surf.mBumpTextures, - head->length); - break; - } - // transparency texture - case AI_LWO_TTEX: - { - pTex = SetupNewTextureLWOB(surf.mOpacityTextures, - head->length); - break; - } - // texture path - case AI_LWO_TIMG: - { - if (pTex) { - GetS0(pTex->mFileName,head->length); - } - else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk"); - break; - } - // texture strength - case AI_LWO_TVAL: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TVAL,1); - if (pTex) { - pTex->mStrength = (float)GetU1()/ 255.f; - } - else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk"); - break; - } - // texture flags - case AI_LWO_TFLG: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TFLG,2); - - if (pTex) - { - const uint16_t s = GetU2(); - if (s & 1) - pTex->majorAxis = LWO::Texture::AXIS_X; - else if (s & 2) - pTex->majorAxis = LWO::Texture::AXIS_Y; - else if (s & 4) - pTex->majorAxis = LWO::Texture::AXIS_Z; - - if (s & 16) - DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture"); - } - else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk"); - break; - } - } - mFileBuffer = next; - } -} - -#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER diff --git a/3rdparty/assimp/code/LWOFileData.h b/3rdparty/assimp/code/LWOFileData.h deleted file mode 100644 index fd58c850..00000000 --- a/3rdparty/assimp/code/LWOFileData.h +++ /dev/null @@ -1,699 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWOFileData.h - * @brief Defines chunk constants used by the LWO file format - -The chunks are taken from the official LightWave SDK headers. - -*/ -#ifndef AI_LWO_FILEDATA_INCLUDED -#define AI_LWO_FILEDATA_INCLUDED - -// STL headers -#include <vector> -#include <list> - -// public ASSIMP headers -#include "../include/aiMesh.h" - -// internal headers -#include "IFF.h" -#include "LWOAnimation.h" - -namespace Assimp { -namespace LWO { - -#define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L','W','O','B') -#define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L','W','O','2') -#define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L','X','O','B') - -// chunks specific to the LWOB format -#define AI_LWO_SRFS AI_IFF_FOURCC('S','R','F','S') -#define AI_LWO_FLAG AI_IFF_FOURCC('F','L','A','G') -#define AI_LWO_VLUM AI_IFF_FOURCC('V','L','U','M') -#define AI_LWO_VDIF AI_IFF_FOURCC('V','D','I','F') -#define AI_LWO_VSPC AI_IFF_FOURCC('V','S','P','C') -#define AI_LWO_RFLT AI_IFF_FOURCC('R','F','L','T') -#define AI_LWO_BTEX AI_IFF_FOURCC('B','T','E','X') -#define AI_LWO_CTEX AI_IFF_FOURCC('C','T','E','X') -#define AI_LWO_DTEX AI_IFF_FOURCC('D','T','E','X') -#define AI_LWO_LTEX AI_IFF_FOURCC('L','T','E','X') -#define AI_LWO_RTEX AI_IFF_FOURCC('R','T','E','X') -#define AI_LWO_STEX AI_IFF_FOURCC('S','T','E','X') -#define AI_LWO_TTEX AI_IFF_FOURCC('T','T','E','X') -#define AI_LWO_TFLG AI_IFF_FOURCC('T','F','L','G') -#define AI_LWO_TSIZ AI_IFF_FOURCC('T','S','I','Z') -#define AI_LWO_TCTR AI_IFF_FOURCC('T','C','T','R') -#define AI_LWO_TFAL AI_IFF_FOURCC('T','F','A','L') -#define AI_LWO_TVEL AI_IFF_FOURCC('T','V','E','L') -#define AI_LWO_TCLR AI_IFF_FOURCC('T','C','L','R') -#define AI_LWO_TVAL AI_IFF_FOURCC('T','V','A','L') -#define AI_LWO_TAMP AI_IFF_FOURCC('T','A','M','P') -#define AI_LWO_TIMG AI_IFF_FOURCC('T','I','M','G') -#define AI_LWO_TAAS AI_IFF_FOURCC('T','A','A','S') -#define AI_LWO_TREF AI_IFF_FOURCC('T','R','E','F') -#define AI_LWO_TOPC AI_IFF_FOURCC('T','O','P','C') -#define AI_LWO_SDAT AI_IFF_FOURCC('S','D','A','T') -#define AI_LWO_TFP0 AI_IFF_FOURCC('T','F','P','0') -#define AI_LWO_TFP1 AI_IFF_FOURCC('T','F','P','1') - - -/* top-level chunks */ -#define AI_LWO_LAYR AI_IFF_FOURCC('L','A','Y','R') -#define AI_LWO_TAGS AI_IFF_FOURCC('T','A','G','S') -#define AI_LWO_PNTS AI_IFF_FOURCC('P','N','T','S') -#define AI_LWO_BBOX AI_IFF_FOURCC('B','B','O','X') -#define AI_LWO_VMAP AI_IFF_FOURCC('V','M','A','P') -#define AI_LWO_VMAD AI_IFF_FOURCC('V','M','A','D') -#define AI_LWO_POLS AI_IFF_FOURCC('P','O','L','S') -#define AI_LWO_PTAG AI_IFF_FOURCC('P','T','A','G') -#define AI_LWO_ENVL AI_IFF_FOURCC('E','N','V','L') -#define AI_LWO_CLIP AI_IFF_FOURCC('C','L','I','P') -#define AI_LWO_SURF AI_IFF_FOURCC('S','U','R','F') -#define AI_LWO_DESC AI_IFF_FOURCC('D','E','S','C') -#define AI_LWO_TEXT AI_IFF_FOURCC('T','E','X','T') -#define AI_LWO_ICON AI_IFF_FOURCC('I','C','O','N') - -/* polygon types */ -#define AI_LWO_FACE AI_IFF_FOURCC('F','A','C','E') -#define AI_LWO_CURV AI_IFF_FOURCC('C','U','R','V') -#define AI_LWO_PTCH AI_IFF_FOURCC('P','T','C','H') -#define AI_LWO_MBAL AI_IFF_FOURCC('M','B','A','L') -#define AI_LWO_BONE AI_IFF_FOURCC('B','O','N','E') -#define AI_LWO_SUBD AI_IFF_FOURCC('S','U','B','D') - -/* polygon tags */ -#define AI_LWO_SURF AI_IFF_FOURCC('S','U','R','F') -#define AI_LWO_PART AI_IFF_FOURCC('P','A','R','T') -#define AI_LWO_SMGP AI_IFF_FOURCC('S','M','G','P') - -/* envelopes */ -#define AI_LWO_PRE AI_IFF_FOURCC('P','R','E',' ') -#define AI_LWO_POST AI_IFF_FOURCC('P','O','S','T') -#define AI_LWO_KEY AI_IFF_FOURCC('K','E','Y',' ') -#define AI_LWO_SPAN AI_IFF_FOURCC('S','P','A','N') -#define AI_LWO_TCB AI_IFF_FOURCC('T','C','B',' ') -#define AI_LWO_HERM AI_IFF_FOURCC('H','E','R','M') -#define AI_LWO_BEZI AI_IFF_FOURCC('B','E','Z','I') -#define AI_LWO_BEZ2 AI_IFF_FOURCC('B','E','Z','2') -#define AI_LWO_LINE AI_IFF_FOURCC('L','I','N','E') -#define AI_LWO_STEP AI_IFF_FOURCC('S','T','E','P') - -/* clips */ -#define AI_LWO_STIL AI_IFF_FOURCC('S','T','I','L') -#define AI_LWO_ISEQ AI_IFF_FOURCC('I','S','E','Q') -#define AI_LWO_ANIM AI_IFF_FOURCC('A','N','I','M') -#define AI_LWO_XREF AI_IFF_FOURCC('X','R','E','F') -#define AI_LWO_STCC AI_IFF_FOURCC('S','T','C','C') -#define AI_LWO_TIME AI_IFF_FOURCC('T','I','M','E') -#define AI_LWO_CONT AI_IFF_FOURCC('C','O','N','T') -#define AI_LWO_BRIT AI_IFF_FOURCC('B','R','I','T') -#define AI_LWO_SATR AI_IFF_FOURCC('S','A','T','R') -#define AI_LWO_HUE AI_IFF_FOURCC('H','U','E',' ') -#define AI_LWO_GAMM AI_IFF_FOURCC('G','A','M','M') -#define AI_LWO_NEGA AI_IFF_FOURCC('N','E','G','A') -#define AI_LWO_IFLT AI_IFF_FOURCC('I','F','L','T') -#define AI_LWO_PFLT AI_IFF_FOURCC('P','F','L','T') - -/* surfaces */ -#define AI_LWO_COLR AI_IFF_FOURCC('C','O','L','R') -#define AI_LWO_LUMI AI_IFF_FOURCC('L','U','M','I') -#define AI_LWO_DIFF AI_IFF_FOURCC('D','I','F','F') -#define AI_LWO_SPEC AI_IFF_FOURCC('S','P','E','C') -#define AI_LWO_GLOS AI_IFF_FOURCC('G','L','O','S') -#define AI_LWO_REFL AI_IFF_FOURCC('R','E','F','L') -#define AI_LWO_RFOP AI_IFF_FOURCC('R','F','O','P') -#define AI_LWO_RIMG AI_IFF_FOURCC('R','I','M','G') -#define AI_LWO_RSAN AI_IFF_FOURCC('R','S','A','N') -#define AI_LWO_TRAN AI_IFF_FOURCC('T','R','A','N') -#define AI_LWO_TROP AI_IFF_FOURCC('T','R','O','P') -#define AI_LWO_TIMG AI_IFF_FOURCC('T','I','M','G') -#define AI_LWO_RIND AI_IFF_FOURCC('R','I','N','D') -#define AI_LWO_TRNL AI_IFF_FOURCC('T','R','N','L') -#define AI_LWO_BUMP AI_IFF_FOURCC('B','U','M','P') -#define AI_LWO_SMAN AI_IFF_FOURCC('S','M','A','N') -#define AI_LWO_SIDE AI_IFF_FOURCC('S','I','D','E') -#define AI_LWO_CLRH AI_IFF_FOURCC('C','L','R','H') -#define AI_LWO_CLRF AI_IFF_FOURCC('C','L','R','F') -#define AI_LWO_ADTR AI_IFF_FOURCC('A','D','T','R') -#define AI_LWO_SHRP AI_IFF_FOURCC('S','H','R','P') -#define AI_LWO_LINE AI_IFF_FOURCC('L','I','N','E') -#define AI_LWO_LSIZ AI_IFF_FOURCC('L','S','I','Z') -#define AI_LWO_ALPH AI_IFF_FOURCC('A','L','P','H') -#define AI_LWO_AVAL AI_IFF_FOURCC('A','V','A','L') -#define AI_LWO_GVAL AI_IFF_FOURCC('G','V','A','L') -#define AI_LWO_BLOK AI_IFF_FOURCC('B','L','O','K') -#define AI_LWO_VCOL AI_IFF_FOURCC('V','C','O','L') - -/* texture layer */ -#define AI_LWO_TYPE AI_IFF_FOURCC('T','Y','P','E') -#define AI_LWO_CHAN AI_IFF_FOURCC('C','H','A','N') -#define AI_LWO_NAME AI_IFF_FOURCC('N','A','M','E') -#define AI_LWO_ENAB AI_IFF_FOURCC('E','N','A','B') -#define AI_LWO_OPAC AI_IFF_FOURCC('O','P','A','C') -#define AI_LWO_FLAG AI_IFF_FOURCC('F','L','A','G') -#define AI_LWO_PROJ AI_IFF_FOURCC('P','R','O','J') -#define AI_LWO_STCK AI_IFF_FOURCC('S','T','C','K') -#define AI_LWO_TAMP AI_IFF_FOURCC('T','A','M','P') - -/* texture coordinates */ -#define AI_LWO_TMAP AI_IFF_FOURCC('T','M','A','P') -#define AI_LWO_AXIS AI_IFF_FOURCC('A','X','I','S') -#define AI_LWO_CNTR AI_IFF_FOURCC('C','N','T','R') -#define AI_LWO_SIZE AI_IFF_FOURCC('S','I','Z','E') -#define AI_LWO_ROTA AI_IFF_FOURCC('R','O','T','A') -#define AI_LWO_OREF AI_IFF_FOURCC('O','R','E','F') -#define AI_LWO_FALL AI_IFF_FOURCC('F','A','L','L') -#define AI_LWO_CSYS AI_IFF_FOURCC('C','S','Y','S') - -/* image map */ -#define AI_LWO_IMAP AI_IFF_FOURCC('I','M','A','P') -#define AI_LWO_IMAG AI_IFF_FOURCC('I','M','A','G') -#define AI_LWO_WRAP AI_IFF_FOURCC('W','R','A','P') -#define AI_LWO_WRPW AI_IFF_FOURCC('W','R','P','W') -#define AI_LWO_WRPH AI_IFF_FOURCC('W','R','P','H') -#define AI_LWO_VMAP AI_IFF_FOURCC('V','M','A','P') -#define AI_LWO_AAST AI_IFF_FOURCC('A','A','S','T') -#define AI_LWO_PIXB AI_IFF_FOURCC('P','I','X','B') - -/* procedural */ -#define AI_LWO_PROC AI_IFF_FOURCC('P','R','O','C') -#define AI_LWO_COLR AI_IFF_FOURCC('C','O','L','R') -#define AI_LWO_VALU AI_IFF_FOURCC('V','A','L','U') -#define AI_LWO_FUNC AI_IFF_FOURCC('F','U','N','C') -#define AI_LWO_FTPS AI_IFF_FOURCC('F','T','P','S') -#define AI_LWO_ITPS AI_IFF_FOURCC('I','T','P','S') -#define AI_LWO_ETPS AI_IFF_FOURCC('E','T','P','S') - -/* gradient */ -#define AI_LWO_GRAD AI_IFF_FOURCC('G','R','A','D') -#define AI_LWO_GRST AI_IFF_FOURCC('G','R','S','T') -#define AI_LWO_GREN AI_IFF_FOURCC('G','R','E','N') -#define AI_LWO_PNAM AI_IFF_FOURCC('P','N','A','M') -#define AI_LWO_INAM AI_IFF_FOURCC('I','N','A','M') -#define AI_LWO_GRPT AI_IFF_FOURCC('G','R','P','T') -#define AI_LWO_FKEY AI_IFF_FOURCC('F','K','E','Y') -#define AI_LWO_IKEY AI_IFF_FOURCC('I','K','E','Y') - -/* shader */ -#define AI_LWO_SHDR AI_IFF_FOURCC('S','H','D','R') -#define AI_LWO_DATA AI_IFF_FOURCC('D','A','T','A') - - -/* VMAP types */ -#define AI_LWO_TXUV AI_IFF_FOURCC('T','X','U','V') -#define AI_LWO_RGB AI_IFF_FOURCC('R','G','B',' ') -#define AI_LWO_RGBA AI_IFF_FOURCC('R','G','B','A') -#define AI_LWO_WGHT AI_IFF_FOURCC('W','G','H','T') - -#define AI_LWO_MNVW AI_IFF_FOURCC('M','N','V','W') -#define AI_LWO_MORF AI_IFF_FOURCC('M','O','R','F') -#define AI_LWO_SPOT AI_IFF_FOURCC('S','P','O','T') -#define AI_LWO_PICK AI_IFF_FOURCC('P','I','C','K') - -// MODO extension - per-vertex normal vectors -#define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M') - - -// --------------------------------------------------------------------------- -/** \brief Data structure for a face in a LWO file - * - * \note We can't use the code in SmoothingGroups.inl here - the mesh - * structures of 3DS/ASE and LWO are too different. - */ -struct Face : public aiFace -{ - //! Default construction - Face() - : surfaceIndex (0) - , smoothGroup (0) - , type (AI_LWO_FACE) - {} - - //! Construction from given type - Face(uint32_t _type) - : surfaceIndex (0) - , smoothGroup (0) - , type (_type) - {} - - //! Copy construction - Face(const Face& f) { - *this = f; - } - - //! Zero-based index into tags chunk - unsigned int surfaceIndex; - - //! Smooth group this face is assigned to - unsigned int smoothGroup; - - //! Type of face - uint32_t type; - - - //! Assignment operator - Face& operator=(const LWO::Face& f) { - aiFace::operator =(f); - surfaceIndex = f.surfaceIndex; - smoothGroup = f.smoothGroup; - type = f.type; - return *this; - } -}; - -// --------------------------------------------------------------------------- -/** \brief Base structure for all vertex map representations - */ -struct VMapEntry -{ - VMapEntry(unsigned int _dims) - : dims(_dims) - {} - - virtual ~VMapEntry() {} - - //! allocates memory for the vertex map - virtual void Allocate(unsigned int num) - { - if (!rawData.empty()) - return; // return if already allocated - - const unsigned int m = num*dims; - rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs - rawData.resize(m,0.f); - abAssigned.resize(num,false); - } - - std::string name; - unsigned int dims; - - std::vector<float> rawData; - std::vector<bool> abAssigned; -}; - -// --------------------------------------------------------------------------- -/** \brief Represents an extra vertex color channel - */ -struct VColorChannel : public VMapEntry -{ - VColorChannel() - : VMapEntry(4) - {} - - //! need to overwrite this function - the alpha channel must - //! be initialized to 1.0 by default - virtual void Allocate(unsigned int num) - { - if (!rawData.empty()) - return; // return if already allocated - - register unsigned int m = num*dims; - rawData.reserve(m + (m>>2u)); // 25% as extra storage for VMADs - rawData.resize(m); - - for (aiColor4D* p = (aiColor4D*)&rawData[0]; p < (aiColor4D*)&rawData[m-1]; ++p) - p->a = 1.f; - - abAssigned.resize(num,false); - } -}; - -// --------------------------------------------------------------------------- -/** \brief Represents an extra vertex UV channel - */ -struct UVChannel : public VMapEntry -{ - UVChannel() - : VMapEntry(2) - {} -}; - -// --------------------------------------------------------------------------- -/** \brief Represents a weight map - */ -struct WeightChannel : public VMapEntry -{ - WeightChannel() - : VMapEntry(1) - {} -}; - -// --------------------------------------------------------------------------- -/** \brief Represents a vertex-normals channel (MODO extension) - */ -struct NormalChannel : public VMapEntry -{ - NormalChannel() - : VMapEntry(3) - {} -}; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a LWO file texture - */ -struct Texture -{ - // we write the enum values out here to make debugging easier ... - enum BlendType - { - Normal = 0, - Subtractive = 1, - Difference = 2, - Multiply = 3, - Divide = 4, - Alpha = 5, - TextureDispl = 6, - Additive = 7 - }; - - enum MappingMode - { - Planar = 0, - Cylindrical = 1, - Spherical = 2, - Cubic = 3, - FrontProjection = 4, - UV = 5 - }; - - enum Axes - { - AXIS_X = 0, - AXIS_Y = 1, - AXIS_Z = 2 - }; - - enum Wrap - { - RESET = 0, - REPEAT = 1, - MIRROR = 2, - EDGE = 3 - }; - - Texture() - : mClipIdx(0xffffffff) - , mStrength (1.0f) - , mUVChannelIndex ("unknown") - , mRealUVIndex (0xffffffff) - , enabled (true) - , blendType (Additive) - , bCanUse (true) - , mapMode (UV) - , majorAxis (AXIS_X) - , wrapAmountH (1.0f) - , wrapAmountW (1.0f) - , wrapModeWidth (REPEAT) - , wrapModeHeight (REPEAT) - , ordinal ("\x00") - {} - - //! File name of the texture - std::string mFileName; - - //! Clip index - unsigned int mClipIdx; - - //! Strength of the texture - blend factor - float mStrength; - - uint32_t type; // type of the texture - - //! Name of the corresponding UV channel - std::string mUVChannelIndex; - unsigned int mRealUVIndex; - - //! is the texture enabled? - bool enabled; - - //! blend type - BlendType blendType; - - //! are we able to use the texture? - bool bCanUse; - - //! mapping mode - MappingMode mapMode; - - //! major axis for planar, cylindrical, spherical projections - Axes majorAxis; - - //! wrap amount for cylindrical and spherical projections - float wrapAmountH,wrapAmountW; - - //! wrapping mode for the texture - Wrap wrapModeWidth,wrapModeHeight; - - //! ordinal string of the texture - std::string ordinal; -}; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a LWO file clip - */ -struct Clip -{ - enum Type - { - STILL, SEQ, REF, UNSUPPORTED - } type; - - Clip() - : type (UNSUPPORTED) - , idx (0) - , negate (false) - {} - - //! path to the base texture - - std::string path; - - //! reference to another CLIP - unsigned int clipRef; - - //! index of the clip - unsigned int idx; - - //! Negate the clip? - bool negate; -}; - - -// --------------------------------------------------------------------------- -/** \brief Data structure for a LWO file shader - * - * Later - */ -struct Shader -{ - Shader() - : ordinal ("\x00") - , functionName ("unknown") - , enabled (true) - {} - - std::string ordinal; - std::string functionName; - bool enabled; -}; - -typedef std::list < Texture > TextureList; -typedef std::list < Shader > ShaderList; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a LWO file surface (= material) - */ -struct Surface -{ - Surface() - : mColor (0.78431f,0.78431f,0.78431f) - , bDoubleSided (false) - , mDiffuseValue (1.f) - , mSpecularValue (0.f) - , mTransparency (0.f) - , mGlossiness (0.4f) - , mLuminosity (0.f) - , mColorHighlights (0.f) - , mMaximumSmoothAngle (0.f) // 0 == not specified, no smoothing - , mVCMap ("") - , mVCMapType (AI_LWO_RGBA) - , mIOR (1.f) // vakuum - , mBumpIntensity (1.f) - , mWireframe (false) - , mAdditiveTransparency (0.f) - {} - - //! Name of the surface - std::string mName; - - //! Color of the surface - aiColor3D mColor; - - //! true for two-sided materials - bool bDoubleSided; - - //! Various material parameters - float mDiffuseValue,mSpecularValue,mTransparency,mGlossiness,mLuminosity,mColorHighlights; - - //! Maximum angle between two adjacent triangles - //! that they can be smoothed - in degrees - float mMaximumSmoothAngle; - - //! Vertex color map to be used to color the surface - std::string mVCMap; - uint32_t mVCMapType; - - //! Names of the special shaders to be applied to the surface - ShaderList mShaders; - - //! Textures - the first entry in the list is evaluated first - TextureList mColorTextures, // color textures are added to both diffuse and specular texture stacks - mDiffuseTextures, - mSpecularTextures, - mOpacityTextures, - mBumpTextures, - mGlossinessTextures, - mReflectionTextures; - - //! Index of refraction - float mIOR; - - //! Bump intensity scaling - float mBumpIntensity; - - //! Wireframe flag - bool mWireframe; - - //! Intensity of additive blending - float mAdditiveTransparency; -}; - -// --------------------------------------------------------------------------- -#define AI_LWO_VALIDATE_CHUNK_LENGTH(length,name,size) \ - if (length < size) \ - { \ - throw DeadlyImportError("LWO: "#name" chunk is too small"); \ - } \ - - -// some typedefs ... to make life with loader monsters like this easier -typedef std::vector < aiVector3D > PointList; -typedef std::vector < LWO::Face > FaceList; -typedef std::vector < LWO::Surface > SurfaceList; -typedef std::vector < std::string > TagList; -typedef std::vector < unsigned int > TagMappingTable; -typedef std::vector < unsigned int > ReferrerList; -typedef std::vector < WeightChannel > WeightChannelList; -typedef std::vector < VColorChannel > VColorChannelList; -typedef std::vector < UVChannel > UVChannelList; -typedef std::vector < Clip > ClipList; -typedef std::vector < Envelope > EnvelopeList; -typedef std::vector < unsigned int > SortedRep; - -// --------------------------------------------------------------------------- -/** \brief Represents a layer in the file - */ -struct Layer -{ - Layer() - : mFaceIDXOfs (0) - , mPointIDXOfs (0) - , mParent (0x0) - , mIndex (0xffff) - , skip (false) - {} - - /** Temporary point list from the file */ - PointList mTempPoints; - - /** Lists for every point the index of another point - that has been copied from *this* point or 0xffffffff if - no copy of the point has been made */ - ReferrerList mPointReferrers; - - /** Weight channel list from the file */ - WeightChannelList mWeightChannels; - - /** Subdivision weight channel list from the file */ - WeightChannelList mSWeightChannels; - - /** Vertex color list from the file */ - VColorChannelList mVColorChannels; - - /** UV channel list from the file */ - UVChannelList mUVChannels; - - /** Normal vector channel from the file */ - NormalChannel mNormals; - - /** Temporary face list from the file*/ - FaceList mFaces; - - /** Current face indexing offset from the beginning of the buffers*/ - unsigned int mFaceIDXOfs; - - /** Current point indexing offset from the beginning of the buffers*/ - unsigned int mPointIDXOfs; - - /** Parent index */ - uint16_t mParent; - - /** Index of the layer */ - uint16_t mIndex; - - /** Name of the layer */ - std::string mName; - - /** Pivot point of the layer */ - aiVector3D mPivot; - - /** Skip this layer? */ - bool skip; -}; - -typedef std::list<LWO::Layer> LayerList; - - -}} - - -#endif // !! AI_LWO_FILEDATA_INCLUDED - diff --git a/3rdparty/assimp/code/LWOLoader.cpp b/3rdparty/assimp/code/LWOLoader.cpp deleted file mode 100644 index 33c84960..00000000 --- a/3rdparty/assimp/code/LWOLoader.cpp +++ /dev/null @@ -1,1403 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWOLoader.cpp - * @brief Implementation of the LWO importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER - -// internal headers -#include "LWOLoader.h" -#include "MaterialSystem.h" -#include "StringComparison.h" -#include "SGSpatialSort.h" -#include "ByteSwap.h" -#include "ProcessHelper.h" -#include "ConvertToLHProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -LWOImporter::LWOImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -LWOImporter::~LWOImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool LWOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "lwo" || extension == "lxo") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[3]; - tokens[0] = AI_LWO_FOURCC_LWOB; - tokens[1] = AI_LWO_FOURCC_LWO2; - tokens[2] = AI_LWO_FOURCC_LXOB; - return CheckMagicToken(pIOHandler,pFile,tokens,3,8); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void LWOImporter::SetupProperties(const Importer* pImp) -{ - configSpeedFlag = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0) ? true : false); - configLayerIndex = pImp->GetPropertyInteger (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,0xffffffff); - configLayerName = pImp->GetPropertyString (AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,""); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void LWOImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, - IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open LWO file " + pFile + "."); - - if ((this->fileSize = (unsigned int)file->FileSize()) < 12) - throw DeadlyImportError("LWO: The file is too small to contain the IFF header"); - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector< uint8_t > mBuffer(fileSize); - file->Read( &mBuffer[0], 1, fileSize); - this->pScene = pScene; - - // Determine the type of the file - uint32_t fileType; - const char* sz = IFF::ReadHeader(&mBuffer[0],fileType); - if (sz)throw DeadlyImportError(sz); - - mFileBuffer = &mBuffer[0] + 12; - fileSize -= 12; - - // Initialize some members with their default values - hasNamedLayer = false; - - // Create temporary storage on the stack but store pointers to it in the class - // instance. Therefore everything will be destructed properly if an exception - // is thrown and we needn't take care of that. - LayerList _mLayers; - SurfaceList _mSurfaces; - TagList _mTags; - TagMappingTable _mMapping; - - mLayers = &_mLayers; - mTags = &_mTags; - mMapping = &_mMapping; - mSurfaces = &_mSurfaces; - - // Allocate a default layer (layer indices are 1-based from now) - mLayers->push_back(Layer()); - mCurLayer = &mLayers->back(); - mCurLayer->mName = "<LWODefault>"; - - // old lightwave file format (prior to v6) - if (AI_LWO_FOURCC_LWOB == fileType) { - DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)"); - - mIsLWO2 = false; - mIsLXOB = false; - LoadLWOBFile(); - } - // New lightwave format - else if (AI_LWO_FOURCC_LWO2 == fileType) { - mIsLXOB = false; - DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)"); - } - // MODO file format - else if (AI_LWO_FOURCC_LXOB == fileType) { - mIsLXOB = true; - DefaultLogger::get()->info("LWO file format: LXOB (Modo)"); - } - // we don't know this format - else - { - char szBuff[5]; - szBuff[0] = (char)(fileType >> 24u); - szBuff[1] = (char)(fileType >> 16u); - szBuff[2] = (char)(fileType >> 8u); - szBuff[3] = (char)(fileType); - szBuff[4] = '\0'; - throw DeadlyImportError(std::string("Unknown LWO sub format: ") + szBuff); - } - - if (AI_LWO_FOURCC_LWOB != fileType) { - mIsLWO2 = true; - LoadLWO2File(); - - // The newer lightwave format allows the user to configure the - // loader that just one layer is used. If this is the case - // we need to check now whether the requested layer has been found. - if (0xffffffff != configLayerIndex && configLayerIndex > mLayers->size()) - throw DeadlyImportError("LWO2: The requested layer was not found"); - - if (configLayerName.length() && !hasNamedLayer) { - throw DeadlyImportError("LWO2: Unable to find the requested layer: " - + configLayerName); - } - } - - // now, as we have loaded all data, we can resolve cross-referenced tags and clips - ResolveTags(); - ResolveClips(); - - // now process all layers and build meshes and nodes - std::vector<aiMesh*> apcMeshes; - std::vector<aiNode*> apcNodes; - apcNodes. reserve(mLayers->size()); - apcMeshes.reserve(mLayers->size()*std::min(((unsigned int)mSurfaces->size()/2u), 1u)); - - unsigned int iDefaultSurface = 0xffffffff; // index of the default surface - for (LayerList::iterator lit = mLayers->begin(), lend = mLayers->end();lit != lend;++lit) { - LWO::Layer& layer = *lit; - if (layer.skip) - continue; - - // I don't know whether there could be dummy layers, but it would be possible - const unsigned int meshStart = (unsigned int)apcMeshes.size(); - if (!layer.mFaces.empty() && !layer.mTempPoints.empty()) { - - // now sort all faces by the surfaces assigned to them - std::vector<SortedRep> pSorted(mSurfaces->size()+1); - - unsigned int i = 0; - for (FaceList::iterator it = layer.mFaces.begin(), end = layer.mFaces.end();it != end;++it,++i) { - // Check whether we support this face's type - if ((*it).type != AI_LWO_FACE && (*it).type != AI_LWO_PTCH && - (*it).type != AI_LWO_BONE && (*it).type != AI_LWO_SUBD) { - continue; - } - - unsigned int idx = (*it).surfaceIndex; - if (idx >= mTags->size()) - { - DefaultLogger::get()->warn("LWO: Invalid face surface index"); - idx = 0xffffffff; - } - if (0xffffffff == idx || 0xffffffff == (idx = _mMapping[idx])) { - if (0xffffffff == iDefaultSurface) { - iDefaultSurface = (unsigned int)mSurfaces->size(); - mSurfaces->push_back(LWO::Surface()); - LWO::Surface& surf = mSurfaces->back(); - surf.mColor.r = surf.mColor.g = surf.mColor.b = 0.6f; - surf.mName = "LWODefaultSurface"; - } - idx = iDefaultSurface; - } - pSorted[idx].push_back(i); - } - if (0xffffffff == iDefaultSurface) { - pSorted.erase(pSorted.end()-1); - } - for (unsigned int p = 0,i = 0;i < mSurfaces->size();++i) { - SortedRep& sorted = pSorted[i]; - if (sorted.empty()) - continue; - - // generate the mesh - aiMesh* mesh = new aiMesh(); - apcMeshes.push_back(mesh); - mesh->mNumFaces = (unsigned int)sorted.size(); - - // count the number of vertices - SortedRep::const_iterator it = sorted.begin(), end = sorted.end(); - for (;it != end;++it) { - mesh->mNumVertices += layer.mFaces[*it].mNumIndices; - } - - aiVector3D *nrm = NULL, * pv = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - aiFace* pf = mesh->mFaces = new aiFace[mesh->mNumFaces]; - mesh->mMaterialIndex = i; - - // find out which vertex color channels and which texture coordinate - // channels are really required by the material attached to this mesh - unsigned int vUVChannelIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - unsigned int vVColorIndices[AI_MAX_NUMBER_OF_COLOR_SETS]; - -#if _DEBUG - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) - vUVChannelIndices[mui] = 0xffffffff; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui ) - vVColorIndices[mui] = 0xffffffff; -#endif - - FindUVChannels(_mSurfaces[i],sorted,layer,vUVChannelIndices); - FindVCChannels(_mSurfaces[i],sorted,layer,vVColorIndices); - - // allocate storage for UV and CV channels - aiVector3D* pvUV[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_TEXTURECOORDS;++mui ) { - if (0xffffffff == vUVChannelIndices[mui]) - break; - - pvUV[mui] = mesh->mTextureCoords[mui] = new aiVector3D[mesh->mNumVertices]; - - // LightWave doesn't support more than 2 UV components (?) - mesh->mNumUVComponents[0] = 2; - } - - if (layer.mNormals.name.length()) - nrm = mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - - aiColor4D* pvVC[AI_MAX_NUMBER_OF_COLOR_SETS]; - for (unsigned int mui = 0; mui < AI_MAX_NUMBER_OF_COLOR_SETS;++mui) { - if (0xffffffff == vVColorIndices[mui])break; - pvVC[mui] = mesh->mColors[mui] = new aiColor4D[mesh->mNumVertices]; - } - - // we would not need this extra array, but the code is much cleaner if we use it - std::vector<unsigned int>& smoothingGroups = layer.mPointReferrers; - smoothingGroups.erase (smoothingGroups.begin(),smoothingGroups.end()); - smoothingGroups.resize(mesh->mNumFaces,0); - - // now convert all faces - unsigned int vert = 0; - std::vector<unsigned int>::iterator outIt = smoothingGroups.begin(); - for (it = sorted.begin(); it != end;++it,++outIt) { - const LWO::Face& face = layer.mFaces[*it]; - *outIt = face.smoothGroup; - - // copy all vertices - for (unsigned int q = 0; q < face.mNumIndices;++q,++vert) { - register unsigned int idx = face.mIndices[q]; - *pv++ = layer.mTempPoints[idx] /*- layer.mPivot*/; - - // process UV coordinates - for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_TEXTURECOORDS;++w) { - if (0xffffffff == vUVChannelIndices[w]) - break; - aiVector3D*& pp = pvUV[w]; - const aiVector2D& src = ((aiVector2D*)&layer.mUVChannels[vUVChannelIndices[w]].rawData[0])[idx]; - pp->x = src.x; - pp->y = src.y; - pp++; - } - - // process normals (MODO extension) - if (nrm) { - *nrm = ((aiVector3D*)&layer.mNormals.rawData[0])[idx]; - nrm->z *= -1.f; - ++nrm; - } - - // process vertex colors - for (unsigned int w = 0; w < AI_MAX_NUMBER_OF_COLOR_SETS;++w) { - if (0xffffffff == vVColorIndices[w]) - break; - *pvVC[w] = ((aiColor4D*)&layer.mVColorChannels[vVColorIndices[w]].rawData[0])[idx]; - - // If a RGB color map is explicitly requested delete the - // alpha channel - it could theoretically be != 1. - if (_mSurfaces[i].mVCMapType == AI_LWO_RGB) - pvVC[w]->a = 1.f; - - pvVC[w]++; - } - -#if 0 - // process vertex weights. We can't properly reconstruct the whole skeleton for now, - // but we can create dummy bones for all weight channels which we have. - for (unsigned int w = 0; w < layer.mWeightChannels.size();++w) - { - } -#endif - - face.mIndices[q] = vert; - } - pf->mIndices = face.mIndices; - pf->mNumIndices = face.mNumIndices; - unsigned int** p = (unsigned int**)&face.mIndices;*p = NULL; // HACK: make sure it won't be deleted - pf++; - } - - if (!mesh->mNormals) { - // Compute normal vectors for the mesh - we can't use our GenSmoothNormal- - // Step here since it wouldn't handle smoothing groups correctly for LWO. - // So we use a separate implementation. - ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]); - } - else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there"); - ++p; - } - } - - // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes - unsigned int num = apcMeshes.size() - meshStart; - if (layer.mName != "<LWODefault>" || num > 0) { - aiNode* pcNode = new aiNode(); - apcNodes.push_back(pcNode); - pcNode->mName.Set(layer.mName); - pcNode->mParent = (aiNode*)&layer; - pcNode->mNumMeshes = num; - - if (pcNode->mNumMeshes) { - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int p = 0; p < pcNode->mNumMeshes;++p) - pcNode->mMeshes[p] = p + meshStart; - } - } - } - - if (apcNodes.empty() || apcMeshes.empty()) - throw DeadlyImportError("LWO: No meshes loaded"); - - // The RemoveRedundantMaterials step will clean this up later - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = (unsigned int)mSurfaces->size()]; - for (unsigned int mat = 0; mat < pScene->mNumMaterials;++mat) { - MaterialHelper* pcMat = new MaterialHelper(); - pScene->mMaterials[mat] = pcMat; - ConvertMaterial((*mSurfaces)[mat],pcMat); - } - - // copy the meshes to the output structure - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = (unsigned int)apcMeshes.size() ]; - ::memcpy(pScene->mMeshes,&apcMeshes[0],pScene->mNumMeshes*sizeof(void*)); - - // generate the final node graph - GenerateNodeGraph(apcNodes); -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups, - const LWO::Surface& surface) -{ - // Allocate output storage - mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - - // First generate per-face normals - aiVector3D* out; - std::vector<aiVector3D> faceNormals; - - // ... in some cases that's already enough - if (!surface.mMaximumSmoothAngle) - out = mesh->mNormals; - else { - faceNormals.resize(mesh->mNumVertices); - out = &faceNormals[0]; - } - - aiFace* begin = mesh->mFaces, *const end = mesh->mFaces+mesh->mNumFaces; - for (; begin != end; ++begin) { - aiFace& face = *begin; - - // LWO doc: "the normal is defined as the cross product of the first and last edges" - aiVector3D* pV1 = mesh->mVertices + face.mIndices[0]; - aiVector3D* pV2 = mesh->mVertices + face.mIndices[1]; - aiVector3D* pV3 = mesh->mVertices + face.mIndices[face.mNumIndices-1]; - - aiVector3D vNor = ((*pV2 - *pV1) ^(*pV3 - *pV1)).Normalize(); - for (unsigned int i = 0; i < face.mNumIndices;++i) - out[face.mIndices[i]] = vNor; - } - if (!surface.mMaximumSmoothAngle)return; - const float posEpsilon = ComputePositionEpsilon(mesh); - - // Now generate the spatial sort tree - SGSpatialSort sSort; - std::vector<unsigned int>::const_iterator it = smoothingGroups.begin(); - for ( begin = mesh->mFaces; begin != end; ++begin, ++it) - { - aiFace& face = *begin; - for (unsigned int i = 0; i < face.mNumIndices;++i) - { - register unsigned int tt = face.mIndices[i]; - sSort.Add(mesh->mVertices[tt],tt,*it); - } - } - // Sort everything - this takes O(nlogn) time - sSort.Prepare(); - std::vector<unsigned int> poResult; - poResult.reserve(20); - - // Generate vertex normals. We have O(logn) for the binary lookup, which we need - // for n elements, thus the EXPECTED complexity is O(nlogn) - if (surface.mMaximumSmoothAngle < 3.f && !configSpeedFlag) { - const float fLimit = cos(surface.mMaximumSmoothAngle); - - for ( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { - const aiFace& face = *begin; - unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices; - for (; beginIdx != endIdx; ++beginIdx) - { - register unsigned int idx = *beginIdx; - sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true); - std::vector<unsigned int>::const_iterator a, end = poResult.end(); - - aiVector3D vNormals; - for (a = poResult.begin();a != end;++a) { - const aiVector3D& v = faceNormals[*a]; - if (v * faceNormals[idx] < fLimit) - continue; - vNormals += v; - } - mesh->mNormals[idx] = vNormals.Normalize(); - } - } - } - // faster code path in case there is no smooth angle - else { - std::vector<bool> vertexDone(mesh->mNumVertices,false); - for ( begin = mesh->mFaces, it = smoothingGroups.begin(); begin != end; ++begin, ++it) { - const aiFace& face = *begin; - unsigned int* beginIdx = face.mIndices, *const endIdx = face.mIndices+face.mNumIndices; - for (; beginIdx != endIdx; ++beginIdx) - { - register unsigned int idx = *beginIdx; - if (vertexDone[idx]) - continue; - sSort.FindPositions(mesh->mVertices[idx],*it,posEpsilon,poResult,true); - std::vector<unsigned int>::const_iterator a, end = poResult.end(); - - aiVector3D vNormals; - for (a = poResult.begin();a != end;++a) { - const aiVector3D& v = faceNormals[*a]; - vNormals += v; - } - vNormals.Normalize(); - for (a = poResult.begin();a != end;++a) { - mesh->mNormals[*a] = vNormals; - vertexDone[*a] = true; - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::AddChildren(aiNode* node, uint16_t parent, std::vector<aiNode*>& apcNodes) -{ - for (std::vector<aiNode*>::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { - if (*it) { - LWO::Layer* layer = (LWO::Layer*)(*it)->mParent; - if (layer->mParent == parent && layer->mIndex != parent) - ++node->mNumChildren; - } - } - - if (node->mNumChildren) { - unsigned int p = 0; - - node->mChildren = new aiNode* [ node->mNumChildren ]; - for (std::vector<aiNode*>::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { - if (*it) { - LWO::Layer* layer = (LWO::Layer*)(*it)->mParent; - if (layer->mParent == parent && layer->mIndex != parent) { - aiNode* nd = node->mChildren[p++] = *it; - nd->mParent = node; - - // fixme: ignore pivot points for the moment - //nd->mTransformation.a4 = layer->mPivot.x; - //nd->mTransformation.b4 = layer->mPivot.y; - //nd->mTransformation.c4 = layer->mPivot.z; - - // recursively add more children - (*it) = NULL; - AddChildren(nd,layer->mIndex,apcNodes); - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::GenerateNodeGraph(std::vector<aiNode*>& apcNodes) -{ - // now generate the final nodegraph - generate a root node and attach children - aiNode* root = pScene->mRootNode = new aiNode(); - root->mName.Set("<LWORoot>"); - AddChildren(root,0,apcNodes); - - // check whether we added all layers with meshes assigned to the output graph. - // if not, add them to the root node - unsigned int extra = 0; - for (std::vector<aiNode*>::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { - if ((*it) && (*it)->mNumMeshes) - ++extra; - } - - if (extra) { - const unsigned int newSize = extra + pScene->mRootNode->mNumChildren; - aiNode** const apcNewNodes = new aiNode*[newSize]; - if ((extra = root->mNumChildren)) - ::memcpy(apcNewNodes,root->mChildren,extra*sizeof(void*)); - - aiNode** cc = apcNewNodes+extra; - for (std::vector<aiNode*>::iterator it = apcNodes.begin(); it != apcNodes.end(); ++it) { - if ((*it) && (*it)->mNumMeshes) { - aiNode* nd = *cc++ = *it; - nd->mParent = pScene->mRootNode; - - // recursively add more children - (*it) = NULL; - AddChildren(nd,((LWO::Layer*)nd->mParent)->mIndex,apcNodes); - } - } - delete[] root->mChildren; - root->mChildren = apcNewNodes; - root->mNumChildren = newSize; - } - if (!pScene->mRootNode->mNumChildren) - throw DeadlyImportError("LWO: Unable to build a valid node graph"); - - // Remove a single root node with no meshes assigned to it ... - if (1 == pScene->mRootNode->mNumChildren) { - aiNode* pc = pScene->mRootNode->mChildren[0]; - pc->mParent = pScene->mRootNode->mChildren[0] = NULL; - delete pScene->mRootNode; - pScene->mRootNode = pc; - } - - // convert the whole stuff to RH with CCW winding - MakeLeftHandedProcess maker; - maker.Execute(pScene); - - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::ResolveTags() -{ - // --- this function is used for both LWO2 and LWOB - mMapping->resize(mTags->size(),0xffffffff); - for (unsigned int a = 0; a < mTags->size();++a) { - - const std::string& c = (*mTags)[a]; - for (unsigned int i = 0; i < mSurfaces->size();++i) { - - const std::string& d = (*mSurfaces)[i].mName; - if (!ASSIMP_stricmp(c,d)) { - - (*mMapping)[a] = i; - break; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::ResolveClips() -{ - for ( unsigned int i = 0; i < mClips.size();++i) { - - Clip& clip = mClips[i]; - if (Clip::REF == clip.type) { - - if (clip.clipRef >= mClips.size()) { - DefaultLogger::get()->error("LWO2: Clip referrer index is out of range"); - clip.clipRef = 0; - } - - Clip& dest = mClips[clip.clipRef]; - if (Clip::REF == dest.type) { - DefaultLogger::get()->error("LWO2: Clip references another clip reference"); - clip.type = Clip::UNSUPPORTED; - } - - else { - clip.path = dest.path; - clip.type = dest.type; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::AdjustTexturePath(std::string& out) -{ - // --- this function is used for both LWO2 and LWOB - if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) { - - // remove the (sequence) and append 000 - DefaultLogger::get()->info("LWOB: Sequence of animated texture found. It will be ignored"); - out = out.substr(0,out.length()-10) + "000"; - } - - // format: drive:path/file - we just need to insert a slash after the drive - std::string::size_type n = out.find_first_of(':'); - if (std::string::npos != n) { - out.insert(n+1,"/"); - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOTags(unsigned int size) -{ - // --- this function is used for both LWO2 and LWOB - - const char* szCur = (const char*)mFileBuffer, *szLast = szCur; - const char* const szEnd = szLast+size; - while (szCur < szEnd) - { - if (!(*szCur)) - { - const size_t len = (size_t)(szCur-szLast); - // FIX: skip empty-sized tags - if (len) - mTags->push_back(std::string(szLast,len)); - szCur += (len&0x1 ? 1 : 2); - szLast = szCur; - } - szCur++; - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWOPoints(unsigned int length) -{ - // --- this function is used for both LWO2 and LWOB but for - // LWO2 we need to allocate 25% more storage - it could be we'll - // need to duplicate some points later. - register unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12; - if (mIsLWO2) - { - mCurLayer->mTempPoints.reserve ( regularSize + (regularSize>>2u) ); - mCurLayer->mTempPoints.resize ( regularSize ); - - // initialize all point referrers with the default values - mCurLayer->mPointReferrers.reserve ( regularSize + (regularSize>>2u) ); - mCurLayer->mPointReferrers.resize ( regularSize, 0xffffffff ); - } - else mCurLayer->mTempPoints.resize( regularSize ); - - // perform endianess conversions -#ifndef AI_BUILD_BIG_ENDIAN - for (unsigned int i = 0; i < length>>2;++i) - ByteSwap::Swap4( mFileBuffer + (i << 2)); -#endif - ::memcpy(&mCurLayer->mTempPoints[0],mFileBuffer,length); -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Polygons(unsigned int length) -{ - LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); - const uint32_t type = GetU4(); - - // Determine the type of the polygons - switch (type) - { - // read unsupported stuff too (although we wont process it) - case AI_LWO_MBAL: - DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)"); - break; - case AI_LWO_CURV: - DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (SPLINE)");; - break; - - // These are ok with no restrictions - case AI_LWO_PTCH: - case AI_LWO_FACE: - case AI_LWO_BONE: - case AI_LWO_SUBD: - break; - default: - - // hm!? wtf is this? ok ... - DefaultLogger::get()->error("LWO2: Ignoring unknown polygon type."); - break; - } - - // first find out how many faces and vertices we'll finally need - uint16_t* cursor= (uint16_t*)mFileBuffer; - - unsigned int iNumFaces = 0,iNumVertices = 0; - CountVertsAndFacesLWO2(iNumVertices,iNumFaces,cursor,end); - - // allocate the output array and copy face indices - if (iNumFaces) { - cursor = (uint16_t*)mFileBuffer; - - mCurLayer->mFaces.resize(iNumFaces,LWO::Face(type)); - FaceList::iterator it = mCurLayer->mFaces.begin(); - CopyFaceIndicesLWO2(it,cursor,end); - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::CountVertsAndFacesLWO2(unsigned int& verts, unsigned int& faces, - uint16_t*& cursor, const uint16_t* const end, unsigned int max) -{ - while (cursor < end && max--) - { - AI_LSWAP2P(cursor); - uint16_t numIndices = *cursor++; - numIndices &= 0x03FF; - verts += numIndices;++faces; - - for (uint16_t i = 0; i < numIndices; i++) - ReadVSizedIntLWO2((uint8_t*&)cursor); - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it, - uint16_t*& cursor, - const uint16_t* const end) -{ - while (cursor < end) { - - LWO::Face& face = *it++;; - if ((face.mNumIndices = (*cursor++) & 0x03FF)) /* byte swapping has already been done */ { - face.mIndices = new unsigned int[face.mNumIndices]; - for (unsigned int i = 0; i < face.mNumIndices; i++) - { - face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs; - if (face.mIndices[i] > mCurLayer->mTempPoints.size()) - { - DefaultLogger::get()->warn("LWO2: Failure evaluating face record, index is out of range"); - face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1; - } - } - } - else throw DeadlyImportError("LWO2: Encountered invalid face record with zero indices"); - } -} - - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2PolygonTags(unsigned int length) -{ - LE_NCONST uint8_t* const end = mFileBuffer+length; - - AI_LWO_VALIDATE_CHUNK_LENGTH(length,PTAG,4); - uint32_t type = GetU4(); - - if (type != AI_LWO_SURF && type != AI_LWO_SMGP) - return; - - while (mFileBuffer < end) { - - unsigned int i = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs; - unsigned int j = GetU2(); - - if (i >= mCurLayer->mFaces.size()) { - DefaultLogger::get()->warn("LWO2: face index in PTAG is out of range"); - continue; - } - - switch (type) { - - case AI_LWO_SURF: - mCurLayer->mFaces[i].surfaceIndex = j; - break; - case AI_LWO_SMGP: /* is that really used? */ - mCurLayer->mFaces[i].smoothGroup = j; - break; - }; - } -} - -// ------------------------------------------------------------------------------------------------ -template <class T> -VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPoly) -{ - for (typename std::vector< T >::iterator it = list.begin(), end = list.end();it != end; ++it) { - if ((*it).name == name) { - if (!perPoly) { - DefaultLogger::get()->warn("LWO2: Found two VMAP sections with equal names"); - } - return &(*it); - } - } - list.push_back( T() ); - VMapEntry* p = &list.back(); - p->name = name; - return p; -} - -// ------------------------------------------------------------------------------------------------ -template <class T> -inline void CreateNewEntry(T& chan, unsigned int srcIdx) -{ - if (!chan.name.length()) - return; - - chan.abAssigned[srcIdx] = true; - chan.abAssigned.resize(chan.abAssigned.size()+1,false); - - for (unsigned int a = 0; a < chan.dims;++a) - chan.rawData.push_back(chan.rawData[srcIdx*chan.dims+a]); -} - -// ------------------------------------------------------------------------------------------------ -template <class T> -inline void CreateNewEntry(std::vector< T >& list, unsigned int srcIdx) -{ - for (typename std::vector< T >::iterator it = list.begin(), end = list.end();it != end;++it) { - CreateNewEntry( *it, srcIdx ); - } -} - -// ------------------------------------------------------------------------------------------------ -inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead, - unsigned int idx, float* data) -{ - ai_assert(NULL != data); - LWO::ReferrerList& refList = mCurLayer->mPointReferrers; - unsigned int i; - - base->abAssigned[idx] = true; - for (i = 0; i < numRead;++i) { - base->rawData[idx*base->dims+i]= data[i]; - } - - if (0xffffffff != (i = refList[idx])) { - DoRecursiveVMAPAssignment(base,numRead,i,data); - } -} - -// ------------------------------------------------------------------------------------------------ -inline void AddToSingleLinkedList(ReferrerList& refList, unsigned int srcIdx, unsigned int destIdx) -{ - if (0xffffffff == refList[srcIdx]) { - refList[srcIdx] = destIdx; - return; - } - AddToSingleLinkedList(refList,refList[srcIdx],destIdx); -} - -// ------------------------------------------------------------------------------------------------ -// Load LWO2 vertex map -void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) -{ - LE_NCONST uint8_t* const end = mFileBuffer+length; - - AI_LWO_VALIDATE_CHUNK_LENGTH(length,VMAP,6); - unsigned int type = GetU4(); - unsigned int dims = GetU2(); - - VMapEntry* base; - - // read the name of the vertex map - std::string name; - GetS0(name,length); - - switch (type) - { - case AI_LWO_TXUV: - if (dims != 2) { - DefaultLogger::get()->warn("LWO2: Skipping UV channel \'" - + name + "\' with !2 components"); - return; - } - base = FindEntry(mCurLayer->mUVChannels,name,perPoly); - break; - case AI_LWO_WGHT: - case AI_LWO_MNVW: - if (dims != 1) { - DefaultLogger::get()->warn("LWO2: Skipping Weight Channel \'" - + name + "\' with !1 components"); - return; - } - base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels - : mCurLayer->mSWeightChannels),name,perPoly); - break; - case AI_LWO_RGB: - case AI_LWO_RGBA: - if (dims != 3 && dims != 4) { - DefaultLogger::get()->warn("LWO2: Skipping Color Map \'" - + name + "\' with a dimension > 4 or < 3"); - return; - } - base = FindEntry(mCurLayer->mVColorChannels,name,perPoly); - break; - - case AI_LWO_MODO_NORM: - /* This is a non-standard extension chunk used by Luxology's MODO. - * It stores per-vertex normals. This VMAP exists just once, has - * 3 dimensions and is btw extremely beautiful. - */ - if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length()) - return; - - DefaultLogger::get()->info("Processing non-standard extension: MODO VMAP.NORM.vert_normals"); - - mCurLayer->mNormals.name = name; - base = & mCurLayer->mNormals; - break; - - case AI_LWO_PICK: /* these VMAPs are just silently dropped */ - case AI_LWO_MORF: - case AI_LWO_SPOT: - return; - - default: - if (name == "APS.Level") { - // XXX handle this (seems to be subdivision-related). - } - DefaultLogger::get()->warn("LWO2: Skipping unknown VMAP/VMAD channel \'" + name + "\'"); - return; - }; - base->Allocate((unsigned int)mCurLayer->mTempPoints.size()); - - // now read all entries in the map - type = std::min(dims,base->dims); - const unsigned int diff = (dims - type)<<2u; - - LWO::FaceList& list = mCurLayer->mFaces; - LWO::PointList& pointList = mCurLayer->mTempPoints; - LWO::ReferrerList& refList = mCurLayer->mPointReferrers; - - float temp[4]; - - const unsigned int numPoints = (unsigned int)pointList.size(); - const unsigned int numFaces = (unsigned int)list.size(); - - while (mFileBuffer < end) { - - unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs; - if (idx >= numPoints) { - DefaultLogger::get()->warn("LWO2: Failure evaluating VMAP/VMAD entry \'" + name + "\', vertex index is out of range"); - mFileBuffer += base->dims<<2u; - continue; - } - if (perPoly) { - unsigned int polyIdx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mFaceIDXOfs; - if (base->abAssigned[idx]) { - // we have already a VMAP entry for this vertex - thus - // we need to duplicate the corresponding polygon. - if (polyIdx >= numFaces) { - DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', polygon index is out of range"); - mFileBuffer += base->dims<<2u; - continue; - } - - LWO::Face& src = list[polyIdx]; - - // generate a new unique vertex for the corresponding index - but only - // if we can find the index in the face - bool had = false; - for (unsigned int i = 0; i < src.mNumIndices;++i) { - - unsigned int srcIdx = src.mIndices[i], tmp = idx; - do { - if (tmp == srcIdx) - break; - } - while ((tmp = refList[tmp]) != 0xffffffff); - if (tmp == 0xffffffff) - continue; - - had = true; - refList.resize(refList.size()+1, 0xffffffff); - - idx = (unsigned int)pointList.size(); - src.mIndices[i] = (unsigned int)pointList.size(); - - // store the index of the new vertex in the old vertex - // so we get a single linked list we can traverse in - // only one direction - AddToSingleLinkedList(refList,srcIdx,src.mIndices[i]); - pointList.push_back(pointList[srcIdx]); - - CreateNewEntry(mCurLayer->mVColorChannels, srcIdx ); - CreateNewEntry(mCurLayer->mUVChannels, srcIdx ); - CreateNewEntry(mCurLayer->mWeightChannels, srcIdx ); - CreateNewEntry(mCurLayer->mSWeightChannels, srcIdx ); - CreateNewEntry(mCurLayer->mNormals, srcIdx ); - } - if (!had) { - DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', vertex index wasn't found in that polygon"); - ai_assert(had); - } - } - } - for (unsigned int l = 0; l < type;++l) - temp[l] = GetF4(); - - DoRecursiveVMAPAssignment(base,type,idx, temp); - mFileBuffer += diff; - } -} - -// ------------------------------------------------------------------------------------------------ -// Load LWO2 clip -void LWOImporter::LoadLWO2Clip(unsigned int length) -{ - AI_LWO_VALIDATE_CHUNK_LENGTH(length,CLIP,10); - - mClips.push_back(LWO::Clip()); - LWO::Clip& clip = mClips.back(); - - // first - get the index of the clip - clip.idx = GetU4(); - - IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - switch (head->type) - { - case AI_LWO_STIL: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,STIL,1); - - // "Normal" texture - GetS0(clip.path,head->length); - clip.type = Clip::STILL; - break; - - case AI_LWO_ISEQ: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ISEQ,16); - // Image sequence. We'll later take the first. - { - uint8_t digits = GetU1(); mFileBuffer++; - int16_t offset = GetU2(); mFileBuffer+=4; - int16_t start = GetU2(); mFileBuffer+=4; - - std::string s;std::stringstream ss; - GetS0(s,head->length); - - head->length -= (unsigned int)s.length()+1; - ss << s; - ss << std::setw(digits) << offset + start; - GetS0(s,head->length); - ss << s; - clip.path = ss.str(); - clip.type = Clip::SEQ; - } - break; - - case AI_LWO_STCC: - DefaultLogger::get()->warn("LWO2: Color shifted images are not supported"); - break; - - case AI_LWO_ANIM: - DefaultLogger::get()->warn("LWO2: Animated textures are not supported"); - break; - - case AI_LWO_XREF: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,XREF,4); - - // Just a cross-reference to another CLIp - clip.type = Clip::REF; - clip.clipRef = GetU4(); - break; - - case AI_LWO_NEGA: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,NEGA,2); - clip.negate = (0 != GetU2()); - break; - - default: - DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk"); - } -} - -// ------------------------------------------------------------------------------------------------ -// Load envelope description -void LWOImporter::LoadLWO2Envelope(unsigned int length) -{ - LE_NCONST uint8_t* const end = mFileBuffer + length; - AI_LWO_VALIDATE_CHUNK_LENGTH(length,ENVL,4); - - mEnvelopes.push_back(LWO::Envelope()); - LWO::Envelope& envelope = mEnvelopes.back(); - - // Get the index of the envelope - envelope.index = ReadVSizedIntLWO2(mFileBuffer); - - // It looks like there might be an extra U4 right after the index, - // at least in modo (LXOB) files: we'll ignore it if it's zero, - // otherwise it represents the start of a subchunk, so we backtrack. - if (mIsLXOB) - { - uint32_t extra = GetU4(); - if (extra) - { - mFileBuffer -= 4; - } - } - - // ... and read all subchunks - while (true) - { - if (mFileBuffer + 6 >= end)break; - LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - throw DeadlyImportError("LWO2: Invalid envelope chunk length"); - - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - // Type & representation of the envelope - case AI_LWO_TYPE: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TYPE,2); - mFileBuffer++; // skip user format - - // Determine type of envelope - envelope.type = (LWO::EnvelopeType)*mFileBuffer; - ++mFileBuffer; - break; - - // precondition - case AI_LWO_PRE: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,PRE,2); - envelope.pre = (LWO::PrePostBehaviour)GetU2(); - break; - - // postcondition - case AI_LWO_POST: - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,POST,2); - envelope.post = (LWO::PrePostBehaviour)GetU2(); - break; - - // keyframe - case AI_LWO_KEY: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,KEY,8); - - envelope.keys.push_back(LWO::Key()); - LWO::Key& key = envelope.keys.back(); - - key.time = GetF4(); - key.value = GetF4(); - break; - } - - // interval interpolation - case AI_LWO_SPAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPAN,4); - if (envelope.keys.size()<2) - DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk"); - else { - LWO::Key& key = envelope.keys.back(); - switch (GetU4()) - { - case AI_LWO_STEP: - key.inter = LWO::IT_STEP;break; - case AI_LWO_LINE: - key.inter = LWO::IT_LINE;break; - case AI_LWO_TCB: - key.inter = LWO::IT_TCB;break; - case AI_LWO_HERM: - key.inter = LWO::IT_HERM;break; - case AI_LWO_BEZI: - key.inter = LWO::IT_BEZI;break; - case AI_LWO_BEZ2: - key.inter = LWO::IT_BEZ2;break; - default: - DefaultLogger::get()->warn("LWO2: Unknown interval interpolation mode"); - }; - - // todo ... read params - } - break; - } - - default: - DefaultLogger::get()->warn("LWO2: Encountered unknown ENVL subchunk"); - } - // regardless how much we did actually read, go to the next chunk - mFileBuffer = next; - } -} - -// ------------------------------------------------------------------------------------------------ -// Load file - master function -void LWOImporter::LoadLWO2File() -{ - bool skip = false; - - LE_NCONST uint8_t* const end = mFileBuffer + fileSize; - while (true) - { - if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; - IFF::ChunkHeader* const head = IFF::LoadChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - { - throw DeadlyImportError("LWO2: Chunk length points behind the file"); - break; - } - uint8_t* const next = mFileBuffer+head->length; - unsigned int iUnnamed = 0; - - switch (head->type) - { - // new layer - case AI_LWO_LAYR: - { - // add a new layer to the list .... - mLayers->push_back ( LWO::Layer() ); - LWO::Layer& layer = mLayers->back(); - mCurLayer = &layer; - - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LAYR,16); - - // Continue loading this layer or ignore it? Check the layer index property - // NOTE: The first layer is the default layer, so the layer index is one-based now - if (0xffffffff != configLayerIndex && configLayerIndex != mLayers->size()-1) { - skip = true; - } - else skip = false; - - // layer index. that's just for internal parenting, from the scope of a LWS file - // all layers are numbered in the oder in which they appear in the file - layer.mIndex = GetU2(); - - // pivot point - mFileBuffer += 2; /* unknown */ - mCurLayer->mPivot.x = GetF4(); - mCurLayer->mPivot.y = GetF4(); - mCurLayer->mPivot.z = GetF4(); - GetS0(layer.mName,head->length-16); - - // if the name is empty, generate a default name - if (layer.mName.empty()) { - char buffer[128]; // should be sufficiently large - ::sprintf(buffer,"Layer_%i", iUnnamed++); - layer.mName = buffer; - } - - // load this layer or ignore it? Check the layer name property - if (configLayerName.length() && configLayerName != layer.mName) { - skip = true; - } - else hasNamedLayer = true; - - // optional: parent of this layer - if (mFileBuffer + 2 <= next) - layer.mParent = GetU2(); - - break; - } - - // vertex list - case AI_LWO_PNTS: - { - if (skip) - break; - - unsigned int old = (unsigned int)mCurLayer->mTempPoints.size(); - LoadLWOPoints(head->length); - mCurLayer->mPointIDXOfs = old; - break; - } - // vertex tags - case AI_LWO_VMAD: - if (mCurLayer->mFaces.empty()) - { - DefaultLogger::get()->warn("LWO2: Unexpected VMAD chunk"); - break; - } - // --- intentionally no break here - case AI_LWO_VMAP: - { - if (skip) - break; - - if (mCurLayer->mTempPoints.empty()) - DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk"); - else LoadLWO2VertexMap(head->length,head->type == AI_LWO_VMAD); - break; - } - // face list - case AI_LWO_POLS: - { - if (skip) - break; - - unsigned int old = (unsigned int)mCurLayer->mFaces.size(); - LoadLWO2Polygons(head->length); - mCurLayer->mFaceIDXOfs = old; - break; - } - // polygon tags - case AI_LWO_PTAG: - { - if (skip) - break; - - if (mCurLayer->mFaces.empty()) - DefaultLogger::get()->warn("LWO2: Unexpected PTAG"); - else LoadLWO2PolygonTags(head->length); - break; - } - // list of tags - case AI_LWO_TAGS: - { - if (!mTags->empty()) - DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice"); - else LoadLWOTags(head->length); - break; - } - - // surface chunk - case AI_LWO_SURF: - { - LoadLWO2Surface(head->length); - break; - } - - // clip chunk - case AI_LWO_CLIP: - { - LoadLWO2Clip(head->length); - break; - } - - // envelope chunk - case AI_LWO_ENVL: - { - LoadLWO2Envelope(head->length); - break; - } - } - mFileBuffer = next; - } -} - -#endif // !! ASSIMP_BUILD_NO_LWO_IMPORTER diff --git a/3rdparty/assimp/code/LWOLoader.h b/3rdparty/assimp/code/LWOLoader.h deleted file mode 100644 index 629ec072..00000000 --- a/3rdparty/assimp/code/LWOLoader.h +++ /dev/null @@ -1,490 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Declaration of the LWO importer class. */ -#ifndef AI_LWOLOADER_H_INCLUDED -#define AI_LWOLOADER_H_INCLUDED - -#include "../include/aiTypes.h" -#include "../include/DefaultLogger.h" - -#include "LWOFileData.h" -#include "BaseImporter.h" -#include "MaterialSystem.h" - -struct aiTexture; -struct aiNode; - -namespace Assimp { -using namespace LWO; - -// --------------------------------------------------------------------------- -/** Class to load LWO files. - * - * @note Methods named "xxxLWO2[xxx]" are used with the newer LWO2 format. - * Methods named "xxxLWOB[xxx]" are used with the older LWOB format. - * Methods named "xxxLWO[xxx]" are used with both formats. - * Methods named "xxx" are used to preprocess the loaded data - - * they aren't specific to one format version -*/ -// --------------------------------------------------------------------------- -class LWOImporter : public BaseImporter -{ - friend class Importer; - - -protected: - /** Constructor to be privately used by Importer */ - LWOImporter(); - - /** Destructor, private as well */ - ~LWOImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions) - { - extensions.insert("lxo"); - extensions.insert("lwo"); - } - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - - // ------------------------------------------------------------------- - /** Loads a LWO file in the older LWOB format (LW < 6) - */ - void LoadLWOBFile(); - - // ------------------------------------------------------------------- - /** Loads a LWO file in the newer LWO2 format (LW >= 6) - */ - void LoadLWO2File(); - - - // ------------------------------------------------------------------- - /** Parsing functions used for all file format versions - */ - inline void GetS0(std::string& out,unsigned int max); - inline float GetF4(); - inline uint32_t GetU4(); - inline uint16_t GetU2(); - inline uint8_t GetU1(); - - - // ------------------------------------------------------------------- - /** Loads a surface chunk from an LWOB file - * @param size Maximum size to be read, in bytes. - */ - void LoadLWOBSurface(unsigned int size); - - // ------------------------------------------------------------------- - /** Loads a surface chunk from an LWO2 file - * @param size Maximum size to be read, in bytes. - */ - void LoadLWO2Surface(unsigned int size); - - // ------------------------------------------------------------------- - /** Loads a texture block from a LWO2 file. - * @param size Maximum size to be read, in bytes. - * @param head Header of the SUF.BLOK header - */ - void LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, - unsigned int size ); - - // ------------------------------------------------------------------- - /** Loads a shader block from a LWO2 file. - * @param size Maximum size to be read, in bytes. - * @param head Header of the SUF.BLOK header - */ - void LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head, - unsigned int size ); - - // ------------------------------------------------------------------- - /** Loads an image map from a LWO2 file - * @param size Maximum size to be read, in bytes. - * @param tex Texture object to be filled - */ - void LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex ); - void LoadLWO2Gradient(unsigned int size, LWO::Texture& tex ); - void LoadLWO2Procedural(unsigned int size, LWO::Texture& tex ); - - // loads the header - used by thethree functions above - void LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex ); - - // ------------------------------------------------------------------- - /** Loads the LWO tag list from the file - * @param size Maximum size to be read, in bytes. - */ - void LoadLWOTags(unsigned int size); - - // ------------------------------------------------------------------- - /** Load polygons from a POLS chunk - * @param length Size of the chunk - */ - void LoadLWO2Polygons(unsigned int length); - void LoadLWOBPolygons(unsigned int length); - - // ------------------------------------------------------------------- - /** Load polygon tags from a PTAG chunk - * @param length Size of the chunk - */ - void LoadLWO2PolygonTags(unsigned int length); - - // ------------------------------------------------------------------- - /** Load a vertex map from a VMAP/VMAD chunk - * @param length Size of the chunk - * @param perPoly Operate on per-polygon base? - */ - void LoadLWO2VertexMap(unsigned int length, bool perPoly); - - // ------------------------------------------------------------------- - /** Load polygons from a PNTS chunk - * @param length Size of the chunk - */ - void LoadLWOPoints(unsigned int length); - - // ------------------------------------------------------------------- - /** Load a clip from a CLIP chunk - * @param length Size of the chunk - */ - void LoadLWO2Clip(unsigned int length); - - // ------------------------------------------------------------------- - /** Load an envelope from an EVL chunk - * @param length Size of the chunk - */ - void LoadLWO2Envelope(unsigned int length); - - // ------------------------------------------------------------------- - /** Count vertices and faces in a LWOB/LWO2 file - */ - void CountVertsAndFacesLWO2(unsigned int& verts, - unsigned int& faces, - uint16_t*& cursor, - const uint16_t* const end, - unsigned int max = 0xffffffff); - - void CountVertsAndFacesLWOB(unsigned int& verts, - unsigned int& faces, - LE_NCONST uint16_t*& cursor, - const uint16_t* const end, - unsigned int max = 0xffffffff); - - // ------------------------------------------------------------------- - /** Read vertices and faces in a LWOB/LWO2 file - */ - void CopyFaceIndicesLWO2(LWO::FaceList::iterator& it, - uint16_t*& cursor, - const uint16_t* const end); - - // ------------------------------------------------------------------- - void CopyFaceIndicesLWOB(LWO::FaceList::iterator& it, - LE_NCONST uint16_t*& cursor, - const uint16_t* const end, - unsigned int max = 0xffffffff); - - // ------------------------------------------------------------------- - /** Resolve the tag and surface lists that have been loaded. - * Generates the mMapping table. - */ - void ResolveTags(); - - // ------------------------------------------------------------------- - /** Resolve the clip list that has been loaded. - * Replaces clip references with real clips. - */ - void ResolveClips(); - - // ------------------------------------------------------------------- - /** Add a texture list to an output material description. - * - * @param pcMat Output material - * @param in Input texture list - * @param type Type identifier of the texture list - */ - bool HandleTextures(MaterialHelper* pcMat, const TextureList& in, - aiTextureType type); - - // ------------------------------------------------------------------- - /** Adjust a texture path - */ - void AdjustTexturePath(std::string& out); - - // ------------------------------------------------------------------- - /** Convert a LWO surface description to an ASSIMP material - */ - void ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat); - - - // ------------------------------------------------------------------- - /** Get a list of all UV/VC channels required by a specific surface. - * - * @param surf Working surface - * @param layer Working layer - * @param out Output list. The members are indices into the - * UV/VC channel lists of the layer - */ - void FindUVChannels(/*const*/ LWO::Surface& surf, - LWO::SortedRep& sorted, - /*const*/ LWO::Layer& layer, - unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]); - - // ------------------------------------------------------------------- - char FindUVChannels(LWO::TextureList& list, - LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next); - - // ------------------------------------------------------------------- - void FindVCChannels(const LWO::Surface& surf, - LWO::SortedRep& sorted, - const LWO::Layer& layer, - unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]); - - // ------------------------------------------------------------------- - /** Generate the final node graph - * Unused nodes are deleted. - * @param apcNodes Flat list of nodes - */ - void GenerateNodeGraph(std::vector<aiNode*>& apcNodes); - - // ------------------------------------------------------------------- - /** Add children to a node - * @param node Node to become a father - * @param parent Index of the node - * @param apcNodes Flat list of nodes - used nodes are set to NULL. - */ - void AddChildren(aiNode* node, uint16_t parent, - std::vector<aiNode*>& apcNodes); - - // ------------------------------------------------------------------- - /** Read a variable sized integer - * @param inout Input and output buffer - */ - int ReadVSizedIntLWO2(uint8_t*& inout); - - // ------------------------------------------------------------------- - /** Assign a value from a VMAP to a vertex and all vertices - * attached to it. - * @param base VMAP destination data - * @param numRead Number of float's to be read - * @param idx Absolute index of the first vertex - * @param data Value of the VMAP to be assigned - read numRead - * floats from this array. - */ - void DoRecursiveVMAPAssignment(VMapEntry* base, unsigned int numRead, - unsigned int idx, float* data); - - // ------------------------------------------------------------------- - /** Compute normal vectors for a mesh - * @param mesh Input mesh - * @param smoothingGroups Smoothing-groups-per-face array - * @param surface Surface for the mesh - */ - void ComputeNormals(aiMesh* mesh, const std::vector<unsigned int>& smoothingGroups, - const LWO::Surface& surface); - - - // ------------------------------------------------------------------- - /** Setup a new texture after the corresponding chunk was - * encountered in the file. - * @param list Texture list - * @param size Maximum number of bytes to be read - * @return Pointer to new texture - */ - LWO::Texture* SetupNewTextureLWOB(LWO::TextureList& list, - unsigned int size); - -protected: - - /** true if the file is a LWO2 file*/ - bool mIsLWO2; - - /** true if the file is a LXOB file*/ - bool mIsLXOB; - - /** Temporary list of layers from the file */ - LayerList* mLayers; - - /** Pointer to the current layer */ - LWO::Layer* mCurLayer; - - /** Temporary tag list from the file */ - TagList* mTags; - - /** Mapping table to convert from tag to surface indices. - 0xffffffff indicates that a no corresponding surface is available */ - TagMappingTable* mMapping; - - /** Temporary surface list from the file */ - SurfaceList* mSurfaces; - - /** Temporary clip list from the file */ - ClipList mClips; - - /** Temporary envelope list from the file */ - EnvelopeList mEnvelopes; - - /** file buffer */ - uint8_t* mFileBuffer; - - /** Size of the file, in bytes */ - unsigned int fileSize; - - /** Output scene */ - aiScene* pScene; - - /** Configuration option: speed flag set? */ - bool configSpeedFlag; - - /** Configuration option: index of layer to be loaded */ - unsigned int configLayerIndex; - - /** Configuration option: name of layer to be loaded */ - std::string configLayerName; - - /** True if we have a named layer */ - bool hasNamedLayer; -}; - - -// ------------------------------------------------------------------------------------------------ -inline float LWOImporter::GetF4() -{ - float f = *((float*)mFileBuffer);mFileBuffer += 4; - AI_LSWAP4(f); - return f; -} - -// ------------------------------------------------------------------------------------------------ -inline uint32_t LWOImporter::GetU4() -{ - uint32_t f = *((uint32_t*)mFileBuffer);mFileBuffer += 4; - AI_LSWAP4(f); - return f; -} - -// ------------------------------------------------------------------------------------------------ -inline uint16_t LWOImporter::GetU2() -{ - uint16_t f = *((uint16_t*)mFileBuffer);mFileBuffer += 2; - AI_LSWAP2(f); - return f; -} - -// ------------------------------------------------------------------------------------------------ -inline uint8_t LWOImporter::GetU1() -{ - return *mFileBuffer++; -} - -// ------------------------------------------------------------------------------------------------ -inline int LWOImporter::ReadVSizedIntLWO2(uint8_t*& inout) -{ - int i; - int c = *inout;inout++; - if (c != 0xFF) - { - i = c << 8; - c = *inout;inout++; - i |= c; - } - else - { - c = *inout;inout++; - i = c << 16; - c = *inout;inout++; - i |= c << 8; - c = *inout;inout++; - i |= c; - } - return i; -} - -// ------------------------------------------------------------------------------------------------ -inline void LWOImporter::GetS0(std::string& out,unsigned int max) -{ - unsigned int iCursor = 0; - const char*sz = (const char*)mFileBuffer; - while (*mFileBuffer) - { - if (++iCursor > max) - { - DefaultLogger::get()->warn("LWO: Invalid file, string is is too long"); - break; - } - ++mFileBuffer; - } - size_t len = (size_t) ((const char*)mFileBuffer-sz); - out = std::string(sz,len); - mFileBuffer += (len&0x1 ? 1 : 2); -} - - - -} // end of namespace Assimp - -#endif // AI_LWOIMPORTER_H_INCLUDED diff --git a/3rdparty/assimp/code/LWOMaterial.cpp b/3rdparty/assimp/code/LWOMaterial.cpp deleted file mode 100644 index f23a5ecc..00000000 --- a/3rdparty/assimp/code/LWOMaterial.cpp +++ /dev/null @@ -1,898 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 material oart of the LWO importer class */ - - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER - -// internal headers -#include "LWOLoader.h" -#include "MaterialSystem.h" -#include "ByteSwap.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -template <class T> -T lerp(const T& one, const T& two, float val) -{ - return one + (two-one)*val; -} - -// ------------------------------------------------------------------------------------------------ -// Convert a lightwave mapping mode to our's -inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) -{ - switch (in) - { - case LWO::Texture::REPEAT: - return aiTextureMapMode_Wrap; - - case LWO::Texture::MIRROR: - return aiTextureMapMode_Mirror; - - case LWO::Texture::RESET: - DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET"); - - // fall though here - case LWO::Texture::EDGE: - return aiTextureMapMode_Clamp; - } - return (aiTextureMapMode)0; -} - -// ------------------------------------------------------------------------------------------------ -bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, aiTextureType type) -{ - ai_assert(NULL != pcMat); - - unsigned int cur = 0, temp = 0; - aiString s; - bool ret = false; - - for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) { - if (!(*it).enabled || !(*it).bCanUse) - continue; - ret = true; - - // Convert lightwave's mapping modes to ours. We let them - // as they are, the GenUVcoords step will compute UV - // channels if they're not there. - - aiTextureMapping mapping; - switch ((*it).mapMode) - { - case LWO::Texture::Planar: - mapping = aiTextureMapping_PLANE; - break; - case LWO::Texture::Cylindrical: - mapping = aiTextureMapping_CYLINDER; - break; - case LWO::Texture::Spherical: - mapping = aiTextureMapping_SPHERE; - break; - case LWO::Texture::Cubic: - mapping = aiTextureMapping_BOX; - break; - case LWO::Texture::FrontProjection: - DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection"); - mapping = aiTextureMapping_OTHER; - break; - case LWO::Texture::UV: - { - if( 0xffffffff == (*it).mRealUVIndex ) { - // We have no UV index for this texture, so we can't display it - continue; - } - - // add the UV source index - temp = (*it).mRealUVIndex; - pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur)); - - mapping = aiTextureMapping_UV; - } - break; - default: - ai_assert(false); - }; - - if (mapping != aiTextureMapping_UV) { - // Setup the main axis - aiVector3D v; - switch ((*it).majorAxis) { - case Texture::AXIS_X: - v = aiVector3D(1.f,0.f,0.f); - break; - case Texture::AXIS_Y: - v = aiVector3D(0.f,1.f,0.f); - break; - default: // case Texture::AXIS_Z: - v = aiVector3D(0.f,0.f,1.f); - break; - } - - pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur)); - - // Setup UV scalings for cylindric and spherical projections - if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) { - aiUVTransform trafo; - trafo.mScaling.x = (*it).wrapAmountW; - trafo.mScaling.y = (*it).wrapAmountH; - - BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5); - pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur)); - } - DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping"); - } - - // The older LWOB format does not use indirect references to clips. - // The file name of a texture is directly specified in the tex chunk. - if (mIsLWO2) { - // find the corresponding clip - ClipList::iterator clip = mClips.begin(); - temp = (*it).mClipIdx; - for (ClipList::iterator end = mClips.end(); clip != end; ++clip) { - if ((*clip).idx == temp) - break; - - } - if (mClips.end() == clip) { - DefaultLogger::get()->error("LWO2: Clip index is out of bounds"); - temp = 0; - - // fixme: appearently some LWO files shipping with Doom3 don't - // have clips at all ... check whether that's true or whether - // it's a bug in the loader. - - s.Set("$texture.png"); - - //continue; - } - else { - if (Clip::UNSUPPORTED == (*clip).type) { - DefaultLogger::get()->error("LWO2: Clip type is not supported"); - continue; - } - AdjustTexturePath((*clip).path); - s.Set((*clip).path); - - // Additional image settings - int flags = 0; - if ((*clip).negate) { - flags |= aiTextureFlags_Invert; - } - pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur)); - } - } - else - { - std::string ss = (*it).mFileName; - if (!ss.length()) { - DefaultLogger::get()->error("LWOB: Empty file name"); - continue; - } - AdjustTexturePath(ss); - s.Set(ss); - } - pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur)); - - // add the blend factor - pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur)); - - // add the blend operation - switch ((*it).blendType) - { - case LWO::Texture::Normal: - case LWO::Texture::Multiply: - temp = (unsigned int)aiTextureOp_Multiply; - break; - - case LWO::Texture::Subtractive: - case LWO::Texture::Difference: - temp = (unsigned int)aiTextureOp_Subtract; - break; - - case LWO::Texture::Divide: - temp = (unsigned int)aiTextureOp_Divide; - break; - - case LWO::Texture::Additive: - temp = (unsigned int)aiTextureOp_Add; - break; - - default: - temp = (unsigned int)aiTextureOp_Multiply; - DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement"); - - } - // Setup texture operation - pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur)); - - // setup the mapping mode - pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur)); - - // add the u-wrapping - temp = (unsigned int)GetMapMode((*it).wrapModeWidth); - pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur)); - - // add the v-wrapping - temp = (unsigned int)GetMapMode((*it).wrapModeHeight); - pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur)); - - ++cur; - } - return ret; -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat) -{ - // copy the name of the surface - aiString st; - st.Set(surf.mName); - pcMat->AddProperty(&st,AI_MATKEY_NAME); - - const int i = surf.bDoubleSided ? 1 : 0; - pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED); - - // add the refraction index and the bump intensity - pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI); - pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING); - - aiShadingMode m; - if (surf.mSpecularValue && surf.mGlossiness) - { - float fGloss; - if (mIsLWO2) { - fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f); - } - else - { - if (16.0f >= surf.mGlossiness) - fGloss = 6.0f; - else if (64.0f >= surf.mGlossiness) - fGloss = 20.0f; - else if (256.0f >= surf.mGlossiness) - fGloss = 50.0f; - else fGloss = 80.0f; - } - - pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH); - pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS); - m = aiShadingMode_Phong; - } - else m = aiShadingMode_Gouraud; - - // specular color - aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights ); - pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR); - pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH); - - // emissive color - // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good. - clr.g = clr.b = clr.r = surf.mLuminosity*0.8f; - pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE); - - // opacity ... either additive or default-blended, please - if (0.f != surf.mAdditiveTransparency) { - - const int add = aiBlendMode_Additive; - pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY); - pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC); - } - - else if (10e10f != surf.mTransparency) { - const int def = aiBlendMode_Default; - const float f = 1.0f-surf.mTransparency; - pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY); - pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC); - } - - - // ADD TEXTURES to the material - // TODO: find out how we can handle COLOR textures correctly... - bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE); - b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE)); - HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR); - HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS); - HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT); - HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY); - HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION); - - // Now we need to know which shader to use .. iterate through the shader list of - // the surface and search for a name which we know ... - for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();it != end;++it) { - //if (!(*it).enabled)continue; - - if ((*it).functionName == "LW_SuperCelShader" || (*it).functionName == "AH_CelShader") { - DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon"); - - m = aiShadingMode_Toon; - break; - } - else if ((*it).functionName == "LW_RealFresnel" || (*it).functionName == "LW_FastFresnel") { - DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel"); - - m = aiShadingMode_Fresnel; - break; - } - else - { - DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName); - } - } - if (surf.mMaximumSmoothAngle <= 0.0f) - m = aiShadingMode_Flat; - pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL); - - // (the diffuse value is just a scaling factor) - // If a diffuse texture is set, we set this value to 1.0 - clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor); - clr.r *= surf.mDiffuseValue; - clr.g *= surf.mDiffuseValue; - clr.b *= surf.mDiffuseValue; - pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE); -} - -// ------------------------------------------------------------------------------------------------ -char LWOImporter::FindUVChannels(LWO::TextureList& list, - LWO::Layer& layer,LWO::UVChannel& uv, unsigned int next) -{ - char ret = 0; - for (TextureList::iterator it = list.begin(), end = list.end();it != end;++it) { - - // Ignore textures with non-UV mappings for the moment. - if (!(*it).enabled || !(*it).bCanUse || (*it).mapMode != LWO::Texture::UV) { - continue; - } - - if ((*it).mUVChannelIndex == uv.name) { - ret = 1; - - // got it. - if ((*it).mRealUVIndex == 0xffffffff || (*it).mRealUVIndex == next) - { - (*it).mRealUVIndex = next; - } - else { - // channel mismatch. need to duplicate the material. - DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]"); - - // TODO - } - } - } - return ret; -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::FindUVChannels(LWO::Surface& surf, - LWO::SortedRep& sorted,LWO::Layer& layer, - unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]) -{ - unsigned int next = 0, extra = 0, num_extra = 0; - - // Check whether we have an UV entry != 0 for one of the faces in 'sorted' - for (unsigned int i = 0; i < layer.mUVChannels.size();++i) { - LWO::UVChannel& uv = layer.mUVChannels[i]; - - for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) { - - LWO::Face& face = layer.mFaces[*it]; - - for (unsigned int n = 0; n < face.mNumIndices; ++n) { - unsigned int idx = face.mIndices[n]; - - if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) { - - if (next >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { - - DefaultLogger::get()->error("LWO: Maximum number of UV channels for " - "this mesh reached. Skipping channel \'" + uv.name + "\'"); - - } - else { - // Search through all textures assigned to 'surf' and look for this UV channel - char had = 0; - had |= FindUVChannels(surf.mColorTextures,layer,uv,next); - had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next); - had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next); - had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next); - had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next); - had |= FindUVChannels(surf.mBumpTextures,layer,uv,next); - had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next); - - if (had != 0) { - - // We have a texture referencing this UV channel so we have to take special care of it - if (num_extra) { - - for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) { - out[a+1] = out[a]; - } - } - ++extra; - out[next++] = i; - } - else { - - // Bäh ... seems not to be used at all. Push to end if enough space is available. - out[extra++] = i; - ++num_extra; - } - } - it = sorted.end()-1; - break; - } - } - } - } - if (next != AI_MAX_NUMBER_OF_TEXTURECOORDS) { - out[extra] = 0xffffffff; - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer, - unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) -{ - unsigned int next = 0; - - // Check whether we have an vc entry != 0 for one of the faces in 'sorted' - for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) { - const LWO::VColorChannel& vc = layer.mVColorChannels[i]; - - if (surf.mVCMap == vc.name) { - // The vertex color map is explicitely requested by the surface so we need to take special care of it - for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) { - out[a+1] = out[a]; - } - out[0] = i; - ++next; - } - else { - - for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) { - const LWO::Face& face = layer.mFaces[*it]; - - for (unsigned int n = 0; n < face.mNumIndices; ++n) { - unsigned int idx = face.mIndices[n]; - - if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) { - if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) { - - DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for " - "this mesh reached. Skipping channel \'" + vc.name + "\'"); - - } - else { - out[next++] = i; - } - it = sorted.end()-1; - break; - } - } - } - } - } - if (next != AI_MAX_NUMBER_OF_COLOR_SETS) { - out[next] = 0xffffffff; - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex ) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; - while (true) - { - if (mFileBuffer + 6 >= end)break; - LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length"); - - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - case AI_LWO_PROJ: - tex.mapMode = (Texture::MappingMode)GetU2(); - break; - case AI_LWO_WRAP: - tex.wrapModeWidth = (Texture::Wrap)GetU2(); - tex.wrapModeHeight = (Texture::Wrap)GetU2(); - break; - case AI_LWO_AXIS: - tex.majorAxis = (Texture::Axes)GetU2(); - break; - case AI_LWO_IMAG: - tex.mClipIdx = GetU2(); - break; - case AI_LWO_VMAP: - GetS0(tex.mUVChannelIndex,head->length); - break; - case AI_LWO_WRPH: - tex.wrapAmountH = GetF4(); - break; - case AI_LWO_WRPW: - tex.wrapAmountW = GetF4(); - break; - } - mFileBuffer = next; - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Procedural(unsigned int size, LWO::Texture& tex ) -{ - // --- not supported at the moment - DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported"); - tex.bCanUse = false; -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Gradient(unsigned int size, LWO::Texture& tex ) -{ - // --- not supported at the moment - DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported"); - tex.bCanUse = false; -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex ) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; - - // get the ordinal string - GetS0( tex.ordinal, size); - - // we could crash later if this is an empty string ... - if (!tex.ordinal.length()) - { - DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string"); - tex.ordinal = "\x00"; - } - while (true) - { - if (mFileBuffer + 6 >= end)break; - LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - throw DeadlyImportError("LWO2: Invalid texture header chunk length"); - - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - case AI_LWO_CHAN: - tex.type = GetU4(); - break; - case AI_LWO_ENAB: - tex.enabled = GetU2() ? true : false; - break; - case AI_LWO_OPAC: - tex.blendType = (Texture::BlendType)GetU2(); - tex.mStrength = GetF4(); - break; - } - mFileBuffer = next; - } -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size ) -{ - ai_assert(!mSurfaces->empty()); - LWO::Surface& surf = mSurfaces->back(); - LWO::Texture tex; - - // load the texture header - LoadLWO2TextureHeader(head->length,tex); - size -= head->length + 6; - - // now get the exact type of the texture - switch (head->type) - { - case AI_LWO_PROC: - LoadLWO2Procedural(size,tex); - break; - case AI_LWO_GRAD: - LoadLWO2Gradient(size,tex); - break; - case AI_LWO_IMAP: - LoadLWO2ImageMap(size,tex); - } - - // get the destination channel - TextureList* listRef = NULL; - switch (tex.type) - { - case AI_LWO_COLR: - listRef = &surf.mColorTextures;break; - case AI_LWO_DIFF: - listRef = &surf.mDiffuseTextures;break; - case AI_LWO_SPEC: - listRef = &surf.mSpecularTextures;break; - case AI_LWO_GLOS: - listRef = &surf.mGlossinessTextures;break; - case AI_LWO_BUMP: - listRef = &surf.mBumpTextures;break; - case AI_LWO_TRAN: - listRef = &surf.mOpacityTextures;break; - case AI_LWO_REFL: - listRef = &surf.mReflectionTextures;break; - default: - DefaultLogger::get()->warn("LWO2: Encountered unknown texture type"); - return; - } - - // now attach the texture to the parent surface - sort by ordinal string - for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) { - if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { - listRef->insert(it,tex); - return; - } - } - listRef->push_back(tex); -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size ) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; - - ai_assert(!mSurfaces->empty()); - LWO::Surface& surf = mSurfaces->back(); - LWO::Shader shader; - - // get the ordinal string - GetS0( shader.ordinal, size); - - // we could crash later if this is an empty string ... - if (!shader.ordinal.length()) - { - DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string"); - shader.ordinal = "\x00"; - } - - // read the header - while (true) - { - if (mFileBuffer + 6 >= end)break; - LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - throw DeadlyImportError("LWO2: Invalid shader header chunk length"); - - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - case AI_LWO_ENAB: - shader.enabled = GetU2() ? true : false; - break; - - case AI_LWO_FUNC: - GetS0( shader.functionName, head->length ); - } - mFileBuffer = next; - } - - // now attach the shader to the parent surface - sort by ordinal string - for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) { - if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { - surf.mShaders.insert(it,shader); - return; - } - } - surf.mShaders.push_back(shader); -} - -// ------------------------------------------------------------------------------------------------ -void LWOImporter::LoadLWO2Surface(unsigned int size) -{ - LE_NCONST uint8_t* const end = mFileBuffer + size; - - mSurfaces->push_back( LWO::Surface () ); - LWO::Surface& surf = mSurfaces->back(); - - GetS0(surf.mName,size); - - // check whether this surface was derived from any other surface - std::string derived; - GetS0(derived,(unsigned int)(end - mFileBuffer)); - if (derived.length()) { - // yes, find this surface - for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) { - if ((*it).mName == derived) { - // we have it ... - surf = *it; - derived.clear();break; - } - } - if (derived.size()) - DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived); - } - - while (true) - { - if (mFileBuffer + 6 >= end) - break; - LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); - - if (mFileBuffer + head->length > end) - throw DeadlyImportError("LWO2: Invalid surface chunk length"); - - uint8_t* const next = mFileBuffer+head->length; - switch (head->type) - { - // diffuse color - case AI_LWO_COLR: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12); - surf.mColor.r = GetF4(); - surf.mColor.g = GetF4(); - surf.mColor.b = GetF4(); - break; - } - // diffuse strength ... hopefully - case AI_LWO_DIFF: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4); - surf.mDiffuseValue = GetF4(); - break; - } - // specular strength ... hopefully - case AI_LWO_SPEC: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4); - surf.mSpecularValue = GetF4(); - break; - } - // transparency - case AI_LWO_TRAN: - { - // transparency explicitly disabled? - if (surf.mTransparency == 10e10f) - break; - - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4); - surf.mTransparency = GetF4(); - break; - } - // additive transparency - case AI_LWO_ADTR: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4); - surf.mAdditiveTransparency = GetF4(); - break; - } - // wireframe mode - case AI_LWO_LINE: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2); - if (GetU2() & 0x1) - surf.mWireframe = true; - break; - } - // glossiness - case AI_LWO_GLOS: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4); - surf.mGlossiness = GetF4(); - break; - } - // bump intensity - case AI_LWO_BUMP: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4); - surf.mBumpIntensity = GetF4(); - break; - } - // color highlights - case AI_LWO_CLRH: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4); - surf.mColorHighlights = GetF4(); - break; - } - // index of refraction - case AI_LWO_RIND: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4); - surf.mIOR = GetF4(); - break; - } - // polygon sidedness - case AI_LWO_SIDE: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2); - surf.bDoubleSided = (3 == GetU2()); - break; - } - // maximum smoothing angle - case AI_LWO_SMAN: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4); - surf.mMaximumSmoothAngle = fabs( GetF4() ); - break; - } - // vertex color channel to be applied to the surface - case AI_LWO_VCOL: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12); - surf.mDiffuseValue *= GetF4(); // strength - ReadVSizedIntLWO2(mFileBuffer); // skip envelope - surf.mVCMapType = GetU4(); // type of the channel - - // name of the channel - GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer )); - break; - } - // surface bock entry - case AI_LWO_BLOK: - { - AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4); - LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer); - - switch (head2->type) - { - case AI_LWO_PROC: - case AI_LWO_GRAD: - case AI_LWO_IMAP: - LoadLWO2TextureBlock(head2, head->length); - break; - case AI_LWO_SHDR: - LoadLWO2ShaderBlock(head2, head->length); - break; - - default: - DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK"); - }; - - break; - } - } - mFileBuffer = next; - } -} - -#endif // !! ASSIMP_BUILD_NO_X_IMPORTER diff --git a/3rdparty/assimp/code/LWSLoader.cpp b/3rdparty/assimp/code/LWSLoader.cpp deleted file mode 100644 index 6a22b111..00000000 --- a/3rdparty/assimp/code/LWSLoader.cpp +++ /dev/null @@ -1,885 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWSLoader.cpp - * @brief Implementation of the LWS importer class - */ - -#include "AssimpPCH.h" - -#include "LWSLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -#include "SceneCombiner.h" -#include "GenericProperty.h" -#include "SkeletonMeshBuilder.h" -#include "ConvertToLHProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Recursive parsing of LWS files -void LWS::Element::Parse (const char*& buffer) -{ - for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) { - - // begin of a new element with children - bool sub = false; - if (*buffer == '{') { - ++buffer; - SkipSpaces(&buffer); - sub = true; - } - else if (*buffer == '}') - return; - - children.push_back(Element()); - - // copy data line - read token per token - - const char* cur = buffer; - while (!IsSpaceOrNewLine(*buffer)) ++buffer; - children.back().tokens[0] = std::string(cur,(size_t) (buffer-cur)); - SkipSpaces(&buffer); - - if (children.back().tokens[0] == "Plugin") - { - DefaultLogger::get()->debug("LWS: Skipping over plugin-specific data"); - - // strange stuff inside Plugin/Endplugin blocks. Needn't - // follow LWS syntax, so we skip over it - for (;SkipSpacesAndLineEnd(&buffer);SkipLine(&buffer)) { - if (!::strncmp(buffer,"EndPlugin",9)) { - //SkipLine(&buffer); - break; - } - } - continue; - } - - cur = buffer; - while (!IsLineEnd(*buffer)) ++buffer; - children.back().tokens[1] = std::string(cur,(size_t) (buffer-cur)); - - // parse more elements recursively - if (sub) - children.back().Parse(buffer); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -LWSImporter::LWSImporter() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -LWSImporter::~LWSImporter() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool LWSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler,bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "lws" || extension == "mot") - return true; - - // if check for extension is not enough, check for the magic tokens LWSC and LWMO - if (!extension.length() || checkSig) { - uint32_t tokens[2]; - tokens[0] = AI_MAKE_MAGIC("LWSC"); - tokens[1] = AI_MAKE_MAGIC("LWMO"); - return CheckMagicToken(pIOHandler,pFile,tokens,2); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get list of file extensions -void LWSImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("lws"); - extensions.insert("mot"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void LWSImporter::SetupProperties(const Importer* pImp) -{ - // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); - - // AI_CONFIG_IMPORT_LWS_ANIM_START - first = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_START, - 150392 /* magic hack */); - - // AI_CONFIG_IMPORT_LWS_ANIM_END - last = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_LWS_ANIM_END, - 150392 /* magic hack */); - - if (last < first) { - std::swap(last,first); - } -} - -// ------------------------------------------------------------------------------------------------ -// Read an envelope description -void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill ) -{ - if (dad.children.empty()) { - DefaultLogger::get()->error("LWS: Envelope descriptions must not be empty"); - return; - } - - // reserve enough storage - std::list< LWS::Element >::const_iterator it = dad.children.begin();; - fill.keys.reserve(strtol10(it->tokens[1].c_str())); - - for (++it; it != dad.children.end(); ++it) { - const char* c = (*it).tokens[1].c_str(); - - if ((*it).tokens[0] == "Key") { - fill.keys.push_back(LWO::Key()); - LWO::Key& key = fill.keys.back(); - - float f; - SkipSpaces(&c); - c = fast_atof_move(c,key.value); - SkipSpaces(&c); - c = fast_atof_move(c,f); - - key.time = f; - - unsigned int span = strtol10(c,&c), num = 0; - switch (span) { - - case 0: - key.inter = LWO::IT_TCB; - num = 5; - break; - case 1: - case 2: - key.inter = LWO::IT_HERM; - num = 5; - break; - case 3: - key.inter = LWO::IT_LINE; - num = 0; - break; - case 4: - key.inter = LWO::IT_STEP; - num = 0; - break; - case 5: - key.inter = LWO::IT_BEZ2; - num = 4; - break; - default: - DefaultLogger::get()->error("LWS: Unknown span type"); - } - for (unsigned int i = 0; i < num;++i) { - SkipSpaces(&c); - c = fast_atof_move(c,key.params[i]); - } - } - else if ((*it).tokens[0] == "Behaviors") { - SkipSpaces(&c); - fill.pre = (LWO::PrePostBehaviour) strtol10(c,&c); - SkipSpaces(&c); - fill.post = (LWO::PrePostBehaviour) strtol10(c,&c); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Read animation channels in the old LightWave animation format -void LWSImporter::ReadEnvelope_Old( - std::list< LWS::Element >::const_iterator& it, - const std::list< LWS::Element >::const_iterator& end, - LWS::NodeDesc& nodes, - unsigned int version) -{ - unsigned int num,sub_num; - if (++it == end)goto unexpected_end; - - num = strtol10((*it).tokens[0].c_str()); - for (unsigned int i = 0; i < num; ++i) { - - nodes.channels.push_back(LWO::Envelope()); - LWO::Envelope& envl = nodes.channels.back(); - - envl.index = i; - envl.type = (LWO::EnvelopeType)(i+1); - - if (++it == end)goto unexpected_end; - sub_num = strtol10((*it).tokens[0].c_str()); - - for (unsigned int n = 0; n < sub_num;++n) { - - if (++it == end)goto unexpected_end; - - // parse value and time, skip the rest for the moment. - LWO::Key key; - const char* c = fast_atof_move((*it).tokens[0].c_str(),key.value); - SkipSpaces(&c); - float f; - fast_atof_move((*it).tokens[0].c_str(),f); - key.time = f; - - envl.keys.push_back(key); - } - } - return; - -unexpected_end: - DefaultLogger::get()->error("LWS: Encountered unexpected end of file while parsing object motion"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup a nice name for a node -void LWSImporter::SetupNodeName(aiNode* nd, LWS::NodeDesc& src) -{ - const unsigned int combined = src.number | ((unsigned int)src.type) << 28u; - - // the name depends on the type. We break LWS's strange naming convention - // and return human-readable, but still machine-parsable and unique, strings. - if (src.type == LWS::NodeDesc::OBJECT) { - - if (src.path.length()) { - std::string::size_type s = src.path.find_last_of("\\/"); - if (s == std::string::npos) - s = 0; - else ++s; - - nd->mName.length = ::sprintf(nd->mName.data,"%s_(%08X)",src.path.substr(s).c_str(),combined); - return; - } - } - nd->mName.length = ::sprintf(nd->mName.data,"%s_(%08X)",src.name,combined); -} - -// ------------------------------------------------------------------------------------------------ -// Recursively build the scenegraph -void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<AttachmentInfo>& attach, - BatchLoader& batch, - aiCamera**& camOut, - aiLight**& lightOut, - std::vector<aiNodeAnim*>& animOut) -{ - // Setup a very cryptic name for the node, we want the user to be happy - SetupNodeName(nd,src); - - // If this is an object from an external file - get the scene and setup proper attachment tags - aiScene* obj = NULL; - if (src.type == LWS::NodeDesc::OBJECT && src.path.length() ) { - obj = batch.GetImport(src.id); - if (!obj) { - DefaultLogger::get()->error("LWS: Failed to read external file " + src.path); - } - else { - attach.push_back(AttachmentInfo(obj,nd)); - } - } - - // If object is a light source - setup a corresponding ai structure - else if (src.type == LWS::NodeDesc::LIGHT) { - aiLight* lit = *lightOut++ = new aiLight(); - - // compute final light color - lit->mColorDiffuse = lit->mColorSpecular = src.lightColor*src.lightIntensity; - - // name to attach light to node -> unique due to LWs indexing system - lit->mName = nd->mName; - - // detemine light type and setup additional members - if (src.lightType == 2) { /* spot light */ - - lit->mType = aiLightSource_SPOT; - lit->mAngleInnerCone = (float)AI_DEG_TO_RAD( src.lightConeAngle ); - lit->mAngleOuterCone = lit->mAngleInnerCone+(float)AI_DEG_TO_RAD( src.lightEdgeAngle ); - - } - else if (src.lightType == 1) { /* directional light source */ - lit->mType = aiLightSource_DIRECTIONAL; - } - else lit->mType = aiLightSource_POINT; - - // fixme: no proper handling of light falloffs yet - if (src.lightFalloffType == 1) - lit->mAttenuationConstant = 1.f; - else if (src.lightFalloffType == 1) - lit->mAttenuationLinear = 1.f; - else - lit->mAttenuationQuadratic = 1.f; - } - - // If object is a camera - setup a corresponding ai structure - else if (src.type == LWS::NodeDesc::CAMERA) { - aiCamera* cam = *camOut++ = new aiCamera(); - - // name to attach cam to node -> unique due to LWs indexing system - cam->mName = nd->mName; - } - - // Get the node transformation from the LWO key - LWO::AnimResolver resolver(src.channels,fps); - resolver.ExtractBindPose(nd->mTransformation); - - // .. and construct animation channels - aiNodeAnim* anim = NULL; - - if (first != last) { - resolver.SetAnimationRange(first,last); - resolver.ExtractAnimChannel(&anim,AI_LWO_ANIM_FLAG_SAMPLE_ANIMS|AI_LWO_ANIM_FLAG_START_AT_ZERO); - if (anim) { - anim->mNodeName = nd->mName; - animOut.push_back(anim); - } - } - - // process pivot point, if any - if (src.pivotPos != aiVector3D()) { - aiMatrix4x4 tmp; - aiMatrix4x4::Translation(-src.pivotPos,tmp); - - if (anim) { - - // We have an animation channel for this node. Problem: to combine the pivot - // point with the node anims, we'd need to interpolate *all* keys, get - // transformation matrices from them, apply the translation and decompose - // the resulting matrices again in order to reconstruct the keys. This - // solution here is *much* easier ... we're just inserting an extra node - // in the hierarchy. - // Maybe the final optimization here will be done during postprocessing. - - aiNode* pivot = new aiNode(); - pivot->mName.length = sprintf( pivot->mName.data, "$Pivot_%s",nd->mName.data); - pivot->mTransformation = tmp; - - pivot->mChildren = new aiNode*[pivot->mNumChildren = 1]; - pivot->mChildren[0] = nd; - - pivot->mParent = nd->mParent; - nd->mParent = pivot; - - // swap children and hope the parents wont see a huge difference - pivot->mParent->mChildren[pivot->mParent->mNumChildren-1] = pivot; - } - else { - nd->mTransformation = tmp*nd->mTransformation; - } - } - - // Add children - if (src.children.size()) { - nd->mChildren = new aiNode*[src.children.size()]; - for (std::list<LWS::NodeDesc*>::iterator it = src.children.begin(); it != src.children.end(); ++it) { - aiNode* ndd = nd->mChildren[nd->mNumChildren++] = new aiNode(); - ndd->mParent = nd; - - BuildGraph(ndd,**it,attach,batch,camOut,lightOut,animOut); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Determine the exact location of a LWO file -std::string LWSImporter::FindLWOFile(const std::string& in) -{ - // insert missing directory seperator if necessary - std::string tmp; - if (in.length() > 3 && in[1] == ':'&& in[2] != '\\' && in[2] != '/') - { - tmp = in[0] + ":\\" + in.substr(2); - } - else tmp = in; - - if (io->Exists(tmp)) - return in; - - // file is not accessible for us ... maybe it's packed by - // LightWave's 'Package Scene' command? - - // Relevant for us are the following two directories: - // <folder>\Objects\<hh>\<*>.lwo - // <folder>\Scenes\<hh>\<*>.lws - // where <hh> is optional. - - std::string test = ".." + io->getOsSeparator() + tmp; - if (io->Exists(test)) - return test; - - test = ".." + io->getOsSeparator() + test; - if (io->Exists(test)) - return test; - - // return original path, maybe the IOsystem knows better - return tmp; -} - -// ------------------------------------------------------------------------------------------------ -// Read file into given scene data structure -void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler) -{ - io = pIOHandler; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open LWS file " + pFile + "."); - } - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector< char > mBuffer; - TextFileToBuffer(file.get(),mBuffer); - - // Parse the file structure - LWS::Element root; const char* dummy = &mBuffer[0]; - root.Parse(dummy); - - // Construct a Batchimporter to read more files recursively - BatchLoader batch(pIOHandler); -// batch.SetBasePath(pFile); - - // Construct an array to receive the flat output graph - std::list<LWS::NodeDesc> nodes; - - unsigned int cur_light = 0, cur_camera = 0, cur_object = 0; - unsigned int num_light = 0, num_camera = 0, num_object = 0; - - // check magic identifier, 'LWSC' - bool motion_file = false; - std::list< LWS::Element >::const_iterator it = root.children.begin(); - - if ((*it).tokens[0] == "LWMO") - motion_file = true; - - if ((*it).tokens[0] != "LWSC" && !motion_file) - throw DeadlyImportError("LWS: Not a LightWave scene, magic tag LWSC not found"); - - // get file format version and print to log - ++it; - unsigned int version = strtol10((*it).tokens[0].c_str()); - DefaultLogger::get()->info("LWS file format version is " + (*it).tokens[0]); - first = 0.; - last = 60.; - fps = 25.; /* seems to be a good default frame rate */ - - // Now read all elements in a very straghtforward manner - for (; it != root.children.end(); ++it) { - const char* c = (*it).tokens[1].c_str(); - - // 'FirstFrame': begin of animation slice - if ((*it).tokens[0] == "FirstFrame") { - if (150392. != first /* see SetupProperties() */) - first = strtol10(c,&c)-1.; /* we're zero-based */ - } - - // 'LastFrame': end of animation slice - else if ((*it).tokens[0] == "LastFrame") { - if (150392. != last /* see SetupProperties() */) - last = strtol10(c,&c)-1.; /* we're zero-based */ - } - - // 'FramesPerSecond': frames per second - else if ((*it).tokens[0] == "FramesPerSecond") { - fps = strtol10(c,&c); - } - - // 'LoadObjectLayer': load a layer of a specific LWO file - else if ((*it).tokens[0] == "LoadObjectLayer") { - - // get layer index - const int layer = strtol10(c,&c); - - // setup the layer to be loaded - BatchLoader::PropertyMap props; - SetGenericProperty(props.ints,AI_CONFIG_IMPORT_LWO_ONE_LAYER_ONLY,layer); - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - if (version >= 4) { // handle LWSC 4 explicit ID - SkipSpaces(&c); - d.number = strtol16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_object++; - - // and add the file to the import list - SkipSpaces(&c); - std::string path = FindLWOFile( c ); - d.path = path; - d.id = batch.AddLoadRequest(path,0,&props); - - nodes.push_back(d); - num_object++; - } - // 'LoadObject': load a LWO file into the scenegraph - else if ((*it).tokens[0] == "LoadObject") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtol16(c,&c) & AI_LWS_MASK; - SkipSpaces(&c); - } - else d.number = cur_object++; - std::string path = FindLWOFile( c ); - d.id = batch.AddLoadRequest(path,0,NULL); - - d.path = path; - nodes.push_back(d); - num_object++; - } - // 'AddNullObject': add a dummy node to the hierarchy - else if ((*it).tokens[0] == "AddNullObject") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - d.name = c; - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtol16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_object++; - nodes.push_back(d); - - num_object++; - } - // 'NumChannels': Number of envelope channels assigned to last layer - else if ((*it).tokens[0] == "NumChannels") { - // ignore for now - } - // 'Channel': preceedes any envelope description - else if ((*it).tokens[0] == "Channel") { - if (nodes.empty()) { - if (motion_file) { - - // LightWave motion file. Add dummy node - LWS::NodeDesc d; - d.type = LWS::NodeDesc::OBJECT; - d.name = c; - d.number = cur_object++; - nodes.push_back(d); - } - else DefaultLogger::get()->error("LWS: Unexpected keyword: \'Channel\'"); - } - - // important: index of channel - nodes.back().channels.push_back(LWO::Envelope()); - LWO::Envelope& env = nodes.back().channels.back(); - - env.index = strtol10(c); - - // currently we can just interpret the standard channels 0...9 - // (hack) assume that index-i yields the binary channel type from LWO - env.type = (LWO::EnvelopeType)(env.index+1); - - } - // 'Envelope': a single animation channel - else if ((*it).tokens[0] == "Envelope") { - if (nodes.empty() || nodes.back().channels.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Envelope\'"); - else { - ReadEnvelope((*it),nodes.back().channels.back()); - } - } - // 'ObjectMotion': animation information for older lightwave formats - else if (version < 3 && ((*it).tokens[0] == "ObjectMotion" || - (*it).tokens[0] == "CameraMotion" || - (*it).tokens[0] == "LightMotion")) { - - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'"); - else { - ReadEnvelope_Old(it,root.children.end(),nodes.back(),version); - } - } - // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2 - else if (version == 2 && (*it).tokens[0] == "Pre/PostBehavior") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'Pre/PostBehavior'"); - else { - for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) { - // two ints per envelope - LWO::Envelope& env = *it; - env.pre = (LWO::PrePostBehaviour) strtol10(c,&c); SkipSpaces(&c); - env.post = (LWO::PrePostBehaviour) strtol10(c,&c); SkipSpaces(&c); - } - } - } - // 'ParentItem': specifies the parent of the current element - else if ((*it).tokens[0] == "ParentItem") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentItem\'"); - - else nodes.back().parent = strtol16(c,&c); - } - // 'ParentObject': deprecated one for older formats - else if (version < 3 && (*it).tokens[0] == "ParentObject") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentObject\'"); - - else { - nodes.back().parent = strtol10(c,&c) | (1u << 28u); - } - } - // 'AddCamera': add a camera to the scenegraph - else if ((*it).tokens[0] == "AddCamera") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::CAMERA; - - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtol16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_camera++; - nodes.push_back(d); - - num_camera++; - } - // 'CameraName': set name of currently active camera - else if ((*it).tokens[0] == "CameraName") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'CameraName\'"); - - else nodes.back().name = c; - } - // 'AddLight': add a light to the scenegraph - else if ((*it).tokens[0] == "AddLight") { - - // add node to list - LWS::NodeDesc d; - d.type = LWS::NodeDesc::LIGHT; - - if (version >= 4) { // handle LWSC 4 explicit ID - d.number = strtol16(c,&c) & AI_LWS_MASK; - } - else d.number = cur_light++; - nodes.push_back(d); - - num_light++; - } - // 'LightName': set name of currently active light - else if ((*it).tokens[0] == "LightName") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightName\'"); - - else nodes.back().name = c; - } - // 'LightIntensity': set intensity of currently active light - else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightIntensity\'"); - - else fast_atof_move(c, nodes.back().lightIntensity ); - - } - // 'LightType': set type of currently active light - else if ((*it).tokens[0] == "LightType") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightType\'"); - - else nodes.back().lightType = strtol10(c); - - } - // 'LightFalloffType': set falloff type of currently active light - else if ((*it).tokens[0] == "LightFalloffType") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightFalloffType\'"); - - else nodes.back().lightFalloffType = strtol10(c); - - } - // 'LightConeAngle': set cone angle of currently active light - else if ((*it).tokens[0] == "LightConeAngle") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightConeAngle\'"); - - else nodes.back().lightConeAngle = fast_atof(c); - - } - // 'LightEdgeAngle': set area where we're smoothing from min to max intensity - else if ((*it).tokens[0] == "LightEdgeAngle") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightEdgeAngle\'"); - - else nodes.back().lightEdgeAngle = fast_atof(c); - - } - // 'LightColor': set color of currently active light - else if ((*it).tokens[0] == "LightColor") { - if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightColor\'"); - - else { - c = fast_atof_move(c, (float&) nodes.back().lightColor.r ); - SkipSpaces(&c); - c = fast_atof_move(c, (float&) nodes.back().lightColor.g ); - SkipSpaces(&c); - c = fast_atof_move(c, (float&) nodes.back().lightColor.b ); - } - } - - // 'PivotPosition': position of local transformation origin - else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") { - if (nodes.empty()) - DefaultLogger::get()->error("LWS: Unexpected keyword: \'PivotPosition\'"); - else { - c = fast_atof_move(c, (float&) nodes.back().pivotPos.x ); - SkipSpaces(&c); - c = fast_atof_move(c, (float&) nodes.back().pivotPos.y ); - SkipSpaces(&c); - c = fast_atof_move(c, (float&) nodes.back().pivotPos.z ); - } - } - } - - // resolve parenting - for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) { - - // check whether there is another node which calls us a parent - for (std::list<LWS::NodeDesc>::iterator dit = nodes.begin(); dit != nodes.end(); ++dit) { - if (dit != it && *it == (*dit).parent) { - if ((*dit).parent_resolved) { - // fixme: it's still possible to produce an overflow due to cross references .. - DefaultLogger::get()->error("LWS: Found cross reference in scenegraph"); - continue; - } - - (*it).children.push_back(&*dit); - (*dit).parent_resolved = &*it; - } - } - } - - // find out how many nodes have no parent yet - unsigned int no_parent = 0; - for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it).parent_resolved) - ++ no_parent; - } - if (!no_parent) - throw DeadlyImportError("LWS: Unable to find scene root node"); - - - // Load all subsequent files - batch.LoadAll(); - - // and build the final output graph by attaching the loaded external - // files to ourselves. first build a master graph - aiScene* master = new aiScene(); - aiNode* nd = master->mRootNode = new aiNode(); - - // allocate storage for cameras&lights - if (num_camera) { - master->mCameras = new aiCamera*[master->mNumCameras = num_camera]; - } - aiCamera** cams = master->mCameras; - if (num_light) { - master->mLights = new aiLight*[master->mNumLights = num_light]; - } - aiLight** lights = master->mLights; - - std::vector<AttachmentInfo> attach; - std::vector<aiNodeAnim*> anims; - - nd->mName.Set("<LWSRoot>"); - nd->mChildren = new aiNode*[no_parent]; - for (std::list<LWS::NodeDesc>::iterator it = nodes.begin(); it != nodes.end(); ++it) { - if (!(*it).parent_resolved) { - aiNode* ro = nd->mChildren[ nd->mNumChildren++ ] = new aiNode(); - ro->mParent = nd; - - // ... and build the scene graph. If we encounter object nodes, - // add then to our attachment table. - BuildGraph(ro,*it, attach, batch, cams, lights, anims); - } - } - - // create a master animation channel for us - if (anims.size()) { - master->mAnimations = new aiAnimation*[master->mNumAnimations = 1]; - aiAnimation* anim = master->mAnimations[0] = new aiAnimation(); - anim->mName.Set("LWSMasterAnim"); - - // LWS uses seconds as time units, but we convert to frames - anim->mTicksPerSecond = fps; - anim->mDuration = last-(first-1); /* fixme ... zero or one-based?*/ - - anim->mChannels = new aiNodeAnim*[anim->mNumChannels = anims.size()]; - std::copy(anims.begin(),anims.end(),anim->mChannels); - } - - // convert the master scene to RH - MakeLeftHandedProcess monster_cheat; - monster_cheat.Execute(master); - - // .. ccw - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); - - // OK ... finally build the output graph - SceneCombiner::MergeScenes(&pScene,master,attach, - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | (!configSpeedFlag ? ( - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY | AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) : 0)); - - // Check flags - if (!pScene->mNumMeshes || !pScene->mNumMaterials) { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - - if (pScene->mNumAnimations) { - // construct skeleton mesh - SkeletonMeshBuilder builder(pScene); - } - } - -} diff --git a/3rdparty/assimp/code/LWSLoader.h b/3rdparty/assimp/code/LWSLoader.h deleted file mode 100644 index e9266dd4..00000000 --- a/3rdparty/assimp/code/LWSLoader.h +++ /dev/null @@ -1,242 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LWSLoader.h - * @brief Declaration of the LightWave scene importer class. - */ -#ifndef AI_LWSLOADER_H_INCLUDED -#define AI_LWSLOADER_H_INCLUDED - -#include "LWOFileData.h" -#include "SceneCombiner.h" - -namespace Assimp { - namespace LWS { - -// --------------------------------------------------------------------------- -/** Represents an element in a LWS file. - * - * This can either be a single data line - <name> <value> or a data - * group - { name <data_line0> ... n } - */ -class Element -{ -public: - Element() - {} - - // first: name, second: rest - std::string tokens[2]; - std::list<Element> children; - - //! Recursive parsing function - void Parse (const char*& buffer); -}; - -#define AI_LWS_MASK (0xffffffff >> 4u) - -// --------------------------------------------------------------------------- -/** Represents a LWS scenegraph element - */ -struct NodeDesc -{ - NodeDesc() - : number (0) - , parent (0) - , name ("") - , lightColor (1.f,1.f,1.f) - , lightIntensity (1.f) - , lightType (0) - , lightFalloffType (0) - , lightConeAngle (45.f) - , parent_resolved (NULL) - {} - - enum { - - OBJECT = 1, - LIGHT = 2, - CAMERA = 3, - BONE = 4 - } type; // type of node - - // if object: path - std::string path; - unsigned int id; - - // number of object - unsigned int number; - - // index of parent index - unsigned int parent; - - // lights & cameras & dummies: name - const char* name; - - // animation channels - std::list< LWO::Envelope > channels; - - // position of pivot point - aiVector3D pivotPos; - - - - // color of light source - aiColor3D lightColor; - - // intensity of light source - float lightIntensity; - - // type of light source - unsigned int lightType; - - // falloff type of light source - unsigned int lightFalloffType; - - // cone angle of (spot) light source - float lightConeAngle; - - // soft cone angle of (spot) light source - float lightEdgeAngle; - - - - // list of resolved children - std::list< NodeDesc* > children; - - // resolved parent node - NodeDesc* parent_resolved; - - - // for std::find() - bool operator == (unsigned int num) const { - if (!num) - return false; - unsigned int _type = num >> 28u; - - return _type == static_cast<unsigned int>(type) && (num & AI_LWS_MASK) == number; - } -}; - -} // end namespace LWS - -// --------------------------------------------------------------------------- -/** LWS (LightWave Scene Format) importer class. - * - * This class does heavily depend on the LWO importer class. LWS files - * contain mainly descriptions how LWO objects are composed together - * in a scene. -*/ -class LWSImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - LWSImporter(); - - /** Destructor, private as well */ - ~LWSImporter(); - -public: - - // ------------------------------------------------------------------- - // Check whether we can read a specific file - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - // Get list of supported extensions - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - // Import file into given scene data structure - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - // Setup import properties - void SetupProperties(const Importer* pImp); - -private: - - - // ------------------------------------------------------------------- - // Read an envelope description - void ReadEnvelope(const LWS::Element& dad, LWO::Envelope& out ); - - // ------------------------------------------------------------------- - // Read an envelope description for the older LW file format - void ReadEnvelope_Old(std::list< LWS::Element >::const_iterator& it, - const std::list< LWS::Element >::const_iterator& end, - LWS::NodeDesc& nodes, - unsigned int version); - - // ------------------------------------------------------------------- - // Setup a nice name for a node - void SetupNodeName(aiNode* nd, LWS::NodeDesc& src); - - // ------------------------------------------------------------------- - // Recursively build the scenegraph - void BuildGraph(aiNode* nd, - LWS::NodeDesc& src, - std::vector<AttachmentInfo>& attach, - BatchLoader& batch, - aiCamera**& camOut, - aiLight**& lightOut, - std::vector<aiNodeAnim*>& animOut); - - // ------------------------------------------------------------------- - // Try several dirs until we find the right location of a LWS file. - std::string FindLWOFile(const std::string& in); - -private: - - bool configSpeedFlag; - IOSystem* io; - - double first,last,fps; -}; - -} // end of namespace Assimp - -#endif // AI_LWSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp b/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp deleted file mode 100644 index ebb18a30..00000000 --- a/3rdparty/assimp/code/LimitBoneWeightsProcess.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -/** Implementation of the LimitBoneWeightsProcess post processing step */ - -#include "AssimpPCH.h" -#include "LimitBoneWeightsProcess.h" - - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -LimitBoneWeightsProcess::LimitBoneWeightsProcess() -{ - mMaxWeights = AI_LMW_MAX_WEIGHTS; -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -LimitBoneWeightsProcess::~LimitBoneWeightsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_LimitBoneWeights) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void LimitBoneWeightsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("LimitBoneWeightsProcess begin"); - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - ProcessMesh( pScene->mMeshes[a]); - - DefaultLogger::get()->debug("LimitBoneWeightsProcess end"); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp) -{ - // get the current value of the property - this->mMaxWeights = pImp->GetPropertyInteger(AI_CONFIG_PP_LBW_MAX_WEIGHTS,AI_LMW_MAX_WEIGHTS); -} - -// ------------------------------------------------------------------------------------------------ -// Unites identical vertices in the given mesh -void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh) -{ - if ( !pMesh->HasBones()) - return; - - // collect all bone weights per vertex - typedef std::vector< std::vector< Weight > > WeightsPerVertex; - WeightsPerVertex vertexWeights( pMesh->mNumVertices); - - // collect all weights per vertex - for ( unsigned int a = 0; a < pMesh->mNumBones; a++) - { - const aiBone* bone = pMesh->mBones[a]; - for ( unsigned int b = 0; b < bone->mNumWeights; b++) - { - const aiVertexWeight& w = bone->mWeights[b]; - vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight)); - } - } - - unsigned int removed = 0, old_bones = pMesh->mNumBones; - - // now cut the weight count if it exceeds the maximum - bool bChanged = false; - for ( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit) - { - if ( vit->size() <= mMaxWeights) - continue; - - bChanged = true; - - // more than the defined maximum -> first sort by weight in descending order. That's - // why we defined the < operator in such a weird way. - std::sort( vit->begin(), vit->end()); - - // now kill everything beyond the maximum count - unsigned int m = vit->size(); - vit->erase( vit->begin() + mMaxWeights, vit->end()); - removed += m-vit->size(); - - // and renormalize the weights - float sum = 0.0f; - for ( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it) - sum += it->mWeight; - for ( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it) - it->mWeight /= sum; - } - - if (bChanged) { - // rebuild the vertex weight array for all bones - typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone; - WeightsPerBone boneWeights( pMesh->mNumBones); - for ( unsigned int a = 0; a < vertexWeights.size(); a++) - { - const std::vector<Weight>& vw = vertexWeights[a]; - for ( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it) - boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight)); - } - - // and finally copy the vertex weight list over to the mesh's bones - std::vector<bool> abNoNeed(pMesh->mNumBones,false); - bChanged = false; - - for ( unsigned int a = 0; a < pMesh->mNumBones; a++) - { - const std::vector<aiVertexWeight>& bw = boneWeights[a]; - aiBone* bone = pMesh->mBones[a]; - - // ignore the bone if no vertex weights were removed there - - // FIX (Aramis, 07|22|08) - // NO! we can't ignore it in this case ... it is possible that - // the number of weights did not change, but the weight values did. - - // if ( bw.size() == bone->mNumWeights) - // continue; - - // FIX (Aramis, 07|21|08) - // It is possible that all weights of a bone have been removed. - // This would naturally cause an exception in &bw[0]. - if ( bw.empty() ) - { - abNoNeed[a] = bChanged = true; - continue; - } - - // copy the weight list. should always be less weights than before, so we don't need a new allocation - ai_assert( bw.size() <= bone->mNumWeights); - bone->mNumWeights = (unsigned int) bw.size(); - ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight)); - } - - if (bChanged) { - // the number of new bones is smaller than before, so we can reuse the old array - aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur; - - for (std::vector<bool>::const_iterator iter = abNoNeed.begin();iter != abNoNeed.end() ;++iter) { - if (*iter) { - delete *ppcSrc; - --pMesh->mNumBones; - } - else *ppcCur++ = *ppcSrc; - ++ppcSrc; - } - } - - if (!DefaultLogger::isNullLogger()) { - char buffer[1024]; - ::sprintf(buffer,"Removed %i weights. Input bones: %i. Output bones: %i",removed,old_bones,pMesh->mNumBones); - DefaultLogger::get()->info(buffer); - } - } -} diff --git a/3rdparty/assimp/code/LimitBoneWeightsProcess.h b/3rdparty/assimp/code/LimitBoneWeightsProcess.h deleted file mode 100644 index 99b72ef9..00000000 --- a/3rdparty/assimp/code/LimitBoneWeightsProcess.h +++ /dev/null @@ -1,146 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -/** Defines a post processing step to limit the number of bones affecting a single vertex. */ -#ifndef AI_LIMITBONEWEIGHTSPROCESS_H_INC -#define AI_LIMITBONEWEIGHTSPROCESS_H_INC - -#include "BaseProcess.h" - -struct aiMesh; -class LimitBoneWeightsTest; - -namespace Assimp -{ - -// NOTE: If you change these limits, don't forget to change the -// corresponding values in all Assimp ports - -// ********************************************************** -// Java: ConfigProperty.java, -// ConfigProperty.DEFAULT_BONE_WEIGHT_LIMIT -// ********************************************************** - -#if (!defined AI_LMW_MAX_WEIGHTS) -# define AI_LMW_MAX_WEIGHTS 0x4 -#endif // !! AI_LMW_MAX_WEIGHTS - -// --------------------------------------------------------------------------- -/** This post processing step limits the number of bones affecting a vertex -* to a certain maximum value. If a vertex is affected by more than that number -* of bones, the bone weight with the least influence on this vertex are removed. -* The other weights on this bone are then renormalized to assure the sum weight -* to be 1. -*/ -class ASSIMP_API LimitBoneWeightsProcess : public BaseProcess -{ - friend class Importer; - friend class ::LimitBoneWeightsTest; - -protected: - /** Constructor to be privately used by Importer */ - LimitBoneWeightsProcess(); - - /** Destructor, private as well */ - ~LimitBoneWeightsProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. - * @param pFlags The processing flags the importer was called with. - * A bitwise combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, - * false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - // ------------------------------------------------------------------- - /** Limits the bone weight count for all vertices in the given mesh. - * @param pMesh The mesh to process. - */ - void ProcessMesh( aiMesh* pMesh); - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - -protected: - - // ------------------------------------------------------------------- - /** Describes a bone weight on a vertex */ - struct Weight - { - unsigned int mBone; ///< Index of the bone - float mWeight; ///< Weight of that bone on this vertex - Weight() { } - Weight( unsigned int pBone, float pWeight) - { - mBone = pBone; - mWeight = pWeight; - } - - /** Comparision operator to sort bone weights by descending weight */ - bool operator < (const Weight& pWeight) const - { - return mWeight > pWeight.mWeight; - } - }; - -public: - /** Maximum number of bones influencing any single vertex. */ - unsigned int mMaxWeights; -}; - -} // end of namespace Assimp - -#endif // AI_LIMITBONEWEIGHTSPROCESS_H_INC diff --git a/3rdparty/assimp/code/LineSplitter.h b/3rdparty/assimp/code/LineSplitter.h deleted file mode 100644 index 61f5b34b..00000000 --- a/3rdparty/assimp/code/LineSplitter.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 LineSplitter.h - * @brief LineSplitter, a helper class to iterate through all lines - * of a file easily. Works with StreamReader. - */ -#ifndef INCLUDED_LINE_SPLITTER_H -#define INCLUDED_LINE_SPLITTER_H - -#include <stdexcept> - -#include "StreamReader.h" -#include "ParsingUtils.h" - -namespace Assimp { - -// ------------------------------------------------------------------------------------------------ -/** Usage: -@code -for (LineSplitter splitter(stream);splitter;++splitter) { - - if (*splitter == "hi!") { - ... - } - else if (splitter->substr(0,5) == "hello") { - ... - // access the third token in the line (tokens are space-separated) - if (strtol(splitter[2]) > 5) { .. } - } - - std::cout << "Current line is: " << splitter.get_index() << std::endl; -} -@endcode */ -// ------------------------------------------------------------------------------------------------ -class LineSplitter -{ -public: - - typedef size_t line_idx; - -public: - - // ----------------------------------------- - /** construct from existing stream reader */ - LineSplitter(StreamReaderLE& stream) - : stream(stream) - , swallow() - { - cur.reserve(1024); - operator++(); - - idx = 0; - } - -public: - - // ----------------------------------------- - /** pseudo-iterator increment */ - LineSplitter& operator++() { - if (swallow) { - swallow = false; - return *this; - } - - if (!*this) { - throw std::logic_error("End of file, no more lines to be retrieved."); - } - - char s; - - cur.clear(); // I will kill you if you deallocate. - while (stream.GetRemainingSize() && (s = stream.GetI1(),1)) { - if (s == '\n' || s == '\r') { - while (stream.GetRemainingSize() && ((s = stream.GetI1()) == ' ' || s == '\r' || s == '\n')); - if (stream.GetRemainingSize()) { - stream.IncPtr(-1); - } - break; - } - cur += s; - } - - ++idx; - return *this; - } - - // ----------------------------------------- - /** get a pointer to the beginning of a particular token */ - const char* operator[] (size_t idx) const { - const char* s = operator->()->c_str(); - - SkipSpaces(&s); - for (size_t i = 0; i < idx; ++i) { - - for (;!IsSpace(*s); ++s) { - if (IsLineEnd(*s)) { - throw std::range_error("Token index out of range, EOL reached"); - } - } - SkipSpaces(&s); - } - return s; - } - - // ----------------------------------------- - /** extract the start positions of N tokens from the current line*/ - template <size_t N> - void get_tokens(const char* (&tokens)[N]) const { - const char* s = operator->()->c_str(); - - SkipSpaces(&s); - for (size_t i = 0; i < N; ++i) { - if (IsLineEnd(*s)) { - throw std::range_error("Token count out of range, EOL reached"); - } - tokens[i] = s; - - for (;*s && !IsSpace(*s); ++s); - SkipSpaces(&s); - } - } - - // ----------------------------------------- - /** member access */ - const std::string* operator -> () const { - return &cur; - } - - const std::string& operator* () const { - return cur; - } - - // ----------------------------------------- - /** boolean context */ - operator bool() const { - return stream.GetRemainingSize()>0; - } - - // ----------------------------------------- - /** line indices are zero-based, empty lines are included */ - operator line_idx() const { - return idx; - } - - line_idx get_index() const { - return idx; - } - - // ----------------------------------------- - /** access the underlying stream object */ - StreamReaderLE& get_stream() { - return stream; - } - - // ----------------------------------------- - /** !strcmp((*this)->substr(0,strlen(check)),check) */ - bool match_start(const char* check) { - const size_t len = strlen(check); - - return len <= cur.length() && std::equal(check,check+len,cur.begin()); - } - - - // ----------------------------------------- - /** swallow the next call to ++, return the previous value. */ - void swallow_next_increment() { - swallow = true; - } - -private: - - line_idx idx; - std::string cur; - StreamReaderLE& stream; - bool swallow; -}; - -} -#endif // INCLUDED_LINE_SPLITTER_H diff --git a/3rdparty/assimp/code/MD2FileData.h b/3rdparty/assimp/code/MD2FileData.h deleted file mode 100644 index 86437470..00000000 --- a/3rdparty/assimp/code/MD2FileData.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD2FileData.h - * @brief Defines helper data structures for importing MD2 files - * http://linux.ucla.edu/~phaethon/q3/formats/md2-schoenblum.html - */ -#ifndef AI_MD2FILEHELPER_H_INC -#define AI_MD2FILEHELPER_H_INC - -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include "../include/aiAnim.h" - -#include "./../include/Compiler/pushpack1.h" - -namespace Assimp { -namespace MD2 { - -// to make it easier for us, we test the magic word against both "endianesses" -#define AI_MD2_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP2") -#define AI_MD2_MAGIC_NUMBER_LE AI_MAKE_MAGIC("2PDI") - -// common limitations -#define AI_MD2_VERSION 15 -#define AI_MD2_MAXQPATH 64 -#define AI_MD2_MAX_FRAMES 512 -#define AI_MD2_MAX_SKINS 32 -#define AI_MD2_MAX_VERTS 2048 -#define AI_MD2_MAX_TRIANGLES 4096 - -// --------------------------------------------------------------------------- -/** \brief Data structure for the MD2 main header - */ -struct Header -{ - uint32_t magic; - uint32_t version; - uint32_t skinWidth; - uint32_t skinHeight; - uint32_t frameSize; - uint32_t numSkins; - uint32_t numVertices; - uint32_t numTexCoords; - uint32_t numTriangles; - uint32_t numGlCommands; - uint32_t numFrames; - uint32_t offsetSkins; - uint32_t offsetTexCoords; - uint32_t offsetTriangles; - uint32_t offsetFrames; - uint32_t offsetGlCommands; - uint32_t offsetEnd; - -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD2 OpenGl draw command - */ -struct GLCommand -{ - float s, t; - uint32_t vertexIndex; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD2 triangle - */ -struct Triangle -{ - uint16_t vertexIndices[3]; - uint16_t textureIndices[3]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD2 vertex - */ -struct Vertex -{ - uint8_t vertex[3]; - uint8_t lightNormalIndex; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD2 frame - */ -struct Frame -{ - float scale[3]; - float translate[3]; - char name[16]; - Vertex vertices[1]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD2 texture coordinate - */ -struct TexCoord -{ - uint16_t s; - uint16_t t; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD2 skin - */ -struct Skin -{ - char name[AI_MD2_MAXQPATH]; /* texture file name */ -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - - -// --------------------------------------------------------------------------- -//! Lookup a normal vector from Quake's normal lookup table -//! \param index Input index (0-161) -//! \param vOut Receives the output normal -void LookupNormalIndex(uint8_t index,aiVector3D& vOut); - - -} -} - -#endif // !! include guard - diff --git a/3rdparty/assimp/code/MD2Loader.cpp b/3rdparty/assimp/code/MD2Loader.cpp deleted file mode 100644 index ad7960f9..00000000 --- a/3rdparty/assimp/code/MD2Loader.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. ---------------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER - -/** @file Implementation of the MD2 importer class */ -#include "MD2Loader.h" -#include "MaterialSystem.h" -#include "ByteSwap.h" -#include "MD2NormalTable.h" // shouldn't be included by other units - -using namespace Assimp; -using namespace Assimp::MD2; - - -// helper macro to determine the size of an array -#if (!defined ARRAYSIZE) -# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0]))) -#endif - -// ------------------------------------------------------------------------------------------------ -// Helper function to lookup a normal in Quake 2's precalculated table -void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut) -{ - // make sure the normal index has a valid value - if (iNormalIndex >= ARRAYSIZE(g_avNormals)) { - DefaultLogger::get()->warn("Index overflow in Quake II normal vector list"); - iNormalIndex = ARRAYSIZE(g_avNormals) - 1; - } - vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex])); -} - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MD2Importer::MD2Importer() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MD2Importer::~MD2Importer() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "md2") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MD2_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all extensions supported by this loader -void MD2Importer::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("md2"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void MD2Importer::SetupProperties(const Importer* pImp) -{ - // The - // AI_CONFIG_IMPORT_MD2_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD2_KEYFRAME,0xffffffff); - if (0xffffffff == configFrameID){ - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } -} -// ------------------------------------------------------------------------------------------------ -// Validate the file header -void MD2Importer::ValidateHeader( ) -{ - // check magic number - if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && - m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) - { - char szBuffer[5]; - szBuffer[0] = ((char*)&m_pcHeader->magic)[0]; - szBuffer[1] = ((char*)&m_pcHeader->magic)[1]; - szBuffer[2] = ((char*)&m_pcHeader->magic)[2]; - szBuffer[3] = ((char*)&m_pcHeader->magic)[3]; - szBuffer[4] = '\0'; - - throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the " - "magic word found is " + std::string(szBuffer)); - } - - // check file format version - if (m_pcHeader->version != 8) - DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ..."); - - // check some values whether they are valid - if (0 == m_pcHeader->numFrames) - throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0"); - - if (m_pcHeader->offsetEnd > (uint32_t)fileSize) - throw DeadlyImportError( "Invalid md2 file: File is too small"); - - if (m_pcHeader->offsetSkins + m_pcHeader->numSkins * sizeof (MD2::Skin) >= fileSize || - m_pcHeader->offsetTexCoords + m_pcHeader->numTexCoords * sizeof (MD2::TexCoord) >= fileSize || - m_pcHeader->offsetTriangles + m_pcHeader->numTriangles * sizeof (MD2::Triangle) >= fileSize || - m_pcHeader->offsetFrames + m_pcHeader->numFrames * sizeof (MD2::Frame) >= fileSize || - m_pcHeader->offsetEnd > fileSize) - { - throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); - } - - if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) - DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports"); - if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES) - DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports"); - if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS) - DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports"); - - if (m_pcHeader->numFrames <= configFrameID ) - throw DeadlyImportError("The requested frame is not existing the file"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MD2Importer::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD2 file " + pFile + ""); - - // check whether the md3 file is large enough to contain - // at least the file header - fileSize = (unsigned int)file->FileSize(); - if ( fileSize < sizeof(MD2::Header)) - throw DeadlyImportError( "MD2 File is too small"); - - std::vector<uint8_t> mBuffer2(fileSize); - file->Read(&mBuffer2[0], 1, fileSize); - mBuffer = &mBuffer2[0]; - - - m_pcHeader = (BE_NCONST MD2::Header*)mBuffer; - -#ifdef AI_BUILD_BIG_ENDIAN - - ByteSwap::Swap4(&m_pcHeader->frameSize); - ByteSwap::Swap4(&m_pcHeader->magic); - ByteSwap::Swap4(&m_pcHeader->numFrames); - ByteSwap::Swap4(&m_pcHeader->numGlCommands); - ByteSwap::Swap4(&m_pcHeader->numSkins); - ByteSwap::Swap4(&m_pcHeader->numTexCoords); - ByteSwap::Swap4(&m_pcHeader->numTriangles); - ByteSwap::Swap4(&m_pcHeader->numVertices); - ByteSwap::Swap4(&m_pcHeader->offsetEnd); - ByteSwap::Swap4(&m_pcHeader->offsetFrames); - ByteSwap::Swap4(&m_pcHeader->offsetGlCommands); - ByteSwap::Swap4(&m_pcHeader->offsetSkins); - ByteSwap::Swap4(&m_pcHeader->offsetTexCoords); - ByteSwap::Swap4(&m_pcHeader->offsetTriangles); - ByteSwap::Swap4(&m_pcHeader->skinHeight); - ByteSwap::Swap4(&m_pcHeader->skinWidth); - ByteSwap::Swap4(&m_pcHeader->version); - -#endif - - ValidateHeader(); - - // there won't be more than one mesh inside the file - pScene->mNumMaterials = 1; - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = new MaterialHelper(); - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - - aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh(); - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // navigate to the begin of the frame data - BE_NCONST MD2::Frame* pcFrame = (BE_NCONST MD2::Frame*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetFrames); - - pcFrame += configFrameID; - - // navigate to the begin of the triangle data - MD2::Triangle* pcTriangles = (MD2::Triangle*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetTriangles); - - // navigate to the begin of the tex coords data - BE_NCONST MD2::TexCoord* pcTexCoords = (BE_NCONST MD2::TexCoord*) ((uint8_t*) - m_pcHeader + m_pcHeader->offsetTexCoords); - - // navigate to the begin of the vertex data - BE_NCONST MD2::Vertex* pcVerts = (BE_NCONST MD2::Vertex*) (pcFrame->vertices); - -#ifdef AI_BUILD_BIG_ENDIAN - for (uint32_t i = 0; i< m_pcHeader->numTriangles; ++i) - { - for (unsigned int p = 0; p < 3;++p) - { - ByteSwap::Swap2(& pcTriangles[i].textureIndices[p]); - ByteSwap::Swap2(& pcTriangles[i].vertexIndices[p]); - } - } - for (uint32_t i = 0; i < m_pcHeader->offsetTexCoords;++i) - { - ByteSwap::Swap2(& pcTexCoords[i].s); - ByteSwap::Swap2(& pcTexCoords[i].t); - } - ByteSwap::Swap4( & pcFrame->scale[0] ); - ByteSwap::Swap4( & pcFrame->scale[1] ); - ByteSwap::Swap4( & pcFrame->scale[2] ); - ByteSwap::Swap4( & pcFrame->translate[0] ); - ByteSwap::Swap4( & pcFrame->translate[1] ); - ByteSwap::Swap4( & pcFrame->translate[2] ); -#endif - - pcMesh->mNumFaces = m_pcHeader->numTriangles; - pcMesh->mFaces = new aiFace[m_pcHeader->numTriangles]; - - // allocate output storage - pcMesh->mNumVertices = (unsigned int)pcMesh->mNumFaces*3; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - - // Not sure whether there are MD2 files without texture coordinates - // NOTE: texture coordinates can be there without a texture, - // but a texture can't be there without a valid UV channel - MaterialHelper* pcHelper = (MaterialHelper*)pScene->mMaterials[0]; - const int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - if (m_pcHeader->numTexCoords && m_pcHeader->numSkins) - { - // navigate to the first texture associated with the mesh - const MD2::Skin* pcSkins = (const MD2::Skin*) ((unsigned char*)m_pcHeader + - m_pcHeader->offsetSkins); - - aiColor3D clr; - clr.b = clr.g = clr.r = 1.0f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - if (pcSkins->name[0]) - { - aiString szString; - const size_t iLen = ::strlen(pcSkins->name); - ::memcpy(szString.data,pcSkins->name,iLen); - szString.data[iLen] = '\0'; - szString.length = iLen; - - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - else{ - DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped."); - } - } - else { - // apply a default material - aiColor3D clr; - clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - aiString szName; - szName.Set(AI_DEFAULT_TEXTURED_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); - - aiString sz; - - // TODO: Try to guess the name of the texture file from the model file name - - sz.Set("$texture_dummy.bmp"); - pcHelper->AddProperty(&sz,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - - - // now read all triangles of the first frame, apply scaling and translation - unsigned int iCurrent = 0; - - float fDivisorU = 1.0f,fDivisorV = 1.0f; - if (m_pcHeader->numTexCoords) { - // allocate storage for texture coordinates, too - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - - // check whether the skin width or height are zero (this would - // cause a division through zero) - if (!m_pcHeader->skinWidth) { - DefaultLogger::get()->error("MD2: No valid skin width given"); - } - else fDivisorU = (float)m_pcHeader->skinWidth; - if (!m_pcHeader->skinHeight){ - DefaultLogger::get()->error("MD2: No valid skin height given"); - } - else fDivisorV = (float)m_pcHeader->skinHeight; - } - - for (unsigned int i = 0; i < (unsigned int)m_pcHeader->numTriangles;++i) { - // Allocate the face - pScene->mMeshes[0]->mFaces[i].mIndices = new unsigned int[3]; - pScene->mMeshes[0]->mFaces[i].mNumIndices = 3; - - // copy texture coordinates - // check whether they are different from the previous value at this index. - // In this case, create a full separate set of vertices/normals/texcoords - for (unsigned int c = 0; c < 3;++c,++iCurrent) { - - // validate vertex indices - register unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c]; - if (iIndex >= m_pcHeader->numVertices) { - DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range"); - iIndex = m_pcHeader->numVertices-1; - } - - // read x,y, and z component of the vertex - aiVector3D& vec = pcMesh->mVertices[iCurrent]; - - vec.x = (float)pcVerts[iIndex].vertex[0] * pcFrame->scale[0]; - vec.x += pcFrame->translate[0]; - - vec.y = (float)pcVerts[iIndex].vertex[1] * pcFrame->scale[1]; - vec.y += pcFrame->translate[1]; - - vec.z = (float)pcVerts[iIndex].vertex[2] * pcFrame->scale[2]; - vec.z += pcFrame->translate[2]; - - // read the normal vector from the precalculated normal table - aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; - LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); - - // flip z and y to become right-handed - std::swap((float&)vNormal.z,(float&)vNormal.y); - std::swap((float&)vec.z,(float&)vec.y); - - if (m_pcHeader->numTexCoords) { - // validate texture coordinates - iIndex = pcTriangles[i].textureIndices[c]; - if (iIndex >= m_pcHeader->numTexCoords) { - DefaultLogger::get()->error("MD2: UV index is outside the allowed range"); - iIndex = m_pcHeader->numTexCoords-1; - } - - aiVector3D& pcOut = pcMesh->mTextureCoords[0][iCurrent]; - - // the texture coordinates are absolute values but we - // need relative values between 0 and 1 - pcOut.x = pcTexCoords[iIndex].s / fDivisorU; - pcOut.y = 1.f-pcTexCoords[iIndex].t / fDivisorV; - } - pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; - } - } -} - -#endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER diff --git a/3rdparty/assimp/code/MD2Loader.h b/3rdparty/assimp/code/MD2Loader.h deleted file mode 100644 index 5a646b8d..00000000 --- a/3rdparty/assimp/code/MD2Loader.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD2Loader.h - * @brief Declaration of the .MD2 importer class. - */ -#ifndef AI_MD2LOADER_H_INCLUDED -#define AI_MD2LOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" - -struct aiNode; -#include "MD2FileData.h" - -namespace Assimp { -class MaterialHelper; - -using namespace MD2; - -// --------------------------------------------------------------------------- -/** Importer class for MD2 -*/ -class MD2Importer : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - MD2Importer(); - - /** Destructor, private as well */ - ~MD2Importer(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - - // ------------------------------------------------------------------- - /** Validate the header of the file - */ - void ValidateHeader(); - -protected: - - /** Configuration option: frame to be loaded */ - unsigned int configFrameID; - - /** Header of the MD2 file */ - BE_NCONST MD2::Header* m_pcHeader; - - /** Buffer to hold the loaded file */ - BE_NCONST uint8_t* mBuffer; - - /** Size of the file, in bytes */ - unsigned int fileSize; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/MD2NormalTable.h b/3rdparty/assimp/code/MD2NormalTable.h deleted file mode 100644 index 288fb4a1..00000000 --- a/3rdparty/assimp/code/MD2NormalTable.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Slightly modified version of the anorms.h header file - * released by ID software with the Quake 2 source code. - * - * Table of normals used by MD2 models - */ - -#ifndef AI_MDL_NORMALTABLE_H_INC -#define AI_MDL_NORMALTABLE_H_INC - - -float g_avNormals[162][3] = { -{ -0.525731f, 0.000000f, 0.850651f }, -{ -0.442863f, 0.238856f, 0.864188f }, -{ -0.295242f, 0.000000f, 0.955423f }, -{ -0.309017f, 0.500000f, 0.809017f }, -{ -0.162460f, 0.262866f, 0.951056f }, -{ 0.000000f, 0.000000f, 1.000000f }, -{ 0.000000f, 0.850651f, 0.525731f }, -{ -0.147621f, 0.716567f, 0.681718f }, -{ 0.147621f, 0.716567f, 0.681718f }, -{ 0.000000f, 0.525731f, 0.850651f }, -{ 0.309017f, 0.500000f, 0.809017f }, -{ 0.525731f, 0.000000f, 0.850651f }, -{ 0.295242f, 0.000000f, 0.955423f }, -{ 0.442863f, 0.238856f, 0.864188f }, -{ 0.162460f, 0.262866f, 0.951056f }, -{ -0.681718f, 0.147621f, 0.716567f }, -{ -0.809017f, 0.309017f, 0.500000f }, -{ -0.587785f, 0.425325f, 0.688191f }, -{ -0.850651f, 0.525731f, 0.000000f }, -{ -0.864188f, 0.442863f, 0.238856f }, -{ -0.716567f, 0.681718f, 0.147621f }, -{ -0.688191f, 0.587785f, 0.425325f }, -{ -0.500000f, 0.809017f, 0.309017f }, -{ -0.238856f, 0.864188f, 0.442863f }, -{ -0.425325f, 0.688191f, 0.587785f }, -{ -0.716567f, 0.681718f, -0.147621f }, -{ -0.500000f, 0.809017f, -0.309017f }, -{ -0.525731f, 0.850651f, 0.000000f }, -{ 0.000000f, 0.850651f, -0.525731f }, -{ -0.238856f, 0.864188f, -0.442863f }, -{ 0.000000f, 0.955423f, -0.295242f }, -{ -0.262866f, 0.951056f, -0.162460f }, -{ 0.000000f, 1.000000f, 0.000000f }, -{ 0.000000f, 0.955423f, 0.295242f }, -{ -0.262866f, 0.951056f, 0.162460f }, -{ 0.238856f, 0.864188f, 0.442863f }, -{ 0.262866f, 0.951056f, 0.162460f }, -{ 0.500000f, 0.809017f, 0.309017f }, -{ 0.238856f, 0.864188f, -0.442863f }, -{ 0.262866f, 0.951056f, -0.162460f }, -{ 0.500000f, 0.809017f, -0.309017f }, -{ 0.850651f, 0.525731f, 0.000000f }, -{ 0.716567f, 0.681718f, 0.147621f }, -{ 0.716567f, 0.681718f, -0.147621f }, -{ 0.525731f, 0.850651f, 0.000000f }, -{ 0.425325f, 0.688191f, 0.587785f }, -{ 0.864188f, 0.442863f, 0.238856f }, -{ 0.688191f, 0.587785f, 0.425325f }, -{ 0.809017f, 0.309017f, 0.500000f }, -{ 0.681718f, 0.147621f, 0.716567f }, -{ 0.587785f, 0.425325f, 0.688191f }, -{ 0.955423f, 0.295242f, 0.000000f }, -{ 1.000000f, 0.000000f, 0.000000f }, -{ 0.951056f, 0.162460f, 0.262866f }, -{ 0.850651f, -0.525731f, 0.000000f }, -{ 0.955423f, -0.295242f, 0.000000f }, -{ 0.864188f, -0.442863f, 0.238856f }, -{ 0.951056f, -0.162460f, 0.262866f }, -{ 0.809017f, -0.309017f, 0.500000f }, -{ 0.681718f, -0.147621f, 0.716567f }, -{ 0.850651f, 0.000000f, 0.525731f }, -{ 0.864188f, 0.442863f, -0.238856f }, -{ 0.809017f, 0.309017f, -0.500000f }, -{ 0.951056f, 0.162460f, -0.262866f }, -{ 0.525731f, 0.000000f, -0.850651f }, -{ 0.681718f, 0.147621f, -0.716567f }, -{ 0.681718f, -0.147621f, -0.716567f }, -{ 0.850651f, 0.000000f, -0.525731f }, -{ 0.809017f, -0.309017f, -0.500000f }, -{ 0.864188f, -0.442863f, -0.238856f }, -{ 0.951056f, -0.162460f, -0.262866f }, -{ 0.147621f, 0.716567f, -0.681718f }, -{ 0.309017f, 0.500000f, -0.809017f }, -{ 0.425325f, 0.688191f, -0.587785f }, -{ 0.442863f, 0.238856f, -0.864188f }, -{ 0.587785f, 0.425325f, -0.688191f }, -{ 0.688191f, 0.587785f, -0.425325f }, -{ -0.147621f, 0.716567f, -0.681718f }, -{ -0.309017f, 0.500000f, -0.809017f }, -{ 0.000000f, 0.525731f, -0.850651f }, -{ -0.525731f, 0.000000f, -0.850651f }, -{ -0.442863f, 0.238856f, -0.864188f }, -{ -0.295242f, 0.000000f, -0.955423f }, -{ -0.162460f, 0.262866f, -0.951056f }, -{ 0.000000f, 0.000000f, -1.000000f }, -{ 0.295242f, 0.000000f, -0.955423f }, -{ 0.162460f, 0.262866f, -0.951056f }, -{ -0.442863f, -0.238856f, -0.864188f }, -{ -0.309017f, -0.500000f, -0.809017f }, -{ -0.162460f, -0.262866f, -0.951056f }, -{ 0.000000f, -0.850651f, -0.525731f }, -{ -0.147621f, -0.716567f, -0.681718f }, -{ 0.147621f, -0.716567f, -0.681718f }, -{ 0.000000f, -0.525731f, -0.850651f }, -{ 0.309017f, -0.500000f, -0.809017f }, -{ 0.442863f, -0.238856f, -0.864188f }, -{ 0.162460f, -0.262866f, -0.951056f }, -{ 0.238856f, -0.864188f, -0.442863f }, -{ 0.500000f, -0.809017f, -0.309017f }, -{ 0.425325f, -0.688191f, -0.587785f }, -{ 0.716567f, -0.681718f, -0.147621f }, -{ 0.688191f, -0.587785f, -0.425325f }, -{ 0.587785f, -0.425325f, -0.688191f }, -{ 0.000000f, -0.955423f, -0.295242f }, -{ 0.000000f, -1.000000f, 0.000000f }, -{ 0.262866f, -0.951056f, -0.162460f }, -{ 0.000000f, -0.850651f, 0.525731f }, -{ 0.000000f, -0.955423f, 0.295242f }, -{ 0.238856f, -0.864188f, 0.442863f }, -{ 0.262866f, -0.951056f, 0.162460f }, -{ 0.500000f, -0.809017f, 0.309017f }, -{ 0.716567f, -0.681718f, 0.147621f }, -{ 0.525731f, -0.850651f, 0.000000f }, -{ -0.238856f, -0.864188f, -0.442863f }, -{ -0.500000f, -0.809017f, -0.309017f }, -{ -0.262866f, -0.951056f, -0.162460f }, -{ -0.850651f, -0.525731f, 0.000000f }, -{ -0.716567f, -0.681718f, -0.147621f }, -{ -0.716567f, -0.681718f, 0.147621f }, -{ -0.525731f, -0.850651f, 0.000000f }, -{ -0.500000f, -0.809017f, 0.309017f }, -{ -0.238856f, -0.864188f, 0.442863f }, -{ -0.262866f, -0.951056f, 0.162460f }, -{ -0.864188f, -0.442863f, 0.238856f }, -{ -0.809017f, -0.309017f, 0.500000f }, -{ -0.688191f, -0.587785f, 0.425325f }, -{ -0.681718f, -0.147621f, 0.716567f }, -{ -0.442863f, -0.238856f, 0.864188f }, -{ -0.587785f, -0.425325f, 0.688191f }, -{ -0.309017f, -0.500000f, 0.809017f }, -{ -0.147621f, -0.716567f, 0.681718f }, -{ -0.425325f, -0.688191f, 0.587785f }, -{ -0.162460f, -0.262866f, 0.951056f }, -{ 0.442863f, -0.238856f, 0.864188f }, -{ 0.162460f, -0.262866f, 0.951056f }, -{ 0.309017f, -0.500000f, 0.809017f }, -{ 0.147621f, -0.716567f, 0.681718f }, -{ 0.000000f, -0.525731f, 0.850651f }, -{ 0.425325f, -0.688191f, 0.587785f }, -{ 0.587785f, -0.425325f, 0.688191f }, -{ 0.688191f, -0.587785f, 0.425325f }, -{ -0.955423f, 0.295242f, 0.000000f }, -{ -0.951056f, 0.162460f, 0.262866f }, -{ -1.000000f, 0.000000f, 0.000000f }, -{ -0.850651f, 0.000000f, 0.525731f }, -{ -0.955423f, -0.295242f, 0.000000f }, -{ -0.951056f, -0.162460f, 0.262866f }, -{ -0.864188f, 0.442863f, -0.238856f }, -{ -0.951056f, 0.162460f, -0.262866f }, -{ -0.809017f, 0.309017f, -0.500000f }, -{ -0.864188f, -0.442863f, -0.238856f }, -{ -0.951056f, -0.162460f, -0.262866f }, -{ -0.809017f, -0.309017f, -0.500000f }, -{ -0.681718f, 0.147621f, -0.716567f }, -{ -0.681718f, -0.147621f, -0.716567f }, -{ -0.850651f, 0.000000f, -0.525731f }, -{ -0.688191f, 0.587785f, -0.425325f }, -{ -0.587785f, 0.425325f, -0.688191f }, -{ -0.425325f, 0.688191f, -0.587785f }, -{ -0.425325f, -0.688191f, -0.587785f }, -{ -0.587785f, -0.425325f, -0.688191f }, -{ -0.688191f, -0.587785f, -0.425325f } -}; - -#endif // !! include guard diff --git a/3rdparty/assimp/code/MD3FileData.h b/3rdparty/assimp/code/MD3FileData.h deleted file mode 100644 index edc34d2f..00000000 --- a/3rdparty/assimp/code/MD3FileData.h +++ /dev/null @@ -1,315 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Md3FileData.h - * - * @brief Defines helper data structures for importing MD3 files. - * http://linux.ucla.edu/~phaethon/q3/formats/md3format.html - */ -#ifndef AI_MD3FILEHELPER_H_INC -#define AI_MD3FILEHELPER_H_INC - -#include <string> -#include <vector> -#include <sstream> - -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include "../include/aiAnim.h" - -#include "./../include/Compiler/pushpack1.h" - -namespace Assimp { -namespace MD3 { - -// to make it easier for us, we test the magic word against both "endianesses" -#define AI_MD3_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDP3") -#define AI_MD3_MAGIC_NUMBER_LE AI_MAKE_MAGIC("3PDI") - -// common limitations -#define AI_MD3_VERSION 15 -#define AI_MD3_MAXQPATH 64 -#define AI_MD3_MAXFRAME 16 -#define AI_MD3_MAX_FRAMES 1024 -#define AI_MD3_MAX_TAGS 16 -#define AI_MD3_MAX_SURFACES 32 -#define AI_MD3_MAX_SHADERS 256 -#define AI_MD3_MAX_VERTS 4096 -#define AI_MD3_MAX_TRIANGLES 8192 - -// master scale factor for all vertices in a MD3 model -#define AI_MD3_XYZ_SCALE (1.0f/64.0f) - -// ------------------------------------------------------------------------------- -/** @brief Data structure for the MD3 main header - */ -struct Header -{ - //! magic number - uint32_t IDENT; - - //! file format version - uint32_t VERSION; - - //! original name in .pak archive - char NAME[ AI_MD3_MAXQPATH ]; - - //! unknown - int32_t FLAGS; - - //! number of frames in the file - uint32_t NUM_FRAMES; - - //! number of tags in the file - uint32_t NUM_TAGS; - - //! number of surfaces in the file - uint32_t NUM_SURFACES; - - //! number of skins in the file - uint32_t NUM_SKINS; - - //! offset of the first frame - uint32_t OFS_FRAMES; - - //! offset of the first tag - uint32_t OFS_TAGS; - - //! offset of the first surface - uint32_t OFS_SURFACES; - - //! end of file - uint32_t OFS_EOF; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------- -/** @brief Data structure for the frame header - */ -struct Frame -{ - //! minimum bounds - aiVector3D min; - - //! maximum bounds - aiVector3D max; - - //! local origin for this frame - aiVector3D origin; - - //! radius of bounding sphere - float radius; - - //! name of frame - char name[ AI_MD3_MAXFRAME ]; - -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------- -/** @brief Data structure for the tag header - */ -struct Tag -{ - //! name of the tag - char NAME[ AI_MD3_MAXQPATH ]; - - //! Local tag origin and orientation - aiVector3D origin; - float orientation[3][3]; - -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------- -/** @brief Data structure for the surface header - */ -struct Surface -{ - //! magic number - int32_t IDENT; - - //! original name of the surface - char NAME[ AI_MD3_MAXQPATH ]; - - //! unknown - int32_t FLAGS; - - //! number of frames in the surface - uint32_t NUM_FRAMES; - - //! number of shaders in the surface - uint32_t NUM_SHADER; - - //! number of vertices in the surface - uint32_t NUM_VERTICES; - - //! number of triangles in the surface - uint32_t NUM_TRIANGLES; - - - //! offset to the triangle data - uint32_t OFS_TRIANGLES; - - //! offset to the shader data - uint32_t OFS_SHADERS; - - //! offset to the texture coordinate data - uint32_t OFS_ST; - - //! offset to the vertex/normal data - uint32_t OFS_XYZNORMAL; - - //! offset to the end of the Surface object - int32_t OFS_END; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------- -/** @brief Data structure for a shader defined in there - */ -struct Shader -{ - //! filename of the shader - char NAME[ AI_MD3_MAXQPATH ]; - - //! index of the shader - uint32_t SHADER_INDEX; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------- -/** @brief Data structure for a triangle - */ -struct Triangle -{ - //! triangle indices - uint32_t INDEXES[3]; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------- -/** @brief Data structure for an UV coord - */ -struct TexCoord -{ - //! UV coordinates - float U,V; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------- -/** @brief Data structure for a vertex - */ -struct Vertex -{ - //! X/Y/Z coordinates - int16_t X,Y,Z; - - //! encoded normal vector - uint16_t NORMAL; -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - -// ------------------------------------------------------------------------------- -/** @brief Unpack a Q3 16 bit vector to its full float3 representation - * - * @param p_iNormal Input normal vector in latitude/longitude form - * @param p_afOut Pointer to an array of three floats to receive the result - * - * @note This has been taken from q3 source (misc_model.c) - */ -inline void LatLngNormalToVec3(uint16_t p_iNormal, float* p_afOut) -{ - float lat = (float)(( p_iNormal >> 8u ) & 0xff); - float lng = (float)(( p_iNormal & 0xff )); - lat *= 3.141926f/128.0f; - lng *= 3.141926f/128.0f; - - p_afOut[0] = cosf(lat) * sinf(lng); - p_afOut[1] = sinf(lat) * sinf(lng); - p_afOut[2] = cosf(lng); - return; -} - - -// ------------------------------------------------------------------------------- -/** @brief Pack a Q3 normal into 16bit latitute/longitude representation - * @param p_vIn Input vector - * @param p_iOut Output normal - * - * @note This has been taken from q3 source (mathlib.c) - */ -inline void Vec3NormalToLatLng( const aiVector3D& p_vIn, uint16_t& p_iOut ) -{ - // check for singularities - if ( 0.0f == p_vIn[0] && 0.0f == p_vIn[1] ) - { - if ( p_vIn[2] > 0.0f ) - { - ((unsigned char*)&p_iOut)[0] = 0; - ((unsigned char*)&p_iOut)[1] = 0; // lat = 0, long = 0 - } - else - { - ((unsigned char*)&p_iOut)[0] = 128; - ((unsigned char*)&p_iOut)[1] = 0; // lat = 0, long = 128 - } - } - else - { - int a, b; - - a = int(57.2957795f * ( atan2f( p_vIn[1], p_vIn[0] ) ) * (255.0f / 360.0f )); - a &= 0xff; - - b = int(57.2957795f * ( acosf( p_vIn[2] ) ) * ( 255.0f / 360.0f )); - b &= 0xff; - - ((unsigned char*)&p_iOut)[0] = b; // longitude - ((unsigned char*)&p_iOut)[1] = a; // lattitude - } -} - -} -} - -#endif // !! AI_MD3FILEHELPER_H_INC - diff --git a/3rdparty/assimp/code/MD3Loader.cpp b/3rdparty/assimp/code/MD3Loader.cpp deleted file mode 100644 index fe1e68a1..00000000 --- a/3rdparty/assimp/code/MD3Loader.cpp +++ /dev/null @@ -1,1043 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD3Loader.cpp - * @brief Implementation of the MD3 importer class - * - * Sources: - * http://www.gamers.org/dEngine/quake3/UQ3S - * http://linux.ucla.edu/~phaethon/q3/formats/md3format.html - * http://www.heppler.com/shader/shader/ - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MD3_IMPORTER - -#include "MD3Loader.h" -#include "ByteSwap.h" -#include "SceneCombiner.h" -#include "GenericProperty.h" -#include "RemoveComments.h" -#include "ParsingUtils.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Convert a Q3 shader blend function to the appropriate enum value -Q3Shader::BlendFunc StringToBlendFunc(const std::string& m) -{ - if (m == "GL_ONE") { - return Q3Shader::BLEND_GL_ONE; - } - if (m == "GL_ZERO") { - return Q3Shader::BLEND_GL_ZERO; - } - if (m == "GL_SRC_ALPHA") { - return Q3Shader::BLEND_GL_SRC_ALPHA; - } - if (m == "GL_ONE_MINUS_SRC_ALPHA") { - return Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA; - } - if (m == "GL_ONE_MINUS_DST_COLOR") { - return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR; - } - DefaultLogger::get()->error("Q3Shader: Unknown blend function: " + m); - return Q3Shader::BLEND_NONE; -} - -// ------------------------------------------------------------------------------------------------ -// Load a Quake 3 shader -bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* io) -{ - boost::scoped_ptr<IOStream> file( io->Open( pFile, "rt")); - if (!file.get()) - return false; // if we can't access the file, don't worry and return - - DefaultLogger::get()->info("Loading Quake3 shader file " + pFile); - - // read file in memory - const size_t s = file->FileSize(); - std::vector<char> _buff(s+1); - file->Read(&_buff[0],s,1); - _buff[s] = 0; - - // remove comments from it (C++ style) - CommentRemover::RemoveLineComments("//",&_buff[0]); - const char* buff = &_buff[0]; - - Q3Shader::ShaderDataBlock* curData = NULL; - Q3Shader::ShaderMapBlock* curMap = NULL; - - // read line per line - for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) { - - if (*buff == '{') { - ++buff; - - // append to last section, if any - if (!curData) { - DefaultLogger::get()->error("Q3Shader: Unexpected shader section token \'{\'"); - return true; // still no failure, the file is there - } - - // read this data section - for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) { - if (*buff == '{') { - ++buff; - // add new map section - curData->maps.push_back(Q3Shader::ShaderMapBlock()); - curMap = &curData->maps.back(); - - for (;SkipSpacesAndLineEnd(&buff);SkipLine(&buff)) { - // 'map' - Specifies texture file name - if (TokenMatchI(buff,"map",3) || TokenMatchI(buff,"clampmap",8)) { - curMap->name = GetNextToken(buff); - } - // 'blendfunc' - Alpha blending mode - else if (TokenMatchI(buff,"blendfunc",9)) { - const std::string blend_src = GetNextToken(buff); - if (blend_src == "add") { - curMap->blend_src = Q3Shader::BLEND_GL_ONE; - curMap->blend_dest = Q3Shader::BLEND_GL_ONE; - } - else if (blend_src == "filter") { - curMap->blend_src = Q3Shader::BLEND_GL_DST_COLOR; - curMap->blend_dest = Q3Shader::BLEND_GL_ZERO; - } - else if (blend_src == "blend") { - curMap->blend_src = Q3Shader::BLEND_GL_SRC_ALPHA; - curMap->blend_dest = Q3Shader::BLEND_GL_ONE_MINUS_SRC_ALPHA; - } - else { - curMap->blend_src = StringToBlendFunc(blend_src); - curMap->blend_dest = StringToBlendFunc(GetNextToken(buff)); - } - } - // 'alphafunc' - Alpha testing mode - else if (TokenMatchI(buff,"alphafunc",9)) { - const std::string at = GetNextToken(buff); - if (at == "GT0") { - curMap->alpha_test = Q3Shader::AT_GT0; - } - else if (at == "LT128") { - curMap->alpha_test = Q3Shader::AT_LT128; - } - else if (at == "GE128") { - curMap->alpha_test = Q3Shader::AT_GE128; - } - } - else if (*buff == '}') { - ++buff; - // close this map section - curMap = NULL; - break; - } - } - - } - else if (*buff == '}') { - ++buff; - curData = NULL; - break; - } - - // 'cull' specifies culling behaviour for the model - else if (TokenMatchI(buff,"cull",4)) { - SkipSpaces(&buff); - if (!ASSIMP_strincmp(buff,"back",4)) { - curData->cull = Q3Shader::CULL_CCW; - } - else if (!ASSIMP_strincmp(buff,"front",5)) { - curData->cull = Q3Shader::CULL_CW; - } - else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) { - curData->cull = Q3Shader::CULL_NONE; - } - else DefaultLogger::get()->error("Q3Shader: Unrecognized cull mode"); - } - } - } - - else { - // add new section - fill.blocks.push_back(Q3Shader::ShaderDataBlock()); - curData = &fill.blocks.back(); - - // get the name of this section - curData->name = GetNextToken(buff); - } - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Load a Quake 3 skin -bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io) -{ - boost::scoped_ptr<IOStream> file( io->Open( pFile, "rt")); - if (!file.get()) - return false; // if we can't access the file, don't worry and return - - DefaultLogger::get()->info("Loading Quake3 skin file " + pFile); - - // read file in memory - const size_t s = file->FileSize(); - std::vector<char> _buff(s+1);const char* buff = &_buff[0]; - file->Read(&_buff[0],s,1); - _buff[s] = 0; - - // remove commas - std::replace(_buff.begin(),_buff.end(),',',' '); - - // read token by token and fill output table - for (;*buff;) { - SkipSpacesAndLineEnd(&buff); - - // get first identifier - std::string ss = GetNextToken(buff); - - // ignore tokens starting with tag_ - if (!::strncmp(&ss[0],"tag_",std::min((size_t)4, ss.length()))) - continue; - - fill.textures.push_back(SkinData::TextureEntry()); - SkinData::TextureEntry& s = fill.textures.back(); - - s.first = ss; - s.second = GetNextToken(buff); - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Convert Q3Shader to material -void Q3Shader::ConvertShaderToMaterial(MaterialHelper* out, const ShaderDataBlock& shader) -{ - ai_assert(NULL != out); - - /* IMPORTANT: This is not a real conversion. Actually we're just guessing and - * hacking around to build an aiMaterial that looks nearly equal to the - * original Quake 3 shader. We're missing some important features like - * animatable material properties in our material system, but at least - * multiple textures should be handled correctly. - */ - - // Two-sided material? - if (shader.cull == Q3Shader::CULL_NONE) { - const int twosided = 1; - out->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); - } - - unsigned int cur_emissive = 0, cur_diffuse = 0, cur_lm =0; - - // Iterate through all textures - for (std::list< Q3Shader::ShaderMapBlock >::const_iterator it = shader.maps.begin(); it != shader.maps.end();++it) { - - // CONVERSION BEHAVIOUR: - // - // - // If the texture is additive - // - if it is the first texture, assume additive blending for the whole material - // - otherwise register it as emissive texture. - // - // If the texture is using standard blend (or if the blend mode is unknown) - // - if first texture: assume default blending for material - // - in any case: set it as diffuse texture - // - // If the texture is using 'filter' blending - // - take as lightmap - // - // Textures with alpha funcs - // - aiTextureFlags_UseAlpha is set (otherwise aiTextureFlags_NoAlpha is explicitly set) - aiString s((*it).name); - aiTextureType type; unsigned int index; - - if ((*it).blend_src == Q3Shader::BLEND_GL_ONE && (*it).blend_dest == Q3Shader::BLEND_GL_ONE) { - if (it == shader.maps.begin()) { - const int additive = aiBlendMode_Additive; - out->AddProperty(&additive,1,AI_MATKEY_BLEND_FUNC); - - index = cur_diffuse++; - type = aiTextureType_DIFFUSE; - } - else { - index = cur_emissive++; - type = aiTextureType_EMISSIVE; - } - } - else if ((*it).blend_src == Q3Shader::BLEND_GL_DST_COLOR && (*it).blend_dest == Q3Shader::BLEND_GL_ZERO) { - index = cur_lm++; - type = aiTextureType_LIGHTMAP; - } - else { - const int blend = aiBlendMode_Default; - out->AddProperty(&blend,1,AI_MATKEY_BLEND_FUNC); - - index = cur_diffuse++; - type = aiTextureType_DIFFUSE; - } - - // setup texture - out->AddProperty(&s,AI_MATKEY_TEXTURE(type,index)); - - // setup texture flags - const int use_alpha = ((*it).alpha_test != Q3Shader::AT_NONE ? aiTextureFlags_UseAlpha : aiTextureFlags_IgnoreAlpha); - out->AddProperty(&use_alpha,1,AI_MATKEY_TEXFLAGS(type,index)); - } - // If at least one emissive texture was set, set the emissive base color to 1 to ensure - // the texture is actually displayed. - if (0 != cur_emissive) { - aiColor3D one(1.f,1.f,1.f); - out->AddProperty(&one,1,AI_MATKEY_COLOR_EMISSIVE); - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MD3Importer::MD3Importer() -: configFrameID (0) -, configHandleMP (true) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MD3Importer::~MD3Importer() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MD3Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "md3") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MD3_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void MD3Importer::ValidateHeaderOffsets() -{ - // Check magic number - if (pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_BE && - pcHeader->IDENT != AI_MD3_MAGIC_NUMBER_LE) - throw DeadlyImportError( "Invalid MD3 file: Magic bytes not found"); - - // Check file format version - if (pcHeader->VERSION > 15) - DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ..."); - - // Check some offset values whether they are valid - if (!pcHeader->NUM_SURFACES) - throw DeadlyImportError( "Invalid md3 file: NUM_SURFACES is 0"); - - if (pcHeader->OFS_FRAMES >= fileSize || pcHeader->OFS_SURFACES >= fileSize || - pcHeader->OFS_EOF > fileSize) { - throw DeadlyImportError("Invalid MD3 header: some offsets are outside the file"); - } - - if (pcHeader->NUM_FRAMES <= configFrameID ) - throw DeadlyImportError("The requested frame is not existing the file"); -} - -// ------------------------------------------------------------------------------------------------ -void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf) -{ - // Calculate the relative offset of the surface - const int32_t ofs = int32_t((const unsigned char*)pcSurf-this->mBuffer); - - // Check whether all data chunks are inside the valid range - if (pcSurf->OFS_TRIANGLES + ofs + pcSurf->NUM_TRIANGLES * sizeof(MD3::Triangle) > fileSize || - pcSurf->OFS_SHADERS + ofs + pcSurf->NUM_SHADER * sizeof(MD3::Shader) > fileSize || - pcSurf->OFS_ST + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::TexCoord) > fileSize || - pcSurf->OFS_XYZNORMAL + ofs + pcSurf->NUM_VERTICES * sizeof(MD3::Vertex) > fileSize) { - - throw DeadlyImportError("Invalid MD3 surface header: some offsets are outside the file"); - } - - // Check whether all requirements for Q3 files are met. We don't - // care, but probably someone does. - if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES) { - DefaultLogger::get()->warn("MD3: Quake III triangle limit exceeded"); - } - - if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS) { - DefaultLogger::get()->warn("MD3: Quake III shader limit exceeded"); - } - - if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS) { - DefaultLogger::get()->warn("MD3: Quake III vertex limit exceeded"); - } - - if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES) { - DefaultLogger::get()->warn("MD3: Quake III frame limit exceeded"); - } -} - -// ------------------------------------------------------------------------------------------------ -void MD3Importer::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("md3"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void MD3Importer::SetupProperties(const Importer* pImp) -{ - // The - // AI_CONFIG_IMPORT_MD3_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_KEYFRAME,0xffffffff); - if (0xffffffff == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } - - // AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART - configHandleMP = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART,1)); - - // AI_CONFIG_IMPORT_MD3_SKIN_NAME - configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME,"default")); - - // AI_CONFIG_IMPORT_MD3_SHADER_SRC - configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC,"")); - - // AI_CONFIG_FAVOUR_SPEED - configSpeedFlag = (0 != pImp->GetPropertyInteger(AI_CONFIG_FAVOUR_SPEED,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Try to read the skin for a MD3 file -void MD3Importer::ReadSkin(Q3Shader::SkinData& fill) const -{ - // skip any postfixes (e.g. lower_1.md3) - std::string::size_type s = filename.find_last_of('_'); - if (s == std::string::npos) { - s = filename.find_last_of('.'); - } - ai_assert(s != std::string::npos); - - const std::string skin_file = path + filename.substr(0,s) + "_" + configSkinFile + ".skin"; - Q3Shader::LoadSkin(fill,skin_file,mIOHandler); -} - -// ------------------------------------------------------------------------------------------------ -// Try to read the shader for a MD3 file -void MD3Importer::ReadShader(Q3Shader::ShaderData& fill) const -{ - // Determine Q3 model name from given path - std::string::size_type s = path.find_last_of("\\/",path.length()-2); - const std::string model_file = path.substr(s+1,path.length()-(s+2)); - - // If no specific dir or file is given, use our default search behaviour - if (!configShaderFile.length()) { - if (!Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + model_file + ".shader",mIOHandler)) { - Q3Shader::LoadShader(fill,path + "..\\..\\..\\scripts\\" + filename + ".shader",mIOHandler); - } - } - else { - // If the given string specifies a file, load this file. - // Otherwise it's a directory. - std::string::size_type st = configShaderFile.find_last_of('.'); - if (st == std::string::npos) { - - if (!Q3Shader::LoadShader(fill,configShaderFile + model_file + ".shader",mIOHandler)) { - Q3Shader::LoadShader(fill,configShaderFile + filename + ".shader",mIOHandler); - } - } - else { - Q3Shader::LoadShader(fill,configShaderFile,mIOHandler); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Tiny helper to remove a single node from its parent' list -void RemoveSingleNodeFromList(aiNode* nd) -{ - if (!nd || nd->mNumChildren || !nd->mParent)return; - aiNode* par = nd->mParent; - for (unsigned int i = 0; i < par->mNumChildren;++i) { - if (par->mChildren[i] == nd) { - --par->mNumChildren; - for (;i < par->mNumChildren;++i) { - par->mChildren[i] = par->mChildren[i+1]; - } - delete nd; - break; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Read a multi-part Q3 player model -bool MD3Importer::ReadMultipartFile() -{ - // check whether the file name contains a common postfix, e.g lower_2.md3 - std::string::size_type s = filename.find_last_of('_'), t = filename.find_last_of('.'); - ai_assert(t != std::string::npos); - if (s == std::string::npos) - s = t; - - const std::string mod_filename = filename.substr(0,s); - const std::string suffix = filename.substr(s,t-s); - - if (mod_filename == "lower" || mod_filename == "upper" || mod_filename == "head"){ - const std::string lower = path + "lower" + suffix + ".md3"; - const std::string upper = path + "upper" + suffix + ".md3"; - const std::string head = path + "head" + suffix + ".md3"; - - aiScene* scene_upper = NULL; - aiScene* scene_lower = NULL; - aiScene* scene_head = NULL; - std::string failure; - - aiNode* tag_torso, *tag_head; - std::vector<AttachmentInfo> attach; - - DefaultLogger::get()->info("Multi part MD3 player model: lower, upper and head parts are joined"); - - // ensure we won't try to load ourselves recursively - BatchLoader::PropertyMap props; - SetGenericProperty( props.ints, AI_CONFIG_IMPORT_MD3_HANDLE_MULTIPART, 0, NULL); - - // now read these three files - BatchLoader batch(mIOHandler); - const unsigned int _lower = batch.AddLoadRequest(lower,0,&props); - const unsigned int _upper = batch.AddLoadRequest(upper,0,&props); - const unsigned int _head = batch.AddLoadRequest(head,0,&props); - batch.LoadAll(); - - // now construct a dummy scene to place these three parts in - aiScene* master = new aiScene(); - aiNode* nd = master->mRootNode = new aiNode(); - nd->mName.Set("<MD3_Player>"); - - // ... and get them. We need all of them. - scene_lower = batch.GetImport(_lower); - if (!scene_lower) { - DefaultLogger::get()->error("M3D: Failed to read multi part model, lower.md3 fails to load"); - failure = "lower"; - goto error_cleanup; - } - - scene_upper = batch.GetImport(_upper); - if (!scene_upper) { - DefaultLogger::get()->error("M3D: Failed to read multi part model, upper.md3 fails to load"); - failure = "upper"; - goto error_cleanup; - } - - scene_head = batch.GetImport(_head); - if (!scene_head) { - DefaultLogger::get()->error("M3D: Failed to read multi part model, head.md3 fails to load"); - failure = "head"; - goto error_cleanup; - } - - // build attachment infos. search for typical Q3 tags - - // original root - scene_lower->mRootNode->mName.Set("lower"); - attach.push_back(AttachmentInfo(scene_lower, nd)); - - // tag_torso - tag_torso = scene_lower->mRootNode->FindNode("tag_torso"); - if (!tag_torso) { - DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_torso expected"); - goto error_cleanup; - } - scene_upper->mRootNode->mName.Set("upper"); - attach.push_back(AttachmentInfo(scene_upper,tag_torso)); - - // tag_head - tag_head = scene_upper->mRootNode->FindNode("tag_head"); - if (!tag_head) { - DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_head expected"); - goto error_cleanup; - } - scene_head->mRootNode->mName.Set("head"); - attach.push_back(AttachmentInfo(scene_head,tag_head)); - - // Remove tag_head and tag_torso from all other model parts ... - // this ensures (together with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) - // that tag_torso/tag_head is also the name of the (unique) output node - RemoveSingleNodeFromList (scene_upper->mRootNode->FindNode("tag_torso")); - RemoveSingleNodeFromList (scene_head-> mRootNode->FindNode("tag_head" )); - - // Undo the rotations which we applied to the coordinate systems. We're - // working in global Quake space here - scene_head->mRootNode->mTransformation = aiMatrix4x4(); - scene_lower->mRootNode->mTransformation = aiMatrix4x4(); - scene_upper->mRootNode->mTransformation = aiMatrix4x4(); - - // and merge the scenes - SceneCombiner::MergeScenes(&mScene,master, attach, - AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES | - AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES | - AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS | - (!configSpeedFlag ? AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY : 0)); - - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - mScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); - - return true; - -error_cleanup: - delete scene_upper; - delete scene_lower; - delete scene_head; - delete master; - - if (failure == mod_filename) { - throw DeadlyImportError("MD3: failure to read multipart host file"); - } - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Convert a MD3 path to a proper value -void MD3Importer::ConvertPath(const char* texture_name, const char* header_name, std::string& out) const -{ - // If the MD3's internal path itself and the given path are using - // the same directory, remove it completely to get right output paths. - const char* end1 = ::strrchr(header_name,'\\'); - if (!end1)end1 = ::strrchr(header_name,'/'); - - const char* end2 = ::strrchr(texture_name,'\\'); - if (!end2)end2 = ::strrchr(texture_name,'/'); - - // HACK: If the paths starts with "models", ignore the - // next two hierarchy levels, it specifies just the model name. - // Ignored by Q3, it might be not equal to the real model location. - if (end2) { - - size_t len2; - const size_t len1 = (size_t)(end1 - header_name); - if (!ASSIMP_strincmp(texture_name,"models",6) && (texture_name[6] == '/' || texture_name[6] == '\\')) { - len2 = 6; // ignore the seventh - could be slash or backslash - - if (!header_name[0]) { - // Use the file name only - out = end2+1; - return; - } - } - else len2 = std::min (len1, (size_t)(end2 - texture_name )); - if (!ASSIMP_strincmp(texture_name,header_name,len2)) { - // Use the file name only - out = end2+1; - return; - } - } - // Use the full path - out = texture_name; -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MD3Importer::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - mFile = pFile; - mScene = pScene; - mIOHandler = pIOHandler; - - // get base path and file name - // todo ... move to PathConverter - std::string::size_type s = mFile.find_last_of("/\\"); - if (s == std::string::npos) { - s = 0; - } - else ++s; - filename = mFile.substr(s), path = mFile.substr(0,s); - for ( std::string::iterator it = filename .begin(); it != filename.end(); ++it) - *it = tolower( *it); - - // Load multi-part model file, if necessary - if (configHandleMP) { - if (ReadMultipartFile()) - return; - } - - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open MD3 file " + pFile + "."); - - // Check whether the md3 file is large enough to contain the header - fileSize = (unsigned int)file->FileSize(); - if ( fileSize < sizeof(MD3::Header)) - throw DeadlyImportError( "MD3 File is too small."); - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector<unsigned char> mBuffer2 (fileSize); - file->Read( &mBuffer2[0], 1, fileSize); - mBuffer = &mBuffer2[0]; - - pcHeader = (BE_NCONST MD3::Header*)mBuffer; - - // Ensure correct endianess -#ifdef AI_BUILD_BIG_ENDIAN - - AI_SWAP4(pcHeader->VERSION); - AI_SWAP4(pcHeader->FLAGS); - AI_SWAP4(pcHeader->IDENT); - AI_SWAP4(pcHeader->NUM_FRAMES); - AI_SWAP4(pcHeader->NUM_SKINS); - AI_SWAP4(pcHeader->NUM_SURFACES); - AI_SWAP4(pcHeader->NUM_TAGS); - AI_SWAP4(pcHeader->OFS_EOF); - AI_SWAP4(pcHeader->OFS_FRAMES); - AI_SWAP4(pcHeader->OFS_SURFACES); - AI_SWAP4(pcHeader->OFS_TAGS); - -#endif - - // Validate the file header - ValidateHeaderOffsets(); - - // Navigate to the list of surfaces - BE_NCONST MD3::Surface* pcSurfaces = (BE_NCONST MD3::Surface*)(mBuffer + pcHeader->OFS_SURFACES); - - // Navigate to the list of tags - BE_NCONST MD3::Tag* pcTags = (BE_NCONST MD3::Tag*)(mBuffer + pcHeader->OFS_TAGS); - - // Allocate output storage - pScene->mNumMeshes = pcHeader->NUM_SURFACES; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - - pScene->mNumMaterials = pcHeader->NUM_SURFACES; - pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]; - - // Set arrays to zero to ensue proper destruction if an exception is raised - ::memset(pScene->mMeshes,0,pScene->mNumMeshes*sizeof(aiMesh*)); - ::memset(pScene->mMaterials,0,pScene->mNumMaterials*sizeof(aiMaterial*)); - - // Now read possible skins from .skin file - Q3Shader::SkinData skins; - ReadSkin(skins); - - // And check whether we can locate a shader file for this model - Q3Shader::ShaderData shaders; - ReadShader(shaders); - - // Adjust all texture paths in the shader - const char* header_name = pcHeader->NAME; - if (shaders.blocks.size()) { - for (std::list< Q3Shader::ShaderDataBlock >::iterator dit = shaders.blocks.begin(); dit != shaders.blocks.end(); ++dit) { - ConvertPath((*dit).name.c_str(),header_name,(*dit).name); - - for (std::list< Q3Shader::ShaderMapBlock >::iterator mit = (*dit).maps.begin(); mit != (*dit).maps.end(); ++mit) { - ConvertPath((*mit).name.c_str(),header_name,(*mit).name); - } - } - } - - // Read all surfaces from the file - unsigned int iNum = pcHeader->NUM_SURFACES; - unsigned int iNumMaterials = 0; - while (iNum-- > 0) { - - // Ensure correct endianess -#ifdef AI_BUILD_BIG_ENDIAN - - AI_SWAP4(pcSurfaces->FLAGS); - AI_SWAP4(pcSurfaces->IDENT); - AI_SWAP4(pcSurfaces->NUM_FRAMES); - AI_SWAP4(pcSurfaces->NUM_SHADER); - AI_SWAP4(pcSurfaces->NUM_TRIANGLES); - AI_SWAP4(pcSurfaces->NUM_VERTICES); - AI_SWAP4(pcSurfaces->OFS_END); - AI_SWAP4(pcSurfaces->OFS_SHADERS); - AI_SWAP4(pcSurfaces->OFS_ST); - AI_SWAP4(pcSurfaces->OFS_TRIANGLES); - AI_SWAP4(pcSurfaces->OFS_XYZNORMAL); - -#endif - - // Validate the surface header - ValidateSurfaceHeaderOffsets(pcSurfaces); - - // Navigate to the vertex list of the surface - BE_NCONST MD3::Vertex* pcVertices = (BE_NCONST MD3::Vertex*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_XYZNORMAL); - - // Navigate to the triangle list of the surface - BE_NCONST MD3::Triangle* pcTriangles = (BE_NCONST MD3::Triangle*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_TRIANGLES); - - // Navigate to the texture coordinate list of the surface - BE_NCONST MD3::TexCoord* pcUVs = (BE_NCONST MD3::TexCoord*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_ST); - - // Navigate to the shader list of the surface - BE_NCONST MD3::Shader* pcShaders = (BE_NCONST MD3::Shader*) - (((uint8_t*)pcSurfaces) + pcSurfaces->OFS_SHADERS); - - // If the submesh is empty ignore it - if (0 == pcSurfaces->NUM_VERTICES || 0 == pcSurfaces->NUM_TRIANGLES) - { - pcSurfaces = (BE_NCONST MD3::Surface*)(((uint8_t*)pcSurfaces) + pcSurfaces->OFS_END); - pScene->mNumMeshes--; - continue; - } - - // Allocate output mesh - pScene->mMeshes[iNum] = new aiMesh(); - aiMesh* pcMesh = pScene->mMeshes[iNum]; - - std::string _texture_name; - const char* texture_name = NULL; - - // Check whether we have a texture record for this surface in the .skin file - std::list< Q3Shader::SkinData::TextureEntry >::iterator it = std::find( - skins.textures.begin(), skins.textures.end(), pcSurfaces->NAME ); - - if (it != skins.textures.end()) { - texture_name = &*( _texture_name = (*it).second).begin(); - DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME); - (*it).resolved = true; // mark entry as resolved - } - - // Get the first shader (= texture?) assigned to the surface - if (!texture_name && pcSurfaces->NUM_SHADER) { - texture_name = pcShaders->NAME; - } - - std::string convertedPath; - if (texture_name) { - ConvertPath(texture_name,header_name,convertedPath); - } - - const Q3Shader::ShaderDataBlock* shader = NULL; - - // Now search the current shader for a record with this name ( - // excluding texture file extension) - if (shaders.blocks.size()) { - - std::string::size_type s = convertedPath.find_last_of('.'); - if (s == std::string::npos) - s = convertedPath.length(); - - const std::string without_ext = convertedPath.substr(0,s); - std::list< Q3Shader::ShaderDataBlock >::const_iterator dit = std::find(shaders.blocks.begin(),shaders.blocks.end(),without_ext); - if (dit != shaders.blocks.end()) { - // Hurra, wir haben einen. Tolle Sache. - shader = &*dit; - DefaultLogger::get()->info("Found shader record for " +without_ext ); - } - else DefaultLogger::get()->warn("Unable to find shader record for " +without_ext ); - } - - MaterialHelper* pcHelper = new MaterialHelper(); - - const int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - // Add a small ambient color value - Quake 3 seems to have one - aiColor3D clr; - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - clr.b = clr.g = clr.r = 1.0f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - // use surface name + skin_name as material name - aiString name; - name.Set("MD3_[" + configSkinFile + "][" + pcSurfaces->NAME + "]"); - pcHelper->AddProperty(&name,AI_MATKEY_NAME); - - if (!shader) { - // Setup dummy texture file name to ensure UV coordinates are kept during postprocessing - aiString szString; - if (convertedPath.length()) { - szString.Set(convertedPath); - } - else { - DefaultLogger::get()->warn("Texture file name has zero length. Using default name"); - szString.Set("dummy_texture.bmp"); - } - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); - - // prevent transparency by default - int no_alpha = aiTextureFlags_IgnoreAlpha; - pcHelper->AddProperty(&no_alpha,1,AI_MATKEY_TEXFLAGS_DIFFUSE(0)); - } - else { - Q3Shader::ConvertShaderToMaterial(pcHelper,*shader); - } - - pScene->mMaterials[iNumMaterials] = (aiMaterial*)pcHelper; - pcMesh->mMaterialIndex = iNumMaterials++; - - // Ensure correct endianess -#ifdef AI_BUILD_BIG_ENDIAN - - for (uint32_t i = 0; i < pcSurfaces->NUM_VERTICES;++i) { - AI_SWAP2( pcVertices[i].NORMAL ); - AI_SWAP2( pcVertices[i].X ); - AI_SWAP2( pcVertices[i].Y ); - AI_SWAP2( pcVertices[i].Z ); - - AI_SWAP4( pcUVs[i].U ); - AI_SWAP4( pcUVs[i].U ); - } - for (uint32_t i = 0; i < pcSurfaces->NUM_TRIANGLES;++i) { - AI_SWAP4(pcTriangles[i].INDEXES[0]); - AI_SWAP4(pcTriangles[i].INDEXES[1]); - AI_SWAP4(pcTriangles[i].INDEXES[2]); - } - -#endif - - // Fill mesh information - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - pcMesh->mNumVertices = pcSurfaces->NUM_TRIANGLES*3; - pcMesh->mNumFaces = pcSurfaces->NUM_TRIANGLES; - pcMesh->mFaces = new aiFace[pcSurfaces->NUM_TRIANGLES]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - - // Fill in all triangles - unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int)pcSurfaces->NUM_TRIANGLES;++i) { - pcMesh->mFaces[i].mIndices = new unsigned int[3]; - pcMesh->mFaces[i].mNumIndices = 3; - - //unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) { - pcMesh->mFaces[i].mIndices[c] = iCurrent; - - // Read vertices - aiVector3D& vec = pcMesh->mVertices[iCurrent]; - vec.x = pcVertices[ pcTriangles->INDEXES[c]].X*AI_MD3_XYZ_SCALE; - vec.y = pcVertices[ pcTriangles->INDEXES[c]].Y*AI_MD3_XYZ_SCALE; - vec.z = pcVertices[ pcTriangles->INDEXES[c]].Z*AI_MD3_XYZ_SCALE; - - // Convert the normal vector to uncompressed float3 format - aiVector3D& nor = pcMesh->mNormals[iCurrent]; - LatLngNormalToVec3(pcVertices[pcTriangles->INDEXES[c]].NORMAL,(float*)&nor); - - // Read texture coordinates - pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[ pcTriangles->INDEXES[c]].U; - pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-pcUVs[ pcTriangles->INDEXES[c]].V; - } - // Flip face order if necessary - if (!shader || shader->cull == Q3Shader::CULL_CW) { - std::swap(pcMesh->mFaces[i].mIndices[2],pcMesh->mFaces[i].mIndices[1]); - } - pcTriangles++; - } - - // Go to the next surface - pcSurfaces = (BE_NCONST MD3::Surface*)(((unsigned char*)pcSurfaces) + pcSurfaces->OFS_END); - } - - // For debugging purposes: check whether we found matches for all entries in the skins file - if (!DefaultLogger::isNullLogger()) { - for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) { - if (!(*it).resolved) { - DefaultLogger::get()->error("MD3: Failed to match skin " + (*it).first + " to surface " + (*it).second); - } - } - } - - if (!pScene->mNumMeshes) - throw DeadlyImportError( "MD3: File contains no valid mesh"); - pScene->mNumMaterials = iNumMaterials; - - // Now we need to generate an empty node graph - pScene->mRootNode = new aiNode("<MD3Root>"); - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - - // Attach tiny children for all tags - if (pcHeader->NUM_TAGS) { - pScene->mRootNode->mNumChildren = pcHeader->NUM_TAGS; - pScene->mRootNode->mChildren = new aiNode*[pcHeader->NUM_TAGS]; - - for (unsigned int i = 0; i < pcHeader->NUM_TAGS; ++i, ++pcTags) { - - aiNode* nd = pScene->mRootNode->mChildren[i] = new aiNode(); - nd->mName.Set((const char*)pcTags->NAME); - nd->mParent = pScene->mRootNode; - - AI_SWAP4(pcTags->origin.x); - AI_SWAP4(pcTags->origin.y); - AI_SWAP4(pcTags->origin.z); - - // Copy local origin, again flip z,y - nd->mTransformation.a4 = pcTags->origin.x; - nd->mTransformation.b4 = pcTags->origin.y; - nd->mTransformation.c4 = pcTags->origin.z; - - // Copy rest of transformation (need to transpose to match row-order matrix) - for (unsigned int a = 0; a < 3;++a) { - for (unsigned int m = 0; m < 3;++m) { - nd->mTransformation[m][a] = pcTags->orientation[a][m]; - AI_SWAP4(nd->mTransformation[m][a]); - } - } - } - } - - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mRootNode->mMeshes[i] = i; - - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); -} - -#endif // !! ASSIMP_BUILD_NO_MD3_IMPORTER diff --git a/3rdparty/assimp/code/MD3Loader.h b/3rdparty/assimp/code/MD3Loader.h deleted file mode 100644 index f2d07834..00000000 --- a/3rdparty/assimp/code/MD3Loader.h +++ /dev/null @@ -1,331 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Md3Loader.h - * @brief Declaration of the .MD3 importer class. - */ -#ifndef AI_MD3LOADER_H_INCLUDED -#define AI_MD3LOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "ByteSwap.h" - -#include "../include/aiTypes.h" - -#include "MD3FileData.h" -namespace Assimp { -class MaterialHelper; - -using namespace MD3; -namespace Q3Shader { - -// --------------------------------------------------------------------------- -/** @brief Tiny utility data structure to hold the data of a .skin file - */ -struct SkinData -{ - //! A single entryin texture list - struct TextureEntry : public std::pair<std::string,std::string> - { - // did we resolve this texture entry? - bool resolved; - - // for std::find() - bool operator == (const std::string& f) const { - return f == first; - } - }; - - //! List of textures - std::list<TextureEntry> textures; - - // rest is ignored for the moment -}; - -// --------------------------------------------------------------------------- -/** @brief Specifies cull modi for Quake shader files. - */ -enum ShaderCullMode -{ - CULL_NONE, - CULL_CW, - CULL_CCW -}; - -// --------------------------------------------------------------------------- -/** @brief Specifies alpha blend modi (src + dest) for Quake shader files - */ -enum BlendFunc -{ - BLEND_NONE, - BLEND_GL_ONE, - BLEND_GL_ZERO, - BLEND_GL_DST_COLOR, - BLEND_GL_ONE_MINUS_DST_COLOR, - BLEND_GL_SRC_ALPHA, - BLEND_GL_ONE_MINUS_SRC_ALPHA -}; - -// --------------------------------------------------------------------------- -/** @brief Specifies alpha test modi for Quake texture maps - */ -enum AlphaTestFunc -{ - AT_NONE, - AT_GT0, - AT_LT128, - AT_GE128 -}; - -// --------------------------------------------------------------------------- -/** @brief Tiny utility data structure to hold a .shader map data block - */ -struct ShaderMapBlock -{ - ShaderMapBlock() - : blend_src (BLEND_NONE) - , blend_dest (BLEND_NONE) - , alpha_test (AT_NONE) - {} - - //! Name of referenced map - std::string name; - - //! Blend and alpha test settings for texture - BlendFunc blend_src,blend_dest; - AlphaTestFunc alpha_test; - - - //! For std::find() - bool operator== (const std::string& o) const { - return !ASSIMP_stricmp(o,name); - } -}; - -// --------------------------------------------------------------------------- -/** @brief Tiny utility data structure to hold a .shader data block - */ -struct ShaderDataBlock -{ - ShaderDataBlock() - : cull (CULL_CW) - {} - - //! Name of referenced data element - std::string name; - - //! Cull mode for the element - ShaderCullMode cull; - - //! Maps defined in the shader - std::list<ShaderMapBlock> maps; - - - //! For std::find() - bool operator== (const std::string& o) const { - return !ASSIMP_stricmp(o,name); - } -}; - -// --------------------------------------------------------------------------- -/** @brief Tiny utility data structure to hold the data of a .shader file - */ -struct ShaderData -{ - //! Shader data blocks - std::list<ShaderDataBlock> blocks; -}; - -// --------------------------------------------------------------------------- -/** @brief Load a shader file - * - * Generally, parsing is error tolerant. There's no failure. - * @param fill Receives output data - * @param file File to be read. - * @param io IOSystem to be used for reading - * @return false if file is not accessible - */ -bool LoadShader(ShaderData& fill, const std::string& file,IOSystem* io); - - -// --------------------------------------------------------------------------- -/** @brief Convert a Q3Shader to an aiMaterial - * - * @param[out] out Material structure to be filled. - * @param[in] shader Input shader - */ -void ConvertShaderToMaterial(MaterialHelper* out, const ShaderDataBlock& shader); - -// --------------------------------------------------------------------------- -/** @brief Load a skin file - * - * Generally, parsing is error tolerant. There's no failure. - * @param fill Receives output data - * @param file File to be read. - * @param io IOSystem to be used for reading - * @return false if file is not accessible - */ -bool LoadSkin(SkinData& fill, const std::string& file,IOSystem* io); - -} // ! namespace Q3SHader - -// --------------------------------------------------------------------------- -/** @brief Importer class to load MD3 files -*/ -class MD3Importer : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - MD3Importer(); - - /** Destructor, private as well */ - ~MD3Importer(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Validate offsets in the header - */ - void ValidateHeaderOffsets(); - void ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurfHeader); - - // ------------------------------------------------------------------- - /** Read a Q3 multipart file - * @return true if multi part has been processed - */ - bool ReadMultipartFile(); - - // ------------------------------------------------------------------- - /** Try to read the skin for a MD3 file - * @param fill Receives output information - */ - void ReadSkin(Q3Shader::SkinData& fill) const; - - // ------------------------------------------------------------------- - /** Try to read the shader for a MD3 file - * @param fill Receives output information - */ - void ReadShader(Q3Shader::ShaderData& fill) const; - - // ------------------------------------------------------------------- - /** Convert a texture path in a MD3 file to a proper value - * @param[in] texture_name Path to be converted - * @param[in] header_path Base path specified in MD3 header - * @param[out] out Receives the converted output string - */ - void ConvertPath(const char* texture_name, const char* header_path, - std::string& out) const; - -protected: - - /** Configuration option: frame to be loaded */ - unsigned int configFrameID; - - /** Configuration option: process multi-part files */ - bool configHandleMP; - - /** Configuration option: name of skin file to be read */ - std::string configSkinFile; - - /** Configuration option: name or path of shader */ - std::string configShaderFile; - - /** Configuration option: speed flag was set? */ - bool configSpeedFlag; - - /** Header of the MD3 file */ - BE_NCONST MD3::Header* pcHeader; - - /** File buffer */ - BE_NCONST unsigned char* mBuffer; - - /** Size of the file, in bytes */ - unsigned int fileSize; - - /** Current file name */ - std::string mFile; - - /** Current base directory */ - std::string path; - - /** Pure file we're currently reading */ - std::string filename; - - /** Output scene to be filled */ - aiScene* mScene; - - /** IO system to be used to access the data*/ - IOSystem* mIOHandler; - }; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/MD4FileData.h b/3rdparty/assimp/code/MD4FileData.h deleted file mode 100644 index c61665c2..00000000 --- a/3rdparty/assimp/code/MD4FileData.h +++ /dev/null @@ -1,218 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the helper data structures for importing MD4 files */ -#ifndef AI_MD4FILEHELPER_H_INC -#define AI_MD4FILEHELPER_H_INC - -#include <string> -#include <vector> -#include <sstream> - -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include "../include/aiAnim.h" - -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) -# pragma pack(push,1) -# define PACK_STRUCT -#elif defined( __GNUC__ ) -# define PACK_STRUCT __attribute__((packed)) -#else -# error Compiler not supported -#endif - - -namespace Assimp -{ -// http://gongo.quakedev.com/md4.html -namespace MD4 -{ - -#define AI_MD4_MAGIC_NUMBER_BE 'IDP4' -#define AI_MD4_MAGIC_NUMBER_LE '4PDI' - -// common limitations -#define AI_MD4_VERSION 4 -#define AI_MD4_MAXQPATH 64 -#define AI_MD4_MAX_FRAMES 2028 -#define AI_MD4_MAX_SURFACES 32 -#define AI_MD4_MAX_BONES 256 -#define AI_MD4_MAX_VERTS 4096 -#define AI_MD4_MAX_TRIANGLES 8192 - -// --------------------------------------------------------------------------- -/** \brief Data structure for the MD4 main header - */ -// --------------------------------------------------------------------------- -struct Header -{ - //! magic number - int32_t magic; - - //! file format version - int32_t version; - - //! original name in .pak archive - unsigned char name[ AI_MD4_MAXQPATH ]; - - //! number of frames in the file - int32_t NUM_FRAMES; - - //! number of bones in the file - int32_t NUM_BONES; - - //! number of surfaces in the file - int32_t NUM_SURFACES; - - //! offset of the first frame - int32_t OFS_FRAMES; - - //! offset of the first bone - int32_t OFS_BONES; - - //! offset of the first surface - int32_t OFS_SURFACES; - - //! end of file - int32_t OFS_EOF; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Stores the local transformation matrix of a bone - */ -// --------------------------------------------------------------------------- -struct BoneFrame -{ - float matrix[3][4]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Stores the name / parent index / flag of a node - */ -// --------------------------------------------------------------------------- -struct BoneName -{ - char name[32] ; - int parent ; - int flags ; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a surface in a MD4 file - */ -// --------------------------------------------------------------------------- -struct Surface -{ - int32_t ident; - char name[64]; - char shader[64]; - int32_t shaderIndex; - int32_t lodBias; - int32_t minLod; - int32_t ofsHeader; - int32_t numVerts; - int32_t ofsVerts; - int32_t numTris; - int32_t ofsTris; - int32_t numBoneRefs; - int32_t ofsBoneRefs; - int32_t ofsCollapseMap; - int32_t ofsEnd; -} PACK_STRUCT; - - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD4 vertex' weight - */ -// --------------------------------------------------------------------------- -struct Weight -{ - int32_t boneIndex; - float boneWeight; - float offset[3]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a vertex in a MD4 file - */ -// --------------------------------------------------------------------------- -struct Vertex -{ - float vertex[3]; - float normal[3]; - float texCoords[2]; - int32_t numWeights; - Weight weights[1]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a triangle in a MD4 file - */ -// --------------------------------------------------------------------------- -struct Triangle -{ - int32_t indexes[3]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MD4 frame - */ -// --------------------------------------------------------------------------- -struct Frame -{ - float bounds[3][2]; - float localOrigin[3]; - float radius; - BoneFrame bones[1]; -} PACK_STRUCT; - - -// reset packing to the original value -#if defined(_MSC_VER) || defined(__BORLANDC__) || defined (__BCPLUSPLUS__) -# pragma pack( pop ) -#endif -#undef PACK_STRUCT - - -}; -}; - -#endif // !! AI_MD4FILEHELPER_H_INC diff --git a/3rdparty/assimp/code/MD5Loader.cpp b/3rdparty/assimp/code/MD5Loader.cpp deleted file mode 100644 index 897bb2ab..00000000 --- a/3rdparty/assimp/code/MD5Loader.cpp +++ /dev/null @@ -1,727 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD5Loader.cpp - * @brief Implementation of the MD5 importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MD5_IMPORTER - -// internal headers -#include "MaterialSystem.h" -#include "RemoveComments.h" -#include "MD5Loader.h" -#include "StringComparison.h" -#include "fast_atof.h" -#include "SkeletonMeshBuilder.h" - -using namespace Assimp; - -// Minimum weight value. Weights inside [-n ... n] are ignored -#define AI_MD5_WEIGHT_EPSILON 1e-5f - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MD5Importer::MD5Importer() -: configNoAutoLoad (false) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MD5Importer::~MD5Importer() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MD5Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - - if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera") - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) - return true; - const char* tokens[] = {"MD5Version"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Get list of all supported extensions -void MD5Importer::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("md5anim"); - extensions.insert("md5mesh"); - extensions.insert("md5camera"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup import properties -void MD5Importer::SetupProperties(const Importer* pImp) -{ - // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD - configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MD5Importer::InternReadFile( const std::string& pFile, - aiScene* _pScene, IOSystem* _pIOHandler) -{ - pIOHandler = _pIOHandler; - pScene = _pScene; - bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false; - - // remove the file extension - std::string::size_type pos = pFile.find_last_of('.'); - mFile = (std::string::npos == pos ? pFile : pFile.substr(0,pos+1)); - - const std::string extension = GetExtension(pFile); - try { - if (extension == "md5camera") { - LoadMD5CameraFile(); - } - else if (configNoAutoLoad || extension == "md5anim") { - // determine file extension and process just *one* file - if (extension.length() == 0) { - /* fixme */ - } - if (extension == "md5anim") { - LoadMD5AnimFile(); - } - else if (extension == "md5mesh") { - LoadMD5MeshFile(); - } - } - else { - LoadMD5MeshFile(); - LoadMD5AnimFile(); - } - } - catch ( std::exception&) { - // XXX use more idiomatic RAII solution - UnloadFileFromMemory(); - throw; - } - - // make sure we have at least one file - if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) - throw DeadlyImportError("Failed to read valid contents from this MD5* file"); - - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); - - // the output scene wouldn't pass the validation without this flag - if (!bHadMD5Mesh) - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; -} - -// ------------------------------------------------------------------------------------------------ -// Load a file into a memory buffer -void MD5Importer::LoadFileIntoMemory (IOStream* file) -{ - ai_assert(NULL != file); - fileSize = (unsigned int)file->FileSize(); - - // allocate storage and copy the contents of the file to a memory buffer - pScene = pScene; - mBuffer = new char[fileSize+1]; - file->Read( (void*)mBuffer, 1, fileSize); - iLineNumber = 1; - - // append a terminal 0 - mBuffer[fileSize] = '\0'; - - // now remove all line comments from the file - CommentRemover::RemoveLineComments("//",mBuffer,' '); -} - -// ------------------------------------------------------------------------------------------------ -// Unload the current memory buffer -void MD5Importer::UnloadFileFromMemory () -{ - // delete the file buffer - delete[] mBuffer; - mBuffer = NULL; - fileSize = 0; -} - -// ------------------------------------------------------------------------------------------------ -// Build unique vertices -void MD5Importer::MakeDataUnique (MD5::MeshDesc& meshSrc) -{ - std::vector<bool> abHad(meshSrc.mVertices.size(),false); - - // allocate enough storage to keep the output structures - const unsigned int iNewNum = meshSrc.mFaces.size()*3; - unsigned int iNewIndex = meshSrc.mVertices.size(); - meshSrc.mVertices.resize(iNewNum); - - // try to guess how much storage we'll need for new weights - const float fWeightsPerVert = meshSrc.mWeights.size() / (float)iNewIndex; - const unsigned int guess = (unsigned int)(fWeightsPerVert*iNewNum); - meshSrc.mWeights.reserve(guess + (guess >> 3)); // + 12.5% as buffer - - for (FaceList::const_iterator iter = meshSrc.mFaces.begin(),iterEnd = meshSrc.mFaces.end();iter != iterEnd;++iter){ - const aiFace& face = *iter; - for (unsigned int i = 0; i < 3;++i) { - if (face.mIndices[0] >= meshSrc.mVertices.size()) - throw DeadlyImportError("MD5MESH: Invalid vertex index"); - - if (abHad[face.mIndices[i]]) { - // generate a new vertex - meshSrc.mVertices[iNewIndex] = meshSrc.mVertices[face.mIndices[i]]; - face.mIndices[i] = iNewIndex++; - } - else abHad[face.mIndices[i]] = true; - } - // swap face order - std::swap(face.mIndices[0],face.mIndices[2]); - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursive node graph construction from a MD5MESH -void MD5Importer::AttachChilds_Mesh(int iParentID,aiNode* piParent, BoneList& bones) -{ - ai_assert(NULL != piParent && !piParent->mNumChildren); - - // First find out how many children we'll have - for (int i = 0; i < (int)bones.size();++i) { - if (iParentID != i && bones[i].mParentIndex == iParentID) { - ++piParent->mNumChildren; - } - } - if (piParent->mNumChildren) { - piParent->mChildren = new aiNode*[piParent->mNumChildren]; - for (int i = 0; i < (int)bones.size();++i) { - // (avoid infinite recursion) - if (iParentID != i && bones[i].mParentIndex == iParentID) { - aiNode* pc; - // setup a new node - *piParent->mChildren++ = pc = new aiNode(); - pc->mName = aiString(bones[i].mName); - pc->mParent = piParent; - - // get the transformation matrix from rotation and translational components - aiQuaternion quat; - MD5::ConvertQuaternion ( bones[i].mRotationQuat, quat ); - - // FIX to get to Assimp's quaternion conventions - quat.w *= -1.f; - - bones[i].mTransform = aiMatrix4x4 ( quat.GetMatrix()); - bones[i].mTransform.a4 = bones[i].mPositionXYZ.x; - bones[i].mTransform.b4 = bones[i].mPositionXYZ.y; - bones[i].mTransform.c4 = bones[i].mPositionXYZ.z; - - // store it for later use - pc->mTransformation = bones[i].mInvTransform = bones[i].mTransform; - bones[i].mInvTransform.Inverse(); - - // the transformations for each bone are absolute, so we need to multiply them - // with the inverse of the absolute matrix of the parent joint - if (-1 != iParentID) { - pc->mTransformation = bones[iParentID].mInvTransform * pc->mTransformation; - } - - // add children to this node, too - AttachChilds_Mesh( i, pc, bones); - } - } - // undo offset computations - piParent->mChildren -= piParent->mNumChildren; - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursive node graph construction from a MD5ANIM -void MD5Importer::AttachChilds_Anim(int iParentID,aiNode* piParent, AnimBoneList& bones,const aiNodeAnim** node_anims) -{ - ai_assert(NULL != piParent && !piParent->mNumChildren); - - // First find out how many children we'll have - for (int i = 0; i < (int)bones.size();++i) { - if (iParentID != i && bones[i].mParentIndex == iParentID) { - ++piParent->mNumChildren; - } - } - if (piParent->mNumChildren) { - piParent->mChildren = new aiNode*[piParent->mNumChildren]; - for (int i = 0; i < (int)bones.size();++i) { - // (avoid infinite recursion) - if (iParentID != i && bones[i].mParentIndex == iParentID) - { - aiNode* pc; - // setup a new node - *piParent->mChildren++ = pc = new aiNode(); - pc->mName = aiString(bones[i].mName); - pc->mParent = piParent; - - // get the corresponding animation channel and its first frame - const aiNodeAnim** cur = node_anims; - while ((**cur).mNodeName != pc->mName)++cur; - - aiMatrix4x4::Translation((**cur).mPositionKeys[0].mValue,pc->mTransformation); - pc->mTransformation = pc->mTransformation * aiMatrix4x4((**cur).mRotationKeys[0].mValue.GetMatrix()) ; - - // add children to this node, too - AttachChilds_Anim( i, pc, bones,node_anims); - } - } - // undo offset computations - piParent->mChildren -= piParent->mNumChildren; - } -} - -// ------------------------------------------------------------------------------------------------ -// Load a MD5MESH file -void MD5Importer::LoadMD5MeshFile () -{ - std::string pFile = mFile + "md5mesh"; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - DefaultLogger::get()->warn("Failed to read MD5MESH file: " + pFile); - return; - } - bHadMD5Mesh = true; - LoadFileIntoMemory(file.get()); - - // now construct a parser and parse the file - MD5::MD5Parser parser(mBuffer,fileSize); - - // load the mesh information from it - MD5::MD5MeshParser meshParser(parser.mSections); - - // create the bone hierarchy - first the root node and dummy nodes for all meshes - pScene->mRootNode = new aiNode("<MD5_Root>"); - pScene->mRootNode->mNumChildren = 2; - pScene->mRootNode->mChildren = new aiNode*[2]; - - // build the hierarchy from the MD5MESH file - aiNode* pcNode = pScene->mRootNode->mChildren[1] = new aiNode(); - pcNode->mName.Set("<MD5_Hierarchy>"); - pcNode->mParent = pScene->mRootNode; - AttachChilds_Mesh(-1,pcNode,meshParser.mJoints); - - pcNode = pScene->mRootNode->mChildren[0] = new aiNode(); - pcNode->mName.Set("<MD5_Mesh>"); - pcNode->mParent = pScene->mRootNode; - -#if 0 - if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */ - SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[1]->mChildren[0]); -#else - std::vector<MD5::MeshDesc>::const_iterator end = meshParser.mMeshes.end(); - - // FIX: MD5 files exported from Blender can have empty meshes - for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) { - if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) - ++pScene->mNumMaterials; - } - - // generate all meshes - pScene->mNumMeshes = pScene->mNumMaterials; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial*[pScene->mNumMeshes]; - - // storage for node mesh indices - pcNode->mNumMeshes = pScene->mNumMeshes; - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - for (unsigned int m = 0; m < pcNode->mNumMeshes;++m) - pcNode->mMeshes[m] = m; - - unsigned int n = 0; - for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(),end = meshParser.mMeshes.end(); it != end;++it) { - MD5::MeshDesc& meshSrc = *it; - if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) - continue; - - aiMesh* mesh = pScene->mMeshes[n] = new aiMesh(); - mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // generate unique vertices in our internal verbose format - MakeDataUnique(meshSrc); - - mesh->mNumVertices = (unsigned int) meshSrc.mVertices.size(); - mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - mesh->mNumUVComponents[0] = 2; - - // copy texture coordinates - aiVector3D* pv = mesh->mTextureCoords[0]; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) { - pv->x = (*iter).mUV.x; - pv->y = 1.0f-(*iter).mUV.y; // D3D to OpenGL - pv->z = 0.0f; - } - - // sort all bone weights - per bone - unsigned int* piCount = new unsigned int[meshParser.mJoints.size()]; - ::memset(piCount,0,sizeof(unsigned int)*meshParser.mJoints.size()); - - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) { - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) - { - MD5::WeightDesc& desc = meshSrc.mWeights[w]; - /* FIX for some invalid exporters */ - if (!(desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON )) - ++piCount[desc.mBone]; - } - } - - // check how many we will need - for (unsigned int p = 0; p < meshParser.mJoints.size();++p) - if (piCount[p])mesh->mNumBones++; - - if (mesh->mNumBones) // just for safety - { - mesh->mBones = new aiBone*[mesh->mNumBones]; - for (unsigned int q = 0,h = 0; q < meshParser.mJoints.size();++q) - { - if (!piCount[q])continue; - aiBone* p = mesh->mBones[h] = new aiBone(); - p->mNumWeights = piCount[q]; - p->mWeights = new aiVertexWeight[p->mNumWeights]; - p->mName = aiString(meshParser.mJoints[q].mName); - p->mOffsetMatrix = meshParser.mJoints[q].mInvTransform; - - // store the index for later use - MD5::BoneDesc& boneSrc = meshParser.mJoints[q]; - boneSrc.mMap = h++; - - // compute w-component of quaternion - MD5::ConvertQuaternion( boneSrc.mRotationQuat, boneSrc.mRotationQuatConverted ); - } - - //unsigned int g = 0; - pv = mesh->mVertices; - for (MD5::VertexList::const_iterator iter = meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) { - // compute the final vertex position from all single weights - *pv = aiVector3D(); - - // there are models which have weights which don't sum to 1 ... - float fSum = 0.0f; - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) - fSum += meshSrc.mWeights[w].mWeight; - if (!fSum) { - DefaultLogger::get()->error("MD5MESH: The sum of all vertex bone weights is 0"); - continue; - } - - // process bone weights - for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w) { - if (w >= meshSrc.mWeights.size()) - throw DeadlyImportError("MD5MESH: Invalid weight index"); - - MD5::WeightDesc& desc = meshSrc.mWeights[w]; - if ( desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON) - continue; - - const float fNewWeight = desc.mWeight / fSum; - - // transform the local position into worldspace - MD5::BoneDesc& boneSrc = meshParser.mJoints[desc.mBone]; - const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (desc.vOffsetPosition); - - // use the original weight to compute the vertex position - // (some MD5s seem to depend on the invalid weight values ...) - *pv += ((boneSrc.mPositionXYZ+v)* desc.mWeight); - - aiBone* bone = mesh->mBones[boneSrc.mMap]; - *bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight); - } - } - - // undo our nice offset tricks ... - for (unsigned int p = 0; p < mesh->mNumBones;++p) - mesh->mBones[p]->mWeights -= mesh->mBones[p]->mNumWeights; - } - - delete[] piCount; - - // now setup all faces - we can directly copy the list - // (however, take care that the aiFace destructor doesn't delete the mIndices array) - mesh->mNumFaces = (unsigned int)meshSrc.mFaces.size(); - mesh->mFaces = new aiFace[mesh->mNumFaces]; - for (unsigned int c = 0; c < mesh->mNumFaces;++c) { - mesh->mFaces[c].mNumIndices = 3; - mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices; - meshSrc.mFaces[c].mIndices = NULL; - } - - // generate a material for the mesh - MaterialHelper* mat = new MaterialHelper(); - pScene->mMaterials[n] = mat; - - // insert the typical doom3 textures: - // nnn_local.tga - normal map - // nnn_h.tga - height map - // nnn_s.tga - specular map - // nnn_d.tga - diffuse map - if (meshSrc.mShader.length && !strchr(meshSrc.mShader.data,'.')) { - - aiString temp(meshSrc.mShader); - temp.Append("_local.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_NORMALS(0)); - - temp = aiString(meshSrc.mShader); - temp.Append("_s.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_SPECULAR(0)); - - temp = aiString(meshSrc.mShader); - temp.Append("_d.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_DIFFUSE(0)); - - temp = aiString(meshSrc.mShader); - temp.Append("_h.tga"); - mat->AddProperty(&temp,AI_MATKEY_TEXTURE_HEIGHT(0)); - - // set this also as material name - mat->AddProperty(&meshSrc.mShader,AI_MATKEY_NAME); - } - else mat->AddProperty(&meshSrc.mShader,AI_MATKEY_TEXTURE_DIFFUSE(0)); - mesh->mMaterialIndex = n++; - } -#endif - // delete the file again - UnloadFileFromMemory(); -} - -// ------------------------------------------------------------------------------------------------ -// Load an MD5ANIM file -void MD5Importer::LoadMD5AnimFile () -{ - std::string pFile = mFile + "md5anim"; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - DefaultLogger::get()->warn("Failed to read MD5ANIM file: " + pFile); - return; - } - LoadFileIntoMemory(file.get()); - - // parse the basic file structure - MD5::MD5Parser parser(mBuffer,fileSize); - - // load the animation information from the parse tree - MD5::MD5AnimParser animParser(parser.mSections); - - // generate and fill the output animation - if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() || - animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) { - - DefaultLogger::get()->error("MD5ANIM: No frames or animated bones loaded"); - } - else { - bHadMD5Anim = true; - - pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations = 1]; - aiAnimation* anim = pScene->mAnimations[0] = new aiAnimation(); - anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size(); - anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - aiNodeAnim* node = anim->mChannels[i] = new aiNodeAnim(); - node->mNodeName = aiString( animParser.mAnimatedBones[i].mName ); - - // allocate storage for the keyframes - node->mPositionKeys = new aiVectorKey[animParser.mFrames.size()]; - node->mRotationKeys = new aiQuatKey[animParser.mFrames.size()]; - } - - // 1 tick == 1 frame - anim->mTicksPerSecond = animParser.fFrameRate; - - for (FrameList::const_iterator iter = animParser.mFrames.begin(), iterEnd = animParser.mFrames.end();iter != iterEnd;++iter){ - double dTime = (double)(*iter).iIndex; - aiNodeAnim** pcAnimNode = anim->mChannels; - if (!(*iter).mValues.empty() || iter == animParser.mFrames.begin()) /* be sure we have at least one frame */ - { - // now process all values in there ... read all joints - MD5::BaseFrameDesc* pcBaseFrame = &animParser.mBaseFrames[0]; - for (AnimBoneList::const_iterator iter2 = animParser.mAnimatedBones.begin(); iter2 != animParser.mAnimatedBones.end();++iter2, - ++pcAnimNode,++pcBaseFrame) - { - if ((*iter2).iFirstKeyIndex >= (*iter).mValues.size()) { - - // Allow for empty frames - if ((*iter2).iFlags != 0) { - throw DeadlyImportError("MD5: Keyframe index is out of range"); - - } - continue; - } - const float* fpCur = &(*iter).mValues[(*iter2).iFirstKeyIndex]; - aiNodeAnim* pcCurAnimBone = *pcAnimNode; - - aiVectorKey* vKey = &pcCurAnimBone->mPositionKeys[pcCurAnimBone->mNumPositionKeys++]; - aiQuatKey* qKey = &pcCurAnimBone->mRotationKeys [pcCurAnimBone->mNumRotationKeys++]; - aiVector3D vTemp; - - // translational component - for (unsigned int i = 0; i < 3; ++i) { - if ((*iter2).iFlags & (1u << i)) - vKey->mValue[i] = *fpCur++; - else vKey->mValue[i] = pcBaseFrame->vPositionXYZ[i]; - } - - // orientation component - for (unsigned int i = 0; i < 3; ++i) { - if ((*iter2).iFlags & (8u << i)) - vTemp[i] = *fpCur++; - else vTemp[i] = pcBaseFrame->vRotationQuat[i]; - } - - MD5::ConvertQuaternion(vTemp, qKey->mValue); - qKey->mTime = vKey->mTime = dTime; - - // we need this to get to Assimp quaternion conventions - qKey->mValue.w *= -1.f; - } - } - - // compute the duration of the animation - anim->mDuration = std::max(dTime,anim->mDuration); - } - - // If we didn't build the hierarchy yet (== we didn't load a MD5MESH), - // construct it now from the data given in the MD5ANIM. - if (!pScene->mRootNode) { - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("<MD5_Hierarchy>"); - - AttachChilds_Anim(-1,pScene->mRootNode,animParser.mAnimatedBones,(const aiNodeAnim**)anim->mChannels); - - // Call SkeletonMeshBuilder to construct a mesh to represent the shape - if (pScene->mRootNode->mNumChildren) { - SkeletonMeshBuilder skeleton_maker(pScene,pScene->mRootNode->mChildren[0]); - } - } - } - // delete the file again - UnloadFileFromMemory(); -} - -// ------------------------------------------------------------------------------------------------ -// Load an MD5CAMERA file -void MD5Importer::LoadMD5CameraFile () -{ - std::string pFile = mFile + "md5camera"; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile); - } - bHadMD5Camera = true; - LoadFileIntoMemory(file.get()); - - // parse the basic file structure - MD5::MD5Parser parser(mBuffer,fileSize); - - // load the camera animation data from the parse tree - MD5::MD5CameraParser cameraParser(parser.mSections); - - if (cameraParser.frames.empty()) - throw DeadlyImportError("MD5CAMERA: No frames parsed"); - - std::vector<unsigned int>& cuts = cameraParser.cuts; - std::vector<MD5::CameraAnimFrameDesc>& frames = cameraParser.frames; - - // Construct output graph - a simple root with a dummy child. - // The root node performs the coordinate system conversion - aiNode* root = pScene->mRootNode = new aiNode("<MD5CameraRoot>"); - root->mChildren = new aiNode*[root->mNumChildren = 1]; - root->mChildren[0] = new aiNode("<MD5Camera>"); - root->mChildren[0]->mParent = root; - - // ... but with one camera assigned to it - pScene->mCameras = new aiCamera*[pScene->mNumCameras = 1]; - aiCamera* cam = pScene->mCameras[0] = new aiCamera(); - cam->mName = "<MD5Camera>"; - - // FIXME: Fov is currently set to the first frame's value - cam->mHorizontalFOV = AI_DEG_TO_RAD( frames.front().fFOV ); - - // every cut is written to a separate aiAnimation - if (!cuts.size()) { - cuts.push_back(0); - cuts.push_back(frames.size()-1); - } - else { - cuts.insert(cuts.begin(),0); - - if (cuts.back() < frames.size()-1) - cuts.push_back(frames.size()-1); - } - - pScene->mNumAnimations = cuts.size()-1; - aiAnimation** tmp = pScene->mAnimations = new aiAnimation*[pScene->mNumAnimations]; - for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end()-1; ++it) { - - aiAnimation* anim = *tmp++ = new aiAnimation(); - anim->mName.length = ::sprintf(anim->mName.data,"anim%u_from_%u_to_%u",(unsigned int)(it-cuts.begin()),(*it),*(it+1)); - - anim->mTicksPerSecond = cameraParser.fFrameRate; - anim->mChannels = new aiNodeAnim*[anim->mNumChannels = 1]; - aiNodeAnim* nd = anim->mChannels[0] = new aiNodeAnim(); - nd->mNodeName.Set("<MD5Camera>"); - - nd->mNumPositionKeys = nd->mNumRotationKeys = *(it+1) - (*it); - nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys]; - nd->mRotationKeys = new aiQuatKey [nd->mNumRotationKeys]; - for (unsigned int i = 0; i < nd->mNumPositionKeys; ++i) { - - nd->mPositionKeys[i].mValue = frames[*it+i].vPositionXYZ; - MD5::ConvertQuaternion(frames[*it+i].vRotationQuat,nd->mRotationKeys[i].mValue); - nd->mRotationKeys[i].mTime = nd->mPositionKeys[i].mTime = *it+i; - } - } -} - -#endif // !! ASSIMP_BUILD_NO_MD5_IMPORTER diff --git a/3rdparty/assimp/code/MD5Loader.h b/3rdparty/assimp/code/MD5Loader.h deleted file mode 100644 index d56cefb1..00000000 --- a/3rdparty/assimp/code/MD5Loader.h +++ /dev/null @@ -1,194 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD5Loader.h - * @brief Definition of the .MD5 importer class. - * http://www.modwiki.net/wiki/MD5_(file_format) -*/ -#ifndef AI_MD5LOADER_H_INCLUDED -#define AI_MD5LOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "MD5Parser.h" - -#include "../include/aiTypes.h" - -namespace Assimp { - -class IOStream; -using namespace Assimp::MD5; - -// --------------------------------------------------------------------------- -/** Importer class for the MD5 file format -*/ -class MD5Importer : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - MD5Importer(); - - /** Destructor, private as well */ - ~MD5Importer(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - - - // ------------------------------------------------------------------- - /** Load a *.MD5MESH file. - */ - void LoadMD5MeshFile (); - - // ------------------------------------------------------------------- - /** Load a *.MD5ANIM file. - */ - void LoadMD5AnimFile (); - - // ------------------------------------------------------------------- - /** Load a *.MD5CAMERA file. - */ - void LoadMD5CameraFile (); - - // ------------------------------------------------------------------- - /** Construct node hierarchy from a given MD5ANIM - * @param iParentID Current parent ID - * @param piParent Parent node to attach to - * @param bones Input bones - * @param node_anims Generated node animations - */ - void AttachChilds_Anim(int iParentID,aiNode* piParent, - AnimBoneList& bones,const aiNodeAnim** node_anims); - - // ------------------------------------------------------------------- - /** Construct node hierarchy from a given MD5MESH - * @param iParentID Current parent ID - * @param piParent Parent node to attach to - * @param bones Input bones - */ - void AttachChilds_Mesh(int iParentID,aiNode* piParent,BoneList& bones); - - // ------------------------------------------------------------------- - /** Build unique vertex buffers from a given MD5ANIM - * @param meshSrc Input data - */ - void MakeDataUnique (MD5::MeshDesc& meshSrc); - - // ------------------------------------------------------------------- - /** Load the contents of a specific file into memory and - * alocates a buffer to keep it. - * - * mBuffer is modified to point to this buffer. - * @param pFile File stream to be read - */ - void LoadFileIntoMemory (IOStream* pFile); - void UnloadFileFromMemory (); - - - /** IOSystem to be used to access files */ - IOSystem* mIOHandler; - - /** Path to the file, excluding the file extension but - with the dot */ - std::string mFile; - - /** Buffer to hold the loaded file */ - char* mBuffer; - - /** Size of the file */ - unsigned int fileSize; - - /** Current line number. For debugging purposes */ - unsigned int iLineNumber; - - /** Scene to be filled */ - aiScene* pScene; - - /** (Custom) I/O handler implementation */ - IOSystem* pIOHandler; - - /** true if a MD5MESH file has already been parsed */ - bool bHadMD5Mesh; - - /** true if a MD5ANIM file has already been parsed */ - bool bHadMD5Anim; - - /** true if a MD5CAMERA file has already been parsed */ - bool bHadMD5Camera; - - /** configuration option: prevent anim autoload */ - bool configNoAutoLoad; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/MD5Parser.cpp b/3rdparty/assimp/code/MD5Parser.cpp deleted file mode 100644 index d5b89399..00000000 --- a/3rdparty/assimp/code/MD5Parser.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD5Parser.cpp - * @brief Implementation of the MD5 parser class - */ -#include "AssimpPCH.h" - -// internal headers -#include "MD5Loader.h" -#include "MaterialSystem.h" -#include "fast_atof.h" -#include "ParsingUtils.h" -#include "StringComparison.h" - -using namespace Assimp; -using namespace Assimp::MD5; - -// ------------------------------------------------------------------------------------------------ -// Parse the segment structure fo a MD5 file -MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize ) -{ - ai_assert(NULL != _buffer && 0 != _fileSize); - - buffer = _buffer; - fileSize = _fileSize; - lineNumber = 0; - - DefaultLogger::get()->debug("MD5Parser begin"); - - // parse the file header - ParseHeader(); - - // and read all sections until we're finished - bool running = true; - while (running) { - mSections.push_back(Section()); - Section& sec = mSections.back(); - if (!ParseSection(sec)) { - break; - } - } - - if ( !DefaultLogger::isNullLogger()) { - char szBuffer[128]; // should be sufficiently large - ::sprintf(szBuffer,"MD5Parser end. Parsed %i sections",(int)mSections.size()); - DefaultLogger::get()->debug(szBuffer); - } -} - -// ------------------------------------------------------------------------------------------------ -// Report error to the log stream -/*static*/ void MD5Parser::ReportError (const char* error, unsigned int line) -{ - char szBuffer[1024]; - ::sprintf(szBuffer,"[MD5] Line %i: %s",line,error); - throw DeadlyImportError(szBuffer); -} - -// ------------------------------------------------------------------------------------------------ -// Report warning to the log stream -/*static*/ void MD5Parser::ReportWarning (const char* warn, unsigned int line) -{ - char szBuffer[1024]; - ::sprintf(szBuffer,"[MD5] Line %i: %s",line,warn); - DefaultLogger::get()->warn(szBuffer); -} - -// ------------------------------------------------------------------------------------------------ -// Parse and validate the MD5 header -void MD5Parser::ParseHeader() -{ - // parse and validate the file version - SkipSpaces(); - if (!TokenMatch(buffer,"MD5Version",10)) { - ReportError("Invalid MD5 file: MD5Version tag has not been found"); - } - SkipSpaces(); - unsigned int iVer = ::strtol10(buffer,(const char**)&buffer); - if (10 != iVer) { - ReportError("MD5 version tag is unknown (10 is expected)"); - } - SkipLine(); - - // print the command line options to the console - // FIX: can break the log length limit, so we need to be careful - char* sz = buffer; - while (!IsLineEnd( *buffer++)); - DefaultLogger::get()->info(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz)))); - SkipSpacesAndLineEnd(); -} - -// ------------------------------------------------------------------------------------------------ -// Recursive MD5 parsing function -bool MD5Parser::ParseSection(Section& out) -{ - // store the current line number for use in error messages - out.iLineNumber = lineNumber; - - // first parse the name of the section - char* sz = buffer; - while (!IsSpaceOrNewLine( *buffer))buffer++; - out.mName = std::string(sz,(uintptr_t)(buffer-sz)); - SkipSpaces(); - - bool running = true; - while (running) { - if ('{' == *buffer) { - // it is a normal section so read all lines - buffer++; - bool run = true; - while (run) - { - if (!SkipSpacesAndLineEnd()) { - return false; // seems this was the last section - } - if ('}' == *buffer) { - buffer++; - break; - } - - out.mElements.push_back(Element()); - Element& elem = out.mElements.back(); - - elem.iLineNumber = lineNumber; - elem.szStart = buffer; - - // terminate the line with zero - while (!IsLineEnd( *buffer))buffer++; - if (*buffer) { - ++lineNumber; - *buffer++ = '\0'; - } - } - break; - } - else if (!IsSpaceOrNewLine(*buffer)) { - // it is an element at global scope. Parse its value and go on - sz = buffer; - while (!IsSpaceOrNewLine( *buffer++)); - out.mGlobalValue = std::string(sz,(uintptr_t)(buffer-sz)); - continue; - } - break; - } - return SkipSpacesAndLineEnd(); -} - -// ------------------------------------------------------------------------------------------------ -// Some dirty macros just because they're so funny and easy to debug - -// skip all spaces ... handle EOL correctly -#define AI_MD5_SKIP_SPACES() if (!SkipSpaces(&sz)) \ - MD5Parser::ReportWarning("Unexpected end of line",(*eit).iLineNumber); - - // read a triple float in brackets: (1.0 1.0 1.0) -#define AI_MD5_READ_TRIPLE(vec) \ - AI_MD5_SKIP_SPACES(); \ - if ('(' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ( was expected",(*eit).iLineNumber); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atof_move(sz,(float&)vec.x); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atof_move(sz,(float&)vec.y); \ - AI_MD5_SKIP_SPACES(); \ - sz = fast_atof_move(sz,(float&)vec.z); \ - AI_MD5_SKIP_SPACES(); \ - if (')' != *sz++) \ - MD5Parser::ReportWarning("Unexpected token: ) was expected",(*eit).iLineNumber); - - // parse a string, enclosed in quotation marks or not -#define AI_MD5_PARSE_STRING(out) \ - bool bQuota = (*sz == '\"'); \ - const char* szStart = sz; \ - while (!IsSpaceOrNewLine(*sz))++sz; \ - const char* szEnd = sz; \ - if (bQuota) { \ - szStart++; \ - if ('\"' != *(szEnd-=1)) { \ - MD5Parser::ReportWarning("Expected closing quotation marks in string", \ - (*eit).iLineNumber); \ - continue; \ - } \ - } \ - out.length = (size_t)(szEnd - szStart); \ - ::memcpy(out.data,szStart,out.length); \ - out.data[out.length] = '\0'; - -// ------------------------------------------------------------------------------------------------ -// .MD5MESH parsing function -MD5MeshParser::MD5MeshParser(SectionList& mSections) -{ - DefaultLogger::get()->debug("MD5MeshParser begin"); - - // now parse all sections - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){ - if ( (*iter).mName == "numMeshes") { - mMeshes.reserve(::strtol10((*iter).mGlobalValue.c_str())); - } - else if ( (*iter).mName == "numJoints") { - mJoints.reserve(::strtol10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "joints") { - // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 ) - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end();eit != eitEnd; ++eit){ - mJoints.push_back(BoneDesc()); - BoneDesc& desc = mJoints.back(); - - const char* sz = (*eit).szStart; - AI_MD5_PARSE_STRING(desc.mName); - AI_MD5_SKIP_SPACES(); - - // negative values, at least -1, is allowed here - desc.mParentIndex = (int)strtol10s(sz,&sz); - - AI_MD5_READ_TRIPLE(desc.mPositionXYZ); - AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there - } - } - else if ((*iter).mName == "mesh") { - mMeshes.push_back(MeshDesc()); - MeshDesc& desc = mMeshes.back(); - - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end();eit != eitEnd; ++eit){ - const char* sz = (*eit).szStart; - - // shader attribute - if (TokenMatch(sz,"shader",6)) { - AI_MD5_SKIP_SPACES(); - AI_MD5_PARSE_STRING(desc.mShader); - } - // numverts attribute - else if (TokenMatch(sz,"numverts",8)) { - AI_MD5_SKIP_SPACES(); - desc.mVertices.resize(strtol10(sz)); - } - // numtris attribute - else if (TokenMatch(sz,"numtris",7)) { - AI_MD5_SKIP_SPACES(); - desc.mFaces.resize(strtol10(sz)); - } - // numweights attribute - else if (TokenMatch(sz,"numweights",10)) { - AI_MD5_SKIP_SPACES(); - desc.mWeights.resize(strtol10(sz)); - } - // vert attribute - // "vert 0 ( 0.394531 0.513672 ) 0 1" - else if (TokenMatch(sz,"vert",4)) { - AI_MD5_SKIP_SPACES(); - const unsigned int idx = ::strtol10(sz,&sz); - AI_MD5_SKIP_SPACES(); - if (idx >= desc.mVertices.size()) - desc.mVertices.resize(idx+1); - - VertexDesc& vert = desc.mVertices[idx]; - if ('(' != *sz++) - MD5Parser::ReportWarning("Unexpected token: ( was expected",(*eit).iLineNumber); - AI_MD5_SKIP_SPACES(); - sz = fast_atof_move(sz,(float&)vert.mUV.x); - AI_MD5_SKIP_SPACES(); - sz = fast_atof_move(sz,(float&)vert.mUV.y); - AI_MD5_SKIP_SPACES(); - if (')' != *sz++) - MD5Parser::ReportWarning("Unexpected token: ) was expected",(*eit).iLineNumber); - AI_MD5_SKIP_SPACES(); - vert.mFirstWeight = ::strtol10(sz,&sz); - AI_MD5_SKIP_SPACES(); - vert.mNumWeights = ::strtol10(sz,&sz); - } - // tri attribute - // "tri 0 15 13 12" - else if (TokenMatch(sz,"tri",3)) { - AI_MD5_SKIP_SPACES(); - const unsigned int idx = strtol10(sz,&sz); - if (idx >= desc.mFaces.size()) - desc.mFaces.resize(idx+1); - - aiFace& face = desc.mFaces[idx]; - face.mIndices = new unsigned int[face.mNumIndices = 3]; - for (unsigned int i = 0; i < 3;++i) { - AI_MD5_SKIP_SPACES(); - face.mIndices[i] = strtol10(sz,&sz); - } - } - // weight attribute - // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )" - else if (TokenMatch(sz,"weight",6)) { - AI_MD5_SKIP_SPACES(); - const unsigned int idx = strtol10(sz,&sz); - AI_MD5_SKIP_SPACES(); - if (idx >= desc.mWeights.size()) - desc.mWeights.resize(idx+1); - - WeightDesc& weight = desc.mWeights[idx]; - weight.mBone = strtol10(sz,&sz); - AI_MD5_SKIP_SPACES(); - sz = fast_atof_move(sz,weight.mWeight); - AI_MD5_READ_TRIPLE(weight.vOffsetPosition); - } - } - } - } - DefaultLogger::get()->debug("MD5MeshParser end"); -} - -// ------------------------------------------------------------------------------------------------ -// .MD5ANIM parsing function -MD5AnimParser::MD5AnimParser(SectionList& mSections) -{ - DefaultLogger::get()->debug("MD5AnimParser begin"); - - fFrameRate = 24.0f; - mNumAnimatedComponents = 0xffffffff; - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { - if ((*iter).mName == "hierarchy") { - // "sheath" 0 63 6 - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end();eit != eitEnd; ++eit) { - mAnimatedBones.push_back ( AnimBoneDesc () ); - AnimBoneDesc& desc = mAnimatedBones.back(); - - const char* sz = (*eit).szStart; - AI_MD5_PARSE_STRING(desc.mName); - AI_MD5_SKIP_SPACES(); - - // parent index - negative values are allowed (at least -1) - desc.mParentIndex = ::strtol10s(sz,&sz); - - // flags (highest is 2^6-1) - AI_MD5_SKIP_SPACES(); - if (63 < (desc.iFlags = ::strtol10(sz,&sz))){ - MD5Parser::ReportWarning("Invalid flag combination in hierarchy section",(*eit).iLineNumber); - } - AI_MD5_SKIP_SPACES(); - - // index of the first animation keyframe component for this joint - desc.iFirstKeyIndex = ::strtol10(sz,&sz); - } - } - else if ((*iter).mName == "baseframe") { - // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 ) - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit) { - const char* sz = (*eit).szStart; - - mBaseFrames.push_back ( BaseFrameDesc () ); - BaseFrameDesc& desc = mBaseFrames.back(); - - AI_MD5_READ_TRIPLE(desc.vPositionXYZ); - AI_MD5_READ_TRIPLE(desc.vRotationQuat); - } - } - else if ((*iter).mName == "frame") { - if (!(*iter).mGlobalValue.length()) { - MD5Parser::ReportWarning("A frame section must have a frame index",(*iter).iLineNumber); - continue; - } - - mFrames.push_back ( FrameDesc () ); - FrameDesc& desc = mFrames.back(); - desc.iIndex = strtol10((*iter).mGlobalValue.c_str()); - - // we do already know how much storage we will presumably need - if (0xffffffff != mNumAnimatedComponents) - desc.mValues.reserve(mNumAnimatedComponents); - - // now read all elements (continous list of floats) - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){ - const char* sz = (*eit).szStart; - while (SkipSpacesAndLineEnd(&sz)) { - float f;sz = fast_atof_move(sz,f); - desc.mValues.push_back(f); - } - } - } - else if ((*iter).mName == "numFrames") { - mFrames.reserve(strtol10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "numJoints") { - const unsigned int num = strtol10((*iter).mGlobalValue.c_str()); - mAnimatedBones.reserve(num); - - // try to guess the number of animated components if that element is not given - if (0xffffffff == mNumAnimatedComponents) - mNumAnimatedComponents = num * 6; - } - else if ((*iter).mName == "numAnimatedComponents") { - mAnimatedBones.reserve( strtol10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "frameRate") { - fast_atof_move((*iter).mGlobalValue.c_str(),fFrameRate); - } - } - DefaultLogger::get()->debug("MD5AnimParser end"); -} - -// ------------------------------------------------------------------------------------------------ -// .MD5CAMERA parsing function -MD5CameraParser::MD5CameraParser(SectionList& mSections) -{ - DefaultLogger::get()->debug("MD5CameraParser begin"); - fFrameRate = 24.0f; - - for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) { - if ((*iter).mName == "numFrames") { - frames.reserve(strtol10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "frameRate") { - fFrameRate = fast_atof ((*iter).mGlobalValue.c_str()); - } - else if ((*iter).mName == "numCuts") { - cuts.reserve(strtol10((*iter).mGlobalValue.c_str())); - } - else if ((*iter).mName == "cuts") { - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){ - cuts.push_back(strtol10((*eit).szStart)+1); - } - } - else if ((*iter).mName == "camera") { - for (ElementList::const_iterator eit = (*iter).mElements.begin(), eitEnd = (*iter).mElements.end(); eit != eitEnd; ++eit){ - const char* sz = (*eit).szStart; - - frames.push_back(CameraAnimFrameDesc()); - CameraAnimFrameDesc& cur = frames.back(); - AI_MD5_READ_TRIPLE(cur.vPositionXYZ); - AI_MD5_READ_TRIPLE(cur.vRotationQuat); - AI_MD5_SKIP_SPACES(); - cur.fFOV = fast_atof(sz); - } - } - } - DefaultLogger::get()->debug("MD5CameraParser end"); -} - diff --git a/3rdparty/assimp/code/MD5Parser.h b/3rdparty/assimp/code/MD5Parser.h deleted file mode 100644 index afb5db8e..00000000 --- a/3rdparty/assimp/code/MD5Parser.h +++ /dev/null @@ -1,460 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MD5Parser.h - * @brief Definition of the .MD5 parser class. - * http://www.modwiki.net/wiki/MD5_(file_format) - */ -#ifndef AI_MD5PARSER_H_INCLUDED -#define AI_MD5PARSER_H_INCLUDED - -#include "../include/aiTypes.h" -#include "ParsingUtils.h" - -struct aiFace; - -namespace Assimp { -namespace MD5 { - -// --------------------------------------------------------------------------- -/** Represents a single element in a MD5 file - * - * Elements are always contained in sections. -*/ -struct Element -{ - //! Points to the starting point of the element - //! Whitespace at the beginning and at the end have been removed, - //! Elements are terminated with \0 - char* szStart; - - //! Original line number (can be used in error messages - //! if a parsing error occurs) - unsigned int iLineNumber; -}; - -typedef std::vector< Element > ElementList; - -// --------------------------------------------------------------------------- -/** Represents a section of a MD5 file (such as the mesh or the joints section) - * - * A section is always enclosed in { and } brackets. -*/ -struct Section -{ - //! Original line number (can be used in error messages - //! if a parsing error occurs) - unsigned int iLineNumber; - - //! List of all elements which have been parsed in this section. - ElementList mElements; - - //! Name of the section - std::string mName; - - //! For global elements: the value of the element as string - //! Iif !length() the section is not a global element - std::string mGlobalValue; -}; - -typedef std::vector< Section> SectionList; - -// --------------------------------------------------------------------------- -/** Basic information about a joint -*/ -struct BaseJointDescription -{ - //! Name of the bone - aiString mName; - - //! Parent index of the bone - int mParentIndex; -}; - -// --------------------------------------------------------------------------- -/** Represents a bone (joint) descriptor in a MD5Mesh file -*/ -struct BoneDesc : BaseJointDescription -{ - //! Absolute position of the bone - aiVector3D mPositionXYZ; - - //! Absolute rotation of the bone - aiVector3D mRotationQuat; - aiQuaternion mRotationQuatConverted; - - //! Absolute transformation of the bone - //! (temporary) - aiMatrix4x4 mTransform; - - //! Inverse transformation of the bone - //! (temporary) - aiMatrix4x4 mInvTransform; - - //! Internal - unsigned int mMap; -}; - -typedef std::vector< BoneDesc > BoneList; - -// --------------------------------------------------------------------------- -/** Represents a bone (joint) descriptor in a MD5Anim file -*/ -struct AnimBoneDesc : BaseJointDescription -{ - //! Flags (AI_MD5_ANIMATION_FLAG_xxx) - unsigned int iFlags; - - //! Index of the first key that corresponds to this anim bone - unsigned int iFirstKeyIndex; -}; - -typedef std::vector< AnimBoneDesc > AnimBoneList; - - -// --------------------------------------------------------------------------- -/** Represents a base frame descriptor in a MD5Anim file -*/ -struct BaseFrameDesc -{ - aiVector3D vPositionXYZ; - aiVector3D vRotationQuat; -}; - -typedef std::vector< BaseFrameDesc > BaseFrameList; - -// --------------------------------------------------------------------------- -/** Represents a camera animation frame in a MDCamera file -*/ -struct CameraAnimFrameDesc : BaseFrameDesc -{ - float fFOV; -}; - -typedef std::vector< CameraAnimFrameDesc > CameraFrameList; - -// --------------------------------------------------------------------------- -/** Represents a frame descriptor in a MD5Anim file -*/ -struct FrameDesc -{ - //! Index of the frame - unsigned int iIndex; - - //! Animation keyframes - a large blob of data at first - std::vector< float > mValues; -}; - -typedef std::vector< FrameDesc > FrameList; - -// --------------------------------------------------------------------------- -/** Represents a vertex descriptor in a MD5 file -*/ -struct VertexDesc -{ - VertexDesc() - : mFirstWeight (0) - , mNumWeights (0) - {} - - //! UV cordinate of the vertex - aiVector2D mUV; - - //! Index of the first weight of the vertex in - //! the vertex weight list - unsigned int mFirstWeight; - - //! Number of weights assigned to this vertex - unsigned int mNumWeights; -}; - -typedef std::vector< VertexDesc > VertexList; - -// --------------------------------------------------------------------------- -/** Represents a vertex weight descriptor in a MD5 file -*/ -struct WeightDesc -{ - //! Index of the bone to which this weight refers - unsigned int mBone; - - //! The weight value - float mWeight; - - //! The offset position of this weight - // ! (in the coordinate system defined by the parent bone) - aiVector3D vOffsetPosition; -}; - -typedef std::vector< WeightDesc > WeightList; -typedef std::vector< aiFace > FaceList; - -// --------------------------------------------------------------------------- -/** Represents a mesh in a MD5 file -*/ -struct MeshDesc -{ - //! Weights of the mesh - WeightList mWeights; - - //! Vertices of the mesh - VertexList mVertices; - - //! Faces of the mesh - FaceList mFaces; - - //! Name of the shader (=texture) to be assigned to the mesh - aiString mShader; -}; - -typedef std::vector< MeshDesc > MeshList; - -// --------------------------------------------------------------------------- -// Convert a quaternion to its usual representation -inline void ConvertQuaternion (const aiVector3D& in, aiQuaternion& out) { - - out.x = in.x; - out.y = in.y; - out.z = in.z; - - const float t = 1.0f - (in.x*in.x) - (in.y*in.y) - (in.z*in.z); - - if (t < 0.0f) - out.w = 0.0f; - else out.w = sqrt (t); -} - -// --------------------------------------------------------------------------- -/** Parses the data sections of a MD5 mesh file -*/ -class MD5MeshParser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5MeshParser instance from an existing - * preparsed list of file sections. - * - * @param mSections List of file sections (output of MD5Parser) - */ - MD5MeshParser(SectionList& mSections); - - //! List of all meshes - MeshList mMeshes; - - //! List of all joints - BoneList mJoints; -}; - -// remove this flag if you need to the bounding box data -#define AI_MD5_PARSE_NO_BOUNDS - -// --------------------------------------------------------------------------- -/** Parses the data sections of a MD5 animation file -*/ -class MD5AnimParser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5AnimParser instance from an existing - * preparsed list of file sections. - * - * @param mSections List of file sections (output of MD5Parser) - */ - MD5AnimParser(SectionList& mSections); - - - //! Output frame rate - float fFrameRate; - - //! List of animation bones - AnimBoneList mAnimatedBones; - - //! List of base frames - BaseFrameList mBaseFrames; - - //! List of animation frames - FrameList mFrames; - - //! Number of animated components - unsigned int mNumAnimatedComponents; -}; - -// --------------------------------------------------------------------------- -/** Parses the data sections of a MD5 camera animation file -*/ -class MD5CameraParser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5CameraParser instance from an existing - * preparsed list of file sections. - * - * @param mSections List of file sections (output of MD5Parser) - */ - MD5CameraParser(SectionList& mSections); - - - //! Output frame rate - float fFrameRate; - - //! List of cuts - std::vector<unsigned int> cuts; - - //! Frames - CameraFrameList frames; -}; - -// --------------------------------------------------------------------------- -/** Parses the block structure of MD5MESH and MD5ANIM files (but does no - * further processing) -*/ -class MD5Parser -{ -public: - - // ------------------------------------------------------------------- - /** Constructs a new MD5Parser instance from an existing buffer. - * - * @param buffer File buffer - * @param fileSize Length of the file in bytes (excluding a terminal 0) - */ - MD5Parser(char* buffer, unsigned int fileSize); - - - // ------------------------------------------------------------------- - /** Report a specific error message and throw an exception - * @param error Error message to be reported - * @param line Index of the line where the error occured - */ - static void ReportError (const char* error, unsigned int line); - - // ------------------------------------------------------------------- - /** Report a specific warning - * @param warn Warn message to be reported - * @param line Index of the line where the error occured - */ - static void ReportWarning (const char* warn, unsigned int line); - - - void ReportError (const char* error) { - return ReportError(error, lineNumber); - } - - void ReportWarning (const char* warn) { - return ReportWarning(warn, lineNumber); - } - -public: - - //! List of all sections which have been read - SectionList mSections; - -private: - - // ------------------------------------------------------------------- - /** Parses a file section. The current file pointer must be outside - * of a section. - * @param out Receives the section data - * @return true if the end of the file has been reached - * @throws ImportErrorException if an error occurs - */ - bool ParseSection(Section& out); - - // ------------------------------------------------------------------- - /** Parses the file header - * @throws ImportErrorException if an error occurs - */ - void ParseHeader(); - - - // override these functions to make sure the line counter gets incremented - // ------------------------------------------------------------------- - bool SkipLine( const char* in, const char** out) - { - ++lineNumber; - return Assimp::SkipLine(in,out); - } - // ------------------------------------------------------------------- - bool SkipLine( ) - { - return SkipLine(buffer,(const char**)&buffer); - } - // ------------------------------------------------------------------- - bool SkipSpacesAndLineEnd( const char* in, const char** out) - { - bool bHad = false; - bool running = true; - while (running) { - if ( *in == '\r' || *in == '\n') { - // we open files in binary mode, so there could be \r\n sequences ... - if (!bHad) { - bHad = true; - ++lineNumber; - } - } - else if (*in == '\t' || *in == ' ')bHad = false; - else break; - in++; - } - *out = in; - return *in != '\0'; - } - // ------------------------------------------------------------------- - bool SkipSpacesAndLineEnd( ) - { - return SkipSpacesAndLineEnd(buffer,(const char**)&buffer); - } - // ------------------------------------------------------------------- - bool SkipSpaces( ) - { - return Assimp::SkipSpaces((const char**)&buffer); - } - - char* buffer; - unsigned int fileSize; - unsigned int lineNumber; -}; -}} - -#endif // AI_MD5PARSER_H_INCLUDED diff --git a/3rdparty/assimp/code/MDCFileData.h b/3rdparty/assimp/code/MDCFileData.h deleted file mode 100644 index 6c33880c..00000000 --- a/3rdparty/assimp/code/MDCFileData.h +++ /dev/null @@ -1,199 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the helper data structures for importing MDC files - -********************************************************************** -File format specification: -http://themdcfile.planetwolfenstein.gamespy.com/MDC_File_Format.pdf -********************************************************************** - -*/ -#ifndef AI_MDCFILEHELPER_H_INC -#define AI_MDCFILEHELPER_H_INC - -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include "../include/aiAnim.h" - -#include "./../include/Compiler/pushpack1.h" - - -namespace Assimp { -namespace MDC { - - -// to make it easier for us, we test the magic word against both "endianesses" -#define AI_MDC_MAGIC_NUMBER_BE AI_MAKE_MAGIC("CPDI") -#define AI_MDC_MAGIC_NUMBER_LE AI_MAKE_MAGIC("IDPC") - -// common limitations -#define AI_MDC_VERSION 2 -#define AI_MDC_MAXQPATH 64 -#define AI_MDC_MAX_BONES 128 - -#define AI_MDC_CVERT_BIAS 127.0f -#define AI_MDC_DELTA_SCALING 4.0f -#define AI_MDC_BASE_SCALING (1.0f / 64.0f) - - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC file's main header - */ -struct Header -{ - uint32_t ulIdent ; - uint32_t ulVersion ; - char ucName [ AI_MDC_MAXQPATH ] ; - uint32_t ulFlags ; - uint32_t ulNumFrames ; - uint32_t ulNumTags ; - uint32_t ulNumSurfaces ; - uint32_t ulNumSkins ; - uint32_t ulOffsetBorderFrames ; - uint32_t ulOffsetTagNames ; - uint32_t ulOffsetTagFrames ; - uint32_t ulOffsetSurfaces ; - uint32_t ulOffsetEnd ; -} PACK_STRUCT ; - - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC file's surface header - */ -struct Surface -{ - uint32_t ulIdent ; - char ucName [ AI_MDC_MAXQPATH ] ; - uint32_t ulFlags ; - uint32_t ulNumCompFrames ; - uint32_t ulNumBaseFrames ; - uint32_t ulNumShaders ; - uint32_t ulNumVertices ; - uint32_t ulNumTriangles ; - uint32_t ulOffsetTriangles ; - uint32_t ulOffsetShaders ; - uint32_t ulOffsetTexCoords ; - uint32_t ulOffsetBaseVerts ; - uint32_t ulOffsetCompVerts ; - uint32_t ulOffsetFrameBaseFrames ; - uint32_t ulOffsetFrameCompFrames ; - uint32_t ulOffsetEnd ; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC frame - */ -struct Frame -{ - //! bounding box minimum coords - aiVector3D bboxMin ; - - //! bounding box maximum coords - aiVector3D bboxMax ; - - //! local origin of the frame - aiVector3D localOrigin ; - - //! radius of the BB - float radius ; - - //! Name of the frame - char name [ 16 ] ; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC triangle - */ -struct Triangle -{ - uint32_t aiIndices[3]; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC texture coordinate - */ -struct TexturCoord -{ - float u,v; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC base vertex - */ -struct BaseVertex -{ - int16_t x,y,z; - uint16_t normal; -} PACK_STRUCT; - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC compressed vertex - */ -struct CompressedVertex -{ - uint8_t xd,yd,zd,nd; -} PACK_STRUCT; - - -// --------------------------------------------------------------------------- -/** \brief Data structure for a MDC shader - */ -struct Shader -{ - char ucName [ AI_MDC_MAXQPATH ] ; - uint32_t ulPath; - -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - - -// --------------------------------------------------------------------------- -/** Build a floating point vertex from the compressed data in MDC files - */ -void BuildVertex(const Frame& frame, - const BaseVertex& bvert, - const CompressedVertex& cvert, - aiVector3D& vXYZOut, - aiVector3D& vNorOut); -}} - -#endif // !! AI_MDCFILEHELPER_H_INC diff --git a/3rdparty/assimp/code/MDCLoader.cpp b/3rdparty/assimp/code/MDCLoader.cpp deleted file mode 100644 index 9e022cf1..00000000 --- a/3rdparty/assimp/code/MDCLoader.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MDC importer class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MDC_IMPORTER - -// internal headers -#include "MDCLoader.h" -#include "MD3FileData.h" -#include "MDCNormalTable.h" // shouldn't be included by other units - -using namespace Assimp; -using namespace Assimp::MDC; - - -// ------------------------------------------------------------------------------------------------ -void MDC::BuildVertex(const Frame& frame, - const BaseVertex& bvert, - const CompressedVertex& cvert, - aiVector3D& vXYZOut, - aiVector3D& vNorOut) -{ - // compute the position - const float xd = (cvert.xd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING; - const float yd = (cvert.yd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING; - const float zd = (cvert.zd - AI_MDC_CVERT_BIAS) * AI_MDC_DELTA_SCALING; - vXYZOut.x = frame.localOrigin.x + AI_MDC_BASE_SCALING * (bvert.x + xd); - vXYZOut.y = frame.localOrigin.y + AI_MDC_BASE_SCALING * (bvert.y + yd); - vXYZOut.z = frame.localOrigin.z + AI_MDC_BASE_SCALING * (bvert.z + zd); - - // compute the normal vector .. ehm ... lookup it in the table :-) - vNorOut.x = mdcNormals[cvert.nd][0]; - vNorOut.y = mdcNormals[cvert.nd][1]; - vNorOut.z = mdcNormals[cvert.nd][2]; -} - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MDCImporter::MDCImporter() -{ -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MDCImporter::~MDCImporter() -{ -} -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MDCImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - if (extension == "mdc") - return true; - - // if check for extension is not enough, check for the magic tokens - if (!extension.length() || checkSig) { - uint32_t tokens[1]; - tokens[0] = AI_MDC_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void MDCImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("mdc"); -} - -// ------------------------------------------------------------------------------------------------ -// Validate the header of the given MDC file -void MDCImporter::ValidateHeader() -{ - AI_SWAP4( this->pcHeader->ulVersion ); - AI_SWAP4( this->pcHeader->ulFlags ); - AI_SWAP4( this->pcHeader->ulNumFrames ); - AI_SWAP4( this->pcHeader->ulNumTags ); - AI_SWAP4( this->pcHeader->ulNumSurfaces ); - AI_SWAP4( this->pcHeader->ulNumSkins ); - AI_SWAP4( this->pcHeader->ulOffsetBorderFrames ); - - if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE && - pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) - { - char szBuffer[5]; - szBuffer[0] = ((char*)&pcHeader->ulIdent)[0]; - szBuffer[1] = ((char*)&pcHeader->ulIdent)[1]; - szBuffer[2] = ((char*)&pcHeader->ulIdent)[2]; - szBuffer[3] = ((char*)&pcHeader->ulIdent)[3]; - szBuffer[4] = '\0'; - - throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the " - "magic word found is " + std::string( szBuffer )); - } - - if (pcHeader->ulVersion != AI_MDC_VERSION) - DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)"); - - if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize || - pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize) - { - throw DeadlyImportError("Some of the offset values in the MDC header are invalid " - "and point to something behind the file."); - } - - if (this->configFrameID >= this->pcHeader->ulNumFrames) - throw DeadlyImportError("The requested frame is not available"); -} - -// ------------------------------------------------------------------------------------------------ -// Validate the header of a given MDC file surface -void MDCImporter::ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf) -{ - AI_SWAP4(pcSurf->ulFlags); - AI_SWAP4(pcSurf->ulNumCompFrames); - AI_SWAP4(pcSurf->ulNumBaseFrames); - AI_SWAP4(pcSurf->ulNumShaders); - AI_SWAP4(pcSurf->ulNumVertices); - AI_SWAP4(pcSurf->ulNumTriangles); - AI_SWAP4(pcSurf->ulOffsetTriangles); - AI_SWAP4(pcSurf->ulOffsetTexCoords); - AI_SWAP4(pcSurf->ulOffsetBaseVerts); - AI_SWAP4(pcSurf->ulOffsetCompVerts); - AI_SWAP4(pcSurf->ulOffsetFrameBaseFrames); - AI_SWAP4(pcSurf->ulOffsetFrameCompFrames); - AI_SWAP4(pcSurf->ulOffsetEnd); - - const unsigned int iMax = this->fileSize - (unsigned int)((int8_t*)pcSurf-(int8_t*)pcHeader); - - if (pcSurf->ulOffsetBaseVerts + pcSurf->ulNumVertices * sizeof(MDC::BaseVertex) > iMax || - (pcSurf->ulNumCompFrames && pcSurf->ulOffsetCompVerts + pcSurf->ulNumVertices * sizeof(MDC::CompressedVertex) > iMax) || - pcSurf->ulOffsetTriangles + pcSurf->ulNumTriangles * sizeof(MDC::Triangle) > iMax || - pcSurf->ulOffsetTexCoords + pcSurf->ulNumVertices * sizeof(MDC::TexturCoord) > iMax || - pcSurf->ulOffsetShaders + pcSurf->ulNumShaders * sizeof(MDC::Shader) > iMax || - pcSurf->ulOffsetFrameBaseFrames + pcSurf->ulNumBaseFrames * 2 > iMax || - (pcSurf->ulNumCompFrames && pcSurf->ulOffsetFrameCompFrames + pcSurf->ulNumCompFrames * 2 > iMax)) - { - throw DeadlyImportError("Some of the offset values in the MDC surface header " - "are invalid and point somewhere behind the file."); - } -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void MDCImporter::SetupProperties(const Importer* pImp) -{ - // The AI_CONFIG_IMPORT_MDC_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - if (0xffffffff == (this->configFrameID = pImp->GetPropertyInteger( - AI_CONFIG_IMPORT_MDC_KEYFRAME,0xffffffff))) - { - this->configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MDCImporter::InternReadFile( - const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open MDC file " + pFile + "."); - - // check whether the mdc file is large enough to contain the file header - fileSize = (unsigned int)file->FileSize(); - if ( fileSize < sizeof(MDC::Header)) - throw DeadlyImportError( "MDC File is too small."); - - std::vector<unsigned char> mBuffer2(fileSize); - file->Read( &mBuffer2[0], 1, fileSize); - mBuffer = &mBuffer2[0]; - - // validate the file header - this->pcHeader = (BE_NCONST MDC::Header*)this->mBuffer; - this->ValidateHeader(); - - std::vector<std::string> aszShaders; - - // get a pointer to the frame we want to read - BE_NCONST MDC::Frame* pcFrame = (BE_NCONST MDC::Frame*)(this->mBuffer+ - this->pcHeader->ulOffsetBorderFrames); - - // no need to swap the other members, we won't need them - pcFrame += configFrameID; - AI_SWAP4( pcFrame->localOrigin[0] ); - AI_SWAP4( pcFrame->localOrigin[1] ); - AI_SWAP4( pcFrame->localOrigin[2] ); - - // get the number of valid surfaces - BE_NCONST MDC::Surface* pcSurface, *pcSurface2; - pcSurface = pcSurface2 = (BE_NCONST MDC::Surface*)(mBuffer + pcHeader->ulOffsetSurfaces); - unsigned int iNumShaders = 0; - for (unsigned int i = 0; i < pcHeader->ulNumSurfaces;++i) - { - // validate the surface header - this->ValidateSurfaceHeader(pcSurface2); - - if (pcSurface2->ulNumVertices && pcSurface2->ulNumTriangles)++pScene->mNumMeshes; - iNumShaders += pcSurface2->ulNumShaders; - pcSurface2 = (BE_NCONST MDC::Surface*)((int8_t*)pcSurface2 + pcSurface2->ulOffsetEnd); - } - aszShaders.reserve(iNumShaders); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - - // necessary that we don't crash if an exception occurs - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mMeshes[i] = NULL; - - // now read all surfaces - unsigned int iDefaultMatIndex = 0xffffffff; - for (unsigned int i = 0, iNum = 0; i < pcHeader->ulNumSurfaces;++i) - { - if (!pcSurface->ulNumVertices || !pcSurface->ulNumTriangles)continue; - aiMesh* pcMesh = pScene->mMeshes[iNum++] = new aiMesh(); - - pcMesh->mNumFaces = pcSurface->ulNumTriangles; - pcMesh->mNumVertices = pcMesh->mNumFaces * 3; - - // store the name of the surface for use as node name. - // FIX: make sure there is a 0 termination - const_cast<char&>(pcSurface->ucName[AI_MDC_MAXQPATH-1]) = '\0'; - pcMesh->mTextureCoords[3] = (aiVector3D*)pcSurface->ucName; - - // go to the first shader in the file. ignore the others. - if (pcSurface->ulNumShaders) - { - const MDC::Shader* pcShader = (const MDC::Shader*)((int8_t*)pcSurface + pcSurface->ulOffsetShaders); - pcMesh->mMaterialIndex = (unsigned int)aszShaders.size(); - - // create a new shader - aszShaders.push_back(std::string( pcShader->ucName, std::min( - ::strlen(pcShader->ucName),sizeof(pcShader->ucName)) )); - } - // need to create a default material - else if (0xffffffff == iDefaultMatIndex) - { - pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size(); - aszShaders.push_back(std::string()); - } - // otherwise assign a reference to the default material - else pcMesh->mMaterialIndex = iDefaultMatIndex; - - // allocate output storage for the mesh - aiVector3D* pcVertCur = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcNorCur = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcUVCur = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - aiFace* pcFaceCur = pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - - // create all vertices/faces - BE_NCONST MDC::Triangle* pcTriangle = (BE_NCONST MDC::Triangle*) - ((int8_t*)pcSurface+pcSurface->ulOffsetTriangles); - - BE_NCONST MDC::TexturCoord* const pcUVs = (BE_NCONST MDC::TexturCoord*) - ((int8_t*)pcSurface+pcSurface->ulOffsetTexCoords); - - // get a pointer to the uncompressed vertices - int16_t iOfs = *((int16_t*) ((int8_t*) pcSurface + - pcSurface->ulOffsetFrameBaseFrames) + this->configFrameID); - - AI_SWAP2(iOfs); - - BE_NCONST MDC::BaseVertex* const pcVerts = (BE_NCONST MDC::BaseVertex*) - ((int8_t*)pcSurface+pcSurface->ulOffsetBaseVerts) + - ((int)iOfs * pcSurface->ulNumVertices * 4); - - // do the main swapping stuff ... -#if (defined AI_BUILD_BIG_ENDIAN) - - // swap all triangles - for (unsigned int i = 0; i < pcSurface->ulNumTriangles;++i) - { - AI_SWAP4( pcTriangle[i].aiIndices[0] ); - AI_SWAP4( pcTriangle[i].aiIndices[1] ); - AI_SWAP4( pcTriangle[i].aiIndices[2] ); - } - - // swap all vertices - for (unsigned int i = 0; i < pcSurface->ulNumVertices*pcSurface->ulNumBaseFrames;++i) - { - AI_SWAP2( pcVerts->normal ); - AI_SWAP2( pcVerts->x ); - AI_SWAP2( pcVerts->y ); - AI_SWAP2( pcVerts->z ); - } - - // swap all texture coordinates - for (unsigned int i = 0; i < pcSurface->ulNumVertices;++i) - { - AI_SWAP4( pcUVs->v ); - AI_SWAP4( pcUVs->v ); - } - -#endif - - const MDC::CompressedVertex* pcCVerts = NULL; - int16_t* mdcCompVert = NULL; - - // access compressed frames for large frame numbers, but never for the first - if ( this->configFrameID && pcSurface->ulNumCompFrames > 0 ) - { - mdcCompVert = (int16_t*) ((int8_t*)pcSurface+pcSurface->ulOffsetFrameCompFrames) + this->configFrameID; - AI_SWAP2P(mdcCompVert); - if ( *mdcCompVert >= 0 ) - { - pcCVerts = (const MDC::CompressedVertex*)((int8_t*)pcSurface + - pcSurface->ulOffsetCompVerts) + *mdcCompVert * pcSurface->ulNumVertices; - } - else mdcCompVert = NULL; - } - - // copy all faces - for (unsigned int iFace = 0; iFace < pcSurface->ulNumTriangles;++iFace, - ++pcTriangle,++pcFaceCur) - { - const unsigned int iOutIndex = iFace*3; - pcFaceCur->mNumIndices = 3; - pcFaceCur->mIndices = new unsigned int[3]; - - for (unsigned int iIndex = 0; iIndex < 3;++iIndex, - ++pcVertCur,++pcUVCur,++pcNorCur) - { - uint32_t quak = pcTriangle->aiIndices[iIndex]; - if (quak >= pcSurface->ulNumVertices) - { - DefaultLogger::get()->error("MDC vertex index is out of range"); - quak = pcSurface->ulNumVertices-1; - } - - // compressed vertices? - if (mdcCompVert) - { - MDC::BuildVertex(*pcFrame,pcVerts[quak],pcCVerts[quak], - *pcVertCur,*pcNorCur); - } - else - { - // copy position - pcVertCur->x = pcVerts[quak].x * AI_MDC_BASE_SCALING; - pcVertCur->y = pcVerts[quak].y * AI_MDC_BASE_SCALING; - pcVertCur->z = pcVerts[quak].z * AI_MDC_BASE_SCALING; - - // copy normals - MD3::LatLngNormalToVec3( pcVerts[quak].normal, &pcNorCur->x ); - - // copy texture coordinates - pcUVCur->x = pcUVs[quak].u; - pcUVCur->y = 1.0f-pcUVs[quak].v; // DX to OGL - } - pcVertCur->x += pcFrame->localOrigin[0] ; - pcVertCur->y += pcFrame->localOrigin[1] ; - pcVertCur->z += pcFrame->localOrigin[2] ; - } - - // swap the face order - DX to OGL - pcFaceCur->mIndices[0] = iOutIndex + 2; - pcFaceCur->mIndices[1] = iOutIndex + 1; - pcFaceCur->mIndices[2] = iOutIndex + 0; - } - - pcSurface = (BE_NCONST MDC::Surface*)((int8_t*)pcSurface + pcSurface->ulOffsetEnd); - } - - // create a flat node graph with a root node and one child for each surface - if (!pScene->mNumMeshes) - throw DeadlyImportError( "Invalid MDC file: File contains no valid mesh"); - else if (1 == pScene->mNumMeshes) - { - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set(std::string((const char*)pScene->mMeshes[0]->mTextureCoords[3])); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - } - else - { - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumChildren = pScene->mNumMeshes; - pScene->mRootNode->mChildren = new aiNode*[pScene->mNumMeshes]; - pScene->mRootNode->mName.Set("<root>"); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - aiNode* pcNode = pScene->mRootNode->mChildren[i] = new aiNode(); - pcNode->mParent = pScene->mRootNode; - pcNode->mName.Set(std::string((const char*)pScene->mMeshes[i]->mTextureCoords[3])); - pcNode->mNumMeshes = 1; - pcNode->mMeshes = new unsigned int[1]; - pcNode->mMeshes[0] = i; - } - } - - // make sure we invalidate the pointer to the mesh name - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mMeshes[i]->mTextureCoords[3] = NULL; - - // create materials - pScene->mNumMaterials = (unsigned int)aszShaders.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { - MaterialHelper* pcMat = new MaterialHelper(); - pScene->mMaterials[i] = pcMat; - - const std::string& name = aszShaders[i]; - - int iMode = (int)aiShadingMode_Gouraud; - pcMat->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - // add a small ambient color value - RtCW seems to have one - aiColor3D clr; - clr.b = clr.g = clr.r = 0.05f; - pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - if (name.length())clr.b = clr.g = clr.r = 1.0f; - else clr.b = clr.g = clr.r = 0.6f; - - pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcMat->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - if (name.length()) - { - aiString path; - path.Set(name); - pcMat->AddProperty(&path,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - } -} - -#endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER diff --git a/3rdparty/assimp/code/MDCLoader.h b/3rdparty/assimp/code/MDCLoader.h deleted file mode 100644 index f97efc73..00000000 --- a/3rdparty/assimp/code/MDCLoader.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MDCLoader.h - * @brief Definition of the MDC importer class. - */ -#ifndef AI_MDCLOADER_H_INCLUDED -#define AI_MDCLOADER_H_INCLUDED - -#include "../include/aiTypes.h" - -#include "BaseImporter.h" -#include "MDCFileData.h" -#include "ByteSwap.h" - -namespace Assimp { -using namespace MDC; - -// --------------------------------------------------------------------------- -/** Importer class to load the RtCW MDC file format -*/ -class MDCImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - MDCImporter(); - - /** Destructor, private as well */ - ~MDCImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - - - // ------------------------------------------------------------------- - /** Validate the header of the file - */ - void ValidateHeader(); - - // ------------------------------------------------------------------- - /** Validate the header of a MDC surface - */ - void ValidateSurfaceHeader(BE_NCONST MDC::Surface* pcSurf); - -protected: - - - /** Configuration option: frame to be loaded */ - unsigned int configFrameID; - - /** Header of the MDC file */ - BE_NCONST MDC::Header* pcHeader; - - /** Buffer to hold the loaded file */ - unsigned char* mBuffer; - - /** size of the file, in bytes */ - unsigned int fileSize; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC - diff --git a/3rdparty/assimp/code/MDCNormalTable.h b/3rdparty/assimp/code/MDCNormalTable.h deleted file mode 100644 index f47e97f3..00000000 --- a/3rdparty/assimp/code/MDCNormalTable.h +++ /dev/null @@ -1,299 +0,0 @@ -/* ----------------------------------------------------------------------------- - -PicoModel Library - -Copyright (c) 2002, Randy Reddig & seaw0lf -All rights reserved. - -Redistribution and use 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 names of the copyright holders nor the names of its contributors may -be used to endorse or promote products derived from this software without -specific prior written permission. - -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. - ------------------------------------------------------------------------------ */ - -#if (!defined MDC_NORMAL_TABLE_INCLUDED) -#define MDC_NORMAL_TABLE_INCLUDED - -/* mdc decoding normal table */ -float mdcNormals[ 256 ][ 3 ] = -{ - { 1.000000f, 0.000000f, 0.000000f }, - { 0.980785f, 0.195090f, 0.000000f }, - { 0.923880f, 0.382683f, 0.000000f }, - { 0.831470f, 0.555570f, 0.000000f }, - { 0.707107f, 0.707107f, 0.000000f }, - { 0.555570f, 0.831470f, 0.000000f }, - { 0.382683f, 0.923880f, 0.000000f }, - { 0.195090f, 0.980785f, 0.000000f }, - { -0.000000f, 1.000000f, 0.000000f }, - { -0.195090f, 0.980785f, 0.000000f }, - { -0.382683f, 0.923880f, 0.000000f }, - { -0.555570f, 0.831470f, 0.000000f }, - { -0.707107f, 0.707107f, 0.000000f }, - { -0.831470f, 0.555570f, 0.000000f }, - { -0.923880f, 0.382683f, 0.000000f }, - { -0.980785f, 0.195090f, 0.000000f }, - { -1.000000f, -0.000000f, 0.000000f }, - { -0.980785f, -0.195090f, 0.000000f }, - { -0.923880f, -0.382683f, 0.000000f }, - { -0.831470f, -0.555570f, 0.000000f }, - { -0.707107f, -0.707107f, 0.000000f }, - { -0.555570f, -0.831469f, 0.000000f }, - { -0.382684f, -0.923880f, 0.000000f }, - { -0.195090f, -0.980785f, 0.000000f }, - { 0.000000f, -1.000000f, 0.000000f }, - { 0.195090f, -0.980785f, 0.000000f }, - { 0.382684f, -0.923879f, 0.000000f }, - { 0.555570f, -0.831470f, 0.000000f }, - { 0.707107f, -0.707107f, 0.000000f }, - { 0.831470f, -0.555570f, 0.000000f }, - { 0.923880f, -0.382683f, 0.000000f }, - { 0.980785f, -0.195090f, 0.000000f }, - { 0.980785f, 0.000000f, -0.195090f }, - { 0.956195f, 0.218245f, -0.195090f }, - { 0.883657f, 0.425547f, -0.195090f }, - { 0.766809f, 0.611510f, -0.195090f }, - { 0.611510f, 0.766809f, -0.195090f }, - { 0.425547f, 0.883657f, -0.195090f }, - { 0.218245f, 0.956195f, -0.195090f }, - { -0.000000f, 0.980785f, -0.195090f }, - { -0.218245f, 0.956195f, -0.195090f }, - { -0.425547f, 0.883657f, -0.195090f }, - { -0.611510f, 0.766809f, -0.195090f }, - { -0.766809f, 0.611510f, -0.195090f }, - { -0.883657f, 0.425547f, -0.195090f }, - { -0.956195f, 0.218245f, -0.195090f }, - { -0.980785f, -0.000000f, -0.195090f }, - { -0.956195f, -0.218245f, -0.195090f }, - { -0.883657f, -0.425547f, -0.195090f }, - { -0.766809f, -0.611510f, -0.195090f }, - { -0.611510f, -0.766809f, -0.195090f }, - { -0.425547f, -0.883657f, -0.195090f }, - { -0.218245f, -0.956195f, -0.195090f }, - { 0.000000f, -0.980785f, -0.195090f }, - { 0.218245f, -0.956195f, -0.195090f }, - { 0.425547f, -0.883657f, -0.195090f }, - { 0.611510f, -0.766809f, -0.195090f }, - { 0.766809f, -0.611510f, -0.195090f }, - { 0.883657f, -0.425547f, -0.195090f }, - { 0.956195f, -0.218245f, -0.195090f }, - { 0.923880f, 0.000000f, -0.382683f }, - { 0.892399f, 0.239118f, -0.382683f }, - { 0.800103f, 0.461940f, -0.382683f }, - { 0.653281f, 0.653281f, -0.382683f }, - { 0.461940f, 0.800103f, -0.382683f }, - { 0.239118f, 0.892399f, -0.382683f }, - { -0.000000f, 0.923880f, -0.382683f }, - { -0.239118f, 0.892399f, -0.382683f }, - { -0.461940f, 0.800103f, -0.382683f }, - { -0.653281f, 0.653281f, -0.382683f }, - { -0.800103f, 0.461940f, -0.382683f }, - { -0.892399f, 0.239118f, -0.382683f }, - { -0.923880f, -0.000000f, -0.382683f }, - { -0.892399f, -0.239118f, -0.382683f }, - { -0.800103f, -0.461940f, -0.382683f }, - { -0.653282f, -0.653281f, -0.382683f }, - { -0.461940f, -0.800103f, -0.382683f }, - { -0.239118f, -0.892399f, -0.382683f }, - { 0.000000f, -0.923880f, -0.382683f }, - { 0.239118f, -0.892399f, -0.382683f }, - { 0.461940f, -0.800103f, -0.382683f }, - { 0.653281f, -0.653282f, -0.382683f }, - { 0.800103f, -0.461940f, -0.382683f }, - { 0.892399f, -0.239117f, -0.382683f }, - { 0.831470f, 0.000000f, -0.555570f }, - { 0.790775f, 0.256938f, -0.555570f }, - { 0.672673f, 0.488726f, -0.555570f }, - { 0.488726f, 0.672673f, -0.555570f }, - { 0.256938f, 0.790775f, -0.555570f }, - { -0.000000f, 0.831470f, -0.555570f }, - { -0.256938f, 0.790775f, -0.555570f }, - { -0.488726f, 0.672673f, -0.555570f }, - { -0.672673f, 0.488726f, -0.555570f }, - { -0.790775f, 0.256938f, -0.555570f }, - { -0.831470f, -0.000000f, -0.555570f }, - { -0.790775f, -0.256938f, -0.555570f }, - { -0.672673f, -0.488726f, -0.555570f }, - { -0.488725f, -0.672673f, -0.555570f }, - { -0.256938f, -0.790775f, -0.555570f }, - { 0.000000f, -0.831470f, -0.555570f }, - { 0.256938f, -0.790775f, -0.555570f }, - { 0.488725f, -0.672673f, -0.555570f }, - { 0.672673f, -0.488726f, -0.555570f }, - { 0.790775f, -0.256938f, -0.555570f }, - { 0.707107f, 0.000000f, -0.707107f }, - { 0.653281f, 0.270598f, -0.707107f }, - { 0.500000f, 0.500000f, -0.707107f }, - { 0.270598f, 0.653281f, -0.707107f }, - { -0.000000f, 0.707107f, -0.707107f }, - { -0.270598f, 0.653282f, -0.707107f }, - { -0.500000f, 0.500000f, -0.707107f }, - { -0.653281f, 0.270598f, -0.707107f }, - { -0.707107f, -0.000000f, -0.707107f }, - { -0.653281f, -0.270598f, -0.707107f }, - { -0.500000f, -0.500000f, -0.707107f }, - { -0.270598f, -0.653281f, -0.707107f }, - { 0.000000f, -0.707107f, -0.707107f }, - { 0.270598f, -0.653281f, -0.707107f }, - { 0.500000f, -0.500000f, -0.707107f }, - { 0.653282f, -0.270598f, -0.707107f }, - { 0.555570f, 0.000000f, -0.831470f }, - { 0.481138f, 0.277785f, -0.831470f }, - { 0.277785f, 0.481138f, -0.831470f }, - { -0.000000f, 0.555570f, -0.831470f }, - { -0.277785f, 0.481138f, -0.831470f }, - { -0.481138f, 0.277785f, -0.831470f }, - { -0.555570f, -0.000000f, -0.831470f }, - { -0.481138f, -0.277785f, -0.831470f }, - { -0.277785f, -0.481138f, -0.831470f }, - { 0.000000f, -0.555570f, -0.831470f }, - { 0.277785f, -0.481138f, -0.831470f }, - { 0.481138f, -0.277785f, -0.831470f }, - { 0.382683f, 0.000000f, -0.923880f }, - { 0.270598f, 0.270598f, -0.923880f }, - { -0.000000f, 0.382683f, -0.923880f }, - { -0.270598f, 0.270598f, -0.923880f }, - { -0.382683f, -0.000000f, -0.923880f }, - { -0.270598f, -0.270598f, -0.923880f }, - { 0.000000f, -0.382683f, -0.923880f }, - { 0.270598f, -0.270598f, -0.923880f }, - { 0.195090f, 0.000000f, -0.980785f }, - { -0.000000f, 0.195090f, -0.980785f }, - { -0.195090f, -0.000000f, -0.980785f }, - { 0.000000f, -0.195090f, -0.980785f }, - { 0.980785f, 0.000000f, 0.195090f }, - { 0.956195f, 0.218245f, 0.195090f }, - { 0.883657f, 0.425547f, 0.195090f }, - { 0.766809f, 0.611510f, 0.195090f }, - { 0.611510f, 0.766809f, 0.195090f }, - { 0.425547f, 0.883657f, 0.195090f }, - { 0.218245f, 0.956195f, 0.195090f }, - { -0.000000f, 0.980785f, 0.195090f }, - { -0.218245f, 0.956195f, 0.195090f }, - { -0.425547f, 0.883657f, 0.195090f }, - { -0.611510f, 0.766809f, 0.195090f }, - { -0.766809f, 0.611510f, 0.195090f }, - { -0.883657f, 0.425547f, 0.195090f }, - { -0.956195f, 0.218245f, 0.195090f }, - { -0.980785f, -0.000000f, 0.195090f }, - { -0.956195f, -0.218245f, 0.195090f }, - { -0.883657f, -0.425547f, 0.195090f }, - { -0.766809f, -0.611510f, 0.195090f }, - { -0.611510f, -0.766809f, 0.195090f }, - { -0.425547f, -0.883657f, 0.195090f }, - { -0.218245f, -0.956195f, 0.195090f }, - { 0.000000f, -0.980785f, 0.195090f }, - { 0.218245f, -0.956195f, 0.195090f }, - { 0.425547f, -0.883657f, 0.195090f }, - { 0.611510f, -0.766809f, 0.195090f }, - { 0.766809f, -0.611510f, 0.195090f }, - { 0.883657f, -0.425547f, 0.195090f }, - { 0.956195f, -0.218245f, 0.195090f }, - { 0.923880f, 0.000000f, 0.382683f }, - { 0.892399f, 0.239118f, 0.382683f }, - { 0.800103f, 0.461940f, 0.382683f }, - { 0.653281f, 0.653281f, 0.382683f }, - { 0.461940f, 0.800103f, 0.382683f }, - { 0.239118f, 0.892399f, 0.382683f }, - { -0.000000f, 0.923880f, 0.382683f }, - { -0.239118f, 0.892399f, 0.382683f }, - { -0.461940f, 0.800103f, 0.382683f }, - { -0.653281f, 0.653281f, 0.382683f }, - { -0.800103f, 0.461940f, 0.382683f }, - { -0.892399f, 0.239118f, 0.382683f }, - { -0.923880f, -0.000000f, 0.382683f }, - { -0.892399f, -0.239118f, 0.382683f }, - { -0.800103f, -0.461940f, 0.382683f }, - { -0.653282f, -0.653281f, 0.382683f }, - { -0.461940f, -0.800103f, 0.382683f }, - { -0.239118f, -0.892399f, 0.382683f }, - { 0.000000f, -0.923880f, 0.382683f }, - { 0.239118f, -0.892399f, 0.382683f }, - { 0.461940f, -0.800103f, 0.382683f }, - { 0.653281f, -0.653282f, 0.382683f }, - { 0.800103f, -0.461940f, 0.382683f }, - { 0.892399f, -0.239117f, 0.382683f }, - { 0.831470f, 0.000000f, 0.555570f }, - { 0.790775f, 0.256938f, 0.555570f }, - { 0.672673f, 0.488726f, 0.555570f }, - { 0.488726f, 0.672673f, 0.555570f }, - { 0.256938f, 0.790775f, 0.555570f }, - { -0.000000f, 0.831470f, 0.555570f }, - { -0.256938f, 0.790775f, 0.555570f }, - { -0.488726f, 0.672673f, 0.555570f }, - { -0.672673f, 0.488726f, 0.555570f }, - { -0.790775f, 0.256938f, 0.555570f }, - { -0.831470f, -0.000000f, 0.555570f }, - { -0.790775f, -0.256938f, 0.555570f }, - { -0.672673f, -0.488726f, 0.555570f }, - { -0.488725f, -0.672673f, 0.555570f }, - { -0.256938f, -0.790775f, 0.555570f }, - { 0.000000f, -0.831470f, 0.555570f }, - { 0.256938f, -0.790775f, 0.555570f }, - { 0.488725f, -0.672673f, 0.555570f }, - { 0.672673f, -0.488726f, 0.555570f }, - { 0.790775f, -0.256938f, 0.555570f }, - { 0.707107f, 0.000000f, 0.707107f }, - { 0.653281f, 0.270598f, 0.707107f }, - { 0.500000f, 0.500000f, 0.707107f }, - { 0.270598f, 0.653281f, 0.707107f }, - { -0.000000f, 0.707107f, 0.707107f }, - { -0.270598f, 0.653282f, 0.707107f }, - { -0.500000f, 0.500000f, 0.707107f }, - { -0.653281f, 0.270598f, 0.707107f }, - { -0.707107f, -0.000000f, 0.707107f }, - { -0.653281f, -0.270598f, 0.707107f }, - { -0.500000f, -0.500000f, 0.707107f }, - { -0.270598f, -0.653281f, 0.707107f }, - { 0.000000f, -0.707107f, 0.707107f }, - { 0.270598f, -0.653281f, 0.707107f }, - { 0.500000f, -0.500000f, 0.707107f }, - { 0.653282f, -0.270598f, 0.707107f }, - { 0.555570f, 0.000000f, 0.831470f }, - { 0.481138f, 0.277785f, 0.831470f }, - { 0.277785f, 0.481138f, 0.831470f }, - { -0.000000f, 0.555570f, 0.831470f }, - { -0.277785f, 0.481138f, 0.831470f }, - { -0.481138f, 0.277785f, 0.831470f }, - { -0.555570f, -0.000000f, 0.831470f }, - { -0.481138f, -0.277785f, 0.831470f }, - { -0.277785f, -0.481138f, 0.831470f }, - { 0.000000f, -0.555570f, 0.831470f }, - { 0.277785f, -0.481138f, 0.831470f }, - { 0.481138f, -0.277785f, 0.831470f }, - { 0.382683f, 0.000000f, 0.923880f }, - { 0.270598f, 0.270598f, 0.923880f }, - { -0.000000f, 0.382683f, 0.923880f }, - { -0.270598f, 0.270598f, 0.923880f }, - { -0.382683f, -0.000000f, 0.923880f }, - { -0.270598f, -0.270598f, 0.923880f }, - { 0.000000f, -0.382683f, 0.923880f }, - { 0.270598f, -0.270598f, 0.923880f }, - { 0.195090f, 0.000000f, 0.980785f }, - { -0.000000f, 0.195090f, 0.980785f }, - { -0.195090f, -0.000000f, 0.980785f }, - { 0.000000f, -0.195090f, 0.980785f } -}; - -#endif // !! MDC_NORMAL_TABLE_INCLUDED diff --git a/3rdparty/assimp/code/MDLDefaultColorMap.h b/3rdparty/assimp/code/MDLDefaultColorMap.h deleted file mode 100644 index a40da826..00000000 --- a/3rdparty/assimp/code/MDLDefaultColorMap.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the default color map used for Quake 1 model textures - * - * The lib tries to load colormap.lmp from the model's directory. - * This table is only used when required. - */ - -#ifndef AI_MDL_DEFAULTLMP_H_INC -#define AI_MDL_DEFAULTLMP_H_INC - -const unsigned char g_aclrDefaultColorMap[256][3] = { -{ 0, 0, 0}, { 15, 15, 15}, { 31, 31, 31}, { 47, 47, 47}, -{ 63, 63, 63}, { 75, 75, 75}, { 91, 91, 91}, {107, 107, 107}, -{123, 123, 123}, {139, 139, 139}, {155, 155, 155}, {171, 171, 171}, -{187, 187, 187}, {203, 203, 203}, {219, 219, 219}, {235, 235, 235}, -{ 15, 11, 7}, { 23, 15, 11}, { 31, 23, 11}, { 39, 27, 15}, -{ 47, 35, 19}, { 55, 43, 23}, { 63, 47, 23}, { 75, 55, 27}, -{ 83, 59, 27}, { 91, 67, 31}, { 99, 75, 31}, {107, 83, 31}, -{115, 87, 31}, {123, 95, 35}, {131, 103, 35}, {143, 111, 35}, -{ 11, 11, 15}, { 19, 19, 27}, { 27, 27, 39}, { 39, 39, 51}, -{ 47, 47, 63}, { 55, 55, 75}, { 63, 63, 87}, { 71, 71, 103}, -{ 79, 79, 115}, { 91, 91, 127}, { 99, 99, 139}, {107, 107, 151}, -{115, 115, 163}, {123, 123, 175}, {131, 131, 187}, {139, 139, 203}, -{ 0, 0, 0}, { 7, 7, 0}, { 11, 11, 0}, { 19, 19, 0}, -{ 27, 27, 0}, { 35, 35, 0}, { 43, 43, 7}, { 47, 47, 7}, -{ 55, 55, 7}, { 63, 63, 7}, { 71, 71, 7}, { 75, 75, 11}, -{ 83, 83, 11}, { 91, 91, 11}, { 99, 99, 11}, {107, 107, 15}, -{ 7, 0, 0}, { 15, 0, 0}, { 23, 0, 0}, { 31, 0, 0}, -{ 39, 0, 0}, { 47, 0, 0}, { 55, 0, 0}, { 63, 0, 0}, -{ 71, 0, 0}, { 79, 0, 0}, { 87, 0, 0}, { 95, 0, 0}, -{103, 0, 0}, {111, 0, 0}, {119, 0, 0}, {127, 0, 0}, -{ 19, 19, 0}, { 27, 27, 0}, { 35, 35, 0}, { 47, 43, 0}, -{ 55, 47, 0}, { 67, 55, 0}, { 75, 59, 7}, { 87, 67, 7}, -{ 95, 71, 7}, {107, 75, 11}, {119, 83, 15}, {131, 87, 19}, -{139, 91, 19}, {151, 95, 27}, {163, 99, 31}, {175, 103, 35}, -{ 35, 19, 7}, { 47, 23, 11}, { 59, 31, 15}, { 75, 35, 19}, -{ 87, 43, 23}, { 99, 47, 31}, {115, 55, 35}, {127, 59, 43}, -{143, 67, 51}, {159, 79, 51}, {175, 99, 47}, {191, 119, 47}, -{207, 143, 43}, {223, 171, 39}, {239, 203, 31}, {255, 243, 27}, -{ 11, 7, 0}, { 27, 19, 0}, { 43, 35, 15}, { 55, 43, 19}, -{ 71, 51, 27}, { 83, 55, 35}, { 99, 63, 43}, {111, 71, 51}, -{127, 83, 63}, {139, 95, 71}, {155, 107, 83}, {167, 123, 95}, -{183, 135, 107}, {195, 147, 123}, {211, 163, 139}, {227, 179, 151}, -{171, 139, 163}, {159, 127, 151}, {147, 115, 135}, {139, 103, 123}, -{127, 91, 111}, {119, 83, 99}, {107, 75, 87}, { 95, 63, 75}, -{ 87, 55, 67}, { 75, 47, 55}, { 67, 39, 47}, { 55, 31, 35}, -{ 43, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7}, -{187, 115, 159}, {175, 107, 143}, {163, 95, 131}, {151, 87, 119}, -{139, 79, 107}, {127, 75, 95}, {115, 67, 83}, {107, 59, 75}, -{ 95, 51, 63}, { 83, 43, 55}, { 71, 35, 43}, { 59, 31, 35}, -{ 47, 23, 27}, { 35, 19, 19}, { 23, 11, 11}, { 15, 7, 7}, -{219, 195, 187}, {203, 179, 167}, {191, 163, 155}, {175, 151, 139}, -{163, 135, 123}, {151, 123, 111}, {135, 111, 95}, {123, 99, 83}, -{107, 87, 71}, { 95, 75, 59}, { 83, 63, 51}, { 67, 51, 39}, -{ 55, 43, 31}, { 39, 31, 23}, { 27, 19, 15}, { 15, 11, 7}, -{111, 131, 123}, {103, 123, 111}, { 95, 115, 103}, { 87, 107, 95}, -{ 79, 99, 87}, { 71, 91, 79}, { 63, 83, 71}, { 55, 75, 63}, -{ 47, 67, 55}, { 43, 59, 47}, { 35, 51, 39}, { 31, 43, 31}, -{ 23, 35, 23}, { 15, 27, 19}, { 11, 19, 11}, { 7, 11, 7}, -{255, 243, 27}, {239, 223, 23}, {219, 203, 19}, {203, 183, 15}, -{187, 167, 15}, {171, 151, 11}, {155, 131, 7}, {139, 115, 7}, -{123, 99, 7}, {107, 83, 0}, { 91, 71, 0}, { 75, 55, 0}, -{ 59, 43, 0}, { 43, 31, 0}, { 27, 15, 0}, { 11, 7, 0}, -{ 0, 0, 255}, { 11, 11, 239}, { 19, 19, 223}, { 27, 27, 207}, -{ 35, 35, 191}, { 43, 43, 175}, { 47, 47, 159}, { 47, 47, 143}, -{ 47, 47, 127}, { 47, 47, 111}, { 47, 47, 95}, { 43, 43, 79}, -{ 35, 35, 63}, { 27, 27, 47}, { 19, 19, 31}, { 11, 11, 15}, -{ 43, 0, 0}, { 59, 0, 0}, { 75, 7, 0}, { 95, 7, 0}, -{111, 15, 0}, {127, 23, 7}, {147, 31, 7}, {163, 39, 11}, -{183, 51, 15}, {195, 75, 27}, {207, 99, 43}, {219, 127, 59}, -{227, 151, 79}, {231, 171, 95}, {239, 191, 119}, {247, 211, 139}, -{167, 123, 59}, {183, 155, 55}, {199, 195, 55}, {231, 227, 87}, -{127, 191, 255}, {171, 231, 255}, {215, 255, 255}, {103, 0, 0}, -{139, 0, 0}, {179, 0, 0}, {215, 0, 0}, {255, 0, 0}, -{255, 243, 147}, {255, 247, 199}, {255, 255, 255}, {159, 91, 83} }; - - -#endif // !! AI_MDL_DEFAULTLMP_H_INC diff --git a/3rdparty/assimp/code/MDLFileData.h b/3rdparty/assimp/code/MDLFileData.h deleted file mode 100644 index b1791d4b..00000000 --- a/3rdparty/assimp/code/MDLFileData.h +++ /dev/null @@ -1,959 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MDLFileData.h - * @brief Definition of in-memory structures for the MDL file format. - * - * The specification has been taken from various sources on the internet. - * - http://tfc.duke.free.fr/coding/mdl-specs-en.html - * - Conitec's MED SDK - * - Many quite long HEX-editor sessions - */ - -#ifndef AI_MDLFILEHELPER_H_INC -#define AI_MDLFILEHELPER_H_INC - -#include "./../include/Compiler/pushpack1.h" - -namespace Assimp { -namespace MDL { - -// ------------------------------------------------------------------------------------- -// to make it easier for us, we test the magic word against both "endianesses" - -// magic bytes used in Quake 1 MDL meshes -#define AI_MDL_MAGIC_NUMBER_BE AI_MAKE_MAGIC("IDPO") -#define AI_MDL_MAGIC_NUMBER_LE AI_MAKE_MAGIC("OPDI") - -// magic bytes used in GameStudio A<very low> MDL meshes -#define AI_MDL_MAGIC_NUMBER_BE_GS3 AI_MAKE_MAGIC("MDL2") -#define AI_MDL_MAGIC_NUMBER_LE_GS3 AI_MAKE_MAGIC("2LDM") - -// magic bytes used in GameStudio A4 MDL meshes -#define AI_MDL_MAGIC_NUMBER_BE_GS4 AI_MAKE_MAGIC("MDL3") -#define AI_MDL_MAGIC_NUMBER_LE_GS4 AI_MAKE_MAGIC("3LDM") - -// magic bytes used in GameStudio A5+ MDL meshes -#define AI_MDL_MAGIC_NUMBER_BE_GS5a AI_MAKE_MAGIC("MDL4") -#define AI_MDL_MAGIC_NUMBER_LE_GS5a AI_MAKE_MAGIC("4LDM") -#define AI_MDL_MAGIC_NUMBER_BE_GS5b AI_MAKE_MAGIC("MDL5") -#define AI_MDL_MAGIC_NUMBER_LE_GS5b AI_MAKE_MAGIC("5LDM") - -// magic bytes used in GameStudio A7+ MDL meshes -#define AI_MDL_MAGIC_NUMBER_BE_GS7 AI_MAKE_MAGIC("MDL7") -#define AI_MDL_MAGIC_NUMBER_LE_GS7 AI_MAKE_MAGIC("7LDM") - - -// common limitations for Quake1 meshes. The loader does not check them, -// (however it warns) but models should not exceed these limits. -#if (!defined AI_MDL_VERSION) -# define AI_MDL_VERSION 6 -#endif -#if (!defined AI_MDL_MAX_FRAMES) -# define AI_MDL_MAX_FRAMES 256 -#endif -#if (!defined AI_MDL_MAX_UVS) -# define AI_MDL_MAX_UVS 1024 -#endif -#if (!defined AI_MDL_MAX_VERTS) -# define AI_MDL_MAX_VERTS 1024 -#endif -#if (!defined AI_MDL_MAX_TRIANGLES) -# define AI_MDL_MAX_TRIANGLES 2048 -#endif - -// material key that is set for dummy materials that are -// just referencing another material -#if (!defined AI_MDL7_REFERRER_MATERIAL) -# define AI_MDL7_REFERRER_MATERIAL "&&&referrer&&&",0,0 -#endif - -// ------------------------------------------------------------------------------------- -/** \struct Header - * \brief Data structure for the MDL main header - */ -struct Header -{ - //! magic number: "IDPO" - uint32_t ident; - - //! version number: 6 - int32_t version; - - //! scale factors for each axis - aiVector3D scale; - - //! translation factors for each axis - aiVector3D translate; - - //! bounding radius of the mesh - float boundingradius; - - //! Position of the viewer's exe. Ignored - aiVector3D vEyePos; - - //! Number of textures - int32_t num_skins; - - //! Texture width in pixels - int32_t skinwidth; - - //! Texture height in pixels - int32_t skinheight; - - //! Number of vertices contained in the file - int32_t num_verts; - - //! Number of triangles contained in the file - int32_t num_tris; - - //! Number of frames contained in the file - int32_t num_frames; - - //! 0 = synchron, 1 = random . Ignored - //! (MDLn formats: number of texture coordinates) - int32_t synctype; - - //! State flag - int32_t flags; - - //! Could be the total size of the file (and not a float) - float size; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct Header_MDL7 - * \brief Data structure for the MDL 7 main header - */ -struct Header_MDL7 -{ - //! magic number: "MDL7" - char ident[4]; - - //! Version number. Ignored - int32_t version; - - //! Number of bones in file - uint32_t bones_num; - - //! Number of groups in file - uint32_t groups_num; - - //! Size of data in the file - uint32_t data_size; - - //! Ignored. Used to store entity specific information - int32_t entlump_size; - - //! Ignored. Used to store MED related data - int32_t medlump_size; - - //! Size of the Bone_MDL7 data structure used in the file - uint16_t bone_stc_size; - - //! Size of the Skin_MDL 7 data structure used in the file - uint16_t skin_stc_size; - - //! Size of a single color (e.g. in a material) - uint16_t colorvalue_stc_size; - - //! Size of the Material_MDL7 data structure used in the file - uint16_t material_stc_size; - - //! Size of a texture coordinate set in the file - uint16_t skinpoint_stc_size; - - //! Size of a triangle in the file - uint16_t triangle_stc_size; - - //! Size of a normal vertex in the file - uint16_t mainvertex_stc_size; - - //! Size of a per-frame animated vertex in the file - //! (this is not supported) - uint16_t framevertex_stc_size; - - //! Size of a bone animation matrix - uint16_t bonetrans_stc_size; - - //! Size of the Frame_MDL7 data structure used in the file - uint16_t frame_stc_size; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct Bone_MDL7 - * \brief Data structure for a bone in a MDL7 file - */ -struct Bone_MDL7 -{ - //! Index of the parent bone of *this* bone. 0xffff means: - //! "hey, I have no parent, I'm an orphan" - uint16_t parent_index; - uint8_t _unused_[2]; - - //! Relative position of the bone (relative to the - //! parent bone) - float x,y,z; - - //! Optional name of the bone - char name[1 /* DUMMY SIZE */]; -} PACK_STRUCT; - -#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS) -# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS (16 + 20) -#endif - -#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS) -# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS (16 + 32) -#endif - -#if (!defined AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE) -# define AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE (16) -#endif - -#if (!defined AI_MDL7_MAX_GROUPNAMESIZE) -# define AI_MDL7_MAX_GROUPNAMESIZE 16 -#endif // ! AI_MDL7_MAX_GROUPNAMESIZE - -// ------------------------------------------------------------------------------------- -/** \struct Group_MDL7 - * \brief Group in a MDL7 file - */ -struct Group_MDL7 -{ - //! = '1' -> triangle based Mesh - unsigned char typ; - - int8_t deformers; - int8_t max_weights; - int8_t _unused_; - - //! size of data for this group in bytes ( MD7_GROUP stc. included). - int32_t groupdata_size; - char name[AI_MDL7_MAX_GROUPNAMESIZE]; - - //! Number of skins - int32_t numskins; - - //! Number of texture coordinates - int32_t num_stpts; - - //! Number of triangles - int32_t numtris; - - //! Number of vertices - int32_t numverts; - - //! Number of frames - int32_t numframes; -} PACK_STRUCT; - -#define AI_MDL7_SKINTYPE_MIPFLAG 0x08 -#define AI_MDL7_SKINTYPE_MATERIAL 0x10 -#define AI_MDL7_SKINTYPE_MATERIAL_ASCDEF 0x20 -#define AI_MDL7_SKINTYPE_RGBFLAG 0x80 - -#if (!defined AI_MDL7_MAX_BONENAMESIZE) -# define AI_MDL7_MAX_BONENAMESIZE 20 -#endif // !! AI_MDL7_MAX_BONENAMESIZE - -// ------------------------------------------------------------------------------------- -/** \struct Deformer_MDL7 - * \brief Deformer in a MDL7 file - */ -struct Deformer_MDL7 -{ - int8_t deformer_version; // 0 - int8_t deformer_typ; // 0 - bones - int8_t _unused_[2]; - int32_t group_index; - int32_t elements; - int32_t deformerdata_size; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct DeformerElement_MDL7 - * \brief Deformer element in a MDL7 file - */ -struct DeformerElement_MDL7 -{ - //! bei deformer_typ==0 (==bones) element_index == bone index - int32_t element_index; - char element_name[AI_MDL7_MAX_BONENAMESIZE]; - int32_t weights; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct DeformerWeight_MDL7 - * \brief Deformer weight in a MDL7 file - */ -struct DeformerWeight_MDL7 -{ - //! for deformer_typ==0 (==bones) index == vertex index - int32_t index; - float weight; -} PACK_STRUCT; - - -// don't know why this was in the original headers ... -typedef int32_t MD7_MATERIAL_ASCDEFSIZE; - -// ------------------------------------------------------------------------------------- -/** \struct ColorValue_MDL7 - * \brief Data structure for a color value in a MDL7 file - */ -struct ColorValue_MDL7 -{ - float r,g,b,a; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct Material_MDL7 - * \brief Data structure for a Material in a MDL7 file - */ -struct Material_MDL7 -{ - //! Diffuse base color of the material - ColorValue_MDL7 Diffuse; - - //! Ambient base color of the material - ColorValue_MDL7 Ambient; - - //! Specular base color of the material - ColorValue_MDL7 Specular; - - //! Emissive base color of the material - ColorValue_MDL7 Emissive; - - //! Phong power - float Power; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct Skin - * \brief Skin data structure #1 - used by Quake1, MDL2, MDL3 and MDL4 - */ -struct Skin -{ - //! 0 = single (Skin), 1 = group (GroupSkin) - //! For MDL3-5: Defines the type of the skin and there - //! fore the size of the data to skip: - //------------------------------------------------------- - //! 2 for 565 RGB, - //! 3 for 4444 ARGB, - //! 10 for 565 mipmapped, - //! 11 for 4444 mipmapped (bpp = 2), - //! 12 for 888 RGB mipmapped (bpp = 3), - //! 13 for 8888 ARGB mipmapped (bpp = 4) - //------------------------------------------------------- - int32_t group; - - //! Texture data - uint8_t *data; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct Skin - * \brief Skin data structure #2 - used by MDL5, MDL6 and MDL7 - * \see Skin - */ -struct Skin_MDL5 -{ - int32_t size, width, height; - uint8_t *data; -} PACK_STRUCT; - -// maximum length of texture file name -#if (!defined AI_MDL7_MAX_TEXNAMESIZE) -# define AI_MDL7_MAX_TEXNAMESIZE 0x10 -#endif - -// --------------------------------------------------------------------------- -/** \struct Skin_MDL7 - * \brief Skin data structure #3 - used by MDL7 and HMP7 - */ -struct Skin_MDL7 -{ - uint8_t typ; - int8_t _unused_[3]; - int32_t width; - int32_t height; - char texture_name[AI_MDL7_MAX_TEXNAMESIZE]; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct RGB565 - * \brief Data structure for a RGB565 pixel in a texture - */ -struct RGB565 -{ - uint16_t r : 5; - uint16_t g : 6; - uint16_t b : 5; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct ARGB4 - * \brief Data structure for a ARGB4444 pixel in a texture - */ -struct ARGB4 -{ - uint16_t a : 4; - uint16_t r : 4; - uint16_t g : 4; - uint16_t b : 4; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct GroupSkin - * \brief Skin data structure #2 (group of pictures) - */ -struct GroupSkin -{ - //! 0 = single (Skin), 1 = group (GroupSkin) - int32_t group; - - //! Number of images - int32_t nb; - - //! Time for each image - float *time; - - //! Data of each image - uint8_t **data; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct TexCoord - * \brief Texture coordinate data structure used by the Quake1 MDL format - */ -struct TexCoord -{ - //! Is the vertex on the noundary between front and back piece? - int32_t onseam; - - //! Texture coordinate in the tx direction - int32_t s; - - //! Texture coordinate in the ty direction - int32_t t; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct TexCoord_MDL3 - * \brief Data structure for an UV coordinate in the 3DGS MDL3 format - */ -struct TexCoord_MDL3 -{ - //! position, horizontally in range 0..skinwidth-1 - int16_t u; - - //! position, vertically in range 0..skinheight-1 - int16_t v; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct TexCoord_MDL7 - * \brief Data structure for an UV coordinate in the 3DGS MDL7 format - */ -struct TexCoord_MDL7 -{ - //! position, horizontally in range 0..1 - float u; - - //! position, vertically in range 0..1 - float v; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct SkinSet_MDL7 - * \brief Skin set data structure for the 3DGS MDL7 format - * MDL7 references UV coordinates per face via an index list. - * This allows the use of multiple skins per face with just one - * UV coordinate set. - */ -struct SkinSet_MDL7 -{ - //! Index into the UV coordinate list - uint16_t st_index[3]; // size 6 - - //! Material index - int32_t material; // size 4 -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct Triangle - * \brief Triangle data structure for the Quake1 MDL format - */ -struct Triangle -{ - //! 0 = backface, 1 = frontface - int32_t facesfront; - - //! Vertex indices - int32_t vertex[3]; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct Triangle_MDL3 - * \brief Triangle data structure for the 3DGS MDL3 format - */ -struct Triangle_MDL3 -{ - //! Index of 3 3D vertices in range 0..numverts - uint16_t index_xyz[3]; - - //! Index of 3 skin vertices in range 0..numskinverts - uint16_t index_uv[3]; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct Triangle_MDL7 - * \brief Triangle data structure for the 3DGS MDL7 format - */ -struct Triangle_MDL7 -{ - //! Vertex indices - uint16_t v_index[3]; // size 6 - - //! Two skinsets. The second will be used for multi-texturing - SkinSet_MDL7 skinsets[2]; -} PACK_STRUCT; - -#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) -# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV (6+sizeof(SkinSet_MDL7)-sizeof(uint32_t)) -#endif -#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX) -# define AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX (6+sizeof(SkinSet_MDL7)) -#endif -#if (!defined AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) -# define AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV (6+2*sizeof(SkinSet_MDL7)) -#endif - -// Helper constants for Triangle::facesfront -#if (!defined AI_MDL_BACKFACE) -# define AI_MDL_BACKFACE 0x0 -#endif -#if (!defined AI_MDL_FRONTFACE) -# define AI_MDL_FRONTFACE 0x1 -#endif - -// ------------------------------------------------------------------------------------- -/** \struct Vertex - * \brief Vertex data structure - */ -struct Vertex -{ - uint8_t v[3]; - uint8_t normalIndex; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -struct Vertex_MDL4 -{ - uint16_t v[3]; - uint8_t normalIndex; - uint8_t unused; -} PACK_STRUCT; - -#define AI_MDL7_FRAMEVERTEX120503_STCSIZE 16 -#define AI_MDL7_FRAMEVERTEX030305_STCSIZE 26 - -// ------------------------------------------------------------------------------------- -/** \struct Vertex_MDL7 - * \brief Vertex data structure used in MDL7 files - */ -struct Vertex_MDL7 -{ - float x,y,z; - uint16_t vertindex; // = bone index - union { - uint8_t norm162index; - float norm[3]; - }; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -/** \struct BoneTransform_MDL7 - * \brief bone transformation matrix structure used in MDL7 files - */ -struct BoneTransform_MDL7 -{ - //! 4*3 - float m [4*4]; - - //! the index of this vertex, 0.. header::bones_num - 1 - uint16_t bone_index; - - //! I HATE 3DGS AND THE SILLY DEVELOPER WHO DESIGNED - //! THIS STUPID FILE FORMAT! - int8_t _unused_[2]; -} PACK_STRUCT; - - -#define AI_MDL7_MAX_FRAMENAMESIZE 16 - - -// ------------------------------------------------------------------------------------- -/** \struct Frame_MDL7 - * \brief Frame data structure used by MDL7 files - */ -struct Frame_MDL7 -{ - char frame_name[AI_MDL7_MAX_FRAMENAMESIZE]; - uint32_t vertices_count; - uint32_t transmatrix_count; -}; - - -// ------------------------------------------------------------------------------------- -/** \struct SimpleFrame - * \brief Data structure for a simple frame - */ -struct SimpleFrame -{ - //! Minimum vertex of the bounding box - Vertex bboxmin; - - //! Maximum vertex of the bounding box - Vertex bboxmax; - - //! Name of the frame - char name[16]; - - //! Vertex list of the frame - Vertex *verts; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct Frame - * \brief Model frame data structure - */ -struct Frame -{ - //! 0 = simple frame, !0 = group frame - int32_t type; - - //! Frame data - SimpleFrame frame; -} PACK_STRUCT; - - -// ------------------------------------------------------------------------------------- -struct SimpleFrame_MDLn_SP -{ - //! Minimum vertex of the bounding box - Vertex_MDL4 bboxmin; - - //! Maximum vertex of the bounding box - Vertex_MDL4 bboxmax; - - //! Name of the frame - char name[16]; - - //! Vertex list of the frame - Vertex_MDL4 *verts; -} PACK_STRUCT; - -// ------------------------------------------------------------------------------------- -/** \struct GroupFrame - * \brief Data structure for a group of frames - */ -struct GroupFrame -{ - //! 0 = simple frame, !0 = group frame - int32_t type; - - //! Minimum vertex for all single frames - Vertex min; - - //! Maximum vertex for all single frames - Vertex max; - - //! Time for all single frames - float *time; - - //! List of single frames - SimpleFrame *frames; -} PACK_STRUCT; - -#include "./../include/Compiler/poppack1.h" - -// ------------------------------------------------------------------------------------- -/** \struct IntFace_MDL7 - * \brief Internal data structure to temporarily represent a face - */ -struct IntFace_MDL7 -{ - // provide a constructor for our own convenience - IntFace_MDL7() - { - // set everything to zero - mIndices[0] = mIndices[1] = mIndices[2] = 0; - iMatIndex[0] = iMatIndex[1] = 0; - } - - //! Vertex indices - uint32_t mIndices[3]; - - //! Material index (maximally two channels, which are joined later) - unsigned int iMatIndex[2]; -}; - -// ------------------------------------------------------------------------------------- -/** \struct IntMaterial_MDL7 - * \brief Internal data structure to temporarily represent a material - * which has been created from two single materials along with the - * original material indices. - */ -struct IntMaterial_MDL7 -{ - // provide a constructor for our own convenience - IntMaterial_MDL7() - { - pcMat = NULL; - iOldMatIndices[0] = iOldMatIndices[1] = 0; - } - - //! Material instance - MaterialHelper* pcMat; - - //! Old material indices - unsigned int iOldMatIndices[2]; -}; - -// ------------------------------------------------------------------------------------- -/** \struct IntBone_MDL7 - * \brief Internal data structure to represent a bone in a MDL7 file with - * all of its animation channels assigned to it. - */ -struct IntBone_MDL7 : aiBone -{ - //! Default constructor - IntBone_MDL7() : iParent (0xffff) - { - pkeyPositions.reserve(30); - pkeyScalings.reserve(30); - pkeyRotations.reserve(30); - } - - //! Parent bone of the bone - uint64_t iParent; - - //! Relative position of the bone - aiVector3D vPosition; - - //! Array of position keys - std::vector<aiVectorKey> pkeyPositions; - - //! Array of scaling keys - std::vector<aiVectorKey> pkeyScalings; - - //! Array of rotation keys - std::vector<aiQuatKey> pkeyRotations; -}; - -// ------------------------------------------------------------------------------------- -//! Describes a MDL7 frame -struct IntFrameInfo_MDL7 -{ - //! Construction from an existing frame header - IntFrameInfo_MDL7(BE_NCONST MDL::Frame_MDL7* _pcFrame,unsigned int _iIndex) - : iIndex(_iIndex) - , pcFrame(_pcFrame) - {} - - //! Index of the frame - unsigned int iIndex; - - //! Points to the header of the frame - BE_NCONST MDL::Frame_MDL7* pcFrame; -}; - -// ------------------------------------------------------------------------------------- -//! Describes a MDL7 mesh group -struct IntGroupInfo_MDL7 -{ - //! Default constructor - IntGroupInfo_MDL7() - : iIndex(0) - , pcGroup(NULL) - , pcGroupUVs(NULL) - , pcGroupTris(NULL) - , pcGroupVerts(NULL) - {} - - //! Construction from an existing group header - IntGroupInfo_MDL7(BE_NCONST MDL::Group_MDL7* _pcGroup, unsigned int _iIndex) - : iIndex(_iIndex) - , pcGroup(_pcGroup) - {} - - //! Index of the group - unsigned int iIndex; - - //! Points to the header of the group - BE_NCONST MDL::Group_MDL7* pcGroup; - - //! Points to the beginning of the uv coordinate section - BE_NCONST MDL::TexCoord_MDL7* pcGroupUVs; - - //! Points to the beginning of the triangle section - BE_NCONST MDL::Triangle_MDL7* pcGroupTris; - - //! Points to the beginning of the vertex section - BE_NCONST MDL::Vertex_MDL7* pcGroupVerts; -}; - -// ------------------------------------------------------------------------------------- -//! Holds the data that belongs to a MDL7 mesh group -struct IntGroupData_MDL7 -{ - IntGroupData_MDL7() - : pcFaces(NULL), bNeed2UV(false) - {} - - //! Array of faces that belong to the group - MDL::IntFace_MDL7* pcFaces; - - //! Array of vertex positions - std::vector<aiVector3D> vPositions; - - //! Array of vertex normals - std::vector<aiVector3D> vNormals; - - //! Array of bones indices - std::vector<unsigned int> aiBones; - - //! First UV coordinate set - std::vector<aiVector3D> vTextureCoords1; - - //! Optional second UV coordinate set - std::vector<aiVector3D> vTextureCoords2; - - //! Specifies whether there are two texture - //! coordinate sets required - bool bNeed2UV; -}; - -// ------------------------------------------------------------------------------------- -//! Holds data from an MDL7 file that is shared by all mesh groups -struct IntSharedData_MDL7 -{ - //! Default constructor - IntSharedData_MDL7() - { - abNeedMaterials.reserve(10); - } - - //! Destruction: properly delete all allocated resources - ~IntSharedData_MDL7() - { - // kill all bones - if (this->apcOutBones) - { - for (unsigned int m = 0; m < iNum;++m) - delete this->apcOutBones[m]; - delete[] this->apcOutBones; - } - } - - //! Specifies which materials are used - std::vector<bool> abNeedMaterials; - - //! List of all materials - std::vector<MaterialHelper*> pcMats; - - //! List of all bones - IntBone_MDL7** apcOutBones; - - //! number of bones - unsigned int iNum; -}; - -// ------------------------------------------------------------------------------------- -//! Contains input data for GenerateOutputMeshes_3DGS_MDL7 -struct IntSplittedGroupData_MDL7 -{ - //! Construction from a given shared data set - IntSplittedGroupData_MDL7(IntSharedData_MDL7& _shared, - std::vector<aiMesh*>& _avOutList) - - : shared(_shared), avOutList(_avOutList) - { - } - - //! Destruction: properly delete all allocated resources - ~IntSplittedGroupData_MDL7() - { - // kill all face lists - if (this->aiSplit) - { - for (unsigned int m = 0; m < shared.pcMats.size();++m) - delete this->aiSplit[m]; - delete[] this->aiSplit; - } - } - - //! Contains a list of all faces per material - std::vector<unsigned int>** aiSplit; - - //! Shared data for all groups of the model - IntSharedData_MDL7& shared; - - //! List of meshes - std::vector<aiMesh*>& avOutList; -}; - - -} -} // end namespaces - -#endif // !! AI_MDLFILEHELPER_H_INC diff --git a/3rdparty/assimp/code/MDLLoader.cpp b/3rdparty/assimp/code/MDLLoader.cpp deleted file mode 100644 index 775e04c3..00000000 --- a/3rdparty/assimp/code/MDLLoader.cpp +++ /dev/null @@ -1,1929 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MDLLoader.cpp - * @brief Implementation of the main parts of the MDL importer class - * *TODO* Cleanup and further testing of some parts necessary - */ - -// internal headers -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER - -#include "MDLLoader.h" -#include "MDLDefaultColorMap.h" -#include "MD2FileData.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Ugly stuff ... nevermind -#define _AI_MDL7_ACCESS(_data, _index, _limit, _type) \ - (*((const _type*)(((const char*)_data) + _index * _limit))) - -#define _AI_MDL7_ACCESS_PTR(_data, _index, _limit, _type) \ - ((BE_NCONST _type*)(((const char*)_data) + _index * _limit)) - -#define _AI_MDL7_ACCESS_VERT(_data, _index, _limit) \ - _AI_MDL7_ACCESS(_data,_index,_limit,MDL::Vertex_MDL7) - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MDLImporter::MDLImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MDLImporter::~MDLImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - - // if check for extension is not enough, check for the magic tokens - if (extension == "mdl" || !extension.length() || checkSig) { - uint32_t tokens[8]; - tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a; - tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b; - tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7; - tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b; - tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a; - tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4; - tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3; - tokens[7] = AI_MDL_MAGIC_NUMBER_LE; - return CheckMagicToken(pIOHandler,pFile,tokens,8,0); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void MDLImporter::SetupProperties(const Importer* pImp) -{ - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MDL_KEYFRAME,0xffffffff); - - // The - // AI_CONFIG_IMPORT_MDL_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - if(0xffffffff == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } - - // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file - configPalette = pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp"); -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all supported extensions -void MDLImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert( "mdl" ); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MDLImporter::InternReadFile( const std::string& pFile, - aiScene* _pScene, IOSystem* _pIOHandler) -{ - pScene = _pScene; - pIOHandler = _pIOHandler; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open MDL file " + pFile + "."); - } - - // This should work for all other types of MDL files, too ... - // the quake header is one of the smallest, afaik - iFileSize = (unsigned int)file->FileSize(); - if( iFileSize < sizeof(MDL::Header)) { - throw DeadlyImportError( "MDL File is too small."); - } - - // Allocate storage and copy the contents of the file to a memory buffer - std::vector<unsigned char> buffer(iFileSize+1); - mBuffer = &buffer[0]; - file->Read( (void*)mBuffer, 1, iFileSize); - - // Append a binary zero to the end of the buffer. - // this is just for safety that string parsing routines - // find the end of the buffer ... - mBuffer[iFileSize] = '\0'; - const uint32_t iMagicWord = *((uint32_t*)mBuffer); - - // Determine the file subtype and call the appropriate member function - - // Original Quake1 format - if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO"); - iGSFileVersion = 0; - InternReadFile_Quake1(); - } - // GameStudio A<old> MDL2 format - used by some test models that come with 3DGS - else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2"); - iGSFileVersion = 2; - InternReadFile_Quake1(); - } - // GameStudio A4 MDL3 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3"); - iGSFileVersion = 3; - InternReadFile_3DGS_MDL345(); - } - // GameStudio A5+ MDL4 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4"); - iGSFileVersion = 4; - InternReadFile_3DGS_MDL345(); - } - // GameStudio A5+ MDL5 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5"); - iGSFileVersion = 5; - InternReadFile_3DGS_MDL345(); - } - // GameStudio A7 MDL7 format - else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord) { - DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7"); - iGSFileVersion = 7; - InternReadFile_3DGS_MDL7(); - } - // IDST/IDSQ Format (CS:S/HL², etc ...) - else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord || - AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) - { - DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ"); - iGSFileVersion = 0; - InternReadFile_HL2(); - } - else { - // print the magic word to the log file - throw DeadlyImportError( "Unknown MDL subformat " + pFile + - ". Magic word (" + std::string((char*)&iMagicWord,4) + ") is not known"); - } - - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f, - 0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f); - - // delete the file buffer and cleanup - AI_DEBUG_INVALIDATE_PTR(mBuffer); - AI_DEBUG_INVALIDATE_PTR(pIOHandler); - AI_DEBUG_INVALIDATE_PTR(pScene); -} - -// ------------------------------------------------------------------------------------------------ -// Check whether we're still inside the valid file range -void MDLImporter::SizeCheck(const void* szPos) -{ - if (!szPos || (const unsigned char*)szPos > this->mBuffer + this->iFileSize) - { - throw DeadlyImportError("Invalid MDL file. The file is too small " - "or contains invalid data."); - } -} - -// ------------------------------------------------------------------------------------------------ -// Just for debgging purposes -void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int iLine) -{ - ai_assert(NULL != szFile); - if (!szPos || (const unsigned char*)szPos > mBuffer + iFileSize) - { - // remove a directory if there is one - const char* szFilePtr = ::strrchr(szFile,'\\'); - if (!szFilePtr) { - if(!(szFilePtr = ::strrchr(szFile,'/'))) - szFilePtr = szFile; - } - if (szFilePtr)++szFilePtr; - - char szBuffer[1024]; - ::sprintf(szBuffer,"Invalid MDL file. The file is too small " - "or contains invalid data (File: %s Line: %i)",szFilePtr,iLine); - - throw DeadlyImportError(szBuffer); - } -} - -// ------------------------------------------------------------------------------------------------ -// Validate a quake file header -void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader) -{ - // some values may not be NULL - if (!pcHeader->num_frames) - throw DeadlyImportError( "[Quake 1 MDL] There are no frames in the file"); - - if (!pcHeader->num_verts) - throw DeadlyImportError( "[Quake 1 MDL] There are no vertices in the file"); - - if (!pcHeader->num_tris) - throw DeadlyImportError( "[Quake 1 MDL] There are no triangles in the file"); - - // check whether the maxima are exceeded ...however, this applies for Quake 1 MDLs only - if (!this->iGSFileVersion) - { - if (pcHeader->num_verts > AI_MDL_MAX_VERTS) - DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices"); - - if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES) - DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles"); - - if (pcHeader->num_frames > AI_MDL_MAX_FRAMES) - DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames"); - - // (this does not apply for 3DGS MDLs) - if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION) - DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is " - "the expected file format version"); - if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight)) - DefaultLogger::get()->warn("Skin width or height are 0"); - } -} - -#ifdef AI_BUILD_BIG_ENDIAN -// ------------------------------------------------------------------------------------------------ -void FlipQuakeHeader(BE_NCONST MDL::Header* pcHeader) -{ - AI_SWAP4( pcHeader->ident); - AI_SWAP4( pcHeader->version); - AI_SWAP4( pcHeader->boundingradius); - AI_SWAP4( pcHeader->flags); - AI_SWAP4( pcHeader->num_frames); - AI_SWAP4( pcHeader->num_skins); - AI_SWAP4( pcHeader->num_tris); - AI_SWAP4( pcHeader->num_verts); - for (unsigned int i = 0; i < 3;++i) - { - AI_SWAP4( pcHeader->scale[i]); - AI_SWAP4( pcHeader->translate[i]); - } - AI_SWAP4( pcHeader->size); - AI_SWAP4( pcHeader->skinheight); - AI_SWAP4( pcHeader->skinwidth); - AI_SWAP4( pcHeader->synctype); -} -#endif - -// ------------------------------------------------------------------------------------------------ -// Read a Quake 1 file -void MDLImporter::InternReadFile_Quake1( ) -{ - ai_assert(NULL != pScene); - BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer; - -#ifdef AI_BUILD_BIG_ENDIAN - FlipQuakeHeader(pcHeader); -#endif - - ValidateHeader_Quake1(pcHeader); - - // current cursor position in the file - const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); - - // need to read all textures - for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) - { - union{BE_NCONST MDL::Skin* pcSkin;BE_NCONST MDL::GroupSkin* pcGroupSkin;}; - pcSkin = (BE_NCONST MDL::Skin*)szCurrent; - - AI_SWAP4( pcSkin->group ); - - // Quake 1 groupskins - if (1 == pcSkin->group) - { - AI_SWAP4( pcGroupSkin->nb ); - - // need to skip multiple images - const unsigned int iNumImages = (unsigned int)pcGroupSkin->nb; - szCurrent += sizeof(uint32_t) * 2; - - if (0 != iNumImages) - { - if (!i) { - // however, create only one output image (the first) - this->CreateTextureARGB8_3DGS_MDL3(szCurrent + iNumImages * sizeof(float)); - } - // go to the end of the skin section / the beginning of the next skin - szCurrent += pcHeader->skinheight * pcHeader->skinwidth + - sizeof(float) * iNumImages; - } - } - // 3DGS has a few files that are using other 3DGS like texture formats here - else - { - szCurrent += sizeof(uint32_t); - unsigned int iSkip = i ? 0xffffffff : 0; - this->CreateTexture_3DGS_MDL4(szCurrent,pcSkin->group,&iSkip); - szCurrent += iSkip; - } - } - // get a pointer to the texture coordinates - BE_NCONST MDL::TexCoord* pcTexCoords = (BE_NCONST MDL::TexCoord*)szCurrent; - szCurrent += sizeof(MDL::TexCoord) * pcHeader->num_verts; - - // get a pointer to the triangles - BE_NCONST MDL::Triangle* pcTriangles = (BE_NCONST MDL::Triangle*)szCurrent; - szCurrent += sizeof(MDL::Triangle) * pcHeader->num_tris; - VALIDATE_FILE_SIZE(szCurrent); - - // now get a pointer to the first frame in the file - BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent; - BE_NCONST MDL::SimpleFrame* pcFirstFrame; - - if (0 == pcFrames->type) - { - // get address of single frame - pcFirstFrame = &pcFrames->frame; - } - else - { - // get the first frame in the group - BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames; - pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type); - } - BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name)); - VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts)); - -#ifdef AI_BUILD_BIG_ENDIAN - for (int i = 0; i<pcHeader->num_verts;++i) - { - AI_SWAP4( pcTexCoords[i].onseam ); - AI_SWAP4( pcTexCoords[i].s ); - AI_SWAP4( pcTexCoords[i].t ); - } - - for (int i = 0; i<pcHeader->num_tris;++i) - { - AI_SWAP4( pcTriangles[i].facesfront); - AI_SWAP4( pcTriangles[i].vertex[0]); - AI_SWAP4( pcTriangles[i].vertex[1]); - AI_SWAP4( pcTriangles[i].vertex[2]); - } -#endif - - // setup materials - SetupMaterialProperties_3DGS_MDL5_Quake1(); - - // allocate enough storage to hold all vertices and triangles - aiMesh* pcMesh = new aiMesh(); - - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pcMesh->mNumVertices = pcHeader->num_tris * 3; - pcMesh->mNumFaces = pcHeader->num_tris; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - - // there won't be more than one mesh inside the file - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - pScene->mMeshes[0] = pcMesh; - - // now iterate through all triangles - unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) - { - pcMesh->mFaces[i].mIndices = new unsigned int[3]; - pcMesh->mFaces[i].mNumIndices = 3; - - unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) - { - pcMesh->mFaces[i].mIndices[c] = iCurrent; - - // read vertices - unsigned int iIndex = pcTriangles->vertex[c]; - if (iIndex >= (unsigned int)pcHeader->num_verts) - { - iIndex = pcHeader->num_verts-1; - DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list."); - } - - aiVector3D& vec = pcMesh->mVertices[iCurrent]; - vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0]; - vec.x += pcHeader->translate[0]; - - vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1]; - vec.y += pcHeader->translate[1]; - //vec.y *= -1.0f; - - vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2]; - vec.z += pcHeader->translate[2]; - - // read the normal vector from the precalculated normal table - MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]); - //pcMesh->mNormals[iCurrent].y *= -1.0f; - - // read texture coordinates - float s = (float)pcTexCoords[iIndex].s; - float t = (float)pcTexCoords[iIndex].t; - - // translate texture coordinates - if (0 == pcTriangles->facesfront && 0 != pcTexCoords[iIndex].onseam) { - s += pcHeader->skinwidth * 0.5f; - } - - // Scale s and t to range from 0.0 to 1.0 - pcMesh->mTextureCoords[0][iCurrent].x = (s + 0.5f) / pcHeader->skinwidth; - pcMesh->mTextureCoords[0][iCurrent].y = 1.0f-(t + 0.5f) / pcHeader->skinheight; - - } - pcMesh->mFaces[i].mIndices[0] = iTemp+2; - pcMesh->mFaces[i].mIndices[1] = iTemp+1; - pcMesh->mFaces[i].mIndices[2] = iTemp+0; - pcTriangles++; - } - return; -} - -// ------------------------------------------------------------------------------------------------ -// Setup material properties for Quake and older GameStudio files -void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1( ) -{ - const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer; - - // allocate ONE material - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = new MaterialHelper(); - pScene->mNumMaterials = 1; - - // setup the material's properties - const int iMode = (int)aiShadingMode_Gouraud; - MaterialHelper* const pcHelper = (MaterialHelper*)pScene->mMaterials[0]; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor4D clr; - if (0 != pcHeader->num_skins && pScene->mNumTextures) { - // can we replace the texture with a single color? - clr = this->ReplaceTextureWithColor(pScene->mTextures[0]); - if (is_not_qnan(clr.r)) { - delete pScene->mTextures[0]; - delete[] pScene->mTextures; - - pScene->mTextures = NULL; - pScene->mNumTextures = 0; - } - else { - clr.b = clr.a = clr.g = clr.r = 1.0f; - aiString szString; - ::memcpy(szString.data,AI_MAKE_EMBEDDED_TEXNAME(0),3); - szString.length = 2; - pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - } - - pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.r *= 0.05f;clr.g *= 0.05f; - clr.b *= 0.05f;clr.a = 1.0f; - pcHelper->AddProperty<aiColor4D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); -} - -// ------------------------------------------------------------------------------------------------ -// Read a MDL 3,4,5 file -void MDLImporter::InternReadFile_3DGS_MDL345( ) -{ - ai_assert(NULL != pScene); - - // the header of MDL 3/4/5 is nearly identical to the original Quake1 header - BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header*)this->mBuffer; -#ifdef AI_BUILD_BIG_ENDIAN - FlipQuakeHeader(pcHeader); -#endif - ValidateHeader_Quake1(pcHeader); - - // current cursor position in the file - const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); - - // need to read all textures - for (unsigned int i = 0; i < (unsigned int)pcHeader->num_skins;++i) { - BE_NCONST MDL::Skin* pcSkin; - pcSkin = (BE_NCONST MDL::Skin*)szCurrent; - AI_SWAP4( pcSkin->group); - // create one output image - unsigned int iSkip = i ? 0xffffffff : 0; - if (5 <= iGSFileVersion) - { - // MDL5 format could contain MIPmaps - CreateTexture_3DGS_MDL5((unsigned char*)pcSkin + sizeof(uint32_t), - pcSkin->group,&iSkip); - } - else { - CreateTexture_3DGS_MDL4((unsigned char*)pcSkin + sizeof(uint32_t), - pcSkin->group,&iSkip); - } - // need to skip one image - szCurrent += iSkip + sizeof(uint32_t); - - } - // get a pointer to the texture coordinates - BE_NCONST MDL::TexCoord_MDL3* pcTexCoords = (BE_NCONST MDL::TexCoord_MDL3*)szCurrent; - szCurrent += sizeof(MDL::TexCoord_MDL3) * pcHeader->synctype; - - // NOTE: for MDLn formats "synctype" corresponds to the number of UV coords - - // get a pointer to the triangles - BE_NCONST MDL::Triangle_MDL3* pcTriangles = (BE_NCONST MDL::Triangle_MDL3*)szCurrent; - szCurrent += sizeof(MDL::Triangle_MDL3) * pcHeader->num_tris; - -#ifdef AI_BUILD_BIG_ENDIAN - - for (int i = 0; i<pcHeader->synctype;++i) { - AI_SWAP2( pcTexCoords[i].u ); - AI_SWAP2( pcTexCoords[i].v ); - } - - for (int i = 0; i<pcHeader->num_tris;++i) { - AI_SWAP2( pcTriangles[i].index_xyz[0]); - AI_SWAP2( pcTriangles[i].index_xyz[1]); - AI_SWAP2( pcTriangles[i].index_xyz[2]); - AI_SWAP2( pcTriangles[i].index_uv[0]); - AI_SWAP2( pcTriangles[i].index_uv[1]); - AI_SWAP2( pcTriangles[i].index_uv[2]); - } - -#endif - - VALIDATE_FILE_SIZE(szCurrent); - - // setup materials - SetupMaterialProperties_3DGS_MDL5_Quake1(); - - // allocate enough storage to hold all vertices and triangles - aiMesh* pcMesh = new aiMesh(); - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - pcMesh->mNumVertices = pcHeader->num_tris * 3; - pcMesh->mNumFaces = pcHeader->num_tris; - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - - // there won't be more than one mesh inside the file - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - pScene->mMeshes[0] = pcMesh; - - // allocate output storage - pcMesh->mNumVertices = (unsigned int)pcHeader->num_tris*3; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - - if (pcHeader->synctype) { - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - } - - // now get a pointer to the first frame in the file - BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent; - AI_SWAP4(pcFrames->type); - - // byte packed vertices - // FIXME: these two snippets below are almost identical ... join them? - ///////////////////////////////////////////////////////////////////////////////////// - if (0 == pcFrames->type || 3 >= this->iGSFileVersion) { - - const MDL::SimpleFrame* pcFirstFrame = (const MDL::SimpleFrame*)(szCurrent + sizeof(uint32_t)); - const MDL::Vertex* pcVertices = (const MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name)); - - VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts); - - // now iterate through all triangles - unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) { - pcMesh->mFaces[i].mIndices = new unsigned int[3]; - pcMesh->mFaces[i].mNumIndices = 3; - - unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) { - // read vertices - unsigned int iIndex = pcTriangles->index_xyz[c]; - if (iIndex >= (unsigned int)pcHeader->num_verts) { - iIndex = pcHeader->num_verts-1; - DefaultLogger::get()->warn("Index overflow in MDLn vertex list"); - } - - aiVector3D& vec = pcMesh->mVertices[iCurrent]; - vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0]; - vec.x += pcHeader->translate[0]; - - vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1]; - vec.y += pcHeader->translate[1]; - // vec.y *= -1.0f; - - vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2]; - vec.z += pcHeader->translate[2]; - - // read the normal vector from the precalculated normal table - MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]); - // pcMesh->mNormals[iCurrent].y *= -1.0f; - - // read texture coordinates - if (pcHeader->synctype) { - ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent], - pcTexCoords,pcTriangles->index_uv[c]); - } - } - pcMesh->mFaces[i].mIndices[0] = iTemp+2; - pcMesh->mFaces[i].mIndices[1] = iTemp+1; - pcMesh->mFaces[i].mIndices[2] = iTemp+0; - pcTriangles++; - } - - } - // short packed vertices - ///////////////////////////////////////////////////////////////////////////////////// - else { - // now get a pointer to the first frame in the file - const MDL::SimpleFrame_MDLn_SP* pcFirstFrame = (const MDL::SimpleFrame_MDLn_SP*) (szCurrent + sizeof(uint32_t)); - - // get a pointer to the vertices - const MDL::Vertex_MDL4* pcVertices = (const MDL::Vertex_MDL4*) ((pcFirstFrame->name) + - sizeof(pcFirstFrame->name)); - - VALIDATE_FILE_SIZE(pcVertices + pcHeader->num_verts); - - // now iterate through all triangles - unsigned int iCurrent = 0; - for (unsigned int i = 0; i < (unsigned int) pcHeader->num_tris;++i) { - pcMesh->mFaces[i].mIndices = new unsigned int[3]; - pcMesh->mFaces[i].mNumIndices = 3; - - unsigned int iTemp = iCurrent; - for (unsigned int c = 0; c < 3;++c,++iCurrent) { - // read vertices - unsigned int iIndex = pcTriangles->index_xyz[c]; - if (iIndex >= (unsigned int)pcHeader->num_verts) { - iIndex = pcHeader->num_verts-1; - DefaultLogger::get()->warn("Index overflow in MDLn vertex list"); - } - - aiVector3D& vec = pcMesh->mVertices[iCurrent]; - vec.x = (float)pcVertices[iIndex].v[0] * pcHeader->scale[0]; - vec.x += pcHeader->translate[0]; - - vec.y = (float)pcVertices[iIndex].v[1] * pcHeader->scale[1]; - vec.y += pcHeader->translate[1]; - // vec.y *= -1.0f; - - vec.z = (float)pcVertices[iIndex].v[2] * pcHeader->scale[2]; - vec.z += pcHeader->translate[2]; - - // read the normal vector from the precalculated normal table - MD2::LookupNormalIndex(pcVertices[iIndex].normalIndex,pcMesh->mNormals[iCurrent]); - // pcMesh->mNormals[iCurrent].y *= -1.0f; - - // read texture coordinates - if (pcHeader->synctype) { - ImportUVCoordinate_3DGS_MDL345(pcMesh->mTextureCoords[0][iCurrent], - pcTexCoords,pcTriangles->index_uv[c]); - } - } - pcMesh->mFaces[i].mIndices[0] = iTemp+2; - pcMesh->mFaces[i].mIndices[1] = iTemp+1; - pcMesh->mFaces[i].mIndices[2] = iTemp+0; - pcTriangles++; - } - } - - // For MDL5 we will need to build valid texture coordinates - // basing upon the file loaded (only support one file as skin) - if (0x5 == iGSFileVersion) - CalculateUVCoordinates_MDL5(); - return; -} - -// ------------------------------------------------------------------------------------------------ -// Get a single UV coordinate for Quake and older GameStudio files -void MDLImporter::ImportUVCoordinate_3DGS_MDL345( - aiVector3D& vOut, - const MDL::TexCoord_MDL3* pcSrc, - unsigned int iIndex) -{ - ai_assert(NULL != pcSrc); - const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer; - - // validate UV indices - if (iIndex >= (unsigned int) pcHeader->synctype) { - iIndex = pcHeader->synctype-1; - DefaultLogger::get()->warn("Index overflow in MDLn UV coord list"); - } - - float s = (float)pcSrc[iIndex].u; - float t = (float)pcSrc[iIndex].v; - - // Scale s and t to range from 0.0 to 1.0 - if (0x5 != iGSFileVersion) { - s = (s + 0.5f) / pcHeader->skinwidth; - t = 1.0f-(t + 0.5f) / pcHeader->skinheight; - } - - vOut.x = s; - vOut.y = t; - vOut.z = 0.0f; -} - -// ------------------------------------------------------------------------------------------------ -// Compute UV coordinates for a MDL5 file -void MDLImporter::CalculateUVCoordinates_MDL5() -{ - const MDL::Header* const pcHeader = (const MDL::Header*)this->mBuffer; - if (pcHeader->num_skins && this->pScene->mNumTextures) { - const aiTexture* pcTex = this->pScene->mTextures[0]; - - // if the file is loaded in DDS format: get the size of the - // texture from the header of the DDS file - // skip three DWORDs and read first height, then the width - unsigned int iWidth, iHeight; - if (!pcTex->mHeight) { - const uint32_t* piPtr = (uint32_t*)pcTex->pcData; - - piPtr += 3; - iHeight = (unsigned int)*piPtr++; - iWidth = (unsigned int)*piPtr; - if (!iHeight || !iWidth) - { - DefaultLogger::get()->warn("Either the width or the height of the " - "embedded DDS texture is zero. Unable to compute final texture " - "coordinates. The texture coordinates remain in their original " - "0-x/0-y (x,y = texture size) range."); - iWidth = 1; - iHeight = 1; - } - } - else { - iWidth = pcTex->mWidth; - iHeight = pcTex->mHeight; - } - - if (1 != iWidth || 1 != iHeight) { - const float fWidth = (float)iWidth; - const float fHeight = (float)iHeight; - aiMesh* pcMesh = this->pScene->mMeshes[0]; - for (unsigned int i = 0; i < pcMesh->mNumVertices;++i) - { - pcMesh->mTextureCoords[0][i].x /= fWidth; - pcMesh->mTextureCoords[0][i].y /= fHeight; - pcMesh->mTextureCoords[0][i].y = 1.0f - pcMesh->mTextureCoords[0][i].y; // DX to OGL - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Validate the header of a MDL7 file -void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader) -{ - ai_assert(NULL != pcHeader); - - // There are some fixed sizes ... - if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) { - throw DeadlyImportError( - "[3DGS MDL7] sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size"); - } - if (sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size) { - throw DeadlyImportError( - "[3DGS MDL7] sizeof(MDL::TexCoord_MDL7) != pcHeader->skinpoint_stc_size"); - } - if (sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size) { - throw DeadlyImportError( - "sizeof(MDL::Skin_MDL7) != pcHeader->skin_stc_size"); - } - - // if there are no groups ... how should we load such a file? - if(!pcHeader->groups_num) { - throw DeadlyImportError( "[3DGS MDL7] No frames found"); - } -} - -// ------------------------------------------------------------------------------------------------ -// resolve bone animation matrices -void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones) -{ - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - const MDL::Bone_MDL7* pcBones = (const MDL::Bone_MDL7*)(pcHeader+1); - ai_assert(NULL != apcOutBones); - - // first find the bone that has NO parent, calculate the - // animation matrix for it, then go on and search for the next parent - // index (0) and so on until we can't find a new node. - uint16_t iParent = 0xffff; - uint32_t iIterations = 0; - while (iIterations++ < pcHeader->bones_num) { - for (uint32_t iBone = 0; iBone < pcHeader->bones_num;++iBone) { - BE_NCONST MDL::Bone_MDL7* pcBone = _AI_MDL7_ACCESS_PTR(pcBones,iBone, - pcHeader->bone_stc_size,MDL::Bone_MDL7); - - AI_SWAP2(pcBone->parent_index); - AI_SWAP4(pcBone->x); - AI_SWAP4(pcBone->y); - AI_SWAP4(pcBone->z); - - if (iParent == pcBone->parent_index) { - // MDL7 readme - //////////////////////////////////////////////////////////////// - /* - The animation matrix is then calculated the following way: - - vector3 bPos = <absolute bone position> - matrix44 laM; // local animation matrix - sphrvector key_rotate = <bone rotation> - - matrix44 m1,m2; - create_trans_matrix(m1, -bPos.x, -bPos.y, -bPos.z); - create_trans_matrix(m2, -bPos.x, -bPos.y, -bPos.z); - - create_rotation_matrix(laM,key_rotate); - - laM = sm1 * laM; - laM = laM * sm2; - */ - ///////////////////////////////////////////////////////////////// - - MDL::IntBone_MDL7* const pcOutBone = apcOutBones[iBone]; - - // store the parent index of the bone - pcOutBone->iParent = pcBone->parent_index; - if (0xffff != iParent) { - const MDL::IntBone_MDL7* pcParentBone = apcOutBones[iParent]; - pcOutBone->mOffsetMatrix.a4 = -pcParentBone->vPosition.x; - pcOutBone->mOffsetMatrix.b4 = -pcParentBone->vPosition.y; - pcOutBone->mOffsetMatrix.c4 = -pcParentBone->vPosition.z; - } - pcOutBone->vPosition.x = pcBone->x; - pcOutBone->vPosition.y = pcBone->y; - pcOutBone->vPosition.z = pcBone->z; - pcOutBone->mOffsetMatrix.a4 -= pcBone->x; - pcOutBone->mOffsetMatrix.b4 -= pcBone->y; - pcOutBone->mOffsetMatrix.c4 -= pcBone->z; - - if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE == pcHeader->bone_stc_size) { - // no real name for our poor bone is specified :-( - pcOutBone->mName.length = ::sprintf(pcOutBone->mName.data, - "UnnamedBone_%i",iBone); - } - else { - // Make sure we won't run over the buffer's end if there is no - // terminal 0 character (however the documentation says there - // should be one) - uint32_t iMaxLen = pcHeader->bone_stc_size-16; - for (uint32_t qq = 0; qq < iMaxLen;++qq) { - if (!pcBone->name[qq]) { - iMaxLen = qq; - break; - } - } - - // store the name of the bone - pcOutBone->mName.length = (size_t)iMaxLen; - ::memcpy(pcOutBone->mName.data,pcBone->name,pcOutBone->mName.length); - pcOutBone->mName.data[pcOutBone->mName.length] = '\0'; - } - } - } - ++iParent; - } -} - -// ------------------------------------------------------------------------------------------------ -// read bones from a MDL7 file -MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7() -{ - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - if (pcHeader->bones_num) { - // validate the size of the bone data structure in the file - if (AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_20_CHARS != pcHeader->bone_stc_size && - AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size && - AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) - { - DefaultLogger::get()->warn("Unknown size of bone data structure"); - return NULL; - } - - MDL::IntBone_MDL7** apcBonesOut = new MDL::IntBone_MDL7*[pcHeader->bones_num]; - for (uint32_t crank = 0; crank < pcHeader->bones_num;++crank) - apcBonesOut[crank] = new MDL::IntBone_MDL7(); - - // and calculate absolute bone offset matrices ... - CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut); - return apcBonesOut; - } - return NULL; -} - -// ------------------------------------------------------------------------------------------------ -// read faces from a MDL7 file -void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData) -{ - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris; - - // iterate through all triangles and build valid display lists - unsigned int iOutIndex = 0; - for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) { - AI_SWAP2(pcGroupTris->v_index[0]); - AI_SWAP2(pcGroupTris->v_index[1]); - AI_SWAP2(pcGroupTris->v_index[2]); - - // iterate through all indices of the current triangle - for (unsigned int c = 0; c < 3;++c,++iOutIndex) { - - // validate the vertex index - unsigned int iIndex = pcGroupTris->v_index[c]; - if(iIndex > (unsigned int)groupInfo.pcGroup->numverts) { - // (we might need to read this section a second time - to process frame vertices correctly) - const_cast<MDL::Triangle_MDL7*>(pcGroupTris)->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1; - DefaultLogger::get()->warn("Index overflow in MDL7 vertex list"); - } - - // write the output face index - groupData.pcFaces[iTriangle].mIndices[2-c] = iOutIndex; - - aiVector3D& vPosition = groupData.vPositions[ iOutIndex ]; - vPosition.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, pcHeader->mainvertex_stc_size) .x; - vPosition.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .y; - vPosition.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .z; - - // if we have bones, save the index - if (!groupData.aiBones.empty()) { - groupData.aiBones[iOutIndex] = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts, - iIndex,pcHeader->mainvertex_stc_size).vertindex; - } - - // now read the normal vector - if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) { - // read the full normal vector - aiVector3D& vNormal = groupData.vNormals[ iOutIndex ]; - vNormal.x = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[0]; - AI_SWAP4(vNormal.x); - vNormal.y = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[1]; - AI_SWAP4(vNormal.y); - vNormal.z = _AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex,pcHeader->mainvertex_stc_size) .norm[2]; - AI_SWAP4(vNormal.z); - } - else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) { - // read the normal vector from Quake2's smart table - aiVector3D& vNormal = groupData.vNormals[ iOutIndex ]; - MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(groupInfo.pcGroupVerts,iIndex, - pcHeader->mainvertex_stc_size) .norm162index,vNormal); - } - // validate and process the first uv coordinate set - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV) { - - if (groupInfo.pcGroup->num_stpts) { - AI_SWAP2(pcGroupTris->skinsets[0].st_index[0]); - AI_SWAP2(pcGroupTris->skinsets[0].st_index[1]); - AI_SWAP2(pcGroupTris->skinsets[0].st_index[2]); - - iIndex = pcGroupTris->skinsets[0].st_index[c]; - if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { - iIndex = groupInfo.pcGroup->num_stpts-1; - DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)"); - } - - float u = groupInfo.pcGroupUVs[iIndex].u; - float v = 1.0f-groupInfo.pcGroupUVs[iIndex].v; // DX to OGL - - groupData.vTextureCoords1[iOutIndex].x = u; - groupData.vTextureCoords1[iOutIndex].y = v; - } - // assign the material index, but only if it is existing - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_ONE_UV_WITH_MATINDEX){ - AI_SWAP4(pcGroupTris->skinsets[0].material); - groupData.pcFaces[iTriangle].iMatIndex[0] = pcGroupTris->skinsets[0].material; - } - } - // validate and process the second uv coordinate set - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { - - if (groupInfo.pcGroup->num_stpts) { - AI_SWAP2(pcGroupTris->skinsets[1].st_index[0]); - AI_SWAP2(pcGroupTris->skinsets[1].st_index[1]); - AI_SWAP2(pcGroupTris->skinsets[1].st_index[2]); - AI_SWAP4(pcGroupTris->skinsets[1].material); - - iIndex = pcGroupTris->skinsets[1].st_index[c]; - if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) { - iIndex = groupInfo.pcGroup->num_stpts-1; - DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)"); - } - - float u = groupInfo.pcGroupUVs[ iIndex ].u; - float v = 1.0f-groupInfo.pcGroupUVs[ iIndex ].v; - - groupData.vTextureCoords2[ iOutIndex ].x = u; - groupData.vTextureCoords2[ iOutIndex ].y = v; // DX to OGL - - // check whether we do really need the second texture - // coordinate set ... wastes memory and loading time - if (0 != iIndex && (u != groupData.vTextureCoords1[ iOutIndex ].x || - v != groupData.vTextureCoords1[ iOutIndex ].y ) ) - groupData.bNeed2UV = true; - - // if the material differs, we need a second skin, too - if (pcGroupTris->skinsets[ 1 ].material != pcGroupTris->skinsets[ 0 ].material) - groupData.bNeed2UV = true; - } - // assign the material index - groupData.pcFaces[ iTriangle ].iMatIndex[ 1 ] = pcGroupTris->skinsets[ 1 ].material; - } - } - // get the next triangle in the list - pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*)pcGroupTris + pcHeader->triangle_stc_size); - } -} - -// ------------------------------------------------------------------------------------------------ -// handle frames in a MDL7 file -bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData, - MDL::IntSharedData_MDL7& shared, - const unsigned char* szCurrent, - const unsigned char** szCurrentOut) -{ - ai_assert(NULL != szCurrent && NULL != szCurrentOut); - const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7*)mBuffer; - - // if we have no bones we can simply skip all frames, - // otherwise we'll need to process them. - // FIX: If we need another frame than the first we must apply frame vertex replacements ... - for(unsigned int iFrame = 0; iFrame < (unsigned int)groupInfo.pcGroup->numframes;++iFrame) { - MDL::IntFrameInfo_MDL7 frame ((BE_NCONST MDL::Frame_MDL7*)szCurrent,iFrame); - - AI_SWAP4(frame.pcFrame->vertices_count); - AI_SWAP4(frame.pcFrame->transmatrix_count); - - const unsigned int iAdd = pcHeader->frame_stc_size + - frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size + - frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size; - - if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size) { - DefaultLogger::get()->warn("Index overflow in frame area. " - "Ignoring all frames and all further mesh groups, too."); - - // don't parse more groups if we can't even read one - // FIXME: sometimes this seems to occur even for valid files ... - *szCurrentOut = szCurrent; - return false; - } - // our output frame? - if (configFrameID == iFrame) { - BE_NCONST MDL::Vertex_MDL7* pcFrameVertices = (BE_NCONST MDL::Vertex_MDL7*)(szCurrent+pcHeader->frame_stc_size); - - for (unsigned int qq = 0; qq < frame.pcFrame->vertices_count;++qq) { - // I assume this are simple replacements for normal vertices, the bone index serving - // as the index of the vertex to be replaced. - uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex; - AI_SWAP2(iIndex); - if (iIndex >= groupInfo.pcGroup->numverts) { - DefaultLogger::get()->warn("Invalid vertex index in frame vertex section"); - continue; - } - - aiVector3D vPosition,vNormal; - - vPosition.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .x; - AI_SWAP4(vPosition.x); - vPosition.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .y; - AI_SWAP4(vPosition.y); - vPosition.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .z; - AI_SWAP4(vPosition.z); - - // now read the normal vector - if (AI_MDL7_FRAMEVERTEX030305_STCSIZE <= pcHeader->mainvertex_stc_size) { - // read the full normal vector - vNormal.x = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[0]; - AI_SWAP4(vNormal.x); - vNormal.y = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[1]; - AI_SWAP4(vNormal.y); - vNormal.z = _AI_MDL7_ACCESS_VERT(pcFrameVertices,qq,pcHeader->framevertex_stc_size) .norm[2]; - AI_SWAP4(vNormal.z); - } - else if (AI_MDL7_FRAMEVERTEX120503_STCSIZE <= pcHeader->mainvertex_stc_size) { - // read the normal vector from Quake2's smart table - MD2::LookupNormalIndex(_AI_MDL7_ACCESS_VERT(pcFrameVertices,qq, - pcHeader->framevertex_stc_size) .norm162index,vNormal); - } - - // FIXME: O(n^2) at the moment ... - BE_NCONST MDL::Triangle_MDL7* pcGroupTris = groupInfo.pcGroupTris; - unsigned int iOutIndex = 0; - for (unsigned int iTriangle = 0; iTriangle < (unsigned int)groupInfo.pcGroup->numtris; ++iTriangle) { - // iterate through all indices of the current triangle - for (unsigned int c = 0; c < 3;++c,++iOutIndex) { - // replace the vertex with the new data - const unsigned int iCurIndex = pcGroupTris->v_index[c]; - if (iCurIndex == iIndex) { - groupData.vPositions[iOutIndex] = vPosition; - groupData.vNormals[iOutIndex] = vNormal; - } - } - // get the next triangle in the list - pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)((const char*) - pcGroupTris + pcHeader->triangle_stc_size); - } - } - } - // parse bone trafo matrix keys (only if there are bones ...) - if (shared.apcOutBones) { - ParseBoneTrafoKeys_3DGS_MDL7(groupInfo,frame,shared); - } - szCurrent += iAdd; - } - *szCurrentOut = szCurrent; - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Sort faces by material, handle multiple UVs correctly -void MDLImporter::SortByMaterials_3DGS_MDL7( - const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData, - MDL::IntSplittedGroupData_MDL7& splittedGroupData) -{ - const unsigned int iNumMaterials = (unsigned int)splittedGroupData.shared.pcMats.size(); - if (!groupData.bNeed2UV) { - // if we don't need a second set of texture coordinates there is no reason to keep it in memory ... - groupData.vTextureCoords2.clear(); - - // allocate the array - splittedGroupData.aiSplit = new std::vector<unsigned int>*[iNumMaterials]; - - for (unsigned int m = 0; m < iNumMaterials;++m) - splittedGroupData.aiSplit[m] = new std::vector<unsigned int>(); - - // iterate through all faces and sort by material - for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) { - // check range - if (groupData.pcFaces[iFace].iMatIndex[0] >= iNumMaterials) { - // use the last material instead - splittedGroupData.aiSplit[iNumMaterials-1]->push_back(iFace); - - // sometimes MED writes -1, but normally only if there is only - // one skin assigned. No warning in this case - if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0]) - DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]"); - } - else splittedGroupData.aiSplit[groupData.pcFaces[iFace]. - iMatIndex[0]]->push_back(iFace); - } - } - else - { - // we need to build combined materials for each combination of - std::vector<MDL::IntMaterial_MDL7> avMats; - avMats.reserve(iNumMaterials*2); - - // fixme: why on the heap? - std::vector<std::vector<unsigned int>* > aiTempSplit(iNumMaterials*2); - for (unsigned int m = 0; m < iNumMaterials;++m) - aiTempSplit[m] = new std::vector<unsigned int>(); - - // iterate through all faces and sort by material - for (unsigned int iFace = 0; iFace < (unsigned int)groupInfo.pcGroup->numtris;++iFace) { - // check range - unsigned int iMatIndex = groupData.pcFaces[iFace].iMatIndex[0]; - if (iMatIndex >= iNumMaterials) { - // sometimes MED writes -1, but normally only if there is only - // one skin assigned. No warning in this case - if(0xffffffff != iMatIndex) - DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]"); - iMatIndex = iNumMaterials-1; - } - unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1]; - - unsigned int iNum = iMatIndex; - if (0xffffffff != iMatIndex2 && iMatIndex != iMatIndex2) { - if (iMatIndex2 >= iNumMaterials) { - // sometimes MED writes -1, but normally only if there is only - // one skin assigned. No warning in this case - DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]"); - iMatIndex2 = iNumMaterials-1; - } - - // do a slow seach in the list ... - iNum = 0; - bool bFound = false; - for (std::vector<MDL::IntMaterial_MDL7>::iterator i = avMats.begin();i != avMats.end();++i,++iNum){ - if ((*i).iOldMatIndices[0] == iMatIndex && (*i).iOldMatIndices[1] == iMatIndex2) { - // reuse this material - bFound = true; - break; - } - } - if (!bFound) { - // build a new material ... - MDL::IntMaterial_MDL7 sHelper; - sHelper.pcMat = new MaterialHelper(); - sHelper.iOldMatIndices[0] = iMatIndex; - sHelper.iOldMatIndices[1] = iMatIndex2; - JoinSkins_3DGS_MDL7(splittedGroupData.shared.pcMats[iMatIndex], - splittedGroupData.shared.pcMats[iMatIndex2],sHelper.pcMat); - - // and add it to the list - avMats.push_back(sHelper); - iNum = (unsigned int)avMats.size()-1; - } - // adjust the size of the file array - if (iNum == aiTempSplit.size()) { - aiTempSplit.push_back(new std::vector<unsigned int>()); - } - } - aiTempSplit[iNum]->push_back(iFace); - } - - // now add the newly created materials to the old list - if (0 == groupInfo.iIndex) { - splittedGroupData.shared.pcMats.resize(avMats.size()); - for (unsigned int o = 0; o < avMats.size();++o) - splittedGroupData.shared.pcMats[o] = avMats[o].pcMat; - } - else { - // This might result in redundant materials ... - splittedGroupData.shared.pcMats.resize(iNumMaterials + avMats.size()); - for (unsigned int o = iNumMaterials; o < avMats.size();++o) - splittedGroupData.shared.pcMats[o] = avMats[o].pcMat; - } - - // and build the final face-to-material array - splittedGroupData.aiSplit = new std::vector<unsigned int>*[aiTempSplit.size()]; - for (unsigned int m = 0; m < iNumMaterials;++m) - splittedGroupData.aiSplit[m] = aiTempSplit[m]; - } -} - -// ------------------------------------------------------------------------------------------------ -// Read a MDL7 file -void MDLImporter::InternReadFile_3DGS_MDL7( ) -{ - ai_assert(NULL != pScene); - - MDL::IntSharedData_MDL7 sharedData; - - // current cursor position in the file - BE_NCONST MDL::Header_MDL7 *pcHeader = (BE_NCONST MDL::Header_MDL7*)this->mBuffer; - const unsigned char* szCurrent = (const unsigned char*)(pcHeader+1); - - AI_SWAP4(pcHeader->version); - AI_SWAP4(pcHeader->bones_num); - AI_SWAP4(pcHeader->groups_num); - AI_SWAP4(pcHeader->data_size); - AI_SWAP4(pcHeader->entlump_size); - AI_SWAP4(pcHeader->medlump_size); - AI_SWAP2(pcHeader->bone_stc_size); - AI_SWAP2(pcHeader->skin_stc_size); - AI_SWAP2(pcHeader->colorvalue_stc_size); - AI_SWAP2(pcHeader->material_stc_size); - AI_SWAP2(pcHeader->skinpoint_stc_size); - AI_SWAP2(pcHeader->triangle_stc_size); - AI_SWAP2(pcHeader->mainvertex_stc_size); - AI_SWAP2(pcHeader->framevertex_stc_size); - AI_SWAP2(pcHeader->bonetrans_stc_size); - AI_SWAP2(pcHeader->frame_stc_size); - - // validate the header of the file. There are some structure - // sizes that are expected by the loader to be constant - this->ValidateHeader_3DGS_MDL7(pcHeader); - - // load all bones (they are shared by all groups, so - // we'll need to add them to all groups/meshes later) - // apcBonesOut is a list of all bones or NULL if they could not been loaded - szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size; - sharedData.apcOutBones = this->LoadBones_3DGS_MDL7(); - - // vector to held all created meshes - std::vector<aiMesh*>* avOutList; - - // 3 meshes per group - that should be OK for most models - avOutList = new std::vector<aiMesh*>[pcHeader->groups_num]; - for (uint32_t i = 0; i < pcHeader->groups_num;++i) - avOutList[i].reserve(3); - - // buffer to held the names of all groups in the file - char* aszGroupNameBuffer = new char[AI_MDL7_MAX_GROUPNAMESIZE*pcHeader->groups_num]; - - // read all groups - for (unsigned int iGroup = 0; iGroup < (unsigned int)pcHeader->groups_num;++iGroup) { - MDL::IntGroupInfo_MDL7 groupInfo((BE_NCONST MDL::Group_MDL7*)szCurrent,iGroup); - szCurrent = (const unsigned char*)(groupInfo.pcGroup+1); - - VALIDATE_FILE_SIZE(szCurrent); - - AI_SWAP4(groupInfo.pcGroup->groupdata_size); - AI_SWAP4(groupInfo.pcGroup->numskins); - AI_SWAP4(groupInfo.pcGroup->num_stpts); - AI_SWAP4(groupInfo.pcGroup->numtris); - AI_SWAP4(groupInfo.pcGroup->numverts); - AI_SWAP4(groupInfo.pcGroup->numframes); - - if (1 != groupInfo.pcGroup->typ) { - // Not a triangle-based mesh - DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily"); - } - - // store the name of the group - const unsigned int ofs = iGroup*AI_MDL7_MAX_GROUPNAMESIZE; - ::memcpy(&aszGroupNameBuffer[ofs], - groupInfo.pcGroup->name,AI_MDL7_MAX_GROUPNAMESIZE); - - // make sure '\0' is at the end - aszGroupNameBuffer[ofs+AI_MDL7_MAX_GROUPNAMESIZE-1] = '\0'; - - // read all skins - sharedData.pcMats.reserve(sharedData.pcMats.size() + groupInfo.pcGroup->numskins); - sharedData.abNeedMaterials.resize(sharedData.abNeedMaterials.size() + - groupInfo.pcGroup->numskins,false); - - for (unsigned int iSkin = 0; iSkin < (unsigned int)groupInfo.pcGroup->numskins;++iSkin) { - ParseSkinLump_3DGS_MDL7(szCurrent,&szCurrent,sharedData.pcMats); - } - // if we have absolutely no skin loaded we need to generate a default material - if (sharedData.pcMats.empty()) { - const int iMode = (int)aiShadingMode_Gouraud; - sharedData.pcMats.push_back(new MaterialHelper()); - MaterialHelper* pcHelper = (MaterialHelper*)sharedData.pcMats[0]; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor3D clr; - clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - aiString szName; - szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); - - sharedData.abNeedMaterials.resize(1,false); - } - - // now get a pointer to all texture coords in the group - groupInfo.pcGroupUVs = (BE_NCONST MDL::TexCoord_MDL7*)szCurrent; - for(int i = 0; i < groupInfo.pcGroup->num_stpts; ++i){ - AI_SWAP4(groupInfo.pcGroupUVs[i].u); - AI_SWAP4(groupInfo.pcGroupUVs[i].v); - } - szCurrent += pcHeader->skinpoint_stc_size * groupInfo.pcGroup->num_stpts; - - // now get a pointer to all triangle in the group - groupInfo.pcGroupTris = (BE_NCONST MDL::Triangle_MDL7*)szCurrent; - szCurrent += pcHeader->triangle_stc_size * groupInfo.pcGroup->numtris; - - // now get a pointer to all vertices in the group - groupInfo.pcGroupVerts = (BE_NCONST MDL::Vertex_MDL7*)szCurrent; - for(int i = 0; i < groupInfo.pcGroup->numverts; ++i){ - AI_SWAP4(groupInfo.pcGroupVerts[i].x); - AI_SWAP4(groupInfo.pcGroupVerts[i].y); - AI_SWAP4(groupInfo.pcGroupVerts[i].z); - - AI_SWAP2(groupInfo.pcGroupVerts[i].vertindex); - //We can not swap the normal information now as we don't know which of the two kinds it is - } - szCurrent += pcHeader->mainvertex_stc_size * groupInfo.pcGroup->numverts; - VALIDATE_FILE_SIZE(szCurrent); - - MDL::IntSplittedGroupData_MDL7 splittedGroupData(sharedData,avOutList[iGroup]); - MDL::IntGroupData_MDL7 groupData; - if (groupInfo.pcGroup->numtris && groupInfo.pcGroup->numverts) - { - // build output vectors - const unsigned int iNumVertices = groupInfo.pcGroup->numtris*3; - groupData.vPositions.resize(iNumVertices); - groupData.vNormals.resize(iNumVertices); - - if (sharedData.apcOutBones)groupData.aiBones.resize(iNumVertices,0xffffffff); - - // it is also possible that there are 0 UV coordinate sets - if (groupInfo.pcGroup->num_stpts){ - groupData.vTextureCoords1.resize(iNumVertices,aiVector3D()); - - // check whether the triangle data structure is large enough - // to contain a second UV coodinate set - if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV) { - groupData.vTextureCoords2.resize(iNumVertices,aiVector3D()); - groupData.bNeed2UV = true; - } - } - groupData.pcFaces = new MDL::IntFace_MDL7[groupInfo.pcGroup->numtris]; - - // read all faces into the preallocated arrays - ReadFaces_3DGS_MDL7(groupInfo, groupData); - - // sort by materials - SortByMaterials_3DGS_MDL7(groupInfo, groupData, - splittedGroupData); - - for (unsigned int qq = 0; qq < sharedData.pcMats.size();++qq) { - if (!splittedGroupData.aiSplit[qq]->empty()) - sharedData.abNeedMaterials[qq] = true; - } - } - else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 " - "vertices or faces. It will be skipped."); - - // process all frames and generate output meshes - ProcessFrames_3DGS_MDL7(groupInfo,groupData, sharedData,szCurrent,&szCurrent); - GenerateOutputMeshes_3DGS_MDL7(groupData,splittedGroupData); - } - - // generate a nodegraph and subnodes for each group - pScene->mRootNode = new aiNode(); - - // now we need to build a final mesh list - for (uint32_t i = 0; i < pcHeader->groups_num;++i) - pScene->mNumMeshes += (unsigned int)avOutList[i].size(); - - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; { - unsigned int p = 0,q = 0; - for (uint32_t i = 0; i < pcHeader->groups_num;++i) { - for (unsigned int a = 0; a < avOutList[i].size();++a) { - pScene->mMeshes[p++] = avOutList[i][a]; - } - if (!avOutList[i].empty())++pScene->mRootNode->mNumChildren; - } - // we will later need an extra node to serve as parent for all bones - if (sharedData.apcOutBones)++pScene->mRootNode->mNumChildren; - this->pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; - p = 0; - for (uint32_t i = 0; i < pcHeader->groups_num;++i) { - if (avOutList[i].empty())continue; - - aiNode* const pcNode = pScene->mRootNode->mChildren[p] = new aiNode(); - pcNode->mNumMeshes = (unsigned int)avOutList[i].size(); - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - pcNode->mParent = this->pScene->mRootNode; - for (unsigned int a = 0; a < pcNode->mNumMeshes;++a) - pcNode->mMeshes[a] = q + a; - q += (unsigned int)avOutList[i].size(); - - // setup the name of the node - char* const szBuffer = &aszGroupNameBuffer[i*AI_MDL7_MAX_GROUPNAMESIZE]; - if ('\0' == *szBuffer) - pcNode->mName.length = ::sprintf(szBuffer,"Group_%i",p); - else pcNode->mName.length = ::strlen(szBuffer); - ::strcpy(pcNode->mName.data,szBuffer); - ++p; - } - } - - // if there is only one root node with a single child we can optimize it a bit ... - if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) { - aiNode* pcOldRoot = this->pScene->mRootNode; - pScene->mRootNode = pcOldRoot->mChildren[0]; - pcOldRoot->mChildren[0] = NULL; - delete pcOldRoot; - pScene->mRootNode->mParent = NULL; - } - else pScene->mRootNode->mName.Set("<mesh_root>"); - - delete[] avOutList; - delete[] aszGroupNameBuffer; - AI_DEBUG_INVALIDATE_PTR(avOutList); - AI_DEBUG_INVALIDATE_PTR(aszGroupNameBuffer); - - // build a final material list. - CopyMaterials_3DGS_MDL7(sharedData); - HandleMaterialReferences_3DGS_MDL7(); - - // generate output bone animations and add all bones to the scenegraph - if (sharedData.apcOutBones) { - // this step adds empty dummy bones to the nodegraph - // insert another dummy node to avoid name conflicts - aiNode* const pc = pScene->mRootNode->mChildren[pScene->mRootNode->mNumChildren-1] = new aiNode(); - - pc->mName.Set("<skeleton_root>"); - - // add bones to the nodegraph - AddBonesToNodeGraph_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **) - sharedData.apcOutBones,pc,0xffff); - - // this steps build a valid output animation - BuildOutputAnims_3DGS_MDL7((const Assimp::MDL::IntBone_MDL7 **) - sharedData.apcOutBones); - } -} - -// ------------------------------------------------------------------------------------------------ -// Copy materials -void MDLImporter::CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared) -{ - pScene->mNumMaterials = (unsigned int)shared.pcMats.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - pScene->mMaterials[i] = shared.pcMats[i]; -} - - -// ------------------------------------------------------------------------------------------------ -// Process material references -void MDLImporter::HandleMaterialReferences_3DGS_MDL7() -{ - // search for referrer materials - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - int iIndex = 0; - if (AI_SUCCESS == aiGetMaterialInteger(pScene->mMaterials[i],AI_MDL7_REFERRER_MATERIAL, &iIndex) ) { - for (unsigned int a = 0; a < pScene->mNumMeshes;++a) { - aiMesh* const pcMesh = pScene->mMeshes[a]; - if (i == pcMesh->mMaterialIndex) { - pcMesh->mMaterialIndex = iIndex; - } - } - // collapse the rest of the array - delete pScene->mMaterials[i]; - for (unsigned int pp = i; pp < pScene->mNumMaterials-1;++pp) { - - pScene->mMaterials[pp] = pScene->mMaterials[pp+1]; - for (unsigned int a = 0; a < pScene->mNumMeshes;++a) { - aiMesh* const pcMesh = pScene->mMeshes[a]; - if (pcMesh->mMaterialIndex > i)--pcMesh->mMaterialIndex; - } - } - --pScene->mNumMaterials; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Read bone transformation keys -void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7( - const MDL::IntGroupInfo_MDL7& groupInfo, - IntFrameInfo_MDL7& frame, - MDL::IntSharedData_MDL7& shared) -{ - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - - // only the first group contains bone animation keys - if (frame.pcFrame->transmatrix_count) { - if (!groupInfo.iIndex) { - // skip all frames vertices. We can't support them - const MDL::BoneTransform_MDL7* pcBoneTransforms = (const MDL::BoneTransform_MDL7*) - (((const char*)frame.pcFrame) + pcHeader->frame_stc_size + - frame.pcFrame->vertices_count * pcHeader->framevertex_stc_size); - - // read all transformation matrices - for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo) { - if(pcBoneTransforms->bone_index >= pcHeader->bones_num) { - DefaultLogger::get()->warn("Index overflow in frame area. " - "Unable to parse this bone transformation"); - } - else { - AddAnimationBoneTrafoKey_3DGS_MDL7(frame.iIndex, - pcBoneTransforms,shared.apcOutBones); - } - pcBoneTransforms = (const MDL::BoneTransform_MDL7*)( - (const char*)pcBoneTransforms + pcHeader->bonetrans_stc_size); - } - } - else { - DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0"); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Attach bones to the output nodegraph -void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBones, - aiNode* pcParent,uint16_t iParentIndex) -{ - ai_assert(NULL != apcBones && NULL != pcParent); - - // get a pointer to the header ... - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - - const MDL::IntBone_MDL7** apcBones2 = apcBones; - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { - - const MDL::IntBone_MDL7* const pcBone = *apcBones2++; - if (pcBone->iParent == iParentIndex) { - ++pcParent->mNumChildren; - } - } - pcParent->mChildren = new aiNode*[pcParent->mNumChildren]; - unsigned int qq = 0; - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { - - const MDL::IntBone_MDL7* const pcBone = *apcBones++; - if (pcBone->iParent != iParentIndex)continue; - - aiNode* pcNode = pcParent->mChildren[qq++] = new aiNode(); - pcNode->mName = aiString( pcBone->mName ); - - AddBonesToNodeGraph_3DGS_MDL7(apcBones,pcNode,(uint16_t)i); - } -} - -// ------------------------------------------------------------------------------------------------ -// Build output animations -void MDLImporter::BuildOutputAnims_3DGS_MDL7( - const MDL::IntBone_MDL7** apcBonesOut) -{ - ai_assert(NULL != apcBonesOut); - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)mBuffer; - - // one animation ... - aiAnimation* pcAnim = new aiAnimation(); - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { - if (!apcBonesOut[i]->pkeyPositions.empty()) { - - // get the last frame ... (needn't be equal to pcHeader->frames_num) - for (size_t qq = 0; qq < apcBonesOut[i]->pkeyPositions.size();++qq) { - pcAnim->mDuration = std::max(pcAnim->mDuration, (double) - apcBonesOut[i]->pkeyPositions[qq].mTime); - } - ++pcAnim->mNumChannels; - } - } - if (pcAnim->mDuration) { - pcAnim->mChannels = new aiNodeAnim*[pcAnim->mNumChannels]; - - unsigned int iCnt = 0; - for (uint32_t i = 0; i < pcHeader->bones_num;++i) { - if (!apcBonesOut[i]->pkeyPositions.empty()) { - const MDL::IntBone_MDL7* const intBone = apcBonesOut[i]; - - aiNodeAnim* const pcNodeAnim = pcAnim->mChannels[iCnt++] = new aiNodeAnim(); - pcNodeAnim->mNodeName = aiString( intBone->mName ); - - // allocate enough storage for all keys - pcNodeAnim->mNumPositionKeys = (unsigned int)intBone->pkeyPositions.size(); - pcNodeAnim->mNumScalingKeys = (unsigned int)intBone->pkeyPositions.size(); - pcNodeAnim->mNumRotationKeys = (unsigned int)intBone->pkeyPositions.size(); - - pcNodeAnim->mPositionKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys]; - pcNodeAnim->mScalingKeys = new aiVectorKey[pcNodeAnim->mNumPositionKeys]; - pcNodeAnim->mRotationKeys = new aiQuatKey[pcNodeAnim->mNumPositionKeys]; - - // copy all keys - for (unsigned int qq = 0; qq < pcNodeAnim->mNumPositionKeys;++qq) { - pcNodeAnim->mPositionKeys[qq] = intBone->pkeyPositions[qq]; - pcNodeAnim->mScalingKeys[qq] = intBone->pkeyScalings[qq]; - pcNodeAnim->mRotationKeys[qq] = intBone->pkeyRotations[qq]; - } - } - } - - // store the output animation - pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[1]; - pScene->mAnimations[0] = pcAnim; - } - else delete pcAnim; -} - -// ------------------------------------------------------------------------------------------------ -void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo, - const MDL::BoneTransform_MDL7* pcBoneTransforms, - MDL::IntBone_MDL7** apcBonesOut) -{ - ai_assert(NULL != pcBoneTransforms); - ai_assert(NULL != apcBonesOut); - - // first .. get the transformation matrix - aiMatrix4x4 mTransform; - mTransform.a1 = pcBoneTransforms->m[0]; - mTransform.b1 = pcBoneTransforms->m[1]; - mTransform.c1 = pcBoneTransforms->m[2]; - mTransform.d1 = pcBoneTransforms->m[3]; - - mTransform.a2 = pcBoneTransforms->m[4]; - mTransform.b2 = pcBoneTransforms->m[5]; - mTransform.c2 = pcBoneTransforms->m[6]; - mTransform.d2 = pcBoneTransforms->m[7]; - - mTransform.a3 = pcBoneTransforms->m[8]; - mTransform.b3 = pcBoneTransforms->m[9]; - mTransform.c3 = pcBoneTransforms->m[10]; - mTransform.d3 = pcBoneTransforms->m[11]; - - // now decompose the transformation matrix into separate - // scaling, rotation and translation - aiVectorKey vScaling,vPosition; - aiQuatKey qRotation; - - // FIXME: Decompose will assert in debug builds if the matrix is invalid ... - mTransform.Decompose(vScaling.mValue,qRotation.mValue,vPosition.mValue); - - // now generate keys - vScaling.mTime = qRotation.mTime = vPosition.mTime = (double)iTrafo; - - // add the keys to the bone - MDL::IntBone_MDL7* const pcBoneOut = apcBonesOut[pcBoneTransforms->bone_index]; - pcBoneOut->pkeyPositions.push_back ( vPosition ); - pcBoneOut->pkeyScalings.push_back ( vScaling ); - pcBoneOut->pkeyRotations.push_back ( qRotation ); -} - -// ------------------------------------------------------------------------------------------------ -// Construct output meshes -void MDLImporter::GenerateOutputMeshes_3DGS_MDL7( - MDL::IntGroupData_MDL7& groupData, - MDL::IntSplittedGroupData_MDL7& splittedGroupData) -{ - const MDL::IntSharedData_MDL7& shared = splittedGroupData.shared; - - // get a pointer to the header ... - const MDL::Header_MDL7* const pcHeader = (const MDL::Header_MDL7*)this->mBuffer; - const unsigned int iNumOutBones = pcHeader->bones_num; - - for (std::vector<MaterialHelper*>::size_type i = 0; i < shared.pcMats.size();++i) { - if (!splittedGroupData.aiSplit[i]->empty()) { - - // allocate the output mesh - aiMesh* pcMesh = new aiMesh(); - - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pcMesh->mMaterialIndex = (unsigned int)i; - - // allocate output storage - pcMesh->mNumFaces = (unsigned int)splittedGroupData.aiSplit[i]->size(); - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - - pcMesh->mNumVertices = pcMesh->mNumFaces*3; - pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - - if (!groupData.vTextureCoords1.empty()) { - pcMesh->mNumUVComponents[0] = 2; - pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - if (!groupData.vTextureCoords2.empty()) { - pcMesh->mNumUVComponents[1] = 2; - pcMesh->mTextureCoords[1] = new aiVector3D[pcMesh->mNumVertices]; - } - } - - // iterate through all faces and build an unique set of vertices - unsigned int iCurrent = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { - pcMesh->mFaces[iFace].mNumIndices = 3; - pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; - - unsigned int iSrcFace = splittedGroupData.aiSplit[i]->operator[](iFace); - const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace]; - - // iterate through all face indices - for (unsigned int c = 0; c < 3;++c) { - const uint32_t iIndex = oldFace.mIndices[c]; - pcMesh->mVertices[iCurrent] = groupData.vPositions[iIndex]; - pcMesh->mNormals[iCurrent] = groupData.vNormals[iIndex]; - - if (!groupData.vTextureCoords1.empty()) { - - pcMesh->mTextureCoords[0][iCurrent] = groupData.vTextureCoords1[iIndex]; - if (!groupData.vTextureCoords2.empty()) { - pcMesh->mTextureCoords[1][iCurrent] = groupData.vTextureCoords2[iIndex]; - } - } - pcMesh->mFaces[iFace].mIndices[c] = iCurrent++; - } - } - - // if we have bones in the mesh we'll need to generate - // proper vertex weights for them - if (!groupData.aiBones.empty()) { - std::vector<std::vector<unsigned int> > aaiVWeightList; - aaiVWeightList.resize(iNumOutBones); - - int iCurrent = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) { - unsigned int iSrcFace = splittedGroupData.aiSplit[i]->operator[](iFace); - const MDL::IntFace_MDL7& oldFace = groupData.pcFaces[iSrcFace]; - - // iterate through all face indices - for (unsigned int c = 0; c < 3;++c) { - unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ]; - if (0xffffffff != iBone) { - if (iBone >= iNumOutBones) { - DefaultLogger::get()->error("Bone index overflow. " - "The bone index of a vertex exceeds the allowed range. "); - iBone = iNumOutBones-1; - } - aaiVWeightList[ iBone ].push_back ( iCurrent ); - } - ++iCurrent; - } - } - // now check which bones are required ... - for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k != aaiVWeightList.end();++k) { - if (!(*k).empty()) { - ++pcMesh->mNumBones; - } - } - pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; - iCurrent = 0; - for (std::vector<std::vector<unsigned int> >::const_iterator k = aaiVWeightList.begin();k!= aaiVWeightList.end();++k,++iCurrent) - { - if ((*k).empty()) - continue; - - // seems we'll need this node - aiBone* pcBone = pcMesh->mBones[ iCurrent ] = new aiBone(); - pcBone->mName = aiString(shared.apcOutBones[ iCurrent ]->mName); - pcBone->mOffsetMatrix = shared.apcOutBones[ iCurrent ]->mOffsetMatrix; - - // setup vertex weights - pcBone->mNumWeights = (unsigned int)(*k).size(); - pcBone->mWeights = new aiVertexWeight[pcBone->mNumWeights]; - - for (unsigned int weight = 0; weight < pcBone->mNumWeights;++weight) { - pcBone->mWeights[weight].mVertexId = (*k)[weight]; - pcBone->mWeights[weight].mWeight = 1.0f; - } - } - } - // add the mesh to the list of output meshes - splittedGroupData.avOutList.push_back(pcMesh); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Join to materials -void MDLImporter::JoinSkins_3DGS_MDL7( - MaterialHelper* pcMat1, - MaterialHelper* pcMat2, - MaterialHelper* pcMatOut) -{ - ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut); - - // first create a full copy of the first skin property set - // and assign it to the output material - MaterialHelper::CopyPropertyList(pcMatOut,pcMat1); - - int iVal = 0; - pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(0)); - - // then extract the diffuse texture from the second skin, - // setup 1 as UV source and we have it - aiString sString; - if(AI_SUCCESS == aiGetMaterialString ( pcMat2, AI_MATKEY_TEXTURE_DIFFUSE(0),&sString )) { - iVal = 1; - pcMatOut->AddProperty<int>(&iVal,1,AI_MATKEY_UVWSRC_DIFFUSE(1)); - pcMatOut->AddProperty(&sString,AI_MATKEY_TEXTURE_DIFFUSE(1)); - } -} - -// ------------------------------------------------------------------------------------------------ -// Read a half-life 2 MDL -void MDLImporter::InternReadFile_HL2( ) -{ - //const MDL::Header_HL2* pcHeader = (const MDL::Header_HL2*)this->mBuffer; - throw DeadlyImportError("HL2 MDLs are not implemented"); -} - -#endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER diff --git a/3rdparty/assimp/code/MDLLoader.h b/3rdparty/assimp/code/MDLLoader.h deleted file mode 100644 index 34c101fc..00000000 --- a/3rdparty/assimp/code/MDLLoader.h +++ /dev/null @@ -1,460 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MDLLoader.h - * @brief Declaration of the loader for MDL files - */ - -#ifndef AI_MDLLOADER_H_INCLUDED -#define AI_MDLLOADER_H_INCLUDED - -#include "BaseImporter.h" - -struct aiNode; -#include "MDLFileData.h" -#include "HalfLifeFileData.h" - -namespace Assimp { -class MaterialHelper; - -using namespace MDL; - -// -------------------------------------------------------------------------------------- -// Include file/line information in debug builds -#ifdef ASSIMP_BUILD_DEBUG -# define VALIDATE_FILE_SIZE(msg) SizeCheck(msg,__FILE__,__LINE__) -#else -# define VALIDATE_FILE_SIZE(msg) SizeCheck(msg) -#endif - -// -------------------------------------------------------------------------------------- -/** @brief Class to load MDL files. - * - * Several subformats exist: - * <ul> - * <li>Quake I</li> - * <li>3D Game Studio MDL3, MDL4</li> - * <li>3D Game Studio MDL5</li> - * <li>3D Game Studio MDL7</li> - * <li>Halflife 2</li> - * </ul> - * These formats are partially identical and it would be possible to load - * them all with a single 1000-line function-beast. However, it has been - * splitted to several code paths to make the code easier to read and maintain. -*/ -class MDLImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - MDLImporter(); - - /** Destructor, private as well */ - ~MDLImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - - // ------------------------------------------------------------------- - /** Import a quake 1 MDL file (IDPO) - */ - void InternReadFile_Quake1( ); - - // ------------------------------------------------------------------- - /** Import a GameStudio A4/A5 file (MDL 3,4,5) - */ - void InternReadFile_3DGS_MDL345( ); - - // ------------------------------------------------------------------- - /** Import a GameStudio A7 file (MDL 7) - */ - void InternReadFile_3DGS_MDL7( ); - - // ------------------------------------------------------------------- - /** Import a CS:S/HL2 MDL file (not fully implemented) - */ - void InternReadFile_HL2( ); - - // ------------------------------------------------------------------- - /** Check whether a given position is inside the valid range - * Throw a DeadlyImportError if it is not - * \param szPos Cursor position - * \param szFile Name of the source file from which the function was called - * \param iLine Source code line from which the function was called - */ - void SizeCheck(const void* szPos); - void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine); - - - // ------------------------------------------------------------------- - /** Validate the header data structure of a game studio MDL7 file - * \param pcHeader Input header to be validated - */ - void ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7* pcHeader); - - // ------------------------------------------------------------------- - /** Validate the header data structure of a Quake 1 model - * \param pcHeader Input header to be validated - */ - void ValidateHeader_Quake1(const MDL::Header* pcHeader); - - - // ------------------------------------------------------------------- - /** Try to load a palette from the current directory (colormap.lmp) - * If it is not found the default palette of Quake1 is returned - */ - void SearchPalette(const unsigned char** pszColorMap); - - // ------------------------------------------------------------------- - /** Free a palette created with a previous call to SearchPalette() - */ - void FreePalette(const unsigned char* pszColorMap); - - - // ------------------------------------------------------------------- - /** Load a paletized texture from the file and convert it to 32bpp - */ - void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData); - - // ------------------------------------------------------------------- - /** Used to load textures from MDL3/4 - * \param szData Input data - * \param iType Color data type - * \param piSkip Receive: Size to skip, in bytes - */ - void CreateTexture_3DGS_MDL4(const unsigned char* szData, - unsigned int iType, - unsigned int* piSkip); - - - // ------------------------------------------------------------------- - /** Used to load textures from MDL5 - * \param szData Input data - * \param iType Color data type - * \param piSkip Receive: Size to skip, in bytes - */ - void CreateTexture_3DGS_MDL5(const unsigned char* szData, - unsigned int iType, - unsigned int* piSkip); - - - // ------------------------------------------------------------------- - /** Checks whether a texture can be replaced with a single color - * This is useful for all file formats before MDL7 (all those - * that are not containing material colors separate from textures). - * MED seems to write dummy 8x8 monochrome images instead. - * \param pcTexture Input texture - * \return aiColor.r is set to qnan if the function fails and no - * color can be found. - */ - aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture); - - - // ------------------------------------------------------------------- - /** Converts the absolute texture coordinates in MDL5 files to - * relative in a range between 0 and 1 - */ - void CalculateUVCoordinates_MDL5(); - - - // ------------------------------------------------------------------- - /** Read an UV coordinate from the file. If the file format is not - * MDL5, the function calculates relative texture coordinates - * \param vOut Receives the output UV coord - * \param pcSrc UV coordinate buffer - * \param UV coordinate index - */ - void ImportUVCoordinate_3DGS_MDL345( aiVector3D& vOut, - const MDL::TexCoord_MDL3* pcSrc, - unsigned int iIndex); - - // ------------------------------------------------------------------- - /** Setup the material properties for Quake and MDL<7 models. - * These formats don't support more than one material per mesh, - * therefore the method processes only ONE skin and removes - * all others. - */ - void SetupMaterialProperties_3DGS_MDL5_Quake1( ); - - - // ------------------------------------------------------------------- - /** Parse a skin lump in a MDL7/HMP7 file with all of its features - * variant 1: Current cursor position is the beginning of the skin header - * \param szCurrent Current data pointer - * \param szCurrentOut Output data pointer - * \param pcMats Material list for this group. To be filled ... - */ - void ParseSkinLump_3DGS_MDL7( - const unsigned char* szCurrent, - const unsigned char** szCurrentOut, - std::vector<MaterialHelper*>& pcMats); - - // ------------------------------------------------------------------- - /** Parse a skin lump in a MDL7/HMP7 file with all of its features - * variant 2: Current cursor position is the beginning of the skin data - * \param szCurrent Current data pointer - * \param szCurrentOut Output data pointer - * \param pcMatOut Output material - * \param iType header.typ - * \param iWidth header.width - * \param iHeight header.height - */ - void ParseSkinLump_3DGS_MDL7( - const unsigned char* szCurrent, - const unsigned char** szCurrentOut, - MaterialHelper* pcMatOut, - unsigned int iType, - unsigned int iWidth, - unsigned int iHeight); - - // ------------------------------------------------------------------- - /** Skip a skin lump in a MDL7/HMP7 file - * \param szCurrent Current data pointer - * \param szCurrentOut Output data pointer. Points to the byte just - * behind the last byte of the skin. - * \param iType header.typ - * \param iWidth header.width - * \param iHeight header.height - */ - void SkipSkinLump_3DGS_MDL7(const unsigned char* szCurrent, - const unsigned char** szCurrentOut, - unsigned int iType, - unsigned int iWidth, - unsigned int iHeight); - - // ------------------------------------------------------------------- - /** Parse texture color data for MDL5, MDL6 and MDL7 formats - * \param szData Current data pointer - * \param iType type of the texture data. No DDS or external - * \param piSkip Receive the number of bytes to skip - * \param pcNew Must point to fully initialized data. Width and - * height must be set. If pcNew->pcData is set to 0xffffffff, - * piSkip will receive the size of the texture, in bytes, but no - * color data will be read. - */ - void ParseTextureColorData(const unsigned char* szData, - unsigned int iType, - unsigned int* piSkip, - aiTexture* pcNew); - - // ------------------------------------------------------------------- - /** Join two materials / skins. Setup UV source ... etc - * \param pcMat1 First input material - * \param pcMat2 Second input material - * \param pcMatOut Output material instance to be filled. Must be empty - */ - void JoinSkins_3DGS_MDL7(MaterialHelper* pcMat1, - MaterialHelper* pcMat2, - MaterialHelper* pcMatOut); - - // ------------------------------------------------------------------- - /** Add a bone transformation key to an animation - * \param iTrafo Index of the transformation (always==frame index?) - * No need to validate this index, it is always valid. - * \param pcBoneTransforms Bone transformation for this index - * \param apcOutBones Output bones array - */ - void AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo, - const MDL::BoneTransform_MDL7* pcBoneTransforms, - MDL::IntBone_MDL7** apcBonesOut); - - // ------------------------------------------------------------------- - /** Load the bone list of a MDL7 file - * \return If the bones could be loaded successfully, a valid - * array containing pointers to a temporary bone - * representation. NULL if the bones could not be loaded. - */ - MDL::IntBone_MDL7** LoadBones_3DGS_MDL7(); - - // ------------------------------------------------------------------- - /** Load bone transformation keyframes from a file chunk - * \param groupInfo -> doc of data structure - * \param frame -> doc of data structure - * \param shared -> doc of data structure - */ - void ParseBoneTrafoKeys_3DGS_MDL7( - const MDL::IntGroupInfo_MDL7& groupInfo, - IntFrameInfo_MDL7& frame, - MDL::IntSharedData_MDL7& shared); - - // ------------------------------------------------------------------- - /** Calculate absolute bone animation matrices for each bone - * \param apcOutBones Output bones array - */ - void CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7** apcOutBones); - - // ------------------------------------------------------------------- - /** Add all bones to the nodegraph (as children of the root node) - * \param apcBonesOut List of bones - * \param pcParent Parent node. New nodes will be added to this node - * \param iParentIndex Index of the parent bone - */ - void AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut, - aiNode* pcParent,uint16_t iParentIndex); - - // ------------------------------------------------------------------- - /** Build output animations - * \param apcBonesOut List of bones - */ - void BuildOutputAnims_3DGS_MDL7(const MDL::IntBone_MDL7** apcBonesOut); - - // ------------------------------------------------------------------- - /** Handles materials that are just referencing another material - * There is no test file for this feature, but Conitec's doc - * say it is used. - */ - void HandleMaterialReferences_3DGS_MDL7(); - - // ------------------------------------------------------------------- - /** Copies only the material that are referenced by at least one - * mesh to the final output material list. All other materials - * will be discarded. - * \param shared -> doc of data structure - */ - void CopyMaterials_3DGS_MDL7(MDL::IntSharedData_MDL7 &shared); - - // ------------------------------------------------------------------- - /** Process the frame section at the end of a group - * \param groupInfo -> doc of data structure - * \param shared -> doc of data structure - * \param szCurrent Pointer to the start of the frame section - * \param szCurrentOut Receives a pointer to the first byte of the - * next data section. - * \return false to read no further groups (a small workaround for - * some tiny and unsolved problems ... ) - */ - bool ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData, - MDL::IntSharedData_MDL7& shared, - const unsigned char* szCurrent, - const unsigned char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Sort all faces by their materials. If the mesh is using - * multiple materials per face (that are blended together) the function - * might create new materials. - * \param groupInfo -> doc of data structure - * \param groupData -> doc of data structure - * \param splittedGroupData -> doc of data structure - */ - void SortByMaterials_3DGS_MDL7( - const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData, - MDL::IntSplittedGroupData_MDL7& splittedGroupData); - - // ------------------------------------------------------------------- - /** Read all faces and vertices from a MDL7 group. The function fills - * preallocated memory buffers. - * \param groupInfo -> doc of data structure - * \param groupData -> doc of data structure - */ - void ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo, - MDL::IntGroupData_MDL7& groupData); - - // ------------------------------------------------------------------- - /** Generate the final output meshes for a7 models - * \param groupData -> doc of data structure - * \param splittedGroupData -> doc of data structure - */ - void GenerateOutputMeshes_3DGS_MDL7( - MDL::IntGroupData_MDL7& groupData, - MDL::IntSplittedGroupData_MDL7& splittedGroupData); - -protected: - - /** Configuration option: frame to be loaded */ - unsigned int configFrameID; - - /** Configuration option: palette to be used to decode palletized images*/ - std::string configPalette; - - /** Buffer to hold the loaded file */ - unsigned char* mBuffer; - - /** For GameStudio MDL files: The number in the magic word, either 3,4 or 5 - * (MDL7 doesn't need this, the format has a separate loader) */ - unsigned int iGSFileVersion; - - /** Output I/O handler. used to load external lmp files */ - IOSystem* pIOHandler; - - /** Output scene to be filled */ - aiScene* pScene; - - /** Size of the input file in bytes */ - unsigned int iFileSize; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/MDLMaterialLoader.cpp b/3rdparty/assimp/code/MDLMaterialLoader.cpp deleted file mode 100644 index 5ed30c30..00000000 --- a/3rdparty/assimp/code/MDLMaterialLoader.cpp +++ /dev/null @@ -1,823 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 material part of the MDL importer class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MDL_IMPORTER - -// internal headers -#include "MDLLoader.h" -#include "MDLDefaultColorMap.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Find a suitable pallette file or take teh default one -void MDLImporter::SearchPalette(const unsigned char** pszColorMap) -{ - // now try to find the color map in the current directory - IOStream* pcStream = pIOHandler->Open(configPalette,"rb"); - - const unsigned char* szColorMap = (const unsigned char*)::g_aclrDefaultColorMap; - if (pcStream) - { - if (pcStream->FileSize() >= 768) - { - szColorMap = new unsigned char[256*3]; - pcStream->Read(const_cast<unsigned char*>(szColorMap),256*3,1); - - DefaultLogger::get()->info("Found valid colormap.lmp in directory. " - "It will be used to decode embedded textures in palletized formats."); - } - delete pcStream; - pcStream = NULL; - } - *pszColorMap = szColorMap; -} - -// ------------------------------------------------------------------------------------------------ -// Free the palette again -void MDLImporter::FreePalette(const unsigned char* szColorMap) -{ - if (szColorMap != (const unsigned char*)::g_aclrDefaultColorMap) - delete[] szColorMap; -} - -// ------------------------------------------------------------------------------------------------ -// Check whether we can replace a texture with a single color -aiColor4D MDLImporter::ReplaceTextureWithColor(const aiTexture* pcTexture) -{ - ai_assert(NULL != pcTexture); - - aiColor4D clrOut; - clrOut.r = get_qnan(); - if (!pcTexture->mHeight || !pcTexture->mWidth) - return clrOut; - - const unsigned int iNumPixels = pcTexture->mHeight*pcTexture->mWidth; - const aiTexel* pcTexel = pcTexture->pcData+1; - const aiTexel* const pcTexelEnd = &pcTexture->pcData[iNumPixels]; - - while (pcTexel != pcTexelEnd) - { - if (*pcTexel != *(pcTexel-1)) - { - pcTexel = NULL; - break; - } - ++pcTexel; - } - if (pcTexel) - { - clrOut.r = pcTexture->pcData->r / 255.0f; - clrOut.g = pcTexture->pcData->g / 255.0f; - clrOut.b = pcTexture->pcData->b / 255.0f; - clrOut.a = pcTexture->pcData->a / 255.0f; - } - return clrOut; -} - -// ------------------------------------------------------------------------------------------------ -// Read a texture from a MDL3 file -void MDLImporter::CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData) -{ - const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function - - VALIDATE_FILE_SIZE(szData + pcHeader->skinwidth * - pcHeader->skinheight); - - // allocate a new texture object - aiTexture* pcNew = new aiTexture(); - pcNew->mWidth = pcHeader->skinwidth; - pcNew->mHeight = pcHeader->skinheight; - - pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; - - const unsigned char* szColorMap; - this->SearchPalette(&szColorMap); - - // copy texture data - for (unsigned int i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) - { - const unsigned char val = szData[i]; - const unsigned char* sz = &szColorMap[val*3]; - - pcNew->pcData[i].a = 0xFF; - pcNew->pcData[i].r = *sz++; - pcNew->pcData[i].g = *sz++; - pcNew->pcData[i].b = *sz; - } - - FreePalette(szColorMap); - - // store the texture - aiTexture** pc = this->pScene->mTextures; - this->pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; - for (unsigned int i = 0; i <pScene->mNumTextures;++i) - pScene->mTextures[i] = pc[i]; - - pScene->mTextures[this->pScene->mNumTextures] = pcNew; - pScene->mNumTextures++; - delete[] pc; - return; -} - -// ------------------------------------------------------------------------------------------------ -// Read a texture from a MDL4 file -void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData, - unsigned int iType, - unsigned int* piSkip) -{ - ai_assert(NULL != piSkip); - - const MDL::Header *pcHeader = (const MDL::Header*)mBuffer; //the endianess is allready corrected in the InternReadFile_3DGS_MDL345 function - - if (iType == 1 || iType > 3) - { - DefaultLogger::get()->error("Unsupported texture file format"); - return; - } - - bool bNoRead = *piSkip == 0xffffffff; - - // allocate a new texture object - aiTexture* pcNew = new aiTexture(); - pcNew->mWidth = pcHeader->skinwidth; - pcNew->mHeight = pcHeader->skinheight; - - if (bNoRead)pcNew->pcData = (aiTexel*)0xffffffff; - ParseTextureColorData(szData,iType,piSkip,pcNew); - - // store the texture - if (!bNoRead) - { - if (!this->pScene->mNumTextures) - { - pScene->mNumTextures = 1; - pScene->mTextures = new aiTexture*[1]; - pScene->mTextures[0] = pcNew; - } - else - { - aiTexture** pc = pScene->mTextures; - pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; - for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) - pScene->mTextures[i] = pc[i]; - pScene->mTextures[pScene->mNumTextures] = pcNew; - pScene->mNumTextures++; - delete[] pc; - } - } - else { - pcNew->pcData = NULL; - delete pcNew; - } - return; -} - -// ------------------------------------------------------------------------------------------------ -// Load color data of a texture and convert it to our output format -void MDLImporter::ParseTextureColorData(const unsigned char* szData, - unsigned int iType, - unsigned int* piSkip, - aiTexture* pcNew) -{ - // allocate storage for the texture image - if ((aiTexel*)0xffffffff != pcNew->pcData) - pcNew->pcData = new aiTexel[pcNew->mWidth * pcNew->mHeight]; - - // R5G6B5 format (with or without MIPs) - // **************************************************************** - if (2 == iType || 10 == iType) - { - VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*2); - - // copy texture data - unsigned int i; - if ((aiTexel*)0xffffffff != pcNew->pcData) - { - for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) - { - MDL::RGB565 val = ((MDL::RGB565*)szData)[i]; - AI_SWAP2(val); - - pcNew->pcData[i].a = 0xFF; - pcNew->pcData[i].r = (unsigned char)val.b << 3; - pcNew->pcData[i].g = (unsigned char)val.g << 2; - pcNew->pcData[i].b = (unsigned char)val.r << 3; - } - } - else i = pcNew->mWidth*pcNew->mHeight; - *piSkip = i * 2; - - // apply MIP maps - if (10 == iType) - { - *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1; - VALIDATE_FILE_SIZE(szData + *piSkip); - } - } - // ARGB4 format (with or without MIPs) - // **************************************************************** - else if (3 == iType || 11 == iType) - { - VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4); - - // copy texture data - unsigned int i; - if ((aiTexel*)0xffffffff != pcNew->pcData) - { - for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) - { - MDL::ARGB4 val = ((MDL::ARGB4*)szData)[i]; - AI_SWAP2(val); - - pcNew->pcData[i].a = (unsigned char)val.a << 4; - pcNew->pcData[i].r = (unsigned char)val.r << 4; - pcNew->pcData[i].g = (unsigned char)val.g << 4; - pcNew->pcData[i].b = (unsigned char)val.b << 4; - } - } - else i = pcNew->mWidth*pcNew->mHeight; - *piSkip = i * 2; - - // apply MIP maps - if (11 == iType) - { - *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 1; - VALIDATE_FILE_SIZE(szData + *piSkip); - } - } - // RGB8 format (with or without MIPs) - // **************************************************************** - else if (4 == iType || 12 == iType) - { - VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*3); - - // copy texture data - unsigned int i; - if ((aiTexel*)0xffffffff != pcNew->pcData) - { - for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) - { - const unsigned char* _szData = &szData[i*3]; - - pcNew->pcData[i].a = 0xFF; - pcNew->pcData[i].b = *_szData++; - pcNew->pcData[i].g = *_szData++; - pcNew->pcData[i].r = *_szData; - } - } - else i = pcNew->mWidth*pcNew->mHeight; - - - // apply MIP maps - *piSkip = i * 3; - if (12 == iType) - { - *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) *3; - VALIDATE_FILE_SIZE(szData + *piSkip); - } - } - // ARGB8 format (with ir without MIPs) - // **************************************************************** - else if (5 == iType || 13 == iType) - { - VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight*4); - - // copy texture data - unsigned int i; - if ((aiTexel*)0xffffffff != pcNew->pcData) - { - for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) - { - const unsigned char* _szData = &szData[i*4]; - - pcNew->pcData[i].b = *_szData++; - pcNew->pcData[i].g = *_szData++; - pcNew->pcData[i].r = *_szData++; - pcNew->pcData[i].a = *_szData; - } - } - else i = pcNew->mWidth*pcNew->mHeight; - - // apply MIP maps - *piSkip = i << 2; - if (13 == iType) - { - *piSkip += ((i >> 2) + (i >> 4) + (i >> 6)) << 2; - } - } - // palletized 8 bit texture. As for Quake 1 - // **************************************************************** - else if (0 == iType) - { - VALIDATE_FILE_SIZE(szData + pcNew->mWidth*pcNew->mHeight); - - // copy texture data - unsigned int i; - if ((aiTexel*)0xffffffff != pcNew->pcData) - { - - const unsigned char* szColorMap; - this->SearchPalette(&szColorMap); - - for (i = 0; i < pcNew->mWidth*pcNew->mHeight;++i) - { - const unsigned char val = szData[i]; - const unsigned char* sz = &szColorMap[val*3]; - - pcNew->pcData[i].a = 0xFF; - pcNew->pcData[i].r = *sz++; - pcNew->pcData[i].g = *sz++; - pcNew->pcData[i].b = *sz; - } - this->FreePalette(szColorMap); - - } - else i = pcNew->mWidth*pcNew->mHeight; - *piSkip = i; - - // FIXME: Also support for MIP maps? - } -} - -// ------------------------------------------------------------------------------------------------ -// Get a texture from a MDL5 file -void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char* szData, - unsigned int iType, - unsigned int* piSkip) -{ - ai_assert(NULL != piSkip); - bool bNoRead = *piSkip == 0xffffffff; - - // allocate a new texture object - aiTexture* pcNew = new aiTexture(); - - VALIDATE_FILE_SIZE(szData+8); - - // first read the size of the texture - pcNew->mWidth = *((uint32_t*)szData); - AI_SWAP4(pcNew->mWidth); - szData += sizeof(uint32_t); - - pcNew->mHeight = *((uint32_t*)szData); - AI_SWAP4(pcNew->mHeight); - szData += sizeof(uint32_t); - - if (bNoRead)pcNew->pcData = (aiTexel*)0xffffffff; - - // this should not occur - at least the docs say it shouldn't - // however, you can easily try out what MED does if you have - // a model with a DDS texture and export it to MDL5 ... - // yes, you're right. It embedds the DDS texture ... :cry: - if (6 == iType) - { - // this is a compressed texture in DDS format - *piSkip = pcNew->mWidth; - VALIDATE_FILE_SIZE(szData + *piSkip); - - if (!bNoRead) - { - // place a hint and let the application know that it's - // a DDS file - pcNew->mHeight = 0; - pcNew->achFormatHint[0] = 'd'; - pcNew->achFormatHint[1] = 'd'; - pcNew->achFormatHint[2] = 's'; - pcNew->achFormatHint[3] = '\0'; - - pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth]; - ::memcpy(pcNew->pcData,szData,pcNew->mWidth); - } - } - else - { - // parse the color data of the texture - ParseTextureColorData(szData,iType, - piSkip,pcNew); - } - *piSkip += sizeof(uint32_t) * 2; - - if (!bNoRead) - { - // store the texture - if (!this->pScene->mNumTextures) - { - pScene->mNumTextures = 1; - pScene->mTextures = new aiTexture*[1]; - pScene->mTextures[0] = pcNew; - } - else - { - aiTexture** pc = pScene->mTextures; - pScene->mTextures = new aiTexture*[pScene->mNumTextures+1]; - for (unsigned int i = 0; i < pScene->mNumTextures;++i) - this->pScene->mTextures[i] = pc[i]; - - pScene->mTextures[pScene->mNumTextures] = pcNew; - pScene->mNumTextures++; - delete[] pc; - } - } - else { - pcNew->pcData = NULL; - delete pcNew; - } - return; -} - -// ------------------------------------------------------------------------------------------------ -// Get a skin from a MDL7 file - more complex than all other subformats -void MDLImporter::ParseSkinLump_3DGS_MDL7( - const unsigned char* szCurrent, - const unsigned char** szCurrentOut, - MaterialHelper* pcMatOut, - unsigned int iType, - unsigned int iWidth, - unsigned int iHeight) -{ - aiTexture* pcNew = NULL; - - // get the type of the skin - unsigned int iMasked = (unsigned int)(iType & 0xF); - - if (0x1 == iMasked) - { - // ***** REFERENCE TO ANOTHER SKIN INDEX ***** - int referrer = (int)iWidth; - pcMatOut->AddProperty<int>(&referrer,1,AI_MDL7_REFERRER_MATERIAL); - } - else if (0x6 == iMasked) - { - // ***** EMBEDDED DDS FILE ***** - if (1 != iHeight) - { - DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, " - "but texture height is not equal to 1, which is not supported by MED"); - } - - pcNew = new aiTexture(); - pcNew->mHeight = 0; - pcNew->mWidth = iWidth; - - // place a proper format hint - pcNew->achFormatHint[0] = 'd'; - pcNew->achFormatHint[1] = 'd'; - pcNew->achFormatHint[2] = 's'; - pcNew->achFormatHint[3] = '\0'; - - pcNew->pcData = (aiTexel*) new unsigned char[pcNew->mWidth]; - memcpy(pcNew->pcData,szCurrent,pcNew->mWidth); - szCurrent += iWidth; - } - if (0x7 == iMasked) - { - // ***** REFERENCE TO EXTERNAL FILE ***** - if (1 != iHeight) - { - DefaultLogger::get()->warn("Found a reference to an external texture, " - "but texture height is not equal to 1, which is not supported by MED"); - } - - aiString szFile; - const size_t iLen = strlen((const char*)szCurrent); - size_t iLen2 = iLen+1; - iLen2 = iLen2 > MAXLEN ? MAXLEN : iLen2; - memcpy(szFile.data,(const char*)szCurrent,iLen2); - szFile.length = iLen; - - szCurrent += iLen2; - - // place this as diffuse texture - pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - else if (iMasked || !iType || (iType && iWidth && iHeight)) - { - // ***** STANDARD COLOR TEXTURE ***** - pcNew = new aiTexture(); - if (!iHeight || !iWidth) - { - DefaultLogger::get()->warn("Found embedded texture, but its width " - "an height are both 0. Is this a joke?"); - - // generate an empty chess pattern - pcNew->mWidth = pcNew->mHeight = 8; - pcNew->pcData = new aiTexel[64]; - for (unsigned int x = 0; x < 8;++x) - { - for (unsigned int y = 0; y < 8;++y) - { - const bool bSet = ((0 == x % 2 && 0 != y % 2) || - (0 != x % 2 && 0 == y % 2)); - - aiTexel* pc = &pcNew->pcData[y * 8 + x]; - pc->r = pc->b = pc->g = (bSet?0xFF:0); - pc->a = 0xFF; - } - } - } - else - { - // it is a standard color texture. Fill in width and height - // and call the same function we used for loading MDL5 files - - pcNew->mWidth = iWidth; - pcNew->mHeight = iHeight; - - unsigned int iSkip = 0; - this->ParseTextureColorData(szCurrent,iMasked,&iSkip,pcNew); - - // skip length of texture data - szCurrent += iSkip; - } - } - - // sometimes there are MDL7 files which have a monochrome - // texture instead of material colors ... posssible they have - // been converted to MDL7 from other formats, such as MDL5 - aiColor4D clrTexture; - if (pcNew)clrTexture = this->ReplaceTextureWithColor(pcNew); - else clrTexture.r = get_qnan(); - - // check whether a material definition is contained in the skin - if (iType & AI_MDL7_SKINTYPE_MATERIAL) - { - BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent; - szCurrent = (unsigned char*)(pcMatIn+1); - VALIDATE_FILE_SIZE(szCurrent); - - aiColor3D clrTemp; - -#define COLOR_MULTIPLY_RGB() \ - if (is_not_qnan(clrTexture.r)) \ - { \ - clrTemp.r *= clrTexture.r; \ - clrTemp.g *= clrTexture.g; \ - clrTemp.b *= clrTexture.b; \ - } - - // read diffuse color - clrTemp.r = pcMatIn->Diffuse.r; - AI_SWAP4(clrTemp.r); - clrTemp.g = pcMatIn->Diffuse.g; - AI_SWAP4(clrTemp.g); - clrTemp.b = pcMatIn->Diffuse.b; - AI_SWAP4(clrTemp.b); - COLOR_MULTIPLY_RGB(); - pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_DIFFUSE); - - // read specular color - clrTemp.r = pcMatIn->Specular.r; - AI_SWAP4(clrTemp.r); - clrTemp.g = pcMatIn->Specular.g; - AI_SWAP4(clrTemp.g); - clrTemp.b = pcMatIn->Specular.b; - AI_SWAP4(clrTemp.b); - COLOR_MULTIPLY_RGB(); - pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_SPECULAR); - - // read ambient color - clrTemp.r = pcMatIn->Ambient.r; - AI_SWAP4(clrTemp.r); - clrTemp.g = pcMatIn->Ambient.g; - AI_SWAP4(clrTemp.g); - clrTemp.b = pcMatIn->Ambient.b; - AI_SWAP4(clrTemp.b); - COLOR_MULTIPLY_RGB(); - pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_AMBIENT); - - // read emissive color - clrTemp.r = pcMatIn->Emissive.r; - AI_SWAP4(clrTemp.r); - clrTemp.g = pcMatIn->Emissive.g; - AI_SWAP4(clrTemp.g); - clrTemp.b = pcMatIn->Emissive.b; - AI_SWAP4(clrTemp.b); - pcMatOut->AddProperty<aiColor3D>(&clrTemp,1,AI_MATKEY_COLOR_EMISSIVE); - -#undef COLOR_MULITPLY_RGB - - // FIX: Take the opacity from the ambient color - // the doc says something else, but it is fact that MED exports the - // opacity like this .... ARRRGGHH! - clrTemp.r = pcMatIn->Ambient.a; - AI_SWAP4(clrTemp.r); - if (is_not_qnan(clrTexture.r)) { - clrTemp.r *= clrTexture.a; - } - pcMatOut->AddProperty<float>(&clrTemp.r,1,AI_MATKEY_OPACITY); - - // read phong power - int iShadingMode = (int)aiShadingMode_Gouraud; - AI_SWAP4(pcMatIn->Power); - if (0.0f != pcMatIn->Power) - { - iShadingMode = (int)aiShadingMode_Phong; - pcMatOut->AddProperty<float>(&pcMatIn->Power,1,AI_MATKEY_SHININESS); - } - pcMatOut->AddProperty<int>(&iShadingMode,1,AI_MATKEY_SHADING_MODEL); - } - else if (is_not_qnan(clrTexture.r)) - { - pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_DIFFUSE); - pcMatOut->AddProperty<aiColor4D>(&clrTexture,1,AI_MATKEY_COLOR_SPECULAR); - } - // if the texture could be replaced by a single material color - // we don't need the texture anymore - if (is_not_qnan(clrTexture.r)) - { - delete pcNew; - pcNew = NULL; - } - - // if an ASCII effect description (HLSL?) is contained in the file, - // we can simply ignore it ... - if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) - { - VALIDATE_FILE_SIZE(szCurrent); - int32_t iMe = *((int32_t*)szCurrent); - AI_SWAP4(iMe); - szCurrent += sizeof(char) * iMe + sizeof(int32_t); - VALIDATE_FILE_SIZE(szCurrent); - } - - // If an embedded texture has been loaded setup the corresponding - // data structures in the aiScene instance - if (pcNew && this->pScene->mNumTextures <= 999) - { - - // place this as diffuse texture - char szCurrent[5]; - ::sprintf(szCurrent,"*%i",this->pScene->mNumTextures); - - aiString szFile; - const size_t iLen = strlen((const char*)szCurrent); - ::memcpy(szFile.data,(const char*)szCurrent,iLen+1); - szFile.length = iLen; - - pcMatOut->AddProperty(&szFile,AI_MATKEY_TEXTURE_DIFFUSE(0)); - - // store the texture - if (!this->pScene->mNumTextures) - { - this->pScene->mNumTextures = 1; - this->pScene->mTextures = new aiTexture*[1]; - this->pScene->mTextures[0] = pcNew; - } - else - { - aiTexture** pc = this->pScene->mTextures; - this->pScene->mTextures = new aiTexture*[this->pScene->mNumTextures+1]; - for (unsigned int i = 0; i < this->pScene->mNumTextures;++i) - this->pScene->mTextures[i] = pc[i]; - - this->pScene->mTextures[this->pScene->mNumTextures] = pcNew; - this->pScene->mNumTextures++; - delete[] pc; - } - } - VALIDATE_FILE_SIZE(szCurrent); - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// Skip a skin lump -void MDLImporter::SkipSkinLump_3DGS_MDL7( - const unsigned char* szCurrent, - const unsigned char** szCurrentOut, - unsigned int iType, - unsigned int iWidth, - unsigned int iHeight) -{ - // get the type of the skin - unsigned int iMasked = (unsigned int)(iType & 0xF); - - if (0x6 == iMasked) - { - szCurrent += iWidth; - } - if (0x7 == iMasked) - { - const size_t iLen = ::strlen((const char*)szCurrent); - szCurrent += iLen+1; - } - else if (iMasked || !iType) - { - if (iMasked || !iType || (iType && iWidth && iHeight)) - { - // ParseTextureColorData(..., aiTexture::pcData == 0xffffffff) will simply - // return the size of the color data in bytes in iSkip - unsigned int iSkip = 0; - - aiTexture tex; - tex.pcData = reinterpret_cast<aiTexel*>(0xffffffff); - tex.mHeight = iHeight; - tex.mWidth = iWidth; - this->ParseTextureColorData(szCurrent,iMasked,&iSkip,&tex); - - // FIX: Important, otherwise the destructor will crash - tex.pcData = NULL; - - // skip length of texture data - szCurrent += iSkip; - } - } - - // check whether a material definition is contained in the skin - if (iType & AI_MDL7_SKINTYPE_MATERIAL) - { - BE_NCONST MDL::Material_MDL7* pcMatIn = (BE_NCONST MDL::Material_MDL7*)szCurrent; - szCurrent = (unsigned char*)(pcMatIn+1); - } - - // if an ASCII effect description (HLSL?) is contained in the file, - // we can simply ignore it ... - if (iType & AI_MDL7_SKINTYPE_MATERIAL_ASCDEF) - { - int32_t iMe = *((int32_t*)szCurrent); - AI_SWAP4(iMe); - szCurrent += sizeof(char) * iMe + sizeof(int32_t); - } - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// What the fuck does this function do? Can't remember -void MDLImporter::ParseSkinLump_3DGS_MDL7( - const unsigned char* szCurrent, - const unsigned char** szCurrentOut, - std::vector<MaterialHelper*>& pcMats) -{ - ai_assert(NULL != szCurrent); - ai_assert(NULL != szCurrentOut); - - *szCurrentOut = szCurrent; - BE_NCONST MDL::Skin_MDL7* pcSkin = (BE_NCONST MDL::Skin_MDL7*)szCurrent; - AI_SWAP4(pcSkin->width); - AI_SWAP4(pcSkin->height); - szCurrent += 12; - - // allocate an output material - MaterialHelper* pcMatOut = new MaterialHelper(); - pcMats.push_back(pcMatOut); - - // skip length of file name - szCurrent += AI_MDL7_MAX_TEXNAMESIZE; - - ParseSkinLump_3DGS_MDL7(szCurrent,szCurrentOut,pcMatOut, - pcSkin->typ,pcSkin->width,pcSkin->height); - - // place the name of the skin in the material - if (pcSkin->texture_name[0]) - { - // the 0 termination could be there or not - we can't know - aiString szFile; - ::memcpy(szFile.data,pcSkin->texture_name,sizeof(pcSkin->texture_name)); - szFile.data[sizeof(pcSkin->texture_name)] = '\0'; - szFile.length = ::strlen(szFile.data); - - pcMatOut->AddProperty(&szFile,AI_MATKEY_NAME); - } -} - -#endif // !! ASSIMP_BUILD_NO_MDL_IMPORTER diff --git a/3rdparty/assimp/code/MS3DLoader.cpp b/3rdparty/assimp/code/MS3DLoader.cpp deleted file mode 100644 index be34db68..00000000 --- a/3rdparty/assimp/code/MS3DLoader.cpp +++ /dev/null @@ -1,645 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MS3DLoader.cpp - * @brief Implementation of the Ms3D importer class. - * Written against http://chumbalum.swissquake.ch/ms3d/ms3dspec.txt - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_MS3D_IMPORTER - -// internal headers -#include "MS3DLoader.h" -#include "StreamReader.h" -using namespace Assimp; - -// ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH -// (enable old code path, which generates extra nodes per mesh while -// the newer code uses aiMesh::mName to express the name of the -// meshes (a.k.a. groups in MS3D)) - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -MS3DImporter::MS3DImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -MS3DImporter::~MS3DImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - // first call - simple extension check - const std::string extension = GetExtension(pFile); - if (extension == "ms3d") { - return true; - } - - // second call - check for magic identifiers - else if (!extension.length() || checkSig) { - if (!pIOHandler) { - return true; - } - const char* tokens[] = {"MS3D000000"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void MS3DImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("ms3d"); -} - -// ------------------------------------------------------------------------------------------------ -void ReadColor(StreamReaderLE& stream, aiColor4D& ambient) -{ - // aiColor4D is packed on gcc, implicit binding to float& fails therefore. - stream >> (float&)ambient.r >> (float&)ambient.g >> (float&)ambient.b >> (float&)ambient.a; -} - -// ------------------------------------------------------------------------------------------------ -void ReadVector(StreamReaderLE& stream, aiVector3D& pos) -{ - // See note in ReadColor() - stream >> (float&)pos.x >> (float&)pos.y >> (float&)pos.z; -} - -// ------------------------------------------------------------------------------------------------ -template<typename T> -void MS3DImporter :: ReadComments(StreamReaderLE& stream, std::vector<T>& outp) -{ - uint16_t cnt; - stream >> cnt; - - for (unsigned int i = 0; i < cnt; ++i) { - uint32_t index, clength; - stream >> index >> clength; - - if (index >= outp.size()) { - DefaultLogger::get()->warn("MS3D: Invalid index in comment section"); - } - else if (clength > stream.GetRemainingSize()) { - throw DeadlyImportError("MS3D: Failure reading comment, length field is out of range"); - } - else { - outp[index].comment = std::string(reinterpret_cast<char*>(stream.GetPtr()),clength); - } - stream.IncPtr(clength); - } -} - -// ------------------------------------------------------------------------------------------------ -template <typename T, typename T2, typename T3> bool inrange(const T& in, const T2& lower, const T3& higher) -{ - return in > lower && in <= higher; -} - -// ------------------------------------------------------------------------------------------------ -void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints, - std::vector<bool>& hadit, - aiNode* nd, - const aiMatrix4x4& absTrafo) -{ - unsigned int cnt = 0; - for (size_t i = 0; i < joints.size(); ++i) { - if (!hadit[i] && !strcmp(joints[i].parentName,nd->mName.data)) { - ++cnt; - } - } - - nd->mChildren = new aiNode*[nd->mNumChildren = cnt]; - cnt = 0; - for (size_t i = 0; i < joints.size(); ++i) { - if (!hadit[i] && !strcmp(joints[i].parentName,nd->mName.data)) { - aiNode* ch = nd->mChildren[cnt++] = new aiNode(joints[i].name); - ch->mParent = nd; - - ch->mTransformation = aiMatrix4x4::Translation(joints[i].position,aiMatrix4x4()=aiMatrix4x4())* - // XXX actually, I don't *know* why we need the inverse here. Probably column vs. row order? - aiMatrix4x4().FromEulerAnglesXYZ(joints[i].rotation).Transpose(); - - const aiMatrix4x4 abs = absTrafo*ch->mTransformation; - for (unsigned int a = 0; a < mScene->mNumMeshes; ++a) { - aiMesh* const msh = mScene->mMeshes[a]; - for (unsigned int n = 0; n < msh->mNumBones; ++n) { - aiBone* const bone = msh->mBones[n]; - - if (bone->mName == ch->mName) { - bone->mOffsetMatrix = aiMatrix4x4(abs).Inverse(); - } - } - } - - hadit[i] = true; - CollectChildJoints(joints,hadit,ch,abs); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints, aiNode* nd) -{ - std::vector<bool> hadit(joints.size(),false); - aiMatrix4x4 trafo; - - CollectChildJoints(joints,hadit,nd,trafo); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void MS3DImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); - - // CanRead() should have done this already - char head[10]; - int32_t version; - - mScene = pScene; - - - // 1 ------------ read into temporary data structures mirroring the original file - - stream.CopyAndAdvance(head,10); - stream >> version; - if (strncmp(head,"MS3D000000",10)) { - throw DeadlyImportError("Not a MS3D file, magic string MS3D000000 not found: "+pFile); - } - - if (version != 4) { - throw DeadlyImportError("MS3D: Unsupported file format version, 4 was expected"); - } - - uint16_t verts; - stream >> verts; - - std::vector<TempVertex> vertices(verts); - for (unsigned int i = 0; i < verts; ++i) { - TempVertex& v = vertices[i]; - - stream.IncPtr(1); - ReadVector(stream,v.pos); - v.bone_id[0] = stream.GetI1(); - v.ref_cnt = stream.GetI1(); - - v.bone_id[1] = v.bone_id[2] = v.bone_id[3] = 0xffffffff; - v.weights[1] = v.weights[2] = v.weights[3] = 0.f; - v.weights[0] = 1.f; - } - - uint16_t tris; - stream >> tris; - - std::vector<TempTriangle> triangles(tris); - for (unsigned int i = 0;i < tris; ++i) { - TempTriangle& t = triangles[i]; - - stream.IncPtr(2); - for (unsigned int i = 0; i < 3; ++i) { - t.indices[i] = stream.GetI2(); - } - - for (unsigned int i = 0; i < 3; ++i) { - ReadVector(stream,t.normals[i]); - } - - for (unsigned int i = 0; i < 3; ++i) { - stream >> (float&)(t.uv[i].x); // see note in ReadColor() - } - for (unsigned int i = 0; i < 3; ++i) { - stream >> (float&)(t.uv[i].y); - } - - t.sg = stream.GetI1(); - t.group = stream.GetI1(); - } - - uint16_t grp; - stream >> grp; - - bool need_default = false; - std::vector<TempGroup> groups(grp); - for (unsigned int i = 0;i < grp; ++i) { - TempGroup& t = groups[i]; - - stream.IncPtr(1); - stream.CopyAndAdvance(t.name,32); - - t.name[32] = '\0'; - uint16_t num; - stream >> num; - - t.triangles.resize(num); - for (unsigned int i = 0; i < num; ++i) { - t.triangles[i] = stream.GetI2(); - } - t.mat = stream.GetI1(); - if (t.mat == 0xffffffff) { - need_default = true; - } - } - - uint16_t mat; - stream >> mat; - - std::vector<TempMaterial> materials(mat); - for (unsigned int i = 0;i < mat; ++i) { - TempMaterial& t = materials[i]; - - stream.CopyAndAdvance(t.name,32); - t.name[32] = '\0'; - - ReadColor(stream,t.ambient); - ReadColor(stream,t.diffuse); - ReadColor(stream,t.specular); - ReadColor(stream,t.emissive); - stream >> t.shininess >> t.transparency; - - stream.IncPtr(1); - - stream.CopyAndAdvance(t.texture,128); - t.texture[128] = '\0'; - - stream.CopyAndAdvance(t.alphamap,128); - t.alphamap[128] = '\0'; - } - - float animfps, currenttime; - uint32_t totalframes; - stream >> animfps >> currenttime >> totalframes; - - uint16_t joint; - stream >> joint; - - std::vector<TempJoint> joints(joint); - for (unsigned int i = 0; i < joint; ++i) { - TempJoint& j = joints[i]; - - stream.IncPtr(1); - stream.CopyAndAdvance(j.name,32); - j.name[32] = '\0'; - - stream.CopyAndAdvance(j.parentName,32); - j.parentName[32] = '\0'; - - // DefaultLogger::get()->debug(j.name); - // DefaultLogger::get()->debug(j.parentName); - - ReadVector(stream,j.rotation); - ReadVector(stream,j.position); - - j.rotFrames.resize(stream.GetI2()); - j.posFrames.resize(stream.GetI2()); - - for (unsigned int a = 0; a < j.rotFrames.size(); ++a) { - TempKeyFrame& kf = j.rotFrames[a]; - stream >> kf.time; - ReadVector(stream,kf.value); - } - for (unsigned int a = 0; a < j.posFrames.size(); ++a) { - TempKeyFrame& kf = j.posFrames[a]; - stream >> kf.time; - ReadVector(stream,kf.value); - } - } - - if (stream.GetRemainingSize() > 4) { - uint32_t subversion; - stream >> subversion; - if (subversion == 1) { - ReadComments<TempGroup>(stream,groups); - ReadComments<TempMaterial>(stream,materials); - ReadComments<TempJoint>(stream,joints); - - // model comment - print it for we have such a nice log. - if (stream.GetI4()) { - const size_t len = static_cast<size_t>(stream.GetI4()); - if (len > stream.GetRemainingSize()) { - throw DeadlyImportError("MS3D: Model comment is too long"); - } - - const std::string& s = std::string(reinterpret_cast<char*>(stream.GetPtr()),len); - } - - if (stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) { - for (unsigned int i = 0; i < verts; ++i) { - TempVertex& v = vertices[i]; - v.weights[3]=1.f; - for (unsigned int n = 0; n < 3; v.weights[3]-=v.weights[n++]) { - v.bone_id[n+1] = stream.GetI1(); - v.weights[n] = static_cast<float>(static_cast<unsigned int>(stream.GetI1()))/255.f; - } - stream.IncPtr((subversion-1)<<2u); - } - - // even further extra data is not of interest for us, at least now now. - } - } - } - - // 2 ------------ convert to proper aiXX data structures ----------------------------------- - - if (need_default && materials.size()) { - DefaultLogger::get()->warn("MS3D: Found group with no material assigned, spawning default material"); - // if one of the groups has no material assigned, but there are other - // groups with materials, a default material needs to be added ( - // scenepreprocessor adds a default material only if nummat==0). - materials.push_back(TempMaterial()); - TempMaterial& m = materials.back(); - - strcpy(m.name,"<MS3D_DefaultMat>"); - m.diffuse = aiColor4D(0.6f,0.6f,0.6f,1.0); - m.transparency = 1.f; - m.shininess = 0.f; - - // this is because these TempXXX struct's have no c'tors. - m.texture[0] = m.alphamap[0] = '\0'; - - for (unsigned int i = 0; i < groups.size(); ++i) { - TempGroup& g = groups[i]; - if (g.mat == 0xffffffff) { - g.mat = materials.size()-1; - } - } - } - - // convert materials to our generic key-value dict-alike - if (materials.size()) { - pScene->mMaterials = new aiMaterial*[materials.size()]; - for (size_t i = 0; i < materials.size(); ++i) { - - MaterialHelper* mo = new MaterialHelper(); - pScene->mMaterials[pScene->mNumMaterials++] = mo; - - const TempMaterial& mi = materials[i]; - - aiString tmp; - if (0[mi.alphamap]) { - tmp = aiString(mi.alphamap); - mo->AddProperty(&tmp,AI_MATKEY_TEXTURE_OPACITY(0)); - } - if (0[mi.texture]) { - tmp = aiString(mi.texture); - mo->AddProperty(&tmp,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - if (0[mi.name]) { - tmp = aiString(mi.name); - mo->AddProperty(&tmp,AI_MATKEY_NAME); - } - - mo->AddProperty(&mi.ambient,1,AI_MATKEY_COLOR_AMBIENT); - mo->AddProperty(&mi.diffuse,1,AI_MATKEY_COLOR_DIFFUSE); - mo->AddProperty(&mi.specular,1,AI_MATKEY_COLOR_SPECULAR); - mo->AddProperty(&mi.emissive,1,AI_MATKEY_COLOR_EMISSIVE); - - mo->AddProperty(&mi.shininess,1,AI_MATKEY_SHININESS); - mo->AddProperty(&mi.transparency,1,AI_MATKEY_OPACITY); - - const int sm = mi.shininess>0.f?aiShadingMode_Phong:aiShadingMode_Gouraud; - mo->AddProperty(&sm,1,AI_MATKEY_SHADING_MODEL); - } - } - - // convert groups to meshes - if (groups.empty()) { - throw DeadlyImportError("MS3D: Didn't get any group records, file is malformed"); - } - - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes=static_cast<unsigned int>(groups.size())](); - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - - aiMesh* m = pScene->mMeshes[i] = new aiMesh(); - const TempGroup& g = groups[i]; - - if (pScene->mNumMaterials && g.mat > pScene->mNumMaterials) { - throw DeadlyImportError("MS3D: Encountered invalid material index, file is malformed"); - } // no error if no materials at all - scenepreprocessor adds one then - - m->mMaterialIndex = g.mat; - m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - m->mFaces = new aiFace[m->mNumFaces = g.triangles.size()]; - m->mNumVertices = m->mNumFaces*3; - - // storage for vertices - verbose format, as requested by the postprocessing pipeline - m->mVertices = new aiVector3D[m->mNumVertices]; - m->mNormals = new aiVector3D[m->mNumVertices]; - m->mTextureCoords[0] = new aiVector3D[m->mNumVertices]; - m->mNumUVComponents[0] = 2; - - typedef std::map<unsigned int,unsigned int> BoneSet; - BoneSet mybones; - - for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) { - aiFace& f = m->mFaces[i]; - if (g.triangles[i]>triangles.size()) { - throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed"); - } - - TempTriangle& t = triangles[g.triangles[i]]; - f.mIndices = new unsigned int[f.mNumIndices=3]; - - for (unsigned int i = 0; i < 3; ++i,++n) { - if (t.indices[i]>vertices.size()) { - throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed"); - } - - const TempVertex& v = vertices[t.indices[i]]; - for (unsigned int a = 0; a < 4; ++a) { - if (v.bone_id[a] != 0xffffffff) { - if (v.bone_id[a] >= joints.size()) { - throw DeadlyImportError("MS3D: Encountered invalid bone index, file is malformed"); - } - if (mybones.find(v.bone_id[a]) == mybones.end()) { - mybones[v.bone_id[a]] = 1; - } - else ++mybones[v.bone_id[a]]; - } - } - - // collect vertex components - m->mVertices[n] = v.pos; - - m->mNormals[n] = t.normals[i]; - m->mTextureCoords[0][n] = aiVector3D(t.uv[i].x,1.f-t.uv[i].y,0.0); - f.mIndices[i] = n; - } - } - - // allocate storage for bones - if (mybones.size()) { - std::vector<unsigned int> bmap(joints.size()); - m->mBones = new aiBone*[mybones.size()](); - for (BoneSet::const_iterator it = mybones.begin(); it != mybones.end(); ++it) { - aiBone* const bn = m->mBones[m->mNumBones] = new aiBone(); - const TempJoint& jnt = joints[(*it).first]; - - bn->mName.Set(jnt.name); - bn->mWeights = new aiVertexWeight[(*it).second]; - - bmap[(*it).first] = m->mNumBones++; - } - - // .. and collect bone weights - for (unsigned int i = 0,n = 0; i < m->mNumFaces; ++i) { - TempTriangle& t = triangles[g.triangles[i]]; - - for (unsigned int i = 0; i < 3; ++i,++n) { - const TempVertex& v = vertices[t.indices[i]]; - for (unsigned int a = 0; a < 4; ++a) { - const unsigned int bone = v.bone_id[a]; - if (bone==0xffffffff){ - continue; - } - - aiBone* const outbone = m->mBones[bmap[bone]]; - aiVertexWeight& outwght = outbone->mWeights[outbone->mNumWeights++]; - - outwght.mVertexId = n; - outwght.mWeight = v.weights[a]; - } - } - } - } - } - - // ... add dummy nodes under a single root, each holding a reference to one - // mesh. If we didn't do this, we'd loose the group name. - aiNode* rt = pScene->mRootNode = new aiNode("<MS3DRoot>"); - -#ifdef ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH - rt->mChildren = new aiNode*[rt->mNumChildren=pScene->mNumMeshes+(joints.size()?1:0)](); - - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - aiNode* nd = rt->mChildren[i] = new aiNode(); - - const TempGroup& g = groups[i]; - - // we need to generate an unique name for all mesh nodes. - // since we want to keep the group name, a prefix is - // prepended. - nd->mName = aiString("<MS3DMesh>_"); - nd->mName.Append(g.name); - nd->mParent = rt; - - nd->mMeshes = new unsigned int[nd->mNumMeshes = 1]; - nd->mMeshes[0] = i; - } -#else - rt->mMeshes = new unsigned int[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - rt->mMeshes[rt->mNumMeshes++] = i; - } -#endif - - // convert animations as well - if (joints.size()) { -#ifndef ASSIMP_BUILD_MS3D_ONE_NODE_PER_MESH - rt->mChildren = new aiNode*[1](); -#endif - aiNode* jt = rt->mChildren[pScene->mNumMeshes] = new aiNode(); - jt->mParent = rt; - CollectChildJoints(joints,jt); - jt->mName.Set("<MS3DJointRoot>"); - - pScene->mAnimations = new aiAnimation*[ pScene->mNumAnimations = 1 ]; - aiAnimation* const anim = pScene->mAnimations[0] = new aiAnimation(); - - anim->mName.Set("<MS3DMasterAnim>"); - - // carry the fps info to the user by scaling all times with it - anim->mTicksPerSecond = animfps; - - // leave duration at its default, so ScenePreprocessor will fill an appropriate - // value (the values taken from some MS3D files seem to be too unreliable - // to pass the validation) - // anim->mDuration = totalframes/animfps; - - anim->mChannels = new aiNodeAnim*[joints.size()](); - for (std::vector<TempJoint>::const_iterator it = joints.begin(); it != joints.end(); ++it) { - if ((*it).rotFrames.empty() && (*it).posFrames.empty()) { - continue; - } - - aiNodeAnim* nd = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim(); - nd->mNodeName.Set((*it).name); - - if ((*it).rotFrames.size()) { - nd->mRotationKeys = new aiQuatKey[(*it).rotFrames.size()]; - for (std::vector<TempKeyFrame>::const_iterator rot = (*it).rotFrames.begin(); rot != (*it).rotFrames.end(); ++rot) { - aiQuatKey& q = nd->mRotationKeys[nd->mNumRotationKeys++]; - - q.mTime = (*rot).time*animfps; - - // XXX it seems our matrix&quaternion code has faults in its conversion routines -- - // aiQuaternion(x,y,z) seems to besomething different as quat(matrix.fromeuler(x,y,z)). - q.mValue = aiQuaternion(aiMatrix3x3(aiMatrix4x4().FromEulerAnglesXYZ((*rot).value)* - aiMatrix4x4().FromEulerAnglesXYZ((*it).rotation)).Transpose()); - } - } - - if ((*it).posFrames.size()) { - nd->mPositionKeys = new aiVectorKey[(*it).posFrames.size()]; - - aiQuatKey* qu = nd->mRotationKeys; - for (std::vector<TempKeyFrame>::const_iterator pos = (*it).posFrames.begin(); pos != (*it).posFrames.end(); ++pos,++qu) { - aiVectorKey& v = nd->mPositionKeys[nd->mNumPositionKeys++]; - - v.mTime = (*pos).time*animfps; - v.mValue = (*it).position + (*pos).value; - } - } - } - // fixup to pass the validation if not a single animation channel is non-trivial - if (!anim->mNumChannels) { - anim->mChannels = NULL; - } - } -} - -#endif diff --git a/3rdparty/assimp/code/MS3DLoader.h b/3rdparty/assimp/code/MS3DLoader.h deleted file mode 100644 index 6725dda3..00000000 --- a/3rdparty/assimp/code/MS3DLoader.h +++ /dev/null @@ -1,158 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MS3DLoader.h - * @brief Declaration of the MS3D importer class. - */ -#ifndef AI_MS3DLOADER_H_INCLUDED -#define AI_MS3DLOADER_H_INCLUDED - -#include "BaseImporter.h" -namespace Assimp { - -// ---------------------------------------------------------------------------------------------- -/** Milkshape 3D importer implementation */ -// ---------------------------------------------------------------------------------------------- -class MS3DImporter - : public BaseImporter -{ - friend class Importer; - -protected: - - MS3DImporter(); - ~MS3DImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details */ - void GetExtensionList(std::set<std::string>& extensions); - - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - -private: - - struct TempJoint; - void CollectChildJoints(const std::vector<TempJoint>& joints, std::vector<bool>& hadit, aiNode* nd,const aiMatrix4x4& absTrafo); - void CollectChildJoints(const std::vector<TempJoint>& joints, aiNode* nd); - - template<typename T> void ReadComments(StreamReaderLE& stream, std::vector<T>& outp); -private: - - aiScene* mScene; - -private: - - struct TempVertex - { - aiVector3D pos; - unsigned int bone_id[4], ref_cnt; - float weights[4]; - }; - - struct TempTriangle - { - unsigned int indices[3]; - aiVector3D normals[3]; - aiVector2D uv[3]; - - unsigned int sg, group; - }; - - struct TempGroup - { - char name[33]; // +0 - std::vector<unsigned int> triangles; - unsigned int mat; // 0xff is no material - std::string comment; - }; - - struct TempMaterial - { - // again, add an extra 0 character to all strings - - char name[33]; - char texture[129]; - char alphamap[129]; - - aiColor4D diffuse,specular,ambient,emissive; - float shininess,transparency; - std::string comment; - }; - - struct TempKeyFrame - { - float time; - aiVector3D value; - }; - - struct TempJoint - { - char name[33]; - char parentName[33]; - aiVector3D rotation, position; - - std::vector<TempKeyFrame> rotFrames; - std::vector<TempKeyFrame> posFrames; - std::string comment; - }; - - //struct TempModel { - // std::string comment; - //}; -}; - -} -#endif diff --git a/3rdparty/assimp/code/MakeVerboseFormat.cpp b/3rdparty/assimp/code/MakeVerboseFormat.cpp deleted file mode 100644 index b232146d..00000000 --- a/3rdparty/assimp/code/MakeVerboseFormat.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step "MakeVerboseFormat" -*/ - -#include "AssimpPCH.h" -#include "MakeVerboseFormat.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -MakeVerboseFormatProcess::MakeVerboseFormatProcess() -{ - // nothing to do here -} -// ------------------------------------------------------------------------------------------------ -MakeVerboseFormatProcess::~MakeVerboseFormatProcess() -{ - // nothing to do here -} -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void MakeVerboseFormatProcess::Execute( aiScene* pScene) -{ - ai_assert(NULL != pScene); - DefaultLogger::get()->debug("MakeVerboseFormatProcess begin"); - - bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { - if ( MakeVerboseFormat( pScene->mMeshes[a])) - bHas = true; - } - if (bHas) DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ..."); - else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do."); - - pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; - -} -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh) -{ - ai_assert(NULL != pcMesh); - - unsigned int iOldNumVertices = pcMesh->mNumVertices; - const unsigned int iNumVerts = pcMesh->mNumFaces*3; - - aiVector3D* pvPositions = new aiVector3D[ iNumVerts ]; - - aiVector3D* pvNormals = NULL; - if (pcMesh->HasNormals()) - { - pvNormals = new aiVector3D[iNumVerts]; - } - aiVector3D* pvTangents = NULL, *pvBitangents = NULL; - if (pcMesh->HasTangentsAndBitangents()) - { - pvTangents = new aiVector3D[iNumVerts]; - pvBitangents = new aiVector3D[iNumVerts]; - } - - ai_assert(AI_MAX_NUMBER_OF_TEXTURECOORDS == 4); - ai_assert(AI_MAX_NUMBER_OF_COLOR_SETS == 4); - - aiVector3D* apvTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS] = {NULL,NULL,NULL,NULL}; - aiColor4D* apvColorSets[AI_MAX_NUMBER_OF_COLOR_SETS] = {NULL,NULL,NULL,NULL}; - - unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) - apvTextureCoords[p++] = new aiVector3D[iNumVerts]; - - p = 0; - while (pcMesh->HasVertexColors(p)) - apvColorSets[p++] = new aiColor4D[iNumVerts]; - - // allocate enough memory to hold output bones and vertex weights ... - std::vector<aiVertexWeight>* newWeights = new std::vector<aiVertexWeight>[pcMesh->mNumBones]; - for (unsigned int i = 0;i < pcMesh->mNumBones;++i) { - newWeights[i].reserve(pcMesh->mBones[i]->mNumWeights*3); - } - - // iterate through all faces and build a clean list - unsigned int iIndex = 0; - for (unsigned int a = 0; a< pcMesh->mNumFaces;++a) - { - aiFace* pcFace = &pcMesh->mFaces[a]; - for (unsigned int q = 0; q < pcFace->mNumIndices;++q,++iIndex) - { - // need to build a clean list of bones, too - for (unsigned int i = 0;i < pcMesh->mNumBones;++i) - { - for (unsigned int a = 0; a < pcMesh->mBones[i]->mNumWeights;a++) - { - const aiVertexWeight& w = pcMesh->mBones[i]->mWeights[a]; - if (pcFace->mIndices[q] == w.mVertexId) - { - aiVertexWeight wNew; - wNew.mVertexId = iIndex; - wNew.mWeight = w.mWeight; - newWeights[i].push_back(wNew); - } - } - } - - pvPositions[iIndex] = pcMesh->mVertices[pcFace->mIndices[q]]; - - if (pcMesh->HasNormals()) - { - pvNormals[iIndex] = pcMesh->mNormals[pcFace->mIndices[q]]; - } - if (pcMesh->HasTangentsAndBitangents()) - { - pvTangents[iIndex] = pcMesh->mTangents[pcFace->mIndices[q]]; - pvBitangents[iIndex] = pcMesh->mBitangents[pcFace->mIndices[q]]; - } - - unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) - { - apvTextureCoords[p][iIndex] = pcMesh->mTextureCoords[p][pcFace->mIndices[q]]; - ++p; - } - p = 0; - while (pcMesh->HasVertexColors(p)) - { - apvColorSets[p][iIndex] = pcMesh->mColors[p][pcFace->mIndices[q]]; - ++p; - } - pcFace->mIndices[q] = iIndex; - } - } - - // build output vertex weights - for (unsigned int i = 0;i < pcMesh->mNumBones;++i) - { - delete pcMesh->mBones[i]->mWeights; - if (!newWeights[i].empty()) - { - pcMesh->mBones[i]->mWeights = new aiVertexWeight[newWeights[i].size()]; - memcpy(pcMesh->mBones[i]->mWeights,&newWeights[i][0], - sizeof(aiVertexWeight) * newWeights[i].size()); - } - else pcMesh->mBones[i]->mWeights = NULL; - } - - // delete the old members - delete[] pcMesh->mVertices; - pcMesh->mVertices = pvPositions; - - p = 0; - while (pcMesh->HasTextureCoords(p)) - { - delete pcMesh->mTextureCoords[p]; - pcMesh->mTextureCoords[p] = apvTextureCoords[p]; - ++p; - } - p = 0; - while (pcMesh->HasVertexColors(p)) - { - delete pcMesh->mColors[p]; - pcMesh->mColors[p] = apvColorSets[p]; - ++p; - } - pcMesh->mNumVertices = iNumVerts; - - if (pcMesh->HasNormals()) - { - delete[] pcMesh->mNormals; - pcMesh->mNormals = pvNormals; - } - if (pcMesh->HasTangentsAndBitangents()) - { - delete[] pcMesh->mTangents; - pcMesh->mTangents = pvTangents; - delete[] pcMesh->mBitangents; - pcMesh->mBitangents = pvBitangents; - } - return (pcMesh->mNumVertices != iOldNumVertices); -} diff --git a/3rdparty/assimp/code/MakeVerboseFormat.h b/3rdparty/assimp/code/MakeVerboseFormat.h deleted file mode 100644 index 6ecb2ed5..00000000 --- a/3rdparty/assimp/code/MakeVerboseFormat.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to bring a given scene - into the verbose format that is expected by most postprocess steps. - This is the inverse of the "JoinIdenticalVertices" step. */ -#ifndef AI_MAKEVERBOSEFORMAT_H_INC -#define AI_MAKEVERBOSEFORMAT_H_INC - -#include "BaseProcess.h" -namespace Assimp { - -// --------------------------------------------------------------------------- -/** MakeVerboseFormatProcess: Class to convert an asset to the verbose - * format which is expected by most postprocess steps. - * - * This is the inverse of what the "JoinIdenticalVertices" step is doing. - * This step has no official flag (since it wouldn't make sense to run it - * during import). It is intended for applications intending to modify the - * returned aiScene. After this step has been executed, they can execute - * other postprocess steps on the data. The code might also be useful to - * quickly adapt code that doesn't result in a verbose representation of - * the scene data. - * The step has been added because it was required by the viewer, however - * it has been moved to the main library since others might find it - * useful, too. */ -class ASSIMP_API MakeVerboseFormatProcess : public BaseProcess -{ - friend class Importer; - -protected: - - /** Constructor to be privately used by Importer, or by applications - which know what they are doing if they modify the aiScene object */ - MakeVerboseFormatProcess(); - - /** Destructor, private as well */ - ~MakeVerboseFormatProcess(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not */ - bool IsActive( unsigned int /*pFlags*/ ) const - { - // NOTE: There is no direct flag that corresponds to - // this postprocess step. - return false; - } - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. */ - void Execute( aiScene* pScene); - - -private: - - //! Apply the postprocess step to a given submesh - bool MakeVerboseFormat (aiMesh* pcMesh); -}; - -} // end of namespace Assimp - -#endif // !!AI_KILLNORMALPROCESS_H_INC diff --git a/3rdparty/assimp/code/MaterialSystem.cpp b/3rdparty/assimp/code/MaterialSystem.cpp deleted file mode 100644 index 0df12ba0..00000000 --- a/3rdparty/assimp/code/MaterialSystem.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MaterialSystem.cpp - * @brief Implementation of the material system of the library - */ - -#include "AssimpPCH.h" - -#include "Hash.h" -#include "fast_atof.h" -#include "ParsingUtils.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Get a specific property from a material -aiReturn aiGetMaterialProperty(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - const aiMaterialProperty** pPropOut) -{ - ai_assert (pMat != NULL); - ai_assert (pKey != NULL); - ai_assert (pPropOut != NULL); - - /* Just search for a property with exactly this name .. - * could be improved by hashing, but it's possibly - * no worth the effort (we're bound to C structures, - * thus std::map or derivates are not applicable. */ - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { - aiMaterialProperty* prop = pMat->mProperties[i]; - - if (prop /* just for safety ... */ - && 0 == strcmp( prop->mKey.data, pKey ) - && (0xffffffff == type || prop->mSemantic == type) /* 0xffffffff is a wildcard, but this is undocumented :-) */ - && (0xffffffff == index || prop->mIndex == index)) - { - *pPropOut = pMat->mProperties[i]; - return AI_SUCCESS; - } - } - *pPropOut = NULL; - return AI_FAILURE; -} - -// ------------------------------------------------------------------------------------------------ -// Get an array of floating-point values from the material. -aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - float* pOut, - unsigned int* pMax) -{ - ai_assert (pOut != NULL); - ai_assert (pMat != NULL); - - const aiMaterialProperty* prop; - aiGetMaterialProperty(pMat,pKey,type,index, (const aiMaterialProperty**) &prop); - if (!prop) { - return AI_FAILURE; - } - - // data is given in floats, simply copy it - unsigned int iWrite; - if ( aiPTI_Float == prop->mType || aiPTI_Buffer == prop->mType) { - iWrite = prop->mDataLength / sizeof(float); - if (pMax) { - iWrite = std::min(*pMax,iWrite); ; - } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast<float> ( reinterpret_cast<float*>(prop->mData)[a] ); - } - if (pMax) { - *pMax = iWrite; - } - } - // data is given in ints, convert to float - else if ( aiPTI_Integer == prop->mType) { - iWrite = prop->mDataLength / sizeof(int32_t); - if (pMax) { - iWrite = std::min(*pMax,iWrite); ; - } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast<float> ( reinterpret_cast<int32_t*>(prop->mData)[a] ); - } - if (pMax) { - *pMax = iWrite; - } - } - // a string ... read floats separated by spaces - else { - if (pMax) { - iWrite = *pMax; - } - // strings are zero-terminated with a 32 bit length prefix, so this is safe - const char* cur = prop->mData+4; - ai_assert(prop->mDataLength>=5 && !prop->mData[prop->mDataLength-1]); - for (unsigned int a = 0; ;++a) { - cur = fast_atof_move(cur,pOut[a]); - if (a==iWrite-1) { - break; - } - if (!IsSpace(*cur)) { - DefaultLogger::get()->error("Material property" + std::string(pKey) + - " is a string; failed to parse a float array out of it."); - return AI_FAILURE; - } - } - - if (pMax) { - *pMax = iWrite; - } - } - return AI_SUCCESS; - -} - -// ------------------------------------------------------------------------------------------------ -// Get an array if integers from the material -aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - int* pOut, - unsigned int* pMax) -{ - ai_assert (pOut != NULL); - ai_assert (pMat != NULL); - - const aiMaterialProperty* prop; - aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**) &prop); - if (!prop) { - return AI_FAILURE; - } - - // data is given in ints, simply copy it - unsigned int iWrite; - if ( aiPTI_Integer == prop->mType || aiPTI_Buffer == prop->mType) { - iWrite = prop->mDataLength / sizeof(int32_t); - if (pMax) { - iWrite = std::min(*pMax,iWrite); ; - } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast<int>(reinterpret_cast<int32_t*>(prop->mData)[a]); - } - if (pMax) { - *pMax = iWrite; - } - } - // data is given in floats convert to int - else if ( aiPTI_Float == prop->mType) { - iWrite = prop->mDataLength / sizeof(float); - if (pMax) { - iWrite = std::min(*pMax,iWrite); ; - } - for (unsigned int a = 0; a < iWrite;++a) { - pOut[a] = static_cast<int>(reinterpret_cast<float*>(prop->mData)[a]); - } - if (pMax) { - *pMax = iWrite; - } - } - // it is a string ... no way to read something out of this - else { - if (pMax) { - iWrite = *pMax; - } - // strings are zero-terminated with a 32 bit length prefix, so this is safe - const char* cur = prop->mData+4; - ai_assert(prop->mDataLength>=5 && !prop->mData[prop->mDataLength-1]); - for (unsigned int a = 0; ;++a) { - pOut[a] = strtol10s(cur,&cur); - if (a==iWrite-1) { - break; - } - if (!IsSpace(*cur)) { - DefaultLogger::get()->error("Material property" + std::string(pKey) + - " is a string; failed to parse an integer array out of it."); - return AI_FAILURE; - } - } - - if (pMax) { - *pMax = iWrite; - } - } - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -// Get a color (3 or 4 floats) from the material -aiReturn aiGetMaterialColor(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - aiColor4D* pOut) -{ - unsigned int iMax = 4; - const aiReturn eRet = aiGetMaterialFloatArray(pMat,pKey,type,index,(float*)pOut,&iMax); - - // if no alpha channel is defined: set it to 1.0 - if (3 == iMax) { - pOut->a = 1.0f; - } - - return eRet; -} - -// ------------------------------------------------------------------------------------------------ -// Get a string from the material -aiReturn aiGetMaterialString(const aiMaterial* pMat, - const char* pKey, - unsigned int type, - unsigned int index, - aiString* pOut) -{ - ai_assert (pOut != NULL); - - const aiMaterialProperty* prop; - aiGetMaterialProperty(pMat,pKey,type,index,(const aiMaterialProperty**)&prop); - if (!prop) { - return AI_FAILURE; - } - - if ( aiPTI_String == prop->mType) { - ai_assert(prop->mDataLength>=5); - - // The string is stored as 32 but length prefix followed by zero-terminated UTF8 data - pOut->length = static_cast<unsigned int>(*reinterpret_cast<uint32_t*>(prop->mData)); - - ai_assert(pOut->length+1+4==prop->mDataLength && !prop->mData[prop->mDataLength-1]); - memcpy(pOut->data,prop->mData+4,pOut->length+1); - } - else { - // TODO - implement lexical cast as well - DefaultLogger::get()->error("Material property" + std::string(pKey) + - " was found, but is no string" ); - return AI_FAILURE; - } - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -// Get the number of textures on a particular texture stack -ASSIMP_API unsigned int aiGetMaterialTextureCount(const C_STRUCT aiMaterial* pMat, - C_ENUM aiTextureType type) -{ - ai_assert (pMat != NULL); - - /* Textures are always stored with ascending indices (ValidateDS provides a check, so we don't need to do it again) */ - unsigned int max = 0; - for (unsigned int i = 0; i < pMat->mNumProperties;++i) { - aiMaterialProperty* prop = pMat->mProperties[i]; - - if (prop /* just a sanity check ... */ - && 0 == strcmp( prop->mKey.data, _AI_MATKEY_TEXTURE_BASE ) - && prop->mSemantic == type) { - - max = std::max(max,prop->mIndex+1); - } - } - return max; -} - -// ------------------------------------------------------------------------------------------------ -aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat, - aiTextureType type, - unsigned int index, - C_STRUCT aiString* path, - aiTextureMapping* _mapping /*= NULL*/, - unsigned int* uvindex /*= NULL*/, - float* blend /*= NULL*/, - aiTextureOp* op /*= NULL*/, - aiTextureMapMode* mapmode /*= NULL*/, - unsigned int* flags /*= NULL*/ - ) -{ - ai_assert(NULL != mat && NULL != path); - - // Get the path to the texture - if (AI_SUCCESS != aiGetMaterialString(mat,AI_MATKEY_TEXTURE(type,index),path)) { - return AI_FAILURE; - } - // Determine mapping type - aiTextureMapping mapping = aiTextureMapping_UV; - aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping); - if (_mapping) - *_mapping = mapping; - - // Get UV index - if (aiTextureMapping_UV == mapping && uvindex) { - aiGetMaterialInteger(mat,AI_MATKEY_UVWSRC(type,index),(int*)uvindex); - } - // Get blend factor - if (blend) { - aiGetMaterialFloat(mat,AI_MATKEY_TEXBLEND(type,index),blend); - } - // Get texture operation - if (op){ - aiGetMaterialInteger(mat,AI_MATKEY_TEXOP(type,index),(int*)op); - } - // Get texture mapping modes - if (mapmode) { - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_U(type,index),(int*)&mapmode[0]); - aiGetMaterialInteger(mat,AI_MATKEY_MAPPINGMODE_V(type,index),(int*)&mapmode[1]); - } - // Get texture flags - if (flags){ - aiGetMaterialInteger(mat,AI_MATKEY_TEXFLAGS(type,index),(int*)flags); - } - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -// Construction. Actually the one and only way to get an aiMaterial instance -MaterialHelper::MaterialHelper() -{ - // Allocate 5 entries by default - mNumProperties = 0; - mNumAllocated = 5; - mProperties = new aiMaterialProperty*[5]; -} - -// ------------------------------------------------------------------------------------------------ -MaterialHelper::~MaterialHelper() -{ - _InternDestruct(); -} - -// ------------------------------------------------------------------------------------------------ -aiMaterial::~aiMaterial() -{ - // HACK (Aramis): This is safe: aiMaterial has a private constructor, - // so instances must be created indirectly via MaterialHelper. We can't - // use a virtual d'tor because we need to preserve binary compatibility - // with good old C ... - ((MaterialHelper*)this)->_InternDestruct(); -} - -// ------------------------------------------------------------------------------------------------ -// Manual destructor -void MaterialHelper::_InternDestruct() -{ - // First clean up all properties - Clear(); - - // Then delete the array that stored them - delete[] mProperties; - AI_DEBUG_INVALIDATE_PTR(mProperties); - - // Update members - mNumAllocated = 0; -} - -// ------------------------------------------------------------------------------------------------ -void MaterialHelper::Clear() -{ - for (unsigned int i = 0; i < mNumProperties;++i) { - // delete this entry - delete mProperties[i]; - AI_DEBUG_INVALIDATE_PTR(mProperties[i]); - } - mNumProperties = 0; - - // The array remains allocated, we just invalidated its contents -} - -// ------------------------------------------------------------------------------------------------ -uint32_t MaterialHelper::ComputeHash(bool includeMatName /*= false*/) -{ - uint32_t hash = 1503; // magic start value, choosen to be my birthday :-) - for (unsigned int i = 0; i < mNumProperties;++i) { - aiMaterialProperty* prop; - - // Exclude all properties whose first character is '?' from the hash - // See doc for aiMaterialProperty. - if ((prop = mProperties[i]) && (includeMatName || prop->mKey.data[0] != '?')) { - - hash = SuperFastHash(prop->mKey.data,(unsigned int)prop->mKey.length,hash); - hash = SuperFastHash(prop->mData,prop->mDataLength,hash); - - // Combine the semantic and the index with the hash - hash = SuperFastHash((const char*)&prop->mSemantic,sizeof(unsigned int),hash); - hash = SuperFastHash((const char*)&prop->mIndex,sizeof(unsigned int),hash); - } - } - return hash; -} - -// ------------------------------------------------------------------------------------------------ -aiReturn MaterialHelper::RemoveProperty (const char* pKey,unsigned int type, - unsigned int index - ) -{ - ai_assert(NULL != pKey); - - for (unsigned int i = 0; i < mNumProperties;++i) { - aiMaterialProperty* prop = mProperties[i]; - - if (prop && !strcmp( prop->mKey.data, pKey ) && - prop->mSemantic == type && prop->mIndex == index) - { - // Delete this entry - delete mProperties[i]; - - // collapse the array behind --. - --mNumProperties; - for (unsigned int a = i; a < mNumProperties;++a) { - mProperties[a] = mProperties[a+1]; - } - return AI_SUCCESS; - } - } - - return AI_FAILURE; -} - -// ------------------------------------------------------------------------------------------------ -aiReturn MaterialHelper::AddBinaryProperty (const void* pInput, - unsigned int pSizeInBytes, - const char* pKey, - unsigned int type, - unsigned int index, - aiPropertyTypeInfo pType - ) -{ - ai_assert (pInput != NULL); - ai_assert (pKey != NULL); - ai_assert (0 != pSizeInBytes); - - // first search the list whether there is already an entry with this key - unsigned int iOutIndex = 0xffffffff; - for (unsigned int i = 0; i < mNumProperties;++i) { - aiMaterialProperty* prop = mProperties[i]; - - if (prop /* just for safety */ && !strcmp( prop->mKey.data, pKey ) && - prop->mSemantic == type && prop->mIndex == index){ - - delete mProperties[i]; - iOutIndex = i; - } - } - - // Allocate a new material property - aiMaterialProperty* pcNew = new aiMaterialProperty(); - - // .. and fill it - pcNew->mType = pType; - pcNew->mSemantic = type; - pcNew->mIndex = index; - - pcNew->mDataLength = pSizeInBytes; - pcNew->mData = new char[pSizeInBytes]; - memcpy (pcNew->mData,pInput,pSizeInBytes); - - pcNew->mKey.length = ::strlen(pKey); - ai_assert ( MAXLEN > pcNew->mKey.length); - strcpy( pcNew->mKey.data, pKey ); - - if (0xffffffff != iOutIndex) { - mProperties[iOutIndex] = pcNew; - return AI_SUCCESS; - } - - // resize the array ... double the storage allocated - if (mNumProperties == mNumAllocated) { - const unsigned int iOld = mNumAllocated; - mNumAllocated *= 2; - - aiMaterialProperty** ppTemp; - try { - ppTemp = new aiMaterialProperty*[mNumAllocated]; - } catch (std::bad_alloc&) { - return AI_OUTOFMEMORY; - } - - // just copy all items over; then replace the old array - memcpy (ppTemp,mProperties,iOld * sizeof(void*)); - - delete[] mProperties; - mProperties = ppTemp; - } - // push back ... - mProperties[mNumProperties++] = pcNew; - return AI_SUCCESS; -} - -// ------------------------------------------------------------------------------------------------ -aiReturn MaterialHelper::AddProperty (const aiString* pInput, - const char* pKey, - unsigned int type, - unsigned int index) -{ - // We don't want to add the whole buffer .. write a 32 bit length - // prefix followed by the zero-terminated UTF8 string. - // (HACK) I don't want to break the ABI now, but we definitely - // ought to change aiString::mLength to uint32_t one day. - if (sizeof(size_t) == 8) { - aiString copy = *pInput; - uint32_t* s = reinterpret_cast<uint32_t*>(©.length); - s[1] = static_cast<uint32_t>(pInput->length); - - return AddBinaryProperty(s+1, - pInput->length+1+4, - pKey, - type, - index, - aiPTI_String); - } - ai_assert(sizeof(size_t)==4); - return AddBinaryProperty(pInput, - pInput->length+1+4, - pKey, - type, - index, - aiPTI_String); -} - -// ------------------------------------------------------------------------------------------------ -void MaterialHelper::CopyPropertyList(MaterialHelper* pcDest, - const MaterialHelper* pcSrc - ) -{ - ai_assert(NULL != pcDest); - ai_assert(NULL != pcSrc); - - unsigned int iOldNum = pcDest->mNumProperties; - pcDest->mNumAllocated += pcSrc->mNumAllocated; - pcDest->mNumProperties += pcSrc->mNumProperties; - - aiMaterialProperty** pcOld = pcDest->mProperties; - pcDest->mProperties = new aiMaterialProperty*[pcDest->mNumAllocated]; - - if (iOldNum && pcOld) { - for (unsigned int i = 0; i < iOldNum;++i) { - pcDest->mProperties[i] = pcOld[i]; - } - - delete[] pcOld; - } - for (unsigned int i = iOldNum; i< pcDest->mNumProperties;++i) { - aiMaterialProperty* propSrc = pcSrc->mProperties[i]; - - // search whether we have already a property with this name -> if yes, overwrite it - aiMaterialProperty* prop; - for (unsigned int q = 0; q < iOldNum;++q) { - prop = pcDest->mProperties[q]; - if (prop /* just for safety */ && prop->mKey == propSrc->mKey && prop->mSemantic == propSrc->mSemantic - && prop->mIndex == propSrc->mIndex) { - delete prop; - - // collapse the whole array ... - memmove(&pcDest->mProperties[q],&pcDest->mProperties[q+1],i-q); - i--; - pcDest->mNumProperties--; - } - } - - // Allocate the output property and copy the source property - prop = pcDest->mProperties[i] = new aiMaterialProperty(); - prop->mKey = propSrc->mKey; - prop->mDataLength = propSrc->mDataLength; - prop->mType = propSrc->mType; - prop->mSemantic = propSrc->mSemantic; - prop->mIndex = propSrc->mIndex; - - prop->mData = new char[propSrc->mDataLength]; - memcpy(prop->mData,propSrc->mData,prop->mDataLength); - } - return; -} - diff --git a/3rdparty/assimp/code/MaterialSystem.h b/3rdparty/assimp/code/MaterialSystem.h deleted file mode 100644 index 1504b688..00000000 --- a/3rdparty/assimp/code/MaterialSystem.h +++ /dev/null @@ -1,246 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MaterialSystem.h - * Definition of the #MaterialHelper utility class. - */ -#ifndef AI_MATERIALSYSTEM_H_INC -#define AI_MATERIALSYSTEM_H_INC - -#include "../include/aiMaterial.h" -namespace Assimp { - -// ---------------------------------------------------------------------------------------- -/** Internal material helper class deriving from aiMaterial. - * - * Intended to be used to fill an aiMaterial structure more easily. - */ -class ASSIMP_API MaterialHelper : public ::aiMaterial -{ -public: - - // Construction and destruction - MaterialHelper(); - ~MaterialHelper(); - - // ------------------------------------------------------------------------------ - /** @brief Add a property with a given key and type info to the material - * structure - * - * @param pInput Pointer to input data - * @param pSizeInBytes Size of input data - * @param pKey Key/Usage of the property (AI_MATKEY_XXX) - * @param type Set by the AI_MATKEY_XXX macro - * @param index Set by the AI_MATKEY_XXX macro - * @param pType Type information hint - */ - aiReturn AddBinaryProperty (const void* pInput, - unsigned int pSizeInBytes, - const char* pKey, - unsigned int type , - unsigned int index , - aiPropertyTypeInfo pType); - - // ------------------------------------------------------------------------------ - /** @brief Add a string property with a given key and type info to the - * material structure - * - * @param pInput Input string - * @param pKey Key/Usage of the property (AI_MATKEY_XXX) - * @param type Set by the AI_MATKEY_XXX macro - * @param index Set by the AI_MATKEY_XXX macro - */ - aiReturn AddProperty (const aiString* pInput, - const char* pKey, - unsigned int type = 0, - unsigned int index = 0); - - // ------------------------------------------------------------------------------ - /** @brief Add a property with a given key to the material structure - * @param pInput Pointer to the input data - * @param pNumValues Number of values in the array - * @param pKey Key/Usage of the property (AI_MATKEY_XXX) - * @param type Set by the AI_MATKEY_XXX macro - * @param index Set by the AI_MATKEY_XXX macro - */ - template<class TYPE> - aiReturn AddProperty (const TYPE* pInput, - unsigned int pNumValues, - const char* pKey, - unsigned int type = 0, - unsigned int index = 0); - - // ------------------------------------------------------------------------------ - /** @brief Remove a given key from the list. - * - * The function fails if the key isn't found - * @param pKey Key to be deleted - */ - aiReturn RemoveProperty (const char* pKey, - unsigned int type = 0, - unsigned int index = 0); - - // ------------------------------------------------------------------------------ - /** @brief Removes all properties from the material. - * - * The data array remains allocated so adding new properties is quite fast. - */ - void Clear(); - - // ------------------------------------------------------------------------------ - /** Computes a hash (hopefully unique) from all material properties - * The hash value reflects the current property state, so if you add any - * proprty and call this method again, the resulting hash value will be - * different. - * - * @param includeMatName Set to 'true' to take all properties with - * '?' as initial character in their name into account. - * Currently #AI_MATKEY_NAME is the only example. - * @return Unique hash - */ - uint32_t ComputeHash(bool includeMatName = false); - - // ------------------------------------------------------------------------------ - /** Copy the property list of a material - * @param pcDest Destination material - * @param pcSrc Source material - */ - static void CopyPropertyList(MaterialHelper* pcDest, - const MaterialHelper* pcSrc); - -public: - // For internal use. That's why it's public. - void _InternDestruct(); -}; - - -// ---------------------------------------------------------------------------------------- -template<class TYPE> -aiReturn MaterialHelper::AddProperty (const TYPE* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(TYPE), - pKey,type,index,aiPTI_Buffer); -} - -// ---------------------------------------------------------------------------------------- -template<> -inline aiReturn MaterialHelper::AddProperty<float> (const float* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(float), - pKey,type,index,aiPTI_Float); -} - -// ---------------------------------------------------------------------------------------- -template<> -inline aiReturn MaterialHelper::AddProperty<aiUVTransform> (const aiUVTransform* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(aiUVTransform), - pKey,type,index,aiPTI_Float); -} - -// ---------------------------------------------------------------------------------------- -template<> -inline aiReturn MaterialHelper::AddProperty<aiColor4D> (const aiColor4D* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(aiColor4D), - pKey,type,index,aiPTI_Float); -} - -// ---------------------------------------------------------------------------------------- -template<> -inline aiReturn MaterialHelper::AddProperty<aiColor3D> (const aiColor3D* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(aiColor3D), - pKey,type,index,aiPTI_Float); -} - -// ---------------------------------------------------------------------------------------- -template<> -inline aiReturn MaterialHelper::AddProperty<aiVector3D> (const aiVector3D* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(aiVector3D), - pKey,type,index,aiPTI_Float); -} - -// ---------------------------------------------------------------------------------------- -template<> -inline aiReturn MaterialHelper::AddProperty<int> (const int* pInput, - const unsigned int pNumValues, - const char* pKey, - unsigned int type, - unsigned int index) -{ - return AddBinaryProperty((const void*)pInput, - pNumValues * sizeof(int), - pKey,type,index,aiPTI_Integer); -} -} // ! namespace Assimp - -#endif //!! AI_MATERIALSYSTEM_H_INC diff --git a/3rdparty/assimp/code/MemoryIOWrapper.h b/3rdparty/assimp/code/MemoryIOWrapper.h deleted file mode 100644 index d40102ee..00000000 --- a/3rdparty/assimp/code/MemoryIOWrapper.h +++ /dev/null @@ -1,181 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 MemoryIOWrapper.h - * Handy IOStream/IOSystem implemetation to read directly from a memory buffer */ -#ifndef AI_MEMORYIOSTREAM_H_INC -#define AI_MEMORYIOSTREAM_H_INC -namespace Assimp { -#define AI_MEMORYIO_MAGIC_FILENAME "$$$___magic___$$$" -#define AI_MEMORYIO_MAGIC_FILENAME_LENGTH 17 - -// ---------------------------------------------------------------------------------- -/** Implementation of IOStream to read directly from a memory buffer */ -// ---------------------------------------------------------------------------------- -class MemoryIOStream : public IOStream -{ - //friend class MemoryIOSystem; -public: - MemoryIOStream (const uint8_t* buff, size_t len) - : buffer (buff), length(len), pos((size_t)0) { - } - -public: - ~MemoryIOStream () { - } - - // ------------------------------------------------------------------- - // Read from stream - size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { - const size_t cnt = std::min(pCount,(length-pos)/pSize),ofs = pSize*cnt; - - memcpy(pvBuffer,buffer+pos,ofs); - pos += ofs; - - return cnt; - } - - // ------------------------------------------------------------------- - // Write to stream - size_t Write(const void* pvBuffer, size_t pSize,size_t pCount) { - ai_assert(false); // won't be needed - return 0; - } - - // ------------------------------------------------------------------- - // Seek specific position - aiReturn Seek(size_t pOffset, aiOrigin pOrigin) { - if (aiOrigin_SET == pOrigin) { - if (pOffset >= length) { - return AI_FAILURE; - } - pos = pOffset; - } - else if (aiOrigin_END == pOrigin) { - if (pOffset >= length) { - return AI_FAILURE; - } - pos = length-pOffset; - } - else { - if (pOffset+pos >= length) { - return AI_FAILURE; - } - pos += pOffset; - } - return AI_SUCCESS; - } - - // ------------------------------------------------------------------- - // Get current seek position - size_t Tell() const { - return pos; - } - - // ------------------------------------------------------------------- - // Get size of file - size_t FileSize() const { - return length; - } - - // ------------------------------------------------------------------- - // Flush file contents - void Flush() { - ai_assert(false); // won't be needed - } - -private: - const uint8_t* buffer; - size_t length,pos; -}; - -// --------------------------------------------------------------------------- -/** Dummy IO system to read from a memory buffer */ -class MemoryIOSystem : public IOSystem -{ -public: - /** Constructor. */ - MemoryIOSystem (const uint8_t* buff, size_t len) - : buffer (buff), length(len) { - } - - /** Destructor. */ - ~MemoryIOSystem() { - } - - // ------------------------------------------------------------------- - /** Tests for the existence of a file at the given path. */ - bool Exists( const char* pFile) const { - return !strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH); - } - - // ------------------------------------------------------------------- - /** Returns the directory separator. */ - char getOsSeparator() const { - return '/'; // why not? it doesn't care - } - - // ------------------------------------------------------------------- - /** Open a new file with a given path. */ - IOStream* Open( const char* pFile, const char* pMode = "rb") { - if (strncmp(pFile,AI_MEMORYIO_MAGIC_FILENAME,AI_MEMORYIO_MAGIC_FILENAME_LENGTH)) { - return NULL; - } - return new MemoryIOStream(buffer,length); - } - - // ------------------------------------------------------------------- - /** Closes the given file and releases all resources associated with it. */ - void Close( IOStream* pFile) { - } - - // ------------------------------------------------------------------- - /** Compare two paths */ - bool ComparePaths (const char* one, const char* second) const { - return false; - } - -private: - const uint8_t* buffer; - size_t length; -}; -} // end namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/NDOLoader.cpp b/3rdparty/assimp/code/NDOLoader.cpp deleted file mode 100644 index 1bd06c92..00000000 --- a/3rdparty/assimp/code/NDOLoader.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2009, ASSIMP Development 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 Development 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 NDOLoader.cpp - * Implementation of the NDO importer class. - */ - -#include "AssimpPCH.h" -#ifndef AI_BUILD_NO_NDO_IMPORTER -#include "NDOLoader.h" - -using namespace Assimp; -#define for_each BOOST_FOREACH - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -NDOImporter::NDOImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -NDOImporter::~NDOImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - // check file extension - const std::string extension = GetExtension(pFile); - - if ( extension == "ndo") - return true; - - if ((checkSig || !extension.length()) && pIOHandler) { - const char* tokens[] = {"nendo"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Build a string of all file extensions supported -void NDOImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("ndo"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties for the loader -void NDOImporter::SetupProperties(const Importer* pImp) -{ - // nothing to be done for the moment -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void NDOImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - StreamReaderBE reader(pIOHandler->Open( pFile, "rb")); - - // first 9 bytes are nendo file format ("nendo 1.n") - const char* head = (const char*)reader.GetPtr(); - reader.IncPtr(9); - - if (strncmp("nendo ",head,6)) { - throw DeadlyImportError("Not a Nendo file; magic signature missing"); - } - // check if this is a supported version. if not, continue, too -- users, - // please don't complain if it doesn't work then ... - unsigned int file_format = 12; - if (!strncmp("1.0",head+6,3)) { - file_format = 10; - DefaultLogger::get()->info("NDO file format is 1.0"); - } - else if (!strncmp("1.1",head+6,3)) { - file_format = 11; - DefaultLogger::get()->info("NDO file format is 1.1"); - } - else if (!strncmp("1.2",head+6,3)) { - file_format = 12; - DefaultLogger::get()->info("NDO file format is 1.2"); - } - else { - DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6)); - } - - reader.IncPtr(2); /* skip flags */ - if (file_format >= 12) { - reader.IncPtr(2); - } - unsigned int temp = reader.GetU1(); - - std::vector<Object> objects(temp); /* buffer to store all the loaded objects in */ - - // read all objects - for (unsigned int o = 0; o < objects.size(); ++o) { - -// if (file_format < 12) { - if (!reader.GetI1()) { - continue; /* skip over empty object */ - } - // reader.GetI2(); -// } - Object& obj = objects[o]; - - temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - head = (const char*)reader.GetPtr(); - reader.IncPtr(temp + 76); /* skip unknown stuff */ - - obj.name = std::string(head, temp); - - // read edge table - temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - obj.edges.reserve(temp); - for (unsigned int e = 0; e < temp; ++e) { - - obj.edges.push_back(Edge()); - Edge& edge = obj.edges.back(); - - for (unsigned int i = 0; i< 8; ++i) { - edge.edge[i] = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - } - edge.hard = file_format >= 11 ? reader.GetU1() : 0; - for (unsigned int i = 0; i< 8; ++i) { - edge.color[i] = reader.GetU1(); - } - } - - // read face table - temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - obj.faces.reserve(temp); - for (unsigned int e = 0; e < temp; ++e) { - - obj.faces.push_back(Face()); - Face& face = obj.faces.back(); - - face.elem = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - } - - // read vertex table - temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - obj.vertices.reserve(temp); - for (unsigned int e = 0; e < temp; ++e) { - - obj.vertices.push_back(Vertex()); - Vertex& v = obj.vertices.back(); - - v.num = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - v.val.x = reader.GetF4(); - v.val.y = reader.GetF4(); - v.val.z = reader.GetF4(); - } - - // read UVs - temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - for (unsigned int e = 0; e < temp; ++e) { - file_format >= 12 ? reader.GetU4() : reader.GetU2(); - } - - temp = file_format >= 12 ? reader.GetU4() : reader.GetU2(); - for (unsigned int e = 0; e < temp; ++e) { - file_format >= 12 ? reader.GetU4() : reader.GetU2(); - } - - if (reader.GetU1()) { - const unsigned int x = reader.GetU2(), y = reader.GetU2(); - temp = 0; - while (temp < x*y) { - unsigned int repeat = reader.GetU1(); - reader.GetU1(); - reader.GetU1(); - reader.GetU1(); - temp += repeat; - } - } - } - - // construct a dummy node graph and add all named objects as child nodes - aiNode* root = pScene->mRootNode = new aiNode("$NDODummyRoot"); - aiNode** cc = root->mChildren = new aiNode* [ root->mNumChildren = static_cast<unsigned int>( objects.size()) ] (); - pScene->mMeshes = new aiMesh* [ root->mNumChildren] (); - - std::vector<aiVector3D> vertices; - std::vector<unsigned int> indices; - - for_each(const Object& obj,objects) { - aiNode* nd = *cc++ = new aiNode(obj.name); - nd->mParent = root; - - // translated from a python dict() - a vector might be sufficient as well - typedef std::map<unsigned int, unsigned int> FaceTable; - FaceTable face_table; - - unsigned int n = 0; - for_each(const Edge& edge, obj.edges) { - - face_table[edge.edge[2]] = n; - face_table[edge.edge[3]] = n; - - ++n; - } - - aiMesh* mesh = new aiMesh(); - aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces=face_table.size()]; - - vertices.clear(); - vertices.reserve(4 * face_table.size()); // arbitrarily choosen - for_each(FaceTable::value_type& v, face_table) { - indices.clear(); - - aiFace& f = *faces++; - - const unsigned int key = v.first; - unsigned int cur_edge = v.second; - while (1) { - unsigned int next_edge, next_vert; - if (key == obj.edges[cur_edge].edge[3]) { - next_edge = obj.edges[cur_edge].edge[5]; - next_vert = obj.edges[cur_edge].edge[1]; - } - else { - next_edge = obj.edges[cur_edge].edge[4]; - next_vert = obj.edges[cur_edge].edge[0]; - } - indices.push_back( vertices.size() ); - vertices.push_back(obj.vertices[ next_vert ].val); - - cur_edge = next_edge; - if (cur_edge == v.second) { - break; - } - } - - f.mIndices = new unsigned int[f.mNumIndices = indices.size()]; - std::copy(indices.begin(),indices.end(),f.mIndices); - } - - mesh->mVertices = new aiVector3D[mesh->mNumVertices = vertices.size()]; - std::copy(vertices.begin(),vertices.end(),mesh->mVertices); - - if (mesh->mNumVertices) { - pScene->mMeshes[pScene->mNumMeshes] = mesh; - - (nd->mMeshes = new unsigned int[nd->mNumMeshes=1])[0]=pScene->mNumMeshes++; - } - } -} - -#endif diff --git a/3rdparty/assimp/code/NDOLoader.h b/3rdparty/assimp/code/NDOLoader.h deleted file mode 100644 index 1bae9c65..00000000 --- a/3rdparty/assimp/code/NDOLoader.h +++ /dev/null @@ -1,116 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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 NDOLoader.h - * Declaration of the Nendo importer class. - */ -#ifndef INCLUDED_AI_NDO_LOADER_H -#define INCLUDED_AI_NDO_LOADER_H -namespace Assimp { - -// --------------------------------------------------------------------------- -/** @brief Importer class to load meshes from Nendo. - * - * Basing on - * <blender>/blender/release/scripts/nendo_import.py by Anthony D'Agostino. -*/ -class NDOImporter : public BaseImporter -{ - friend class Importer; -protected: - /** Constructor to be privately used by Importer */ - NDOImporter(); - - /** Destructor, private as well */ - ~NDOImporter(); - -public: - - //! Represents a single edge - struct Edge - { - unsigned int edge[8]; - unsigned int hard; - uint8_t color[8]; - }; - - //! Represents a single face - struct Face - { - unsigned int elem; - }; - - struct Vertex - { - unsigned int num; - aiVector3D val; - }; - - //! Represents a single object - struct Object - { - std::string name; - - std::vector<Edge> edges; - std::vector<Face> faces; - std::vector<Vertex> vertices; - }; - - // ------------------------------------------------------------------- - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - -}; // end of class NDOImporter -} // end of namespace Assimp -#endif // INCLUDED_AI_NDO_LOADER_H diff --git a/3rdparty/assimp/code/NFFLoader.cpp b/3rdparty/assimp/code/NFFLoader.cpp deleted file mode 100644 index 158fcb8d..00000000 --- a/3rdparty/assimp/code/NFFLoader.cpp +++ /dev/null @@ -1,1256 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 STL importer class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_NFF_IMPORTER - -// internal headers -#include "NFFLoader.h" -#include "ParsingUtils.h" -#include "StandardShapes.h" -#include "fast_atof.h" -#include "RemoveComments.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -NFFImporter::NFFImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -NFFImporter::~NFFImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool NFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - return SimpleExtensionCheck(pFile,"nff","enff"); -} - -// ------------------------------------------------------------------------------------------------ -// Get the list of all supported file extensions -void NFFImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("enff"); - extensions.insert("nff"); -} - -// ------------------------------------------------------------------------------------------------ -#define AI_NFF_PARSE_FLOAT(f) \ - SkipSpaces(&sz); \ - if (!::IsLineEnd(*sz))sz = fast_atof_move(sz, (float&)f); - -// ------------------------------------------------------------------------------------------------ -#define AI_NFF_PARSE_TRIPLE(v) \ - AI_NFF_PARSE_FLOAT(v[0]) \ - AI_NFF_PARSE_FLOAT(v[1]) \ - AI_NFF_PARSE_FLOAT(v[2]) - -// ------------------------------------------------------------------------------------------------ -#define AI_NFF_PARSE_SHAPE_INFORMATION() \ - aiVector3D center, radius(1.0f,get_qnan(),get_qnan()); \ - AI_NFF_PARSE_TRIPLE(center); \ - AI_NFF_PARSE_TRIPLE(radius); \ - if (is_qnan(radius.z))radius.z = radius.x; \ - if (is_qnan(radius.y))radius.y = radius.x; \ - currentMesh.radius = radius; \ - currentMesh.center = center; - -// ------------------------------------------------------------------------------------------------ -#define AI_NFF2_GET_NEXT_TOKEN() \ - do \ - { \ - if (!GetNextLine(buffer,line)) \ - {DefaultLogger::get()->warn("NFF2: Unexpected EOF, can't read next token");break;} \ - SkipSpaces(line,&sz); \ - } \ - while (IsLineEnd(*sz)) - - -// ------------------------------------------------------------------------------------------------ -// Loads the materail table for the NFF2 file format from an external file -void NFFImporter::LoadNFF2MaterialTable(std::vector<ShadingInfo>& output, - const std::string& path, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( path, "rb")); - - // Check whether we can read from the file - if ( !file.get()) { - DefaultLogger::get()->error("NFF2: Unable to open material library " + path + "."); - return; - } - - // get the size of the file - const unsigned int m = (unsigned int)file->FileSize(); - - // allocate storage and copy the contents of the file to a memory buffer - // (terminate it with zero) - std::vector<char> mBuffer2(m+1); - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; - - // First of all: remove all comments from the file - CommentRemover::RemoveLineComments("//",&mBuffer2[0]); - - // The file should start with the magic sequence "mat" - if (!TokenMatch(buffer,"mat",3)) { - DefaultLogger::get()->error("NFF2: Not a valid material library " + path + "."); - return; - } - - ShadingInfo* curShader = NULL; - - // No read the file line per line - char line[4096]; - const char* sz; - while (GetNextLine(buffer,line)) - { - SkipSpaces(line,&sz); - - // 'version' defines the version of the file format - if (TokenMatch(sz,"version",7)) - { - DefaultLogger::get()->info("NFF (Sense8) material library file format: " + std::string(sz)); - } - // 'matdef' starts a new material in the file - else if (TokenMatch(sz,"matdef",6)) - { - // add a new material to the list - output.push_back( ShadingInfo() ); - curShader = & output.back(); - - // parse the name of the material - } - else if (!TokenMatch(sz,"valid",5)) - { - // check whether we have an active material at the moment - if (!IsLineEnd(*sz)) - { - if (!curShader) - { - DefaultLogger::get()->error(std::string("NFF2 material library: Found element ") + - sz + "but there is no active material"); - continue; - } - } - else continue; - - // now read the material property and determine its type - aiColor3D c; - if (TokenMatch(sz,"ambient",7)) - { - AI_NFF_PARSE_TRIPLE(c); - curShader->ambient = c; - } - else if (TokenMatch(sz,"diffuse",7) || TokenMatch(sz,"ambientdiffuse",14) /* correct? */) - { - AI_NFF_PARSE_TRIPLE(c); - curShader->diffuse = curShader->ambient = c; - } - else if (TokenMatch(sz,"specular",8)) - { - AI_NFF_PARSE_TRIPLE(c); - curShader->specular = c; - } - else if (TokenMatch(sz,"emission",8)) - { - AI_NFF_PARSE_TRIPLE(c); - curShader->emissive = c; - } - else if (TokenMatch(sz,"shininess",9)) - { - AI_NFF_PARSE_FLOAT(curShader->shininess); - } - else if (TokenMatch(sz,"opacity",7)) - { - AI_NFF_PARSE_FLOAT(curShader->opacity); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void NFFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( !file.get()) - throw DeadlyImportError( "Failed to open NFF file " + pFile + "."); - - unsigned int m = (unsigned int)file->FileSize(); - - // allocate storage and copy the contents of the file to a memory buffer - // (terminate it with zero) - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; - - // mesh arrays - separate here to make the handling of the pointers below easier. - std::vector<MeshInfo> meshes; - std::vector<MeshInfo> meshesWithNormals; - std::vector<MeshInfo> meshesWithUVCoords; - std::vector<MeshInfo> meshesLocked; - - char line[4096]; - const char* sz; - - // camera parameters - aiVector3D camPos, camUp(0.f,1.f,0.f), camLookAt(0.f,0.f,1.f); - float angle = 45.f; - aiVector2D resolution; - - bool hasCam = false; - - MeshInfo* currentMeshWithNormals = NULL; - MeshInfo* currentMesh = NULL; - MeshInfo* currentMeshWithUVCoords = NULL; - - ShadingInfo s; // current material info - - // degree of tesselation - unsigned int iTesselation = 4; - - // some temporary variables we need to parse the file - unsigned int sphere = 0, - cylinder = 0, - cone = 0, - numNamed = 0, - dodecahedron = 0, - octahedron = 0, - tetrahedron = 0, - hexahedron = 0; - - // lights imported from the file - std::vector<Light> lights; - - // check whether this is the NFF2 file format - if (TokenMatch(buffer,"nff",3)) - { - const float qnan = get_qnan(); - const aiColor4D cQNAN = aiColor4D (qnan,0.f,0.f,1.f); - const aiVector3D vQNAN = aiVector3D(qnan,0.f,0.f); - - // another NFF file format ... just a raw parser has been implemented - // no support for further details, I don't think it is worth the effort - // http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/nff/nff2.html - // http://www.netghost.narod.ru/gff/graphics/summary/sense8.htm - - // First of all: remove all comments from the file - CommentRemover::RemoveLineComments("//",&mBuffer2[0]); - - while (GetNextLine(buffer,line)) - { - SkipSpaces(line,&sz); - if (TokenMatch(sz,"version",7)) - { - DefaultLogger::get()->info("NFF (Sense8) file format: " + std::string(sz)); - } - else if (TokenMatch(sz,"viewpos",7)) - { - AI_NFF_PARSE_TRIPLE(camPos); - hasCam = true; - } - else if (TokenMatch(sz,"viewdir",7)) - { - AI_NFF_PARSE_TRIPLE(camLookAt); - hasCam = true; - } - // This starts a new object section - else if (!IsSpaceOrNewLine(*sz)) - { - unsigned int subMeshIdx = 0; - - // read the name of the object, skip all spaces - // at the end of it. - const char* sz3 = sz; - while (!IsSpaceOrNewLine(*sz))++sz; - std::string objectName = std::string(sz3,(unsigned int)(sz-sz3)); - - const unsigned int objStart = (unsigned int)meshes.size(); - - // There could be a material table in a separate file - std::vector<ShadingInfo> materialTable; - while (true) - { - AI_NFF2_GET_NEXT_TOKEN(); - - // material table - an external file - if (TokenMatch(sz,"mtable",6)) - { - SkipSpaces(&sz); - sz3 = sz; - while (!IsSpaceOrNewLine(*sz))++sz; - const unsigned int diff = (unsigned int)(sz-sz3); - if (!diff)DefaultLogger::get()->warn("NFF2: Found empty mtable token"); - else - { - // The material table has the file extension .mat. - // If it is not there, we need to append it - std::string path = std::string(sz3,diff); - if (std::string::npos == path.find_last_of(".mat")) - { - path.append(".mat"); - } - - // Now extract the working directory from the path to - // this file and append the material library filename - // to it. - std::string::size_type s; - if ((std::string::npos == (s = path.find_last_of('\\')) || !s) && - (std::string::npos == (s = path.find_last_of('/')) || !s) ) - { - s = pFile.find_last_of('\\'); - if (std::string::npos == s)s = pFile.find_last_of('/'); - if (std::string::npos != s) - { - path = pFile.substr(0,s+1) + path; - } - } - LoadNFF2MaterialTable(materialTable,path,pIOHandler); - } - } - else break; - } - - // read the numbr of vertices - unsigned int num = ::strtol10(sz,&sz); - - // temporary storage - std::vector<aiColor4D> tempColors; - std::vector<aiVector3D> tempPositions,tempTextureCoords,tempNormals; - - bool hasNormals = false,hasUVs = false,hasColor = false; - - tempPositions.reserve (num); - tempColors.reserve (num); - tempNormals.reserve (num); - tempTextureCoords.reserve (num); - for (unsigned int i = 0; i < num; ++i) - { - AI_NFF2_GET_NEXT_TOKEN(); - aiVector3D v; - AI_NFF_PARSE_TRIPLE(v); - tempPositions.push_back(v); - - // parse all other attributes in the line - while (true) - { - SkipSpaces(&sz); - if (IsLineEnd(*sz))break; - - // color definition - if (TokenMatch(sz,"0x",2)) - { - hasColor = true; - register unsigned int numIdx = ::strtol16(sz,&sz); - aiColor4D clr; - clr.a = 1.f; - - // 0xRRGGBB - clr.r = ((numIdx >> 16u) & 0xff) / 255.f; - clr.g = ((numIdx >> 8u) & 0xff) / 255.f; - clr.b = ((numIdx) & 0xff) / 255.f; - tempColors.push_back(clr); - } - // normal vector - else if (TokenMatch(sz,"norm",4)) - { - hasNormals = true; - AI_NFF_PARSE_TRIPLE(v); - tempNormals.push_back(v); - } - // UV coordinate - else if (TokenMatch(sz,"uv",2)) - { - hasUVs = true; - AI_NFF_PARSE_FLOAT(v.x); - AI_NFF_PARSE_FLOAT(v.y); - v.z = 0.f; - tempTextureCoords.push_back(v); - } - } - - // fill in dummies for all attributes that have not been set - if (tempNormals.size() != tempPositions.size()) - tempNormals.push_back(vQNAN); - - if (tempTextureCoords.size() != tempPositions.size()) - tempTextureCoords.push_back(vQNAN); - - if (tempColors.size() != tempPositions.size()) - tempColors.push_back(cQNAN); - } - - AI_NFF2_GET_NEXT_TOKEN(); - if (!num)throw DeadlyImportError("NFF2: There are zero vertices"); - num = ::strtol10(sz,&sz); - - std::vector<unsigned int> tempIdx; - tempIdx.reserve(10); - for (unsigned int i = 0; i < num; ++i) - { - AI_NFF2_GET_NEXT_TOKEN(); - SkipSpaces(line,&sz); - unsigned int numIdx = ::strtol10(sz,&sz); - - // read all faces indices - if (numIdx) - { - // mesh.faces.push_back(numIdx); - // tempIdx.erase(tempIdx.begin(),tempIdx.end()); - tempIdx.resize(numIdx); - - for (unsigned int a = 0; a < numIdx;++a) - { - SkipSpaces(sz,&sz); - m = ::strtol10(sz,&sz); - if (m >= (unsigned int)tempPositions.size()) - { - DefaultLogger::get()->error("NFF2: Vertex index overflow"); - m= 0; - } - // mesh.vertices.push_back (tempPositions[idx]); - tempIdx[a] = m; - } - } - - // build a temporary shader object for the face. - ShadingInfo shader; - unsigned int matIdx = 0; - - // white material color - we have vertex colors - shader.color = aiColor3D(1.f,1.f,1.f); - aiColor4D c = aiColor4D(1.f,1.f,1.f,1.f); - while (true) - { - SkipSpaces(sz,&sz); - if (IsLineEnd(*sz))break; - - // per-polygon colors - if (TokenMatch(sz,"0x",2)) - { - hasColor = true; - const char* sz2 = sz; - numIdx = ::strtol16(sz,&sz); - const unsigned int diff = (unsigned int)(sz-sz2); - - // 0xRRGGBB - if (diff > 3) - { - c.r = ((numIdx >> 16u) & 0xff) / 255.f; - c.g = ((numIdx >> 8u) & 0xff) / 255.f; - c.b = ((numIdx) & 0xff) / 255.f; - } - // 0xRGB - else - { - c.r = ((numIdx >> 8u) & 0xf) / 16.f; - c.g = ((numIdx >> 4u) & 0xf) / 16.f; - c.b = ((numIdx) & 0xf) / 16.f; - } - } - // TODO - implement texture mapping here -#if 0 - // mirror vertex texture coordinate? - else if (TokenMatch(sz,"mirror",6)) - { - } - // texture coordinate scaling - else if (TokenMatch(sz,"scale",5)) - { - } - // texture coordinate translation - else if (TokenMatch(sz,"trans",5)) - { - } - // texture coordinate rotation angle - else if (TokenMatch(sz,"rot",3)) - { - } -#endif - - // texture file name for this polygon + mapping information - else if ('_' == sz[0]) - { - // get mapping information - switch (sz[1]) - { - case 'v': - case 'V': - - shader.shaded = false; - break; - - case 't': - case 'T': - case 'u': - case 'U': - - DefaultLogger::get()->warn("Unsupported NFF2 texture attribute: trans"); - }; - if (!sz[1] || '_' != sz[2]) - { - DefaultLogger::get()->warn("NFF2: Expected underscore after texture attributes"); - continue; - } - const char* sz2 = sz+3; - while (!IsSpaceOrNewLine( *sz ))++sz; - const unsigned int diff = (unsigned int)(sz-sz2); - if (diff)shader.texFile = std::string(sz2,diff); - } - - // Two-sided material? - else if (TokenMatch(sz,"both",4)) - { - shader.twoSided = true; - } - - // Material ID? - else if (!materialTable.empty() && TokenMatch(sz,"matid",5)) - { - SkipSpaces(&sz); - matIdx = ::strtol10(sz,&sz); - if (matIdx >= materialTable.size()) - { - DefaultLogger::get()->error("NFF2: Material index overflow."); - matIdx = 0; - } - - // now combine our current shader with the shader we - // read from the material table. - ShadingInfo& mat = materialTable[matIdx]; - shader.ambient = mat.ambient; - shader.diffuse = mat.diffuse; - shader.emissive = mat.emissive; - shader.opacity = mat.opacity; - shader.specular = mat.specular; - shader.shininess = mat.shininess; - } - else SkipToken(sz); - } - - // search the list of all shaders we have for this object whether - // there is an identical one. In this case, we append our mesh - // data to it. - MeshInfo* mesh = NULL; - for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end(); - it != end; ++it) - { - if ((*it).shader == shader && (*it).matIndex == matIdx) - { - // we have one, we can append our data to it - mesh = &(*it); - } - } - if (!mesh) - { - meshes.push_back(MeshInfo(PatchType_Simple,false)); - mesh = &meshes.back(); - mesh->matIndex = matIdx; - - // We need to add a new mesh to the list. We assign - // an unique name to it to make sure the scene will - // pass the validation step for the moment. - // TODO: fix naming of objects in the scenegraph later - if (objectName.length()) - { - ::strcpy(mesh->name,objectName.c_str()); - ASSIMP_itoa10(&mesh->name[objectName.length()],30,subMeshIdx++); - } - - // copy the shader to the mesh. - mesh->shader = shader; - } - - // fill the mesh with data - if (!tempIdx.empty()) - { - mesh->faces.push_back((unsigned int)tempIdx.size()); - for (std::vector<unsigned int>::const_iterator it = tempIdx.begin(), end = tempIdx.end(); - it != end;++it) - { - m = *it; - - // copy colors -vertex color specifications override polygon color specifications - if (hasColor) - { - const aiColor4D& clr = tempColors[m]; - mesh->colors.push_back((is_qnan( clr.r ) ? c : clr)); - } - - // positions should always be there - mesh->vertices.push_back (tempPositions[m]); - - // copy normal vectors - if (hasNormals) - mesh->normals.push_back (tempNormals[m]); - - // copy texture coordinates - if (hasUVs) - mesh->uvs.push_back (tempTextureCoords[m]); - } - } - } - if (!num)throw DeadlyImportError("NFF2: There are zero faces"); - } - } - camLookAt = camLookAt + camPos; - } - else // "Normal" Neutral file format that is quite more common - { - while (GetNextLine(buffer,line)) - { - sz = line; - if ('p' == line[0] || TokenMatch(sz,"tpp",3)) - { - MeshInfo* out = NULL; - - // 'tpp' - texture polygon patch primitive - if ('t' == line[0]) - { - currentMeshWithUVCoords = NULL; - for (std::vector<MeshInfo>::iterator it = meshesWithUVCoords.begin(), end = meshesWithUVCoords.end(); - it != end;++it) - { - if ((*it).shader == s) - { - currentMeshWithUVCoords = &(*it); - break; - } - } - - if (!currentMeshWithUVCoords) - { - meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals)); - currentMeshWithUVCoords = &meshesWithUVCoords.back(); - currentMeshWithUVCoords->shader = s; - } - out = currentMeshWithUVCoords; - } - // 'pp' - polygon patch primitive - else if ('p' == line[1]) - { - currentMeshWithNormals = NULL; - for (std::vector<MeshInfo>::iterator it = meshesWithNormals.begin(), end = meshesWithNormals.end(); - it != end;++it) - { - if ((*it).shader == s) - { - currentMeshWithNormals = &(*it); - break; - } - } - - if (!currentMeshWithNormals) - { - meshesWithNormals.push_back(MeshInfo(PatchType_Normals)); - currentMeshWithNormals = &meshesWithNormals.back(); - currentMeshWithNormals->shader = s; - } - sz = &line[2];out = currentMeshWithNormals; - } - // 'p' - polygon primitive - else - { - currentMesh = NULL; - for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end(); - it != end;++it) - { - if ((*it).shader == s) - { - currentMesh = &(*it); - break; - } - } - - if (!currentMesh) - { - meshes.push_back(MeshInfo(PatchType_Simple)); - currentMesh = &meshes.back(); - currentMesh->shader = s; - } - sz = &line[1];out = currentMesh; - } - SkipSpaces(sz,&sz); - m = strtol10(sz); - - // ---- flip the face order - out->vertices.resize(out->vertices.size()+m); - if (out != currentMesh) - { - out->normals.resize(out->vertices.size()); - } - if (out == currentMeshWithUVCoords) - { - out->uvs.resize(out->vertices.size()); - } - for (unsigned int n = 0; n < m;++n) - { - if (!GetNextLine(buffer,line)) - { - DefaultLogger::get()->error("NFF: Unexpected EOF was encountered. Patch definition incomplete"); - continue; - } - - aiVector3D v; sz = &line[0]; - AI_NFF_PARSE_TRIPLE(v); - out->vertices[out->vertices.size()-n-1] = v; - - if (out != currentMesh) - { - AI_NFF_PARSE_TRIPLE(v); - out->normals[out->vertices.size()-n-1] = v; - } - if (out == currentMeshWithUVCoords) - { - // FIX: in one test file this wraps over multiple lines - SkipSpaces(&sz); - if (IsLineEnd(*sz)) - { - GetNextLine(buffer,line); - sz = line; - } - AI_NFF_PARSE_FLOAT(v.x); - SkipSpaces(&sz); - if (IsLineEnd(*sz)) - { - GetNextLine(buffer,line); - sz = line; - } - AI_NFF_PARSE_FLOAT(v.y); - v.y = 1.f - v.y; - out->uvs[out->vertices.size()-n-1] = v; - } - } - out->faces.push_back(m); - } - // 'f' - shading information block - else if (TokenMatch(sz,"f",1)) - { - float d; - - // read the RGB colors - AI_NFF_PARSE_TRIPLE(s.color); - - // read the other properties - AI_NFF_PARSE_FLOAT(s.diffuse.r); - AI_NFF_PARSE_FLOAT(s.specular.r); - AI_NFF_PARSE_FLOAT(d); // skip shininess and transmittance - AI_NFF_PARSE_FLOAT(d); - AI_NFF_PARSE_FLOAT(s.refracti); - - // NFF2 uses full colors here so we need to use them too - // although NFF uses simple scaling factors - s.diffuse.g = s.diffuse.b = s.diffuse.r; - s.specular.g = s.specular.b = s.specular.r; - - // if the next one is NOT a number we assume it is a texture file name - // this feature is used by some NFF files on the internet and it has - // been implemented as it can be really useful - SkipSpaces(&sz); - if (!IsNumeric(*sz)) - { - // TODO: Support full file names with spaces and quotation marks ... - const char* p = sz; - while (!IsSpaceOrNewLine( *sz ))++sz; - - unsigned int diff = (unsigned int)(sz-p); - if (diff) - { - s.texFile = std::string(p,diff); - } - } - else - { - AI_NFF_PARSE_FLOAT(s.ambient); // optional - } - } - // 'shader' - other way to specify a texture - else if (TokenMatch(sz,"shader",6)) - { - SkipSpaces(&sz); - const char* old = sz; - while (!IsSpaceOrNewLine(*sz))++sz; - s.texFile = std::string(old, (uintptr_t)sz - (uintptr_t)old); - } - // 'l' - light source - else if (TokenMatch(sz,"l",1)) - { - lights.push_back(Light()); - Light& light = lights.back(); - - AI_NFF_PARSE_TRIPLE(light.position); - AI_NFF_PARSE_FLOAT (light.intensity); - AI_NFF_PARSE_TRIPLE(light.color); - } - // 's' - sphere - else if (TokenMatch(sz,"s",1)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; - - AI_NFF_PARSE_SHAPE_INFORMATION(); - - // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeSphere(iTesselation, currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); - - // generate a name for the mesh - ::sprintf(currentMesh.name,"sphere_%i",sphere++); - } - // 'dod' - dodecahedron - else if (TokenMatch(sz,"dod",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; - - AI_NFF_PARSE_SHAPE_INFORMATION(); - - // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeDodecahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); - - // generate a name for the mesh - ::sprintf(currentMesh.name,"dodecahedron_%i",dodecahedron++); - } - - // 'oct' - octahedron - else if (TokenMatch(sz,"oct",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; - - AI_NFF_PARSE_SHAPE_INFORMATION(); - - // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeOctahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); - - // generate a name for the mesh - ::sprintf(currentMesh.name,"octahedron_%i",octahedron++); - } - - // 'tet' - tetrahedron - else if (TokenMatch(sz,"tet",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_SPHERE; - - AI_NFF_PARSE_SHAPE_INFORMATION(); - - // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeTetrahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); - - // generate a name for the mesh - ::sprintf(currentMesh.name,"tetrahedron_%i",tetrahedron++); - } - - // 'hex' - hexahedron - else if (TokenMatch(sz,"hex",3)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_BOX; - - AI_NFF_PARSE_SHAPE_INFORMATION(); - - // we don't need scaling or translation here - we do it in the node's transform - StandardShapes::MakeHexahedron(currentMesh.vertices); - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); - - // generate a name for the mesh - ::sprintf(currentMesh.name,"hexahedron_%i",hexahedron++); - } - // 'c' - cone - else if (TokenMatch(sz,"c",1)) - { - meshesLocked.push_back(MeshInfo(PatchType_Simple,true)); - MeshInfo& currentMesh = meshesLocked.back(); - currentMesh.shader = s; - currentMesh.shader.mapping = aiTextureMapping_CYLINDER; - - if (!GetNextLine(buffer,line)) - { - DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)"); - break; - } - sz = line; - - // read the two center points and the respective radii - aiVector3D center1, center2; float radius1, radius2; - AI_NFF_PARSE_TRIPLE(center1); - AI_NFF_PARSE_FLOAT(radius1); - - if (!GetNextLine(buffer,line)) - { - DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)"); - break; - } - sz = line; - - AI_NFF_PARSE_TRIPLE(center2); - AI_NFF_PARSE_FLOAT(radius2); - - // compute the center point of the cone/cylinder - - // it is its local transformation origin - currentMesh.dir = center2-center1; - currentMesh.center = center1+currentMesh.dir/2.f; - - float f; - if (( f = currentMesh.dir.Length()) < 10e-3f ) - { - DefaultLogger::get()->error("NFF: Cone height is close to zero"); - continue; - } - currentMesh.dir /= f; // normalize - - // generate the cone - it consists of simple triangles - StandardShapes::MakeCone(f, radius1, radius2, - integer_pow(4, iTesselation), currentMesh.vertices); - - // MakeCone() returns tris - currentMesh.faces.resize(currentMesh.vertices.size()/3,3); - - // generate a name for the mesh. 'cone' if it a cone, - // 'cylinder' if it is a cylinder. Funny, isn't it? - if (radius1 != radius2) - ::sprintf(currentMesh.name,"cone_%i",cone++); - else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++); - } - // 'tess' - tesselation - else if (TokenMatch(sz,"tess",4)) - { - SkipSpaces(&sz); - iTesselation = strtol10(sz); - } - // 'from' - camera position - else if (TokenMatch(sz,"from",4)) - { - AI_NFF_PARSE_TRIPLE(camPos); - hasCam = true; - } - // 'at' - camera look-at vector - else if (TokenMatch(sz,"at",2)) - { - AI_NFF_PARSE_TRIPLE(camLookAt); - hasCam = true; - } - // 'up' - camera up vector - else if (TokenMatch(sz,"up",2)) - { - AI_NFF_PARSE_TRIPLE(camUp); - hasCam = true; - } - // 'angle' - (half?) camera field of view - else if (TokenMatch(sz,"angle",5)) - { - AI_NFF_PARSE_FLOAT(angle); - hasCam = true; - } - // 'resolution' - used to compute the screen aspect - else if (TokenMatch(sz,"resolution",10)) - { - AI_NFF_PARSE_FLOAT(resolution.x); - AI_NFF_PARSE_FLOAT(resolution.y); - hasCam = true; - } - // 'pb' - bezier patch. Not supported yet - else if (TokenMatch(sz,"pb",2)) - { - DefaultLogger::get()->error("NFF: Encountered unsupported ID: bezier patch"); - } - // 'pn' - NURBS. Not supported yet - else if (TokenMatch(sz,"pn",2) || TokenMatch(sz,"pnn",3)) - { - DefaultLogger::get()->error("NFF: Encountered unsupported ID: NURBS"); - } - // '' - comment - else if ('#' == line[0]) - { - const char* sz;SkipSpaces(&line[1],&sz); - if (!IsLineEnd(*sz))DefaultLogger::get()->info(sz); - } - } - } - - // copy all arrays into one large - meshes.reserve (meshes.size()+meshesLocked.size()+meshesWithNormals.size()+meshesWithUVCoords.size()); - meshes.insert (meshes.end(),meshesLocked.begin(),meshesLocked.end()); - meshes.insert (meshes.end(),meshesWithNormals.begin(),meshesWithNormals.end()); - meshes.insert (meshes.end(),meshesWithUVCoords.begin(),meshesWithUVCoords.end()); - - // now generate output meshes. first find out how many meshes we'll need - std::vector<MeshInfo>::const_iterator it = meshes.begin(), end = meshes.end(); - for (;it != end;++it) - { - if (!(*it).faces.empty()) - { - ++pScene->mNumMeshes; - if ((*it).name[0])++numNamed; - } - } - - // generate a dummy root node - assign all unnamed elements such - // as polygons and polygon patches to the root node and generate - // sub nodes for named objects such as spheres and cones. - aiNode* const root = new aiNode(); - root->mName.Set("<NFF_Root>"); - root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int) lights.size(); - root->mNumMeshes = pScene->mNumMeshes-numNamed; - - aiNode** ppcChildren = NULL; - unsigned int* pMeshes = NULL; - if (root->mNumMeshes) - pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes]; - if (root->mNumChildren) - ppcChildren = root->mChildren = new aiNode*[root->mNumChildren]; - - // generate the camera - if (hasCam) - { - aiNode* nd = *ppcChildren = new aiNode(); - nd->mName.Set("<NFF_Camera>"); - nd->mParent = root; - - // allocate the camera in the scene - pScene->mNumCameras = 1; - pScene->mCameras = new aiCamera*[1]; - aiCamera* c = pScene->mCameras[0] = new aiCamera; - - c->mName = nd->mName; // make sure the names are identical - c->mHorizontalFOV = AI_DEG_TO_RAD( angle ); - c->mLookAt = camLookAt - camPos; - c->mPosition = camPos; - c->mUp = camUp; - - // If the resolution is not specified in the file, we - // need to set 1.0 as aspect. - c->mAspect = (!resolution.y ? 0.f : resolution.x / resolution.y); - ++ppcChildren; - } - - // generate light sources - if (!lights.empty()) - { - pScene->mNumLights = (unsigned int)lights.size(); - pScene->mLights = new aiLight*[pScene->mNumLights]; - for (unsigned int i = 0; i < pScene->mNumLights;++i,++ppcChildren) - { - const Light& l = lights[i]; - - aiNode* nd = *ppcChildren = new aiNode(); - nd->mParent = root; - - nd->mName.length = ::sprintf(nd->mName.data,"<NFF_Light%i>",i); - - // allocate the light in the scene data structure - aiLight* out = pScene->mLights[i] = new aiLight(); - out->mName = nd->mName; // make sure the names are identical - out->mType = aiLightSource_POINT; - out->mColorDiffuse = out->mColorSpecular = l.color * l.intensity; - out->mPosition = l.position; - } - } - - if (!pScene->mNumMeshes)throw DeadlyImportError("NFF: No meshes loaded"); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes]; - for (it = meshes.begin(), m = 0; it != end;++it) - { - if ((*it).faces.empty())continue; - - const MeshInfo& src = *it; - aiMesh* const mesh = pScene->mMeshes[m] = new aiMesh(); - mesh->mNumVertices = (unsigned int)src.vertices.size(); - mesh->mNumFaces = (unsigned int)src.faces.size(); - - // Generate sub nodes for named meshes - if (src.name[0]) - { - aiNode* const node = *ppcChildren = new aiNode(); - node->mParent = root; - node->mNumMeshes = 1; - node->mMeshes = new unsigned int[1]; - node->mMeshes[0] = m; - node->mName.Set(src.name); - - // setup the transformation matrix of the node - aiMatrix4x4::FromToMatrix(aiVector3D(0.f,1.f,0.f), - src.dir,node->mTransformation); - - aiMatrix4x4& mat = node->mTransformation; - mat.a1 *= src.radius.x; mat.b1 *= src.radius.x; mat.c1 *= src.radius.x; - mat.a2 *= src.radius.y; mat.b2 *= src.radius.y; mat.c2 *= src.radius.y; - mat.a3 *= src.radius.z; mat.b3 *= src.radius.z; mat.c3 *= src.radius.z; - mat.a4 = src.center.x; - mat.b4 = src.center.y; - mat.c4 = src.center.z; - - ++ppcChildren; - } - else *pMeshes++ = m; - - // copy vertex positions - mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - ::memcpy(mesh->mVertices,&src.vertices[0], - sizeof(aiVector3D)*mesh->mNumVertices); - - // NFF2: there could be vertex colors - if (!src.colors.empty()) - { - ai_assert(src.colors.size() == src.vertices.size()); - - // copy vertex colors - mesh->mColors[0] = new aiColor4D[mesh->mNumVertices]; - ::memcpy(mesh->mColors[0],&src.colors[0], - sizeof(aiColor4D)*mesh->mNumVertices); - } - - if (!src.normals.empty()) - { - ai_assert(src.normals.size() == src.vertices.size()); - - // copy normal vectors - mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - ::memcpy(mesh->mNormals,&src.normals[0], - sizeof(aiVector3D)*mesh->mNumVertices); - } - - if (!src.uvs.empty()) - { - ai_assert(src.uvs.size() == src.vertices.size()); - - // copy texture coordinates - mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]; - ::memcpy(mesh->mTextureCoords[0],&src.uvs[0], - sizeof(aiVector3D)*mesh->mNumVertices); - } - - // generate faces - unsigned int p = 0; - aiFace* pFace = mesh->mFaces = new aiFace[mesh->mNumFaces]; - for (std::vector<unsigned int>::const_iterator it2 = src.faces.begin(), - end2 = src.faces.end(); - it2 != end2;++it2,++pFace) - { - pFace->mIndices = new unsigned int [ pFace->mNumIndices = *it2 ]; - for (unsigned int o = 0; o < pFace->mNumIndices;++o) - pFace->mIndices[o] = p++; - } - - // generate a material for the mesh - MaterialHelper* pcMat = (MaterialHelper*)(pScene->mMaterials[m] = new MaterialHelper()); - - mesh->mMaterialIndex = m++; - - aiString s; - s.Set(AI_DEFAULT_MATERIAL_NAME); - pcMat->AddProperty(&s, AI_MATKEY_NAME); - - // FIX: Ignore diffuse == 0 - aiColor3D c = src.shader.color * (src.shader.diffuse.r ? src.shader.diffuse : aiColor3D(1.f,1.f,1.f)); - pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE); - c = src.shader.color * src.shader.specular; - pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR); - - // NFF2 - default values for NFF - pcMat->AddProperty(&src.shader.ambient, 1,AI_MATKEY_COLOR_AMBIENT); - pcMat->AddProperty(&src.shader.emissive,1,AI_MATKEY_COLOR_EMISSIVE); - pcMat->AddProperty(&src.shader.opacity, 1,AI_MATKEY_OPACITY); - - // setup the first texture layer, if existing - if (src.shader.texFile.length()) - { - s.Set(src.shader.texFile); - pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); - - if (aiTextureMapping_UV != src.shader.mapping) { - - aiVector3D v(0.f,-1.f,0.f); - pcMat->AddProperty(&v, 1,AI_MATKEY_TEXMAP_AXIS_DIFFUSE(0)); - pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0)); - } - } - - // setup the name of the material - if (src.shader.name.length()) - { - s.Set(src.shader.texFile); - pcMat->AddProperty(&s,AI_MATKEY_NAME); - } - - // setup some more material properties that are specific to NFF2 - int i; - if (src.shader.twoSided) - { - i = 1; - pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED); - } - i = (src.shader.shaded ? aiShadingMode_Gouraud : aiShadingMode_NoShading); - if (src.shader.shininess) - { - i = aiShadingMode_Phong; - pcMat->AddProperty(&src.shader.shininess,1,AI_MATKEY_SHININESS); - } - pcMat->AddProperty(&i,1,AI_MATKEY_SHADING_MODEL); - } - pScene->mRootNode = root; -} - -#endif // !! ASSIMP_BUILD_NO_NFF_IMPORTER diff --git a/3rdparty/assimp/code/NFFLoader.h b/3rdparty/assimp/code/NFFLoader.h deleted file mode 100644 index 2e21bdc8..00000000 --- a/3rdparty/assimp/code/NFFLoader.h +++ /dev/null @@ -1,216 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 NFFLoader.h - * @brief Declaration of the NFF importer class. - */ -#ifndef AI_NFFLOADER_H_INCLUDED -#define AI_NFFLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include <vector> - -#include "../include/aiTypes.h" - -namespace Assimp { - -// ---------------------------------------------------------------------------------- -/** NFF (Neutral File Format) Importer class. - * - * The class implements both Eric Haynes NFF format and Sense8's NFF (NFF2) format. - * Both are quite different and the loading code is somewhat dirty at - * the moment. Sense8 should be moved to a separate loader. -*/ -class NFFImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - NFFImporter(); - - /** Destructor, private as well */ - ~NFFImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - - - // describes face material properties - struct ShadingInfo - { - ShadingInfo() - : color (0.6f,0.6f,0.6f) - , diffuse (1.f,1.f,1.f) - , specular (1.f,1.f,1.f) - , ambient (0.f,0.f,0.f) - , emissive (0.f,0.f,0.f) - , refracti (1.f) - , twoSided (false) // for NFF2 - , shaded (true) // for NFF2 - , opacity (1.f) - , shininess (0.f) - , mapping (aiTextureMapping_UV) - {} - - aiColor3D color,diffuse,specular,ambient,emissive; - float refracti; - - std::string texFile; - - // For NFF2 - bool twoSided; - bool shaded; - float opacity, shininess; - - std::string name; - - // texture mapping to be generated for the mesh - uv is the default - // it means: use UV if there, nothing otherwise. This property is - // used for locked meshes. - aiTextureMapping mapping; - - // shininess is ignored for the moment - bool operator == (const ShadingInfo& other) const - { - return color == other.color && - diffuse == other.diffuse && - specular == other.specular && - ambient == other.ambient && - refracti == other.refracti && - texFile == other.texFile && - twoSided == other.twoSided && - shaded == other.shaded; - - // Some properties from NFF2 aren't compared by this operator. - // Comparing MeshInfo::matIndex should do that. - } - }; - - // describes a NFF light source - struct Light - { - Light() - : intensity (1.f) - , color (1.f,1.f,1.f) - {} - - aiVector3D position; - float intensity; - aiColor3D color; - }; - - enum PatchType - { - PatchType_Simple = 0x0, - PatchType_Normals = 0x1, - PatchType_UVAndNormals = 0x2 - }; - - // describes a NFF mesh - struct MeshInfo - { - MeshInfo(PatchType _pType, bool bL = false) - : pType (_pType) - , bLocked (bL) - , radius (1.f,1.f,1.f) - , dir (0.f,1.f,0.f) - , matIndex (0) - { - name[0] = '\0'; // by default meshes are unnamed - } - - ShadingInfo shader; - PatchType pType; - bool bLocked; - - // for spheres, cones and cylinders: center point of the object - aiVector3D center, radius, dir; - - char name[128]; - - std::vector<aiVector3D> vertices, normals, uvs; - std::vector<unsigned int> faces; - - // for NFF2 - std::vector<aiColor4D> colors; - unsigned int matIndex; - }; - - - // ------------------------------------------------------------------- - /** Loads the material table for the NFF2 file format from an - * external file. - * - * @param output Receives the list of output meshes - * @param path Path to the file (abs. or rel.) - * @param pIOHandler IOSystem to be used to open the file - */ - void LoadNFF2MaterialTable(std::vector<ShadingInfo>& output, - const std::string& path, IOSystem* pIOHandler); - -}; - -} // end of namespace Assimp - -#endif // AI_NFFIMPORTER_H_IN diff --git a/3rdparty/assimp/code/OFFLoader.cpp b/3rdparty/assimp/code/OFFLoader.cpp deleted file mode 100644 index 38e21b49..00000000 --- a/3rdparty/assimp/code/OFFLoader.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OFFLoader.cpp - * @brief Implementation of the OFF importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER - -// internal headers -#include "OFFLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -OFFImporter::OFFImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -OFFImporter::~OFFImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - - if (extension == "off") - return true; - else if (!extension.length() || checkSig) - { - if (!pIOHandler)return true; - const char* tokens[] = {"off"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void OFFImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("off"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void OFFImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open OFF file " + pFile + "."); - } - - // allocate storage and copy the contents of the file to a memory buffer - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; - - char line[4096]; - GetNextLine(buffer,line); - if ('O' == line[0]) { - GetNextLine(buffer,line); // skip the 'OFF' line - } - - const char* sz = line; SkipSpaces(&sz); - const unsigned int numVertices = strtol10(sz,&sz);SkipSpaces(&sz); - const unsigned int numFaces = strtol10(sz,&sz); - - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes = 1 ]; - aiMesh* mesh = pScene->mMeshes[0] = new aiMesh(); - aiFace* faces = mesh->mFaces = new aiFace [mesh->mNumFaces = numFaces]; - - std::vector<aiVector3D> tempPositions(numVertices); - - // now read all vertex lines - for (unsigned int i = 0; i< numVertices;++i) - { - if (!GetNextLine(buffer,line)) - { - DefaultLogger::get()->error("OFF: The number of verts in the header is incorrect"); - break; - } - aiVector3D& v = tempPositions[i]; - - sz = line; SkipSpaces(&sz); - sz = fast_atof_move(sz,(float&)v.x); SkipSpaces(&sz); - sz = fast_atof_move(sz,(float&)v.y); SkipSpaces(&sz); - fast_atof_move(sz,(float&)v.z); - } - - - // First find out how many vertices we'll need - const char* old = buffer; - for (unsigned int i = 0; i< mesh->mNumFaces;++i) - { - if (!GetNextLine(buffer,line)) - { - DefaultLogger::get()->error("OFF: The number of faces in the header is incorrect"); - break; - } - sz = line;SkipSpaces(&sz); - if (!(faces->mNumIndices = strtol10(sz,&sz)) || faces->mNumIndices > 9) - { - DefaultLogger::get()->error("OFF: Faces with zero indices aren't allowed"); - --mesh->mNumFaces; - continue; - } - mesh->mNumVertices += faces->mNumIndices; - ++faces; - } - - if (!mesh->mNumVertices) - throw DeadlyImportError("OFF: There are no valid faces"); - - // allocate storage for the output vertices - aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - - // second: now parse all face indices - buffer = old;faces = mesh->mFaces; - for (unsigned int i = 0, p = 0; i< mesh->mNumFaces;) - { - if (!GetNextLine(buffer,line))break; - - unsigned int idx; - sz = line;SkipSpaces(&sz); - if (!(idx = strtol10(sz,&sz)) || idx > 9) - continue; - - faces->mIndices = new unsigned int [faces->mNumIndices]; - for (unsigned int m = 0; m < faces->mNumIndices;++m) - { - SkipSpaces(&sz); - if ((idx = strtol10(sz,&sz)) >= numVertices) - { - DefaultLogger::get()->error("OFF: Vertex index is out of range"); - idx = numVertices-1; - } - faces->mIndices[m] = p++; - *verts++ = tempPositions[idx]; - } - ++i; - ++faces; - } - - // generate the output node graph - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("<OFFRoot>"); - pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes = 1]; - pScene->mRootNode->mMeshes[0] = 0; - - // generate a default material - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = 1]; - MaterialHelper* pcMat = new MaterialHelper(); - - aiColor4D clr(0.6f,0.6f,0.6f,1.0f); - pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - pScene->mMaterials[0] = pcMat; - - const int twosided =1; - pcMat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED); -} - -#endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER diff --git a/3rdparty/assimp/code/OFFLoader.h b/3rdparty/assimp/code/OFFLoader.h deleted file mode 100644 index e4247b6a..00000000 --- a/3rdparty/assimp/code/OFFLoader.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OFFLoader.h - * @brief Declaration of the OFF importer class. - */ -#ifndef AI_OFFLOADER_H_INCLUDED -#define AI_OFFLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" -#include <vector> - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Importer class for the Object File Format (.off) -*/ -class OFFImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - OFFImporter(); - - /** Destructor, private as well */ - ~OFFImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_IN diff --git a/3rdparty/assimp/code/ObjFileData.h b/3rdparty/assimp/code/ObjFileData.h deleted file mode 100644 index 7edfee51..00000000 --- a/3rdparty/assimp/code/ObjFileData.h +++ /dev/null @@ -1,324 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef OBJ_FILEDATA_H_INC -#define OBJ_FILEDATA_H_INC - -#include <vector> -#include <map> -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" - -namespace Assimp -{ - -namespace ObjFile -{ -// ------------------------------------------------------------------------------------------------ -struct Object; -struct Face; -struct Material; - -// ------------------------------------------------------------------------------------------------ -//! \struct Face -//! \brief Datastructure for a simple obj-face, descripes discredisation and materials -struct Face -{ - typedef std::vector<unsigned int> IndexArray; - - //! Primitive type - int m_PrimitiveType; - //! Vertex indices - IndexArray *m_pVertices; - //! Normal indices - IndexArray *m_pNormals; - //! Texture coordinates indices - IndexArray *m_pTexturCoords; - //! Pointer to assigned material - Material *m_pMaterial; - - //! \brief Default constructor - //! \param pVertices Pointer to assigned vertex indexbuffer - //! \param pNormals Pointer to assigned normals indexbuffer - //! \param pTexCoords Pointer to assigned texture indexbuffer - Face( std::vector<unsigned int> *pVertices, - std::vector<unsigned int> *pNormals, - std::vector<unsigned int> *pTexCoords) : - m_PrimitiveType( 2 ), - m_pVertices( pVertices ), - m_pNormals( pNormals ), - m_pTexturCoords( pTexCoords ), - m_pMaterial( 0L ) - { - // empty - } - - //! \brief Destructor - ~Face() - { - delete m_pVertices; - m_pVertices = NULL; - delete m_pNormals; - m_pNormals = NULL; - delete m_pTexturCoords; - m_pTexturCoords = NULL; - } -}; - -// ------------------------------------------------------------------------------------------------ -//! \struct Object -//! \brief Stores all objects of an objfile object definition -struct Object -{ - enum ObjectType - { - ObjType, - GroupType - }; - - //! Object name - std::string m_strObjName; - //! Transformation matrix, stored in OpenGL format - aiMatrix4x4 m_Transformation; - //! All sub-objects referenced by this object - std::vector<Object*> m_SubObjects; - /// Assigned meshes - std::vector<unsigned int> m_Meshes; - - //! \brief Default constructor - Object() : - m_strObjName("") - { - // empty - } - - //! \brief Destructor - ~Object() - { - for (std::vector<Object*>::iterator it = m_SubObjects.begin(); - it != m_SubObjects.end(); ++it) - { - delete *it; - } - m_SubObjects.clear(); - } -}; - -// ------------------------------------------------------------------------------------------------ -//! \struct Material -//! \brief Data structure to store all material specific data -struct Material -{ - //! Name of material description - aiString MaterialName; - - //! Texture names - aiString texture; - aiString textureSpecular; - aiString textureAmbient; - aiString textureBump; - aiString textureSpecularity; - aiString textureOpacity; - - //! Ambient color - aiColor3D ambient; - //! Diffuse color - aiColor3D diffuse; - //! Speculao color - aiColor3D specular; - //! Alpha value - float alpha; - //! Shineness factor - float shineness; - //! Illumination model - int illumination_model; - //! Index of refraction - float ior; - - //! Constructor - Material() - : diffuse (0.6f,0.6f,0.6f) - , alpha (1.f) - , shineness (0.0f) - , illumination_model (1) - , ior (1.f) - { - // empty - } - - // Destructor - ~Material() - { - // empty - } -}; - -// ------------------------------------------------------------------------------------------------ -//! \struct Mesh -//! \brief Data structure to store a mesh -struct Mesh -{ - static const unsigned int NoMaterial = 999999999; - - /// Array with pointer to all stored faces - std::vector<Face*> m_Faces; - /// Assigned material - Material *m_pMaterial; - /// Number of stored indices. - unsigned int m_uiNumIndices; - /// Number of UV - unsigned int m_uiUVCoordinates[ AI_MAX_NUMBER_OF_TEXTURECOORDS ]; - /// Material index. - unsigned int m_uiMaterialIndex; - /// True, if normals are stored. - bool m_hasNormals; - /// Constructor - Mesh() : - m_pMaterial(NULL), - m_uiNumIndices(0), - m_uiMaterialIndex( NoMaterial ), - m_hasNormals(false) - { - memset(m_uiUVCoordinates, 0, sizeof( unsigned int ) * AI_MAX_NUMBER_OF_TEXTURECOORDS); - } - - /// Destructor - ~Mesh() - { - for (std::vector<Face*>::iterator it = m_Faces.begin(); - it != m_Faces.end(); ++it) - { - delete *it; - } - - } -}; - -// ------------------------------------------------------------------------------------------------ -//! \struct Model -//! \brief Data structure to store all obj-specific model datas -struct Model -{ - typedef std::map<std::string*, std::vector<unsigned int>* > GroupMap; - typedef std::map<std::string*, std::vector<unsigned int>* >::iterator GroupMapIt; - typedef std::map<std::string*, std::vector<unsigned int>* >::const_iterator ConstGroupMapIt; - - //! Model name - std::string m_ModelName; - //! List ob assigned objects - std::vector<Object*> m_Objects; - //! Pointer to current object - ObjFile::Object *m_pCurrent; - //! Pointer to current material - ObjFile::Material *m_pCurrentMaterial; - //! Pointer to default material - ObjFile::Material *m_pDefaultMaterial; - //! Vector with all generated materials - std::vector<std::string> m_MaterialLib; - //! Vector with all generated group - std::vector<std::string> m_GroupLib; - //! Vector with all generated vertices - std::vector<aiVector3D> m_Vertices; - //! vector with all generated normals - std::vector<aiVector3D> m_Normals; - //! Groupmap - GroupMap m_Groups; - //! Group to face id assignment - std::vector<unsigned int> *m_pGroupFaceIDs; - //! Active group - std::string m_strActiveGroup; - //! Vector with generated texture coordinates - std::vector<aiVector2D> m_TextureCoord; - //! Current mesh instance - Mesh *m_pCurrentMesh; - //! Vector with stored meshes - std::vector<Mesh*> m_Meshes; - //! Material map - std::map<std::string, Material*> m_MaterialMap; - - - //! \brief Default constructor - Model() : - m_ModelName(""), - m_pCurrent(NULL), - m_pCurrentMaterial(NULL), - m_pDefaultMaterial(NULL), - m_strActiveGroup(""), - m_pCurrentMesh(NULL) - { - // empty - } - - //! \brief Destructor - ~Model() - { - // Clear all stored object instances - for (std::vector<Object*>::iterator it = m_Objects.begin(); - it != m_Objects.end(); ++it) - { - delete *it; - } - m_Objects.clear(); - - // Clear all stored mesh instances - for (std::vector<Mesh*>::iterator it = m_Meshes.begin(); - it != m_Meshes.end(); ++it) - { - delete *it; - } - - m_Meshes.clear(); - - for (GroupMapIt it = m_Groups.begin(); - it != m_Groups.end(); ++it) - { - delete it->second; - } - - m_Groups.clear(); - } -}; - -// ------------------------------------------------------------------------------------------------ - -} // Namespace ObjFile -} // Namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/ObjFileImporter.cpp b/3rdparty/assimp/code/ObjFileImporter.cpp deleted file mode 100644 index 2cd68ee1..00000000 --- a/3rdparty/assimp/code/ObjFileImporter.cpp +++ /dev/null @@ -1,521 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. ---------------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER - -#include "DefaultIOSystem.h" -#include "ObjFileImporter.h" -#include "ObjFileParser.h" -#include "ObjFileData.h" - -namespace Assimp { - -using namespace std; - -// ------------------------------------------------------------------------------------------------ -// Default constructor -ObjFileImporter::ObjFileImporter() : - m_Buffer(), - m_pRootObject( NULL ), - m_strAbsPath( "" ) -{ - DefaultIOSystem io; - m_strAbsPath = io.getOsSeparator(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -ObjFileImporter::~ObjFileImporter() -{ - // Release root object instance - if (NULL != m_pRootObject) - { - delete m_pRootObject; - m_pRootObject = NULL; - } -} - -// ------------------------------------------------------------------------------------------------ -// Returns true, if file is an obj file. -bool ObjFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler , bool checkSig ) const -{ - if (!checkSig) //Check File Extension - { - return SimpleExtensionCheck(pFile,"obj"); - } - else //Check file Header - { - const char* tokens[] = {"mtllib","usemtl","vt ","vn ","o "}; - return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, 5); - } -} - -// ------------------------------------------------------------------------------------------------ -// Obj-file import implementation -void ObjFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - DefaultIOSystem io; - - // Read file into memory - const std::string mode = "rb"; - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, mode)); - if (NULL == file.get()) - throw DeadlyImportError( "Failed to open file " + pFile + "."); - - // Get the filesize and vaslidate it, throwing an exception when failes - size_t fileSize = file->FileSize(); - if ( fileSize < 16) - throw DeadlyImportError( "OBJ-file is too small."); - - // Allocate buffer and read file into it - TextFileToBuffer(file.get(),m_Buffer); - - // Get the model name - std::string strModelName; - std::string::size_type pos = pFile.find_last_of( "\\/" ); - if ( pos != std::string::npos ) - { - strModelName = pFile.substr(pos+1, pFile.size() - pos - 1); - } - else - { - strModelName = pFile; - } - - // parse the file into a temporary representation - ObjFileParser parser(m_Buffer, strModelName, pIOHandler); - - // And create the proper return structures out of it - CreateDataFromImport(parser.GetModel(), pScene); - - // Clean up allocated storage for the next import - m_Buffer.clear(); -} - -// ------------------------------------------------------------------------------------------------ -// Create the data from parsed obj-file -void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene) -{ - if (0L == pModel) - return; - - // Create the root node of the scene - pScene->mRootNode = new aiNode; - if ( !pModel->m_ModelName.empty() ) - { - // Set the name of the scene - pScene->mRootNode->mName.Set(pModel->m_ModelName); - } - else - { - // This is an error, so break down the application - ai_assert(false); - } - - // Create nodes for the whole scene - std::vector<aiMesh*> MeshArray; - for (size_t index = 0; index < pModel->m_Objects.size(); index++) - { - createNodes(pModel, pModel->m_Objects[ index ], index, pScene->mRootNode, pScene, MeshArray); - } - - // Create mesh pointer buffer for this scene - if (pScene->mNumMeshes > 0) - { - pScene->mMeshes = new aiMesh*[ MeshArray.size() ]; - for (size_t index =0; index < MeshArray.size(); index++) - { - pScene->mMeshes [ index ] = MeshArray[ index ]; - } - } - - // Create all materials - createMaterials( pModel, pScene ); -} - -// ------------------------------------------------------------------------------------------------ -// Creates all nodes of the model -aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pObject, - unsigned int uiMeshIndex, - aiNode *pParent, aiScene* pScene, - std::vector<aiMesh*> &MeshArray ) -{ - ai_assert( NULL != pModel ); - if ( NULL == pObject ) - return NULL; - - // Store older mesh size to be able to computate mesh offsets for new mesh instances - const size_t oldMeshSize = MeshArray.size(); - aiNode *pNode = new aiNode; - pNode->mName = aiString(pObject->m_strObjName); - - if (pParent != NULL) - appendChildToParentNode(pParent, pNode); - - - for ( unsigned int i=0; i< pObject->m_Meshes.size(); i++ ) - { - unsigned int meshId = pObject->m_Meshes[ i ]; - aiMesh *pMesh = new aiMesh; - createTopology( pModel, pObject, meshId, pMesh ); - if ( pMesh->mNumVertices > 0 ) - { - MeshArray.push_back( pMesh ); - } - else - { - delete pMesh; - } - } - - // Create all nodes from the sub-objects stored in the current object - if ( !pObject->m_SubObjects.empty() ) - { - size_t numChilds = pObject->m_SubObjects.size(); - pNode->mNumChildren = static_cast<unsigned int>( numChilds ); - pNode->mChildren = new aiNode*[ numChilds ]; - pNode->mNumMeshes = 1; - pNode->mMeshes = new unsigned int[ 1 ]; - } - - // Set mesh instances into scene- and node-instances - const size_t meshSizeDiff = MeshArray.size()- oldMeshSize; - if ( meshSizeDiff > 0 ) - { - pNode->mMeshes = new unsigned int[ meshSizeDiff ]; - pNode->mNumMeshes = static_cast<unsigned int>( meshSizeDiff ); - size_t index = 0; - for (size_t i = oldMeshSize; i < MeshArray.size(); i++) - { - pNode->mMeshes[ index ] = pScene->mNumMeshes; - pScene->mNumMeshes++; - index++; - } - } - - return pNode; -} - -// ------------------------------------------------------------------------------------------------ -// Create topology data -void ObjFileImporter::createTopology(const ObjFile::Model* pModel, - const ObjFile::Object* pData, - unsigned int uiMeshIndex, - aiMesh* pMesh ) -{ - // Checking preconditions - ai_assert( NULL != pModel ); - if (NULL == pData) - return; - - // Create faces - ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ]; - ai_assert( NULL != pObjMesh ); - pMesh->mNumFaces = static_cast<unsigned int>( pObjMesh->m_Faces.size() ); - if ( pMesh->mNumFaces > 0 ) - { - pMesh->mFaces = new aiFace[ pMesh->mNumFaces ]; - if ( pObjMesh->m_uiMaterialIndex != ObjFile::Mesh::NoMaterial ) - { - pMesh->mMaterialIndex = pObjMesh->m_uiMaterialIndex; - } - - // Copy all data from all stored meshes - for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) - { - aiFace *pFace = &pMesh->mFaces[ index ]; - const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_pVertices->size(); - pFace->mNumIndices = (unsigned int) uiNumIndices; - if (pFace->mNumIndices > 0) - { - pFace->mIndices = new unsigned int[ uiNumIndices ]; - ObjFile::Face::IndexArray *pIndexArray = pObjMesh->m_Faces[ index ]->m_pVertices; - ai_assert ( NULL != pIndexArray ); - for ( size_t a=0; a<pFace->mNumIndices; a++ ) - { - pFace->mIndices[ a ] = pIndexArray->at( a ); - } - } - else - { - pFace->mIndices = NULL; - } - } - } - - // Create mesh vertices - createVertexArray(pModel, pData, uiMeshIndex, pMesh); -} - -// ------------------------------------------------------------------------------------------------ -// Creates a vertex array -void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel, - const ObjFile::Object* pCurrentObject, - unsigned int uiMeshIndex, - aiMesh* pMesh) -{ - // Checking preconditions - ai_assert( NULL != pCurrentObject ); - - // Break, if no faces are stored in object - if ( pCurrentObject->m_Meshes.empty() ) - return; - - // Get current mesh - ObjFile::Mesh *pObjMesh = pModel->m_Meshes[ uiMeshIndex ]; - if ( NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1) - return; - - // Copy vertices of this mesh instance - pMesh->mNumVertices = (unsigned int) pObjMesh->m_uiNumIndices; - pMesh->mVertices = new aiVector3D[ pMesh->mNumVertices ]; - - // Allocate buffer for normal vectors - if ( !pModel->m_Normals.empty() && pObjMesh->m_hasNormals ) - pMesh->mNormals = new aiVector3D[ pMesh->mNumVertices ]; - - // Allocate buffer for texture coordinates - if ( !pModel->m_TextureCoord.empty() && pObjMesh->m_uiUVCoordinates[0] ) - { - pMesh->mNumUVComponents[ 0 ] = 2; - pMesh->mTextureCoords[ 0 ] = new aiVector3D[ pMesh->mNumVertices ]; - } - - // Copy vertices, normals and textures into aiMesh instance - unsigned int newIndex = 0; - for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ ) - { - // Get destination face - aiFace *pDestFace = &pMesh->mFaces[ index ]; - - // Get source face - ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ]; - - // Copy all index arrays - for ( size_t vertexIndex = 0; vertexIndex < pSourceFace->m_pVertices->size(); vertexIndex++ ) - { - const unsigned int vertex = pSourceFace->m_pVertices->at( vertexIndex ); - ai_assert( vertex < pModel->m_Vertices.size() ); - pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ]; - - // Copy all normals - if ( !pSourceFace->m_pNormals->empty() ) - { - const unsigned int normal = pSourceFace->m_pNormals->at( vertexIndex ); - ai_assert( normal < pModel->m_Normals.size() ); - pMesh->mNormals[ newIndex ] = pModel->m_Normals[ normal ]; - } - - // Copy all texture coordinates - if ( !pModel->m_TextureCoord.empty() ) - { - if ( !pSourceFace->m_pTexturCoords->empty() ) - { - const unsigned int tex = pSourceFace->m_pTexturCoords->at( vertexIndex ); - ai_assert( tex < pModel->m_TextureCoord.size() ); - for ( size_t i=0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; i++ ) - { - if ( pMesh->mNumUVComponents[ i ] > 0 ) - { - aiVector2D coord2d = pModel->m_TextureCoord[ tex ]; - pMesh->mTextureCoords[ i ][ newIndex ] = aiVector3D( coord2d.x, coord2d.y, 0.0 ); - } - } - } - } - - ai_assert( pMesh->mNumVertices > newIndex ); - pDestFace->mIndices[ vertexIndex ] = newIndex; - ++newIndex; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Counts all stored meshes -void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes) -{ - iNumMeshes = 0; - if ( rObjects.empty() ) - return; - - iNumMeshes += static_cast<unsigned int>( rObjects.size() ); - for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin(); - it != rObjects.end(); - ++it) - { - if (!(*it)->m_SubObjects.empty()) - { - countObjects((*it)->m_SubObjects, iNumMeshes); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Creates the material -void ObjFileImporter::createMaterials(const ObjFile::Model* pModel, aiScene* pScene ) -{ - ai_assert( NULL != pScene ); - if ( NULL == pScene ) - return; - - const unsigned int numMaterials = (unsigned int) pModel->m_MaterialLib.size(); - pScene->mNumMaterials = 0; - if ( pModel->m_MaterialLib.empty() ) - return; - - pScene->mMaterials = new aiMaterial*[ numMaterials ]; - for ( unsigned int matIndex = 0; matIndex < numMaterials; matIndex++ ) - { - Assimp::MaterialHelper* mat = new Assimp::MaterialHelper; - - // Store material name - std::map<std::string, ObjFile::Material*>::const_iterator it; - it = pModel->m_MaterialMap.find( pModel->m_MaterialLib[ matIndex ] ); - - // No material found, use the default material - if ( pModel->m_MaterialMap.end() == it ) - continue; - - ObjFile::Material *pCurrentMaterial = (*it).second; - mat->AddProperty( &pCurrentMaterial->MaterialName, AI_MATKEY_NAME ); - - // convert illumination model - int sm = 0; - switch (pCurrentMaterial->illumination_model) - { - case 0: - sm = aiShadingMode_NoShading; - break; - case 1: - sm = aiShadingMode_Gouraud; - break; - case 2: - sm = aiShadingMode_Phong; - break; - default: - sm = aiShadingMode_Gouraud; - DefaultLogger::get()->error("OBJ/MTL: Unexpected illumination model (0-2 recognized)"); - } - mat->AddProperty<int>( &sm, 1, AI_MATKEY_SHADING_MODEL); - - // multiplying the specular exponent with 2 seems to yield better results - pCurrentMaterial->shineness *= 4.f; - - // Adding material colors - mat->AddProperty( &pCurrentMaterial->ambient, 1, AI_MATKEY_COLOR_AMBIENT ); - mat->AddProperty( &pCurrentMaterial->diffuse, 1, AI_MATKEY_COLOR_DIFFUSE ); - mat->AddProperty( &pCurrentMaterial->specular, 1, AI_MATKEY_COLOR_SPECULAR ); - mat->AddProperty( &pCurrentMaterial->shineness, 1, AI_MATKEY_SHININESS ); - mat->AddProperty( &pCurrentMaterial->alpha, 1, AI_MATKEY_OPACITY ); - - // Adding refraction index - mat->AddProperty( &pCurrentMaterial->ior, 1, AI_MATKEY_REFRACTI ); - - // Adding textures - if ( 0 != pCurrentMaterial->texture.length ) - mat->AddProperty( &pCurrentMaterial->texture, AI_MATKEY_TEXTURE_DIFFUSE(0)); - - if ( 0 != pCurrentMaterial->textureAmbient.length ) - mat->AddProperty( &pCurrentMaterial->textureAmbient, AI_MATKEY_TEXTURE_AMBIENT(0)); - - if ( 0 != pCurrentMaterial->textureSpecular.length ) - mat->AddProperty( &pCurrentMaterial->textureSpecular, AI_MATKEY_TEXTURE_SPECULAR(0)); - - if ( 0 != pCurrentMaterial->textureBump.length ) - mat->AddProperty( &pCurrentMaterial->textureBump, AI_MATKEY_TEXTURE_HEIGHT(0)); - - if ( 0 != pCurrentMaterial->textureOpacity.length ) - mat->AddProperty( &pCurrentMaterial->textureOpacity, AI_MATKEY_TEXTURE_OPACITY(0)); - - if ( 0 != pCurrentMaterial->textureSpecularity.length ) - mat->AddProperty( &pCurrentMaterial->textureSpecularity, AI_MATKEY_TEXTURE_SHININESS(0)); - - // Store material property info in material array in scene - pScene->mMaterials[ pScene->mNumMaterials ] = mat; - pScene->mNumMaterials++; - } - - // Test number of created materials. - ai_assert( pScene->mNumMaterials == numMaterials ); -} - -// ------------------------------------------------------------------------------------------------ -// Appends this node to the parent node -void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) -{ - // Checking preconditions - ai_assert( NULL != pParent ); - ai_assert( NULL != pChild ); - - // Assign parent to child - pChild->mParent = pParent; - size_t sNumChildren = 0; - - // If already children was assigned to the parent node, store them in a - std::vector<aiNode*> temp; - if (pParent->mChildren != NULL) - { - sNumChildren = pParent->mNumChildren; - ai_assert( 0 != sNumChildren ); - for (size_t index = 0; index < pParent->mNumChildren; index++) - { - temp.push_back(pParent->mChildren [ index ] ); - } - delete [] pParent->mChildren; - } - - // Copy node instances into parent node - pParent->mNumChildren++; - pParent->mChildren = new aiNode*[ pParent->mNumChildren ]; - for (size_t index = 0; index < pParent->mNumChildren-1; index++) - { - pParent->mChildren[ index ] = temp [ index ]; - } - pParent->mChildren[ pParent->mNumChildren-1 ] = pChild; -} - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Assimp - -#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER diff --git a/3rdparty/assimp/code/ObjFileImporter.h b/3rdparty/assimp/code/ObjFileImporter.h deleted file mode 100644 index 7edecac8..00000000 --- a/3rdparty/assimp/code/ObjFileImporter.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - - -#ifndef OBJ_FILE_IMPORTER_H_INC -#define OBJ_FILE_IMPORTER_H_INC - -#include "BaseImporter.h" -#include <vector> - -struct aiMesh; -struct aiNode; - -namespace Assimp -{ - -namespace ObjFile -{ -struct Object; -struct Model; -} - -// ------------------------------------------------------------------------------------------------ -/// \class ObjFileImporter -/// \brief Imports a waveform obj file -// ------------------------------------------------------------------------------------------------ -class ObjFileImporter : - BaseImporter -{ - friend class Importer; - -protected: - /// \brief Default constructor - ObjFileImporter(); - - /// \brief Destructor - ~ObjFileImporter(); - -public: - /// \brief Returns whether the class can handle the format of the given file. - /// \remark See BaseImporter::CanRead() for details. - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; - -private: - - //! \brief Appends the supported extention. - void GetExtensionList(std::set<std::string>& extensions); - - //! \brief File import implementation. - void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - - //! \brief Create the data from imported content. - void CreateDataFromImport(const ObjFile::Model* pModel, aiScene* pScene); - - //! \brief Creates all nodes stored in imported content. - aiNode *createNodes(const ObjFile::Model* pModel, const ObjFile::Object* pData, unsigned int uiMeshIndex, - aiNode *pParent, aiScene* pScene, std::vector<aiMesh*> &MeshArray); - - //! \brief Creates topology data like faces and meshes for the geometry. - void createTopology(const ObjFile::Model* pModel, const ObjFile::Object* pData, - unsigned int uiMeshIndex, aiMesh* pMesh); - - //! \brief Creates vertices from model. - void createVertexArray(const ObjFile::Model* pModel, const ObjFile::Object* pCurrentObject, - unsigned int uiMeshIndex, aiMesh* pMesh); - - //! \brief Object counter helper method. - void countObjects(const std::vector<ObjFile::Object*> &rObjects, int &iNumMeshes); - - //! \brief Material creation. - void createMaterials(const ObjFile::Model* pModel, aiScene* pScene); - - //! \brief Appends a child node to a parentnode and updates the datastructures. - void appendChildToParentNode(aiNode *pParent, aiNode *pChild); - - //! \brief TODO! - void createAnimations(); - -private: - //! Data buffer - std::vector<char> m_Buffer; - //! Pointer to root object instance - ObjFile::Object *m_pRootObject; - //! Absolute pathname of model in filesystem - std::string m_strAbsPath; -}; - -// ------------------------------------------------------------------------------------------------ -// -inline void ObjFileImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("obj"); -} - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/ObjFileMtlImporter.cpp b/3rdparty/assimp/code/ObjFileMtlImporter.cpp deleted file mode 100644 index 99de1a67..00000000 --- a/3rdparty/assimp/code/ObjFileMtlImporter.cpp +++ /dev/null @@ -1,294 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. ---------------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER - -#include "ObjFileMtlImporter.h" -#include "ObjTools.h" -#include "ObjFileData.h" -#include "fast_atof.h" - -namespace Assimp { - -// ------------------------------------------------------------------- -// Constructor -ObjFileMtlImporter::ObjFileMtlImporter( std::vector<char> &buffer, - const std::string & /*strAbsPath*/, - ObjFile::Model *pModel ) : - m_DataIt( buffer.begin() ), - m_DataItEnd( buffer.end() ), - m_pModel( pModel ), - m_uiLine( 0 ) -{ - ai_assert( NULL != m_pModel ); - if ( NULL == m_pModel->m_pDefaultMaterial ) - { - m_pModel->m_pDefaultMaterial = new ObjFile::Material; - m_pModel->m_pDefaultMaterial->MaterialName.Set( "default" ); - } - load(); -} - -// ------------------------------------------------------------------- -// Destructor -ObjFileMtlImporter::~ObjFileMtlImporter() -{ - // empty -} - -// ------------------------------------------------------------------- -// Private copy constructor -ObjFileMtlImporter::ObjFileMtlImporter(const ObjFileMtlImporter & /* rOther */ ) -{ - // empty -} - -// ------------------------------------------------------------------- -// Private copy constructor -ObjFileMtlImporter &ObjFileMtlImporter::operator = ( const ObjFileMtlImporter & /*rOther */ ) -{ - return *this; -} - -// ------------------------------------------------------------------- -// Loads the material description -void ObjFileMtlImporter::load() -{ - if ( m_DataIt == m_DataItEnd ) - return; - - while ( m_DataIt != m_DataItEnd ) - { - switch (*m_DataIt) - { - case 'K': - { - ++m_DataIt; - if (*m_DataIt == 'a') // Ambient color - { - ++m_DataIt; - getColorRGBA( &m_pModel->m_pCurrentMaterial->ambient ); - } - else if (*m_DataIt == 'd') // Diffuse color - { - ++m_DataIt; - getColorRGBA( &m_pModel->m_pCurrentMaterial->diffuse ); - } - else if (*m_DataIt == 's') - { - ++m_DataIt; - getColorRGBA( &m_pModel->m_pCurrentMaterial->specular ); - } - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - - case 'd': // Alpha value - { - ++m_DataIt; - getFloatValue( m_pModel->m_pCurrentMaterial->alpha ); - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - - case 'N': // Shineness - { - ++m_DataIt; - switch(*m_DataIt) - { - case 's': - ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->shineness); - break; - case 'i': //Index Of refraction - ++m_DataIt; - getFloatValue(m_pModel->m_pCurrentMaterial->ior); - break; - } - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - break; - } - break; - - - case 'm': // Texture - case 'b': // quick'n'dirty - for 'bump' sections - { - getTexture(); - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - - case 'n': // New material name - { - createMaterial(); - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - - case 'i': // Illumination model - { - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - getIlluminationModel( m_pModel->m_pCurrentMaterial->illumination_model ); - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - - default: - { - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - } - } -} - -// ------------------------------------------------------------------- -// Loads a color definition -void ObjFileMtlImporter::getColorRGBA( aiColor3D *pColor ) -{ - ai_assert( NULL != pColor ); - - float r, g, b; - m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, r ); - pColor->r = r; - - m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, g ); - pColor->g = g; - - m_DataIt = getFloat<DataArrayIt>( m_DataIt, m_DataItEnd, b ); - pColor->b = b; -} - -// ------------------------------------------------------------------- -// Loads the kind of illumination model. -void ObjFileMtlImporter::getIlluminationModel( int &illum_model ) -{ - m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE ); - illum_model = atoi(m_buffer); -} - -// ------------------------------------------------------------------- -// Loads a single float value. -void ObjFileMtlImporter::getFloatValue( float &value ) -{ - m_DataIt = CopyNextWord<DataArrayIt>( m_DataIt, m_DataItEnd, m_buffer, BUFFERSIZE ); - value = (float) fast_atof(m_buffer); -} - -// ------------------------------------------------------------------- -// Creates a material from loaded data. -void ObjFileMtlImporter::createMaterial() -{ - std::string strName( "" ); - m_DataIt = getName<DataArrayIt>( m_DataIt, m_DataItEnd, strName ); - if ( m_DataItEnd == m_DataIt ) - return; - - std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName ); - if ( m_pModel->m_MaterialMap.end() == it) - { - // New Material created - m_pModel->m_pCurrentMaterial = new ObjFile::Material(); - m_pModel->m_pCurrentMaterial->MaterialName.Set( strName ); - m_pModel->m_MaterialLib.push_back( strName ); - m_pModel->m_MaterialMap[ strName ] = m_pModel->m_pCurrentMaterial; - } - else - { - // Use older material - m_pModel->m_pCurrentMaterial = (*it).second; - } -} - -// ------------------------------------------------------------------- -// Gets a texture name from data. -void ObjFileMtlImporter::getTexture() -{ - aiString *out = NULL; - - // FIXME: just a quick'n'dirty hack, consider cleanup later - - // Diffuse texture - if (!ASSIMP_strincmp(&(*m_DataIt),"map_kd",6)) - out = & m_pModel->m_pCurrentMaterial->texture; - - // Ambient texture - else if (!ASSIMP_strincmp(&(*m_DataIt),"map_ka",6)) - out = & m_pModel->m_pCurrentMaterial->textureAmbient; - - // Specular texture - else if (!ASSIMP_strincmp(&(*m_DataIt),"map_ks",6)) - out = & m_pModel->m_pCurrentMaterial->textureSpecular; - - // Opacity texture - else if (!ASSIMP_strincmp(&(*m_DataIt),"map_d",5)) - out = & m_pModel->m_pCurrentMaterial->textureOpacity; - - // Ambient texture - else if (!ASSIMP_strincmp(&(*m_DataIt),"map_ka",6)) - out = & m_pModel->m_pCurrentMaterial->textureAmbient; - - // Bump texture - else if (!ASSIMP_strincmp(&(*m_DataIt),"map_bump",8) || !ASSIMP_strincmp(&(*m_DataIt),"bump",4)) - out = & m_pModel->m_pCurrentMaterial->textureBump; - - // Specularity scaling (glossiness) - else if (!ASSIMP_strincmp(&(*m_DataIt),"map_ns",6)) - out = & m_pModel->m_pCurrentMaterial->textureSpecularity; - - else - { - DefaultLogger::get()->error("OBJ/MTL: Encountered unknown texture type"); - return; - } - - std::string strTexture; - m_DataIt = getName<DataArrayIt>( m_DataIt, m_DataItEnd, strTexture ); - out->Set( strTexture ); -} - -// ------------------------------------------------------------------- - -} // Namespace Assimp - -#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER diff --git a/3rdparty/assimp/code/ObjFileMtlImporter.h b/3rdparty/assimp/code/ObjFileMtlImporter.h deleted file mode 100644 index f98cbbca..00000000 --- a/3rdparty/assimp/code/ObjFileMtlImporter.h +++ /dev/null @@ -1,115 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - -----------------------------------------------------------------------*/ -#ifndef OBJFILEMTLIMPORTER_H_INC -#define OBJFILEMTLIMPORTER_H_INC - -#include <vector> -#include <string> - -struct aiColor3D; - -namespace Assimp -{ - -namespace ObjFile -{ -struct Model; -struct Material; - -} - - -/** - * @class ObjFileMtlImporter - * @brief Loads the material description from a mtl file. - */ -class ObjFileMtlImporter -{ -public: - static const size_t BUFFERSIZE = 2048; - typedef std::vector<char> DataArray; - typedef std::vector<char>::iterator DataArrayIt; - typedef std::vector<char>::const_iterator ConstDataArrayIt; - -public: - //! \brief Default constructor - ObjFileMtlImporter( std::vector<char> &buffer, const std::string &strAbsPath, - ObjFile::Model *pModel ); - - //! \brief DEstructor - ~ObjFileMtlImporter(); - -private: - /// Copy constructor, empty. - ObjFileMtlImporter(const ObjFileMtlImporter &rOther); - /// \brief Assignment operator, returns only a reference of this instance. - ObjFileMtlImporter &operator = (const ObjFileMtlImporter &rOther); - /// Load the whole material description - void load(); - /// Get color data. - void getColorRGBA( aiColor3D *pColor); - /// Get illumination model from loaded data - void getIlluminationModel( int &illum_model ); - /// Gets a float value from data. - void getFloatValue( float &value ); - /// Creates a new material from loaded data. - void createMaterial(); - /// Get texture name from loaded data. - void getTexture(); - -private: - //! Absolute pathname - std::string m_strAbsPath; - //! Data iterator showing to the current position in data buffer - DataArrayIt m_DataIt; - //! Data iterator to end of buffer - DataArrayIt m_DataItEnd; - //! USed model instance - ObjFile::Model *m_pModel; - //! Current line in file - unsigned int m_uiLine; - //! Helper buffer - char m_buffer[BUFFERSIZE]; -}; - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/ObjFileParser.cpp b/3rdparty/assimp/code/ObjFileParser.cpp deleted file mode 100644 index 3d214bd1..00000000 --- a/3rdparty/assimp/code/ObjFileParser.cpp +++ /dev/null @@ -1,665 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. ---------------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER - -#include "ObjFileParser.h" -#include "ObjFileMtlImporter.h" -#include "ObjTools.h" -#include "ObjFileData.h" -#include "fast_atof.h" -#include "../include/aiTypes.h" -#include "DefaultIOSystem.h" - -namespace Assimp -{ - -// ------------------------------------------------------------------- -const std::string ObjFileParser::DEFAULT_MATERIAL = AI_DEFAULT_MATERIAL_NAME; -// fix: changed that to our standard default name - -// ------------------------------------------------------------------- -// Constructor with loaded data and directories. -ObjFileParser::ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem *io ) : - m_DataIt(Data.begin()), - m_DataItEnd(Data.end()), - m_pModel(NULL), - m_uiLine(0), - m_pIO( io ) -{ - // Create the model instance to store all the data - m_pModel = new ObjFile::Model(); - m_pModel->m_ModelName = strModelName; - - m_pModel->m_pDefaultMaterial = new ObjFile::Material(); - m_pModel->m_pDefaultMaterial->MaterialName.Set( DEFAULT_MATERIAL ); - m_pModel->m_MaterialLib.push_back( DEFAULT_MATERIAL ); - m_pModel->m_MaterialMap[ DEFAULT_MATERIAL ] = m_pModel->m_pDefaultMaterial; - - // Start parsing the file - parseFile(); -} - -// ------------------------------------------------------------------- -// Destrcutor. -ObjFileParser::~ObjFileParser() -{ - delete m_pModel->m_pDefaultMaterial; - m_pModel->m_pDefaultMaterial = NULL; - - delete m_pModel; - m_pModel = NULL; -} - -// ------------------------------------------------------------------- -// Returns a pointer to the model instance. -ObjFile::Model *ObjFileParser::GetModel() const -{ - return m_pModel; -} - -// ------------------------------------------------------------------- -// File parsing method. -void ObjFileParser::parseFile() -{ - if (m_DataIt == m_DataItEnd) - return; - - while (m_DataIt != m_DataItEnd) - { - switch (*m_DataIt) - { - case 'v': // Parse a vertex texture coordinate - { - ++m_DataIt; - if (*m_DataIt == ' ') - { - // Read in vertex definition - getVector3(m_pModel->m_Vertices); - } - else if (*m_DataIt == 't') - { - // Read in texture coordinate (2D) - ++m_DataIt; - getVector2(m_pModel->m_TextureCoord); - } - else if (*m_DataIt == 'n') - { - // Read in normal vector definition - ++m_DataIt; - getVector3( m_pModel->m_Normals ); - } - } - break; - - case 'f': // Parse a face - { - getFace(); - } - break; - - case '#': // Parse a comment - { - getComment(); - } - break; - - case 'u': // Parse a material desc. setter - { - getMaterialDesc(); - } - break; - - case 'm': // Parse a material library - { - getMaterialLib(); - } - break; - - case 'g': // Parse group name - { - getGroupName(); - } - break; - - case 's': // Parse group number - { - getGroupNumber(); - } - break; - - case 'o': // Parse object name - { - getObjectName(); - } - break; - - default: - { - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - } - break; - } - } -} - -// ------------------------------------------------------------------- -// Copy the next word in a temporary buffer -void ObjFileParser::copyNextWord(char *pBuffer, size_t length) -{ - size_t index = 0; - m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); - while ( !isSeparator(*m_DataIt) && m_DataIt != m_DataItEnd ) - { - pBuffer[index] = *m_DataIt; - index++; - if (index == length-1) - break; - ++m_DataIt; - } - pBuffer[index] = '\0'; -} - -// ------------------------------------------------------------------- -// Copy the next line into a temporary buffer -void ObjFileParser::copyNextLine(char *pBuffer, size_t length) -{ - size_t index = 0; - while (m_DataIt != m_DataItEnd) - { - if (*m_DataIt == '\n' || *m_DataIt == '\r' || index == length-1) - break; - - pBuffer[ index ] = *m_DataIt; - ++index; - ++m_DataIt; - } - pBuffer[ index ] = '\0'; -} - -// ------------------------------------------------------------------- -// Get values for a new 3D vector instance -void ObjFileParser::getVector3(std::vector<aiVector3D> &point3d_array) -{ - float x, y, z; - copyNextWord(m_buffer, BUFFERSIZE); - x = (float) fast_atof(m_buffer); - - copyNextWord(m_buffer, BUFFERSIZE); - y = (float) fast_atof(m_buffer); - - copyNextWord(m_buffer, BUFFERSIZE); - z = (float) fast_atof(m_buffer); - - point3d_array.push_back( aiVector3D( x, y, z ) ); - //skipLine(); - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -// Get values for a new 2D vector instance -void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) -{ - float x, y; - copyNextWord(m_buffer, BUFFERSIZE); - x = (float) fast_atof(m_buffer); - - copyNextWord(m_buffer, BUFFERSIZE); - y = (float) fast_atof(m_buffer); - - point2d_array.push_back(aiVector2D(x, y)); - - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -// Get values for a new face instance -void ObjFileParser::getFace() -{ - copyNextLine(m_buffer, BUFFERSIZE); - if (m_DataIt == m_DataItEnd) - return; - - char *pPtr = m_buffer; - char *pEnd = &pPtr[BUFFERSIZE]; - pPtr = getNextToken<char*>(pPtr, pEnd); - if (pPtr == '\0') - return; - - std::vector<unsigned int> *pIndices = new std::vector<unsigned int>; - std::vector<unsigned int> *pTexID = new std::vector<unsigned int>; - std::vector<unsigned int> *pNormalID = new std::vector<unsigned int>; - bool hasNormal = false; - - bool vt = (!m_pModel->m_TextureCoord.empty()); - bool vn = (!m_pModel->m_Normals.empty()); - int iStep = 0, iPos = 0; - while (pPtr != pEnd) - { - iStep = 1; - if (*pPtr == '\0') - break; - - if (*pPtr=='\r') - break; - - if (*pPtr=='/' ) - { - if (iPos == 0) - { - //if there are no texturecoordinates in the obj file but normals - if (!vt && vn) { - iPos = 1; - iStep++; - } - } - iPos++; - } - else if ( isSeparator(*pPtr) ) - { - iPos = 0; - } - else - { - //OBJ USES 1 Base ARRAYS!!!! - const int iVal = atoi( pPtr ); - int tmp = iVal; - while ( ( tmp = tmp / 10 )!=0 ) - ++iStep; - - if ( iVal > 0 ) - { - // Store parsed index - if ( 0 == iPos ) - { - pIndices->push_back( iVal-1 ); - } - else if ( 1 == iPos ) - { - pTexID->push_back( iVal-1 ); - } - else if ( 2 == iPos ) - { - pNormalID->push_back( iVal-1 ); - hasNormal = true; - } - else - { - reportErrorTokenInFace(); - } - } - } - for ( int i=0; i<iStep; i++ ) - ++pPtr; - } - - ObjFile::Face *face = new ObjFile::Face( pIndices, pNormalID, pTexID ); - - // Set active material, if one set - if (NULL != m_pModel->m_pCurrentMaterial) - face->m_pMaterial = m_pModel->m_pCurrentMaterial; - else - face->m_pMaterial = m_pModel->m_pDefaultMaterial; - - // Create a default object, if nothing there - if ( NULL == m_pModel->m_pCurrent ) - createObject( "defaultobject" ); - - // Assign face to mesh - if ( NULL == m_pModel->m_pCurrentMesh ) - { - createMesh(); - } - - // Store the face - m_pModel->m_pCurrentMesh->m_Faces.push_back( face ); - m_pModel->m_pCurrentMesh->m_uiNumIndices += (unsigned int)face->m_pVertices->size(); - m_pModel->m_pCurrentMesh->m_uiUVCoordinates[ 0 ] += (unsigned int)face->m_pTexturCoords[0].size(); - if ( !m_pModel->m_pCurrentMesh->m_hasNormals && hasNormal ) - { - m_pModel->m_pCurrentMesh->m_hasNormals = true; - } - // Skip the rest of the line - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -// Get values for a new material description -void ObjFileParser::getMaterialDesc() -{ - // Get next data for material data - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) - return; - - char *pStart = &(*m_DataIt); - while ( !isSeparator(*m_DataIt) && m_DataIt != m_DataItEnd ) - ++m_DataIt; - - // Get name - std::string strName(pStart, &(*m_DataIt)); - if ( strName.empty()) - return; - - // Search for material - std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strName ); - if ( it == m_pModel->m_MaterialMap.end() ) - { - // Not found, use default material - m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; - } - else - { - // Found, using detected material - m_pModel->m_pCurrentMaterial = (*it).second; - if ( needsNewMesh( strName )) - { - createMesh(); - } - m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strName ); - } - - // Skip rest of line - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -// Get a comment, values will be skipped -void ObjFileParser::getComment() -{ - bool running = true; - while (running) - { - if ( '\n' == (*m_DataIt) || m_DataIt == m_DataItEnd ) - { - ++m_DataIt; - break; - } - else - { - ++m_DataIt; - } - } -} - -// ------------------------------------------------------------------- -// Get material library from file. -void ObjFileParser::getMaterialLib() -{ - // Translate tuple - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) - return; - - char *pStart = &(*m_DataIt); - while (!isNewLine(*m_DataIt)) - m_DataIt++; - - // Check for existence - const std::string strMatName(pStart, &(*m_DataIt)); - IOStream *pFile = m_pIO->Open(strMatName); - - if (!pFile ) - { - DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - return; - } - - // Import material library data from file - std::vector<char> buffer; - BaseImporter::TextFileToBuffer(pFile,buffer); - m_pIO->Close( pFile ); - - // Importing the material library - ObjFileMtlImporter mtlImporter( buffer, strMatName, m_pModel ); -} - -// ------------------------------------------------------------------- -// Set a new material definition as the current material. -void ObjFileParser::getNewMaterial() -{ - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); - if ( m_DataIt == m_DataItEnd ) - return; - - char *pStart = &(*m_DataIt); - std::string strMat( pStart, *m_DataIt ); - while ( isSeparator( *m_DataIt ) ) - m_DataIt++; - std::map<std::string, ObjFile::Material*>::iterator it = m_pModel->m_MaterialMap.find( strMat ); - if ( it == m_pModel->m_MaterialMap.end() ) - { - // Show a warning, if material was not found - DefaultLogger::get()->warn("OBJ: Unsupported material requested: " + strMat); - m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; - } - else - { - // Set new material - if ( needsNewMesh( strMat ) ) - { - createMesh(); - } - m_pModel->m_pCurrentMesh->m_uiMaterialIndex = getMaterialIndex( strMat ); - } - - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -int ObjFileParser::getMaterialIndex( const std::string &strMaterialName ) -{ - int mat_index = -1; - if ( strMaterialName.empty() ) - return mat_index; - for (size_t index = 0; index < m_pModel->m_MaterialLib.size(); ++index) - { - if ( strMaterialName == m_pModel->m_MaterialLib[ index ]) - { - mat_index = (int)index; - break; - } - } - return mat_index; -} - -// ------------------------------------------------------------------- -// Getter for a group name. -void ObjFileParser::getGroupName() -{ - // Get next word from data buffer - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd); - if ( isEndOfBuffer( m_DataIt, m_DataItEnd ) ) - return; - - // Store groupname in group library - char *pStart = &(*m_DataIt); - while ( !isSeparator(*m_DataIt) ) - m_DataIt++; - std::string strGroupName(pStart, &(*m_DataIt)); - - // Change active group, if necessary - if ( m_pModel->m_strActiveGroup != strGroupName ) - { - // Search for already existing entry - ObjFile::Model::ConstGroupMapIt it = m_pModel->m_Groups.find(&strGroupName); - - // We are mapping groups into the object structure - createObject( strGroupName ); - - // New group name, creating a new entry - if (it == m_pModel->m_Groups.end()) - { - std::vector<unsigned int> *pFaceIDArray = new std::vector<unsigned int>; - m_pModel->m_Groups[ &strGroupName ] = pFaceIDArray; - m_pModel->m_pGroupFaceIDs = (pFaceIDArray); - } - else - { - m_pModel->m_pGroupFaceIDs = (*it).second; - } - m_pModel->m_strActiveGroup = strGroupName; - } - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -// Not supported -void ObjFileParser::getGroupNumber() -{ - // Not used - - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} - -// ------------------------------------------------------------------- -// Stores values for a new object instance, name will be used to -// identify it. -void ObjFileParser::getObjectName() -{ - m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); - if (m_DataIt == m_DataItEnd) - return; - char *pStart = &(*m_DataIt); - while ( !isSeparator( *m_DataIt ) ) - ++m_DataIt; - - std::string strObjectName(pStart, &(*m_DataIt)); - if (!strObjectName.empty()) - { - // Reset current object - m_pModel->m_pCurrent = NULL; - - // Search for actual object - for (std::vector<ObjFile::Object*>::const_iterator it = m_pModel->m_Objects.begin(); - it != m_pModel->m_Objects.end(); - ++it) - { - if ((*it)->m_strObjName == strObjectName) - { - m_pModel->m_pCurrent = *it; - break; - } - } - - // Allocate a new object, if current one was not found before - if ( NULL == m_pModel->m_pCurrent ) - createObject(strObjectName); - } - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); -} -// ------------------------------------------------------------------- -// Creates a new object instance -void ObjFileParser::createObject(const std::string &strObjectName) -{ - ai_assert( NULL != m_pModel ); - //ai_assert( !strObjectName.empty() ); - - m_pModel->m_pCurrent = new ObjFile::Object; - m_pModel->m_pCurrent->m_strObjName = strObjectName; - m_pModel->m_Objects.push_back( m_pModel->m_pCurrent ); - - - createMesh(); - - if ( m_pModel->m_pCurrentMaterial ) - { - m_pModel->m_pCurrentMesh->m_uiMaterialIndex = - getMaterialIndex( m_pModel->m_pCurrentMaterial->MaterialName.data ); - m_pModel->m_pCurrentMesh->m_pMaterial = m_pModel->m_pCurrentMaterial; - } -} -// ------------------------------------------------------------------- -// Creates a new mesh -void ObjFileParser::createMesh() -{ - ai_assert( NULL != m_pModel ); - m_pModel->m_pCurrentMesh = new ObjFile::Mesh; - m_pModel->m_Meshes.push_back( m_pModel->m_pCurrentMesh ); - unsigned int meshId = m_pModel->m_Meshes.size()-1; - if ( NULL != m_pModel->m_pCurrent ) - { - m_pModel->m_pCurrent->m_Meshes.push_back( meshId ); - } - else - { - DefaultLogger::get()->error("OBJ: No object detected to attach a new mesh instance."); - } -} - -// ------------------------------------------------------------------- -// Returns true, if a new mesh must be created. -bool ObjFileParser::needsNewMesh( const std::string &rMaterialName ) -{ - if (m_pModel->m_pCurrentMesh == 0) - { - // No mesh data yet - return true; - } - bool newMat = false; - int matIdx = getMaterialIndex( rMaterialName ); - unsigned int curMatIdx = m_pModel->m_pCurrentMesh->m_uiMaterialIndex; - if ( curMatIdx != ObjFile::Mesh::NoMaterial || curMatIdx != (unsigned int)matIdx ) - { - // New material -> only one material per mesh, so we need to create a new - // material - newMat = true; - } - return newMat; -} - -// ------------------------------------------------------------------- -// Shows an error in parsing process. -void ObjFileParser::reportErrorTokenInFace() -{ - m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine ); - DefaultLogger::get()->error("OBJ: Not supported token in face description detected"); -} - -// ------------------------------------------------------------------- - -} // Namespace Assimp - -#endif // !! ASSIMP_BUILD_NO_OBJ_IMPORTER diff --git a/3rdparty/assimp/code/ObjFileParser.h b/3rdparty/assimp/code/ObjFileParser.h deleted file mode 100644 index e972a9ad..00000000 --- a/3rdparty/assimp/code/ObjFileParser.h +++ /dev/null @@ -1,137 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - - -#ifndef OBJ_FILEPARSER_H_INC -#define OBJ_FILEPARSER_H_INC - -#include <vector> -#include <string> -#include <map> - -namespace Assimp -{ - -namespace ObjFile -{ -struct Model; -struct Object; -struct Material; -struct Point3; -struct Point2; -} -class ObjFileImporter; -class IOSystem; - -/// \class ObjFileParser -/// \brief Parser for a obj waveform file -class ObjFileParser -{ -public: - static const size_t BUFFERSIZE = 4096; - typedef std::vector<char> DataArray; - typedef std::vector<char>::iterator DataArrayIt; - typedef std::vector<char>::const_iterator ConstDataArrayIt; - -public: - /// \brief Constructor with data array. - ObjFileParser(std::vector<char> &Data,const std::string &strModelName, IOSystem* io); - /// \brief Destructor - ~ObjFileParser(); - /// \brief Model getter. - ObjFile::Model *GetModel() const; - -private: - /// Parse the loadedfile - void parseFile(); - /// Method to copy the new delimited word in the current line. - void copyNextWord(char *pBuffer, size_t length); - /// Method to copy the new line. - void copyNextLine(char *pBuffer, size_t length); - /// Stores the following 3d vector. - void getVector3( std::vector<aiVector3D> &point3d_array ); - /// Stores the following 3d vector. - void getVector2(std::vector<aiVector2D> &point2d_array); - /// Stores the following face. - void getFace(); - void getMaterialDesc(); - /// Gets a comment. - void getComment(); - /// Gets a a material library. - void getMaterialLib(); - /// Creates a new material. - void getNewMaterial(); - /// Gets the groupname from file. - void getGroupName(); - /// Gets the group number from file. - void getGroupNumber(); - /// Returns the index of the material. Is -1 if not material was found. - int getMaterialIndex( const std::string &strMaterialName ); - /// Parse object name - void getObjectName(); - /// Creates a new object. - void createObject(const std::string &strObjectName); - /// Creates a new mesh. - void createMesh(); - /// Returns true, if a new mesh instance must be created. - bool needsNewMesh( const std::string &rMaterialName ); - /// Error report in token - void reportErrorTokenInFace(); - -private: - /// Default material name - static const std::string DEFAULT_MATERIAL; - //! Iterator to current position in buffer - DataArrayIt m_DataIt; - //! Iterator to end position of buffer - DataArrayIt m_DataItEnd; - //! Pointer to model instance - ObjFile::Model *m_pModel; - //! Current line (for debugging) - unsigned int m_uiLine; - //! Helper buffer - char m_buffer[BUFFERSIZE]; - /// Pointer to IO system instance. - IOSystem *m_pIO; -}; - -} // Namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/ObjTools.h b/3rdparty/assimp/code/ObjTools.h deleted file mode 100644 index 96c339e5..00000000 --- a/3rdparty/assimp/code/ObjTools.h +++ /dev/null @@ -1,220 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ObjTools.h - * @brief Some helpful templates for text parsing - */ -#ifndef OBJ_TOOLS_H_INC -#define OBJ_TOOLS_H_INC - -#include "fast_atof.h" - -namespace Assimp -{ - -/** @brief Returns true, if the last entry of the buffer is reached. - * @param it Iterator of current position. - * @param end Iterator with end of buffer. - * @return true, if the end of the buffer is reached. - */ -template<class char_t> -inline bool isEndOfBuffer( char_t it, char_t end ) -{ - if ( it == end ) - { - return true; - } - else - { - end--; - } - return ( it == end ); -} - -/** @brief Returns true, if token is a space on any supported platform -* @param token Token to search in -* @return true, if token is a space -*/ -inline bool isSeparator( char token ) -{ - return ( token == ' ' || - token == '\n' || - token == '\f' || - token == '\r' || - token == '\t' ); -} - -/** @brief Returns true, fi token id a new line marking token. - * @param token Token to search in - * @return true, if token is a newline token. - */ -inline bool isNewLine( char token ) -{ - return ( token == '\n' || token == '\f' || token == '\r' ); -} - -/** @brief Returns next word separated by a space - * @param pBuffer Pointer to data buffer - * @param pEnd Pointer to end of buffer - * @return Pointer to next space - */ -template<class Char_T> -inline Char_T getNextWord( Char_T pBuffer, Char_T pEnd ) -{ - while ( !isEndOfBuffer( pBuffer, pEnd ) ) - { - if ( !isSeparator( *pBuffer ) || isNewLine( *pBuffer ) ) - break; - pBuffer++; - } - return pBuffer; -} - -/** @brief Returns ponter a next token - * @param pBuffer Pointer to data buffer - * @param pEnd Pointer to end of buffer - * @return Pointer to next token - */ -template<class Char_T> -inline Char_T getNextToken( Char_T pBuffer, Char_T pEnd ) -{ - while ( !isEndOfBuffer( pBuffer, pEnd ) ) - { - if ( isSeparator( *pBuffer ) ) - break; - pBuffer++; - } - return getNextWord( pBuffer, pEnd ); -} - -/** @brief Skips a line - * @param it Iterator set to current position - * @param end Iterator set to end of scratch buffer for readout - * @param uiLine Current linenumber in format - * @return Current-iterator with new position - */ -template<class char_t> -inline char_t skipLine( char_t it, char_t end, unsigned int &uiLine ) -{ - while ( !isEndOfBuffer( it, end ) && !isNewLine( *it ) ) - ++it; - if ( it != end ) - { - ++it; - ++uiLine; - } - // fix .. from time to time there are spaces at the beginning of a material line - while ( it != end && (*it == '\t' || *it == ' ') ) - ++it; - return it; -} - -/** @brief Get a name, must be separated with a blank. - * @param it set to current position - * @param end set to end of scratch buffer for readout - * @param name Separated name - * @return Current-iterator with new position - */ -template<class char_t> -inline char_t getName( char_t it, char_t end, std::string &name ) -{ - name = ""; - it = getNextToken<char_t>( it, end ); - if ( isEndOfBuffer( it, end ) ) - return end; - - char *pStart = &( *it ); - while ( !isEndOfBuffer( it, end ) && !isSeparator( *it ) ) - ++it; - - // Get name - std::string strName( pStart, &(*it) ); - if ( strName.empty() ) - return it; - else - name = strName; - - return it; -} - -/** @brief Get next word from given line - * @param it set to current position - * @param end set to end of scratch buffer for readout - * @param pBuffer Buffer for next word - * @param length Buffer length - * @return Current-iterator with new position - */ -template<class char_t> -inline char_t CopyNextWord( char_t it, char_t end, char *pBuffer, size_t length ) -{ - size_t index = 0; - it = getNextWord<char_t>( it, end ); - while ( !isSeparator( *it ) && !isEndOfBuffer( it, end ) ) - { - pBuffer[index] = *it ; - index++; - if (index == length-1) - break; - ++it; - } - pBuffer[ index ] = '\0'; - return it; -} - -/** @brief Get next float from given line - * @param it set to current position - * @param end set to end of scratch buffer for readout - * @param value Separated float value. - * @return Current-iterator with new position - */ -template<class char_t> -inline char_t getFloat( char_t it, char_t end, float &value ) -{ - static const size_t BUFFERSIZE = 1024; - char buffer[ BUFFERSIZE ]; - it = CopyNextWord<char_t>( it, end, buffer, BUFFERSIZE ); - value = (float) fast_atof( buffer ); - - return it; -} - -} // Namespace Assimp - -#endif diff --git a/3rdparty/assimp/code/OgreImporter.cpp b/3rdparty/assimp/code/OgreImporter.cpp deleted file mode 100644 index 9981b563..00000000 --- a/3rdparty/assimp/code/OgreImporter.cpp +++ /dev/null @@ -1,876 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OgreImporter.cpp - * @brief Implementation of the Ogre XML (.mesh.xml) loader. - */ -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER - -#include <vector> -#include <sstream> -using namespace std; - -//#include "boost/format.hpp" -//#include "boost/foreach.hpp" -//using namespace boost; - -#include "TinyFormatter.h" - -#include "OgreImporter.h" -#include "irrXMLWrapper.h" - - -namespace Assimp -{ -namespace Ogre -{ - - -bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const -{ - if (!checkSig)//Check File Extension - { - std::string extension("mesh.xml"); - int l=extension.length(); - return pFile.substr(pFile.length()-l, l)==extension; - } - else//Check file Header - { - const char* tokens[] = {"<mesh>"}; - return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1); - } -} - - - -void OgreImporter::InternReadFile(const std::string &pFile, aiScene *pScene, Assimp::IOSystem *pIOHandler) -{ - m_CurrentFilename=pFile; - m_CurrentIOHandler=pIOHandler; - m_CurrentScene=pScene; - - //Open the File: - boost::scoped_ptr<IOStream> file(pIOHandler->Open(pFile)); - if ( file.get() == NULL) - throw DeadlyImportError("Failed to open file "+pFile+"."); - - //Read the Mesh File: - boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get())); - XmlReader* MeshFile = irr::io::createIrrXMLReader(mIOWrapper.get()); - if (!MeshFile)//parse the xml file - throw DeadlyImportError("Failed to create XML Reader for "+pFile); - - - DefaultLogger::get()->debug("Mesh File opened"); - - //Read root Node: - if (!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="mesh")) - { - throw DeadlyImportError("Root Node is not <mesh>! "+pFile+" "+MeshFile->getNodeName()); - } - - //Go to the submeshs: - if (!(XmlRead(MeshFile) && string(MeshFile->getNodeName())=="submeshes")) - { - throw DeadlyImportError("No <submeshes> node in <mesh> node! "+pFile); - } - - - //-------------------Read the submeshs and materials:----------------------- - std::list<boost::shared_ptr<SubMesh> > SubMeshes; - vector<aiMaterial*> Materials; - XmlRead(MeshFile); - while (MeshFile->getNodeName()==string("submesh")) - { - SubMesh* theSubMesh=new SubMesh(); - theSubMesh->MaterialName=GetAttribute<string>(MeshFile, "material"); - DefaultLogger::get()->debug("Loading Submehs with Material: "+theSubMesh->MaterialName); - ReadSubMesh(*theSubMesh, MeshFile); - - //just a index in a array, we add a mesh in each loop cycle, so we get indicies like 0, 1, 2 ... n; - //so it is important to do this before pushing the mesh in the vector! - theSubMesh->MaterialIndex=SubMeshes.size(); - - SubMeshes.push_back(boost::shared_ptr<SubMesh>(theSubMesh)); - - //Load the Material: - aiMaterial* MeshMat=LoadMaterial(theSubMesh->MaterialName); - - //Set the Material: - Materials.push_back(MeshMat); - } - - if (SubMeshes.empty()) - throw DeadlyImportError("no submesh loaded!"); - if (SubMeshes.size()!=Materials.size()) - throw DeadlyImportError("materialcount doesn't match mesh count!"); - - //____________________________________________________________ - - - //----------------Load the skeleton: ------------------------------- - vector<Bone> Bones; - vector<Animation> Animations; - if (MeshFile->getNodeName()==string("skeletonlink")) - { - string SkeletonFile=GetAttribute<string>(MeshFile, "name"); - LoadSkeleton(SkeletonFile, Bones, Animations); - } - else - { - DefaultLogger::get()->warn("No skeleton file will be loaded"); - DefaultLogger::get()->warn(MeshFile->getNodeName()); - } - //__________________________________________________________________ - - - //----------------- Now fill the Assimp scene --------------------------- - - //put the aiMaterials in the scene: - m_CurrentScene->mMaterials=new aiMaterial*[Materials.size()]; - m_CurrentScene->mNumMaterials=Materials.size(); - for (unsigned int i=0; i<Materials.size(); ++i) - m_CurrentScene->mMaterials[i]=Materials[i]; - - //create the aiMehs... - vector<aiMesh*> aiMeshes; - BOOST_FOREACH(boost::shared_ptr<SubMesh> theSubMesh, SubMeshes) - { - aiMeshes.push_back(CreateAssimpSubMesh(*theSubMesh, Bones)); - } - //... and put them in the scene: - m_CurrentScene->mNumMeshes=aiMeshes.size(); - m_CurrentScene->mMeshes=new aiMesh*[aiMeshes.size()]; - memcpy(m_CurrentScene->mMeshes, &(aiMeshes[0]), sizeof(aiMeshes[0])*aiMeshes.size()); - - //Create the root node - m_CurrentScene->mRootNode=new aiNode("root"); - - //link the meshs with the root node: - m_CurrentScene->mRootNode->mMeshes=new unsigned int[SubMeshes.size()]; - m_CurrentScene->mRootNode->mNumMeshes=SubMeshes.size(); - for (unsigned int i=0; i<SubMeshes.size(); ++i) - m_CurrentScene->mRootNode->mMeshes[i]=i; - - - - CreateAssimpSkeleton(Bones, Animations); - PutAnimationsInScene(Bones, Animations); - //___________________________________________________________ -} - - - -void OgreImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("mesh.xml"); -} - - -void OgreImporter::SetupProperties(const Importer* pImp) -{ - m_MaterialLibFilename=pImp->GetPropertyString(AI_CONFIG_IMPORT_OGRE_MATERIAL_FILE, "Scene.material"); -} - -void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader) -{ - XmlRead(Reader); - //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order - //of faces and geometry changed, and not if we have more than one of one - while (Reader->getNodeName()==string("faces") || string(Reader->getNodeName())=="geometry" || Reader->getNodeName()==string("boneassignments")) - { - if (string(Reader->getNodeName())=="faces")//Read the face list - { - //some info logging: - unsigned int NumFaces=GetAttribute<int>(Reader, "count"); - stringstream ss; ss <<"Submesh has " << NumFaces << " Faces."; - DefaultLogger::get()->debug(ss.str()); - - while (XmlRead(Reader) && Reader->getNodeName()==string("face")) - { - Face NewFace; - NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1"); - NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2"); - NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3"); - if (Reader->getAttributeValue("v4"))//this should be supported in the future - { - throw DeadlyImportError("Submesh has quads, only traingles are supported!"); - } - theSubMesh.FaceList.push_back(NewFace); - } - - }//end of faces - else if (string(Reader->getNodeName())=="geometry")//Read the vertexdata - { - //some info logging: - unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount"); - stringstream ss; ss<<"VertexCount: "<<NumVertices; - DefaultLogger::get()->debug(ss.str()); - - //General Informations about vertices - XmlRead(Reader); - if (!(Reader->getNodeName()==string("vertexbuffer"))) - { - throw DeadlyImportError("vertexbuffer node is not first in geometry node!"); - } - theSubMesh.HasPositions=GetAttribute<bool>(Reader, "positions"); - theSubMesh.HasNormals=GetAttribute<bool>(Reader, "normals"); - if (!Reader->getAttributeValue("texture_coords"))//we can have 1 or 0 uv channels, and if the mesh has no uvs, it also doesn't have the attribute - theSubMesh.NumUvs=0; - else - theSubMesh.NumUvs=GetAttribute<int>(Reader, "texture_coords"); - if (theSubMesh.NumUvs>1) - throw DeadlyImportError("too many texcoords (just 1 supported!)"); - - //read all the vertices: - XmlRead(Reader); - while (Reader->getNodeName()==string("vertex")) - { - //read all vertex attributes: - - //Position - if (theSubMesh.HasPositions) - { - XmlRead(Reader); - aiVector3D NewPos; - NewPos.x=GetAttribute<float>(Reader, "x"); - NewPos.y=GetAttribute<float>(Reader, "y"); - NewPos.z=GetAttribute<float>(Reader, "z"); - theSubMesh.Positions.push_back(NewPos); - } - - //Normal - if (theSubMesh.HasNormals) - { - XmlRead(Reader); - aiVector3D NewNormal; - NewNormal.x=GetAttribute<float>(Reader, "x"); - NewNormal.y=GetAttribute<float>(Reader, "y"); - NewNormal.z=GetAttribute<float>(Reader, "z"); - theSubMesh.Normals.push_back(NewNormal); - } - - //Uv: - if (1==theSubMesh.NumUvs) - { - XmlRead(Reader); - aiVector3D NewUv; - NewUv.x=GetAttribute<float>(Reader, "u"); - NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so! - theSubMesh.Uvs.push_back(NewUv); - } - XmlRead(Reader); - } - - }//end of "geometry - - - else if (string(Reader->getNodeName())=="boneassignments") - { - theSubMesh.Weights.resize(theSubMesh.Positions.size()); - while (XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment")) - { - Weight NewWeight; - unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex"); - NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex"); - NewWeight.Value=GetAttribute<float>(Reader, "weight"); - theSubMesh.BonesUsed=max(theSubMesh.BonesUsed, NewWeight.BoneId+1);//calculate the number of bones used (this is the highest id +1 becuase bone ids start at 0) - - theSubMesh.Weights[VertexId].push_back(NewWeight); - - //XmlRead(Reader);//Once i had this line, and than i got only every second boneassignment, but my first test models had even boneassignment counts, so i thougt, everything would work. And yes, i HATE irrXML!!! - } - - }//end of boneassignments - } - DefaultLogger::get()->debug((Formatter::format(), - "Positionen: ",theSubMesh.Positions.size(), - " Normale: ",theSubMesh.Normals.size(), - " TexCoords: ",theSubMesh.Uvs.size() - )); - DefaultLogger::get()->warn(Reader->getNodeName()); - - - - //---------------Make all Vertexes unique: (this is required by assimp)----------------------- - vector<Face> UniqueFaceList(theSubMesh.FaceList.size()); - unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^ - vector<aiVector3D> UniquePositions(UniqueVertexCount); - vector<aiVector3D> UniqueNormals(UniqueVertexCount); - vector<aiVector3D> UniqueUvs(UniqueVertexCount); - vector< vector<Weight> > UniqueWeights((theSubMesh.Weights.size() ? UniqueVertexCount : 0)); - - for (unsigned int i=0; i<theSubMesh.FaceList.size(); ++i) - { - //We precalculate the index vlaues her, because we need them in all vertex attributes - unsigned int Vertex1=theSubMesh.FaceList[i].VertexIndices[0]; - unsigned int Vertex2=theSubMesh.FaceList[i].VertexIndices[1]; - unsigned int Vertex3=theSubMesh.FaceList[i].VertexIndices[2]; - - UniquePositions[3*i+0]=theSubMesh.Positions[Vertex1]; - UniquePositions[3*i+1]=theSubMesh.Positions[Vertex2]; - UniquePositions[3*i+2]=theSubMesh.Positions[Vertex3]; - - UniqueNormals[3*i+0]=theSubMesh.Normals[Vertex1]; - UniqueNormals[3*i+1]=theSubMesh.Normals[Vertex2]; - UniqueNormals[3*i+2]=theSubMesh.Normals[Vertex3]; - - if (1==theSubMesh.NumUvs) - { - UniqueUvs[3*i+0]=theSubMesh.Uvs[Vertex1]; - UniqueUvs[3*i+1]=theSubMesh.Uvs[Vertex2]; - UniqueUvs[3*i+2]=theSubMesh.Uvs[Vertex3]; - } - - if (theSubMesh.Weights.size()) { - UniqueWeights[3*i+0]=theSubMesh.Weights[Vertex1]; - UniqueWeights[3*i+1]=theSubMesh.Weights[Vertex2]; - UniqueWeights[3*i+2]=theSubMesh.Weights[Vertex3]; - } - - //The indexvalues a just continuous numbers (0, 1, 2, 3, 4, 5, 6...) - UniqueFaceList[i].VertexIndices[0]=3*i+0; - UniqueFaceList[i].VertexIndices[1]=3*i+1; - UniqueFaceList[i].VertexIndices[2]=3*i+2; - } - //_________________________________________________________________________________________ - - //now we have the unique datas, but want them in the SubMesh, so we swap all the containers: - theSubMesh.FaceList.swap(UniqueFaceList); - theSubMesh.Positions.swap(UniquePositions); - theSubMesh.Normals.swap(UniqueNormals); - theSubMesh.Uvs.swap(UniqueUvs); - theSubMesh.Weights.swap(UniqueWeights); - - //------------- normalize weights ----------------------------- - //The Blender exporter doesn't care about whether the sum of all boneweights for a single vertex equals 1 or not, - //so we have to make this sure: - for (unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices - { - float WeightSum=0.0f; - for (unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones - { - WeightSum+=theSubMesh.Weights[VertexId][BoneId].Value; - } - - //check if the sum is too far away from 1 - if (WeightSum<1.0f-0.05f || WeightSum>1.0f+0.05f) - { - //normalize all weights: - for (unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones - { - theSubMesh.Weights[VertexId][BoneId].Value/=WeightSum; - } - } - } - //_________________________________________________________ -} - - -aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones) const -{ - const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene - - aiMesh* NewAiMesh=new aiMesh(); - - //Positions - NewAiMesh->mVertices=new aiVector3D[theSubMesh.Positions.size()]; - memcpy(NewAiMesh->mVertices, &theSubMesh.Positions[0], theSubMesh.Positions.size()*sizeof(aiVector3D)); - NewAiMesh->mNumVertices=theSubMesh.Positions.size(); - - //Normals - NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()]; - memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D)); - - //Uvs - if (0!=theSubMesh.NumUvs) - { - NewAiMesh->mNumUVComponents[0]=2; - NewAiMesh->mTextureCoords[0]= new aiVector3D[theSubMesh.Uvs.size()]; - memcpy(NewAiMesh->mTextureCoords[0], &theSubMesh.Uvs[0], theSubMesh.Uvs.size()*sizeof(aiVector3D)); - } - - - //---------------------------------------- Bones -------------------------------------------- - - //Copy the weights in in Bone-Vertices Struktur - //(we have them in a Vertex-Bones Structur, this is much easier for making them unique, which is required by assimp - vector< vector<aiVertexWeight> > aiWeights(theSubMesh.BonesUsed);//now the outer list are the bones, and the inner vector the vertices - for (unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices - { - for (unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones - { - aiVertexWeight NewWeight; - NewWeight.mVertexId=VertexId;//the current Vertex, we can't use the Id form the submehs weights, because they are bone id's - NewWeight.mWeight=theSubMesh.Weights[VertexId][BoneId].Value; - aiWeights[theSubMesh.Weights[VertexId][BoneId].BoneId].push_back(NewWeight); - } - } - - - - vector<aiBone*> aiBones; - aiBones.reserve(theSubMesh.BonesUsed);//the vector might be smaller, because there might be empty bones (bones that are not attached to any vertex) - - //create all the bones and fill them with informations - for (unsigned int i=0; i<theSubMesh.BonesUsed; ++i) - { - if (aiWeights[i].size()>0) - { - aiBone* NewBone=new aiBone(); - NewBone->mNumWeights=aiWeights[i].size(); - NewBone->mWeights=new aiVertexWeight[aiWeights[i].size()]; - memcpy(NewBone->mWeights, &(aiWeights[i][0]), sizeof(aiVertexWeight)*aiWeights[i].size()); - NewBone->mName=Bones[i].Name;//The bone list should be sorted after its id's, this was done in LoadSkeleton - NewBone->mOffsetMatrix=Bones[i].BoneToWorldSpace; - - aiBones.push_back(NewBone); - } - } - NewAiMesh->mNumBones=aiBones.size(); - - // mBones must be NULL if mNumBones is non 0 or the validation fails. - if (aiBones.size()) { - NewAiMesh->mBones=new aiBone* [aiBones.size()]; - memcpy(NewAiMesh->mBones, &(aiBones[0]), aiBones.size()*sizeof(aiBone*)); - } - - //______________________________________________________________________________________________________ - - - - //Faces - NewAiMesh->mFaces=new aiFace[theSubMesh.FaceList.size()]; - for (unsigned int i=0; i<theSubMesh.FaceList.size(); ++i) - { - NewAiMesh->mFaces[i].mNumIndices=3; - NewAiMesh->mFaces[i].mIndices=new unsigned int[3]; - - NewAiMesh->mFaces[i].mIndices[0]=theSubMesh.FaceList[i].VertexIndices[0]; - NewAiMesh->mFaces[i].mIndices[1]=theSubMesh.FaceList[i].VertexIndices[1]; - NewAiMesh->mFaces[i].mIndices[2]=theSubMesh.FaceList[i].VertexIndices[2]; - } - NewAiMesh->mNumFaces=theSubMesh.FaceList.size(); - - //Link the material: - NewAiMesh->mMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh - - return NewAiMesh; -} - - -void OgreImporter::LoadSkeleton(std::string FileName, vector<Bone> &Bones, vector<Animation> &Animations) const -{ - const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene - - - //most likely the skeleton file will only end with .skeleton - //But this is a xml reader, so we need: .skeleton.xml - FileName+=".xml"; - - DefaultLogger::get()->debug(string("Loading Skeleton: ")+FileName); - - //Open the File: - boost::scoped_ptr<IOStream> File(m_CurrentIOHandler->Open(FileName)); - if (NULL==File.get()) - throw DeadlyImportError("Failed to open skeleton file "+FileName+"."); - - //Read the Mesh File: - boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(File.get())); - XmlReader* SkeletonFile = irr::io::createIrrXMLReader(mIOWrapper.get()); - if (!SkeletonFile) - throw DeadlyImportError(string("Failed to create XML Reader for ")+FileName); - - //Quick note: Whoever read this should know this one thing: irrXml fucking sucks!!! - - XmlRead(SkeletonFile); - if (string("skeleton")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("No <skeleton> node in SkeletonFile: "+FileName); - - - - //------------------------------------load bones----------------------------------------- - XmlRead(SkeletonFile); - if (string("bones")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("No bones node in skeleton "+FileName); - - XmlRead(SkeletonFile); - - while (string("bone")==SkeletonFile->getNodeName()) - { - //TODO: Maybe we can have bone ids for the errrors, but normaly, they should never appear, so what.... - - //read a new bone: - Bone NewBone; - NewBone.Id=GetAttribute<int>(SkeletonFile, "id"); - NewBone.Name=GetAttribute<string>(SkeletonFile, "name"); - - //load the position: - XmlRead(SkeletonFile); - if (string("position")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("Position is not first node in Bone!"); - NewBone.Position.x=GetAttribute<float>(SkeletonFile, "x"); - NewBone.Position.y=GetAttribute<float>(SkeletonFile, "y"); - NewBone.Position.z=GetAttribute<float>(SkeletonFile, "z"); - - //Rotation: - XmlRead(SkeletonFile); - if (string("rotation")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("Rotation is not the second node in Bone!"); - NewBone.RotationAngle=GetAttribute<float>(SkeletonFile, "angle"); - XmlRead(SkeletonFile); - if (string("axis")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("No axis specified for bone rotation!"); - NewBone.RotationAxis.x=GetAttribute<float>(SkeletonFile, "x"); - NewBone.RotationAxis.y=GetAttribute<float>(SkeletonFile, "y"); - NewBone.RotationAxis.z=GetAttribute<float>(SkeletonFile, "z"); - - //append the newly loaded bone to the bone list - Bones.push_back(NewBone); - - //Proceed to the next bone: - XmlRead(SkeletonFile); - } - //The bones in the file a not neccesarly ordered by there id's so we do it now: - std::sort(Bones.begin(), Bones.end()); - - //now the id of each bone should be equal to its position in the vector: - //so we do a simple check: - { - bool IdsOk=true; - for (int i=0; i<static_cast<signed int>(Bones.size()); ++i)//i is signed, because all Id's are also signed! - { - if (Bones[i].Id!=i) - IdsOk=false; - } - if (!IdsOk) - throw DeadlyImportError("Bone Ids are not valid!"+FileName); - } - DefaultLogger::get()->debug((Formatter::format(),"Number of bones: ",Bones.size())); - //________________________________________________________________________________ - - - - - - - //----------------------------load bonehierarchy-------------------------------- - if (string("bonehierarchy")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("no bonehierarchy node in "+FileName); - - DefaultLogger::get()->debug("loading bonehierarchy..."); - XmlRead(SkeletonFile); - while (string("boneparent")==SkeletonFile->getNodeName()) - { - string Child, Parent; - Child=GetAttribute<string>(SkeletonFile, "bone"); - Parent=GetAttribute<string>(SkeletonFile, "parent"); - - unsigned int ChildId, ParentId; - ChildId=find(Bones.begin(), Bones.end(), Child)->Id; - ParentId=find(Bones.begin(), Bones.end(), Parent)->Id; - - Bones[ChildId].ParentId=ParentId; - Bones[ParentId].Children.push_back(ChildId); - - XmlRead(SkeletonFile);//i once forget this line, which led to an endless loop, did i mentioned, that irrxml sucks?? - } - //_____________________________________________________________________________ - - - //--------- Calculate the WorldToBoneSpace Matrix recursivly for all bones: ------------------ - BOOST_FOREACH(Bone theBone, Bones) - { - if (-1==theBone.ParentId) //the bone is a root bone - { - theBone.CalculateBoneToWorldSpaceMatrix(Bones); - } - } - //_______________________________________________________________________ - - - //---------------------------load animations----------------------------- - if (string("animations")==SkeletonFile->getNodeName())//animations are optional values - { - DefaultLogger::get()->debug("Loading Animations"); - XmlRead(SkeletonFile); - while (string("animation")==SkeletonFile->getNodeName()) - { - Animation NewAnimation; - NewAnimation.Name=GetAttribute<string>(SkeletonFile, "name"); - NewAnimation.Length=GetAttribute<float>(SkeletonFile, "length"); - - //Load all Tracks - XmlRead(SkeletonFile); - if (string("tracks")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("no tracks node in animation"); - XmlRead(SkeletonFile); - while (string("track")==SkeletonFile->getNodeName()) - { - Track NewTrack; - NewTrack.BoneName=GetAttribute<string>(SkeletonFile, "bone"); - - //Load all keyframes; - XmlRead(SkeletonFile); - if (string("keyframes")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("no keyframes node!"); - XmlRead(SkeletonFile); - while (string("keyframe")==SkeletonFile->getNodeName()) - { - Keyframe NewKeyframe; - NewKeyframe.Time=GetAttribute<float>(SkeletonFile, "time"); - - //Position: - XmlRead(SkeletonFile); - if (string("translate")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("translate node not first in keyframe"); - NewKeyframe.Position.x=GetAttribute<float>(SkeletonFile, "x"); - NewKeyframe.Position.y=GetAttribute<float>(SkeletonFile, "y"); - NewKeyframe.Position.z=GetAttribute<float>(SkeletonFile, "z"); - - //Rotation: - XmlRead(SkeletonFile); - if (string("rotate")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("rotate is not second node in keyframe"); - float RotationAngle=GetAttribute<float>(SkeletonFile, "angle"); - aiVector3D RotationAxis; - XmlRead(SkeletonFile); - if (string("axis")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("No axis for keyframe rotation!"); - RotationAxis.x=GetAttribute<float>(SkeletonFile, "x"); - RotationAxis.y=GetAttribute<float>(SkeletonFile, "y"); - RotationAxis.z=GetAttribute<float>(SkeletonFile, "z"); - NewKeyframe.Rotation=aiQuaternion(RotationAxis, RotationAngle); - - //Scaling: - XmlRead(SkeletonFile); - if (string("scale")!=SkeletonFile->getNodeName()) - throw DeadlyImportError("no scalling key in keyframe!"); - NewKeyframe.Scaling.x=GetAttribute<float>(SkeletonFile, "x"); - NewKeyframe.Scaling.y=GetAttribute<float>(SkeletonFile, "y"); - NewKeyframe.Scaling.z=GetAttribute<float>(SkeletonFile, "z"); - - - NewTrack.Keyframes.push_back(NewKeyframe); - XmlRead(SkeletonFile); - } - - - NewAnimation.Tracks.push_back(NewTrack); - } - - Animations.push_back(NewAnimation); - } - } - //_____________________________________________________________________________ - -} - - -void OgreImporter::CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations) -{ - if (!m_CurrentScene->mRootNode) - throw DeadlyImportError("No root node exists!!"); - if (0!=m_CurrentScene->mRootNode->mNumChildren) - throw DeadlyImportError("Root Node already has childnodes!"); - - - //Createt the assimp bone hierarchy - DefaultLogger::get()->debug("Root Bones"); - vector<aiNode*> RootBoneNodes; - BOOST_FOREACH(Bone theBone, Bones) - { - if (-1==theBone.ParentId) //the bone is a root bone - { - DefaultLogger::get()->debug(theBone.Name); - RootBoneNodes.push_back(CreateAiNodeFromBone(theBone.Id, Bones, m_CurrentScene->mRootNode));//which will recursily add all other nodes - } - } - - if (RootBoneNodes.size()) { - m_CurrentScene->mRootNode->mNumChildren=RootBoneNodes.size(); - m_CurrentScene->mRootNode->mChildren=new aiNode*[RootBoneNodes.size()]; - memcpy(m_CurrentScene->mRootNode->mChildren, &RootBoneNodes[0], sizeof(aiNode*)*RootBoneNodes.size()); - } -} - - -void OgreImporter::PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations) -{ - //-----------------Create the Assimp Animations -------------------- - if (Animations.size()>0)//Maybe the model had only a skeleton and no animations. (If it also has no skeleton, this function would'nt have been called - { - m_CurrentScene->mNumAnimations=Animations.size(); - m_CurrentScene->mAnimations=new aiAnimation*[Animations.size()]; - for (unsigned int i=0; i<Animations.size(); ++i)//create all animations - { - aiAnimation* NewAnimation=new aiAnimation(); - NewAnimation->mName=Animations[i].Name; - NewAnimation->mDuration=Animations[i].Length; - NewAnimation->mTicksPerSecond=1.0f; - - //Create all tracks in this animation - NewAnimation->mNumChannels=Animations[i].Tracks.size(); - NewAnimation->mChannels=new aiNodeAnim*[Animations[i].Tracks.size()]; - for (unsigned int j=0; j<Animations[i].Tracks.size(); ++j) - { - aiNodeAnim* NewNodeAnim=new aiNodeAnim(); - NewNodeAnim->mNodeName=Animations[i].Tracks[j].BoneName; - - //we need this, to acces the bones default pose, which we need to make keys absolute - vector<Bone>::const_iterator CurBone=find(Bones.begin(), Bones.end(), NewNodeAnim->mNodeName); - aiMatrix4x4 t0, t1; - aiMatrix4x4 DefBonePose=//The default bone pose doesnt have a scaling value - aiMatrix4x4::Rotation(CurBone->RotationAngle, CurBone->RotationAxis, t0) - * aiMatrix4x4::Translation(CurBone->Position, t1); - - //Create the keyframe arrays... - unsigned int KeyframeCount=Animations[i].Tracks[j].Keyframes.size(); - NewNodeAnim->mNumPositionKeys=KeyframeCount; - NewNodeAnim->mPositionKeys=new aiVectorKey[KeyframeCount]; - NewNodeAnim->mNumRotationKeys=KeyframeCount; - NewNodeAnim->mRotationKeys=new aiQuatKey[KeyframeCount]; - NewNodeAnim->mNumScalingKeys=KeyframeCount; - NewNodeAnim->mScalingKeys=new aiVectorKey[KeyframeCount]; - - //...and fill them - for (unsigned int k=0; k<KeyframeCount; ++k) - { - aiMatrix4x4 t2, t3; - - //Create a matrix to transfrom a vector from the bones default pose to the bone bones in this animation key - aiMatrix4x4 PoseToKey=aiMatrix4x4::Scaling(Animations[i].Tracks[j].Keyframes[k].Scaling, t2) //scale - * aiMatrix4x4(Animations[i].Tracks[j].Keyframes[k].Rotation.GetMatrix()) //rot - * aiMatrix4x4::Translation(Animations[i].Tracks[j].Keyframes[k].Position, t3); //pos - - - //calculate the complete transformation from world space to bone space - aiMatrix4x4 CompleteTransform=DefBonePose * PoseToKey; - - aiVector3D Pos; - aiQuaternion Rot; - aiVector3D Scale; - - CompleteTransform.Decompose(Scale, Rot, Pos); - - - NewNodeAnim->mPositionKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; - NewNodeAnim->mPositionKeys[k].mValue=Pos; - - NewNodeAnim->mRotationKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; - NewNodeAnim->mRotationKeys[k].mValue=Rot; - - NewNodeAnim->mScalingKeys[k].mTime=Animations[i].Tracks[j].Keyframes[k].Time; - NewNodeAnim->mScalingKeys[k].mValue=Scale; - } - - NewAnimation->mChannels[j]=NewNodeAnim; - } - - m_CurrentScene->mAnimations[i]=NewAnimation; - } - } -//TODO: Auf nicht vorhandene Animationskeys achten! -//#pragma warning (s.o.) - //__________________________________________________________________ -} - - - -aiNode* OgreImporter::CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode) const -{ - const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene - - //----Create the node for this bone and set its values----- - aiNode* NewNode=new aiNode(Bones[BoneId].Name); - NewNode->mParent=ParentNode; - - aiMatrix4x4 t0,t1; - //create a matrix from the transformation values of the ogre bone - NewNode->mTransformation=aiMatrix4x4::Rotation(Bones[BoneId].RotationAngle, Bones[BoneId].RotationAxis, t1) - * aiMatrix4x4::Translation(Bones[BoneId].Position, t0) - - ; - //__________________________________________________________ - - - //---------- recursivly create all children Nodes: ---------- - NewNode->mNumChildren=Bones[BoneId].Children.size(); - NewNode->mChildren=new aiNode*[Bones[BoneId].Children.size()]; - for (unsigned int i=0; i<Bones[BoneId].Children.size(); ++i) - { - NewNode->mChildren[i]=CreateAiNodeFromBone(Bones[BoneId].Children[i], Bones, NewNode); - } - //____________________________________________________ - - - return NewNode; -} - - -void Bone::CalculateBoneToWorldSpaceMatrix(vector<Bone> &Bones) -{ - //Calculate the matrix for this bone: - - aiMatrix4x4 t0,t1; - aiMatrix4x4 Transf=aiMatrix4x4::Translation(-Position, t0) - * aiMatrix4x4::Rotation(-RotationAngle, RotationAxis, t1) - ; - if (-1==ParentId) - { - BoneToWorldSpace=Transf; - } - else - { - BoneToWorldSpace=Transf*Bones[ParentId].BoneToWorldSpace; - } - - //and recursivly for all children: - BOOST_FOREACH(int theChildren, Children) - { - Bones[theChildren].CalculateBoneToWorldSpaceMatrix(Bones); - } -} - -}//namespace Ogre -}//namespace Assimp - -#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER diff --git a/3rdparty/assimp/code/OgreImporter.h b/3rdparty/assimp/code/OgreImporter.h deleted file mode 100644 index ee574726..00000000 --- a/3rdparty/assimp/code/OgreImporter.h +++ /dev/null @@ -1,142 +0,0 @@ -#include "BaseImporter.h" - -#include <vector> - -#include "OgreXmlHelper.h" -#include "irrXMLWrapper.h" - -namespace Assimp -{ -namespace Ogre -{ - - -//Forward declarations: -struct SubMesh; - -///For the moment just triangles, no other polygon types! -struct Face -{ - unsigned int VertexIndices[3]; -}; - -///for a vertex->bone structur -struct Weight -{ - unsigned int BoneId; - float Value; -}; - -/// Helper Class to describe an ogre-bone for the skeleton: -/** All Id's are signed ints, because than we have -1 as a simple INVALID_ID Value (we start from 0 so 0 is a valid bone ID!*/ -struct Bone -{ - int Id; - int ParentId; - std::string Name; - aiVector3D Position; - float RotationAngle; - aiVector3D RotationAxis; - std::vector<int> Children; - aiMatrix4x4 BoneToWorldSpace; - - ///ctor - Bone(): Id(-1), ParentId(-1), RotationAngle(0.0f) {} - ///this operator is needed to sort the bones after Id's - bool operator<(const Bone& rval) const - {return Id<rval.Id; } - ///this operator is needed to find a bone by its name in a vector<Bone> - bool operator==(const std::string& rval) const - {return Name==rval; } - bool operator==(const aiString& rval) const - {return Name==std::string(rval.data); } - - void CalculateBoneToWorldSpaceMatrix(std::vector<Bone>& Bones); - -}; - -/// keyframe (bone transformation) from a track from a animation -struct Keyframe -{ - float Time; - aiVector3D Position; - aiQuaternion Rotation; - aiVector3D Scaling; -}; - -///a track (keyframes for one bone) from an animation -struct Track -{ - std::string BoneName; - std::vector<Keyframe> Keyframes; -}; - -///Describes an Ogre Animation -struct Animation -{ - std::string Name; - float Length; - std::vector<Track> Tracks; -}; - -///The Main Ogre Importer Class -class OgreImporter : public BaseImporter -{ -public: - virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const; - virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - virtual void GetExtensionList(std::set<std::string>& extensions); - virtual void SetupProperties(const Importer* pImp); -private: - - /// Helper Functions to read parts of the XML File - void ReadSubMesh(SubMesh& theSubMesh, XmlReader* Reader);//the submesh reference is the result value - - /// writes the results in Bones and Animations, Filename is not const, because its call-by-value and the function will change it! - void LoadSkeleton(std::string FileName, std::vector<Bone> &Bones, std::vector<Animation> &Animations) const; - - /// converts the animations in aiAnimations and puts them into the scene - void PutAnimationsInScene(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations); - - /// uses the bone data to convert a SubMesh into a aiMesh which will be created and returned - aiMesh* CreateAssimpSubMesh(const SubMesh &theSubMesh, const std::vector<Bone>& Bones) const; - - //creates the aiskeleton in current scene - void CreateAssimpSkeleton(const std::vector<Bone> &Bones, const std::vector<Animation> &Animations); - - aiMaterial* LoadMaterial(const std::string MaterialName) const; - - ///Recursivly creates a filled aiNode from a given root bone - aiNode* CreateAiNodeFromBone(int BoneId, const std::vector<Bone> &Bones, aiNode* ParentNode) const; - - //Now we don't have to give theses parameters to all functions - std::string m_CurrentFilename; - std::string m_MaterialLibFilename; - IOSystem* m_CurrentIOHandler; - aiScene *m_CurrentScene; -}; - -///A submesh from Ogre -struct SubMesh -{ - std::string Name; - std::string MaterialName; - std::vector<Face> FaceList; - std::vector<aiVector3D> Positions; bool HasPositions; - std::vector<aiVector3D> Normals; bool HasNormals; - std::vector<aiVector3D> Uvs; unsigned int NumUvs;//nearly always 2d, but assimp has always 3d texcoords - std::vector< std::vector<Weight> > Weights;//a list of bones for each vertex - int MaterialIndex;///< The Index in the Assimp Materialarray from the material witch is attached to this submesh - unsigned int BonesUsed;//the highest index of a bone from a bone weight, this is needed to create the assimp bone structur (converting from Vertex-Bones to Bone-Vertices) - - SubMesh(): HasPositions(false), HasNormals(false), NumUvs(0), MaterialIndex(-1), BonesUsed(0) {}//initialize everything -}; - -struct BoneAssignment -{ - unsigned int BoneId;//this is, what we get from ogre - std::string BoneName;//this is, what we need for assimp -}; - -}//namespace Ogre -}//namespace Assimp diff --git a/3rdparty/assimp/code/OgreImporterMaterial.cpp b/3rdparty/assimp/code/OgreImporterMaterial.cpp deleted file mode 100644 index 02f18a7a..00000000 --- a/3rdparty/assimp/code/OgreImporterMaterial.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -/** -This file contains material related code. This is -spilitted up from the main file OgreImporter.cpp -to make it shorter easier to maintain. -*/ -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER - -#include <vector> -#include <sstream> -using namespace std; - -//#include "boost/format.hpp" -//#include "boost/foreach.hpp" -//using namespace boost; - -#include "OgreImporter.h" -#include "irrXMLWrapper.h" -#include "TinyFormatter.h" - -namespace Assimp -{ -namespace Ogre -{ - - - -aiMaterial* OgreImporter::LoadMaterial(const std::string MaterialName) const -{ - const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene - - MaterialHelper *NewMaterial=new MaterialHelper(); - - aiString ts(MaterialName.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_NAME); - /*For bettetr understanding of the material parser, here is a material example file: - - material Sarg - { - receive_shadows on - technique - { - pass - { - ambient 0.500000 0.500000 0.500000 1.000000 - diffuse 0.640000 0.640000 0.640000 1.000000 - specular 0.500000 0.500000 0.500000 1.000000 12.500000 - emissive 0.000000 0.000000 0.000000 1.000000 - texture_unit - { - texture SargTextur.tga - tex_address_mode wrap - filtering linear linear none - } - } - } - } - - */ - - - const string MaterialFileName=m_CurrentFilename.substr(0, m_CurrentFilename.find('.'))+".material"; - DefaultLogger::get()->info("Trying to load " +MaterialFileName); - - //Read the file into memory and put it in a stringstream - stringstream ss; - {// after this block, the temporarly loaded data will be released - IOStream* MatFilePtr=m_CurrentIOHandler->Open(MaterialFileName); - if (NULL==MatFilePtr) - { - MatFilePtr=m_CurrentIOHandler->Open(m_MaterialLibFilename); - if (NULL==MatFilePtr) - { - DefaultLogger::get()->error(m_MaterialLibFilename+" and "+MaterialFileName + " could not be opened, Material will not be loaded!"); - return NewMaterial; - } - } - boost::scoped_ptr<IOStream> MaterialFile(MatFilePtr); - vector<char> FileData(MaterialFile->FileSize()); - MaterialFile->Read(&FileData[0], MaterialFile->FileSize(), 1); - BaseImporter::ConvertToUTF8(FileData); - - ss << &FileData[0]; - } - - string Line; - ss >> Line; -// unsigned int Level=0;//Hierarchielevels in the material file, like { } blocks into another - while (!ss.eof()) - { - if (Line=="material") - { - ss >> Line; - if (Line==MaterialName)//Load the next material - { - ss >> Line; - if (Line!="{") - throw DeadlyImportError("empty material!"); - - while (Line!="}")//read until the end of the material - { - //Proceed to the first technique - ss >> Line; - if (Line=="technique") - { - ss >> Line; - if (Line!="{") - throw DeadlyImportError("empty technique!"); - while (Line!="}")//read until the end of the technique - { - ss >> Line; - if (Line=="pass") - { - ss >> Line; - if (Line!="{") - throw DeadlyImportError("empty pass!"); - while (Line!="}")//read until the end of the pass - { - ss >> Line; - if (Line=="ambient") - { - float r,g,b; - ss >> r >> g >> b; - const aiColor3D Color(r,g,b); - NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_AMBIENT); - } - else if (Line=="diffuse") - { - float r,g,b; - ss >> r >> g >> b; - const aiColor3D Color(r,g,b); - NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_DIFFUSE); - } - else if (Line=="specular") - { - float r,g,b; - ss >> r >> g >> b; - const aiColor3D Color(r,g,b); - NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_SPECULAR); - } - else if (Line=="emmisive") - { - float r,g,b; - ss >> r >> g >> b; - const aiColor3D Color(r,g,b); - NewMaterial->AddProperty(&Color, 1, AI_MATKEY_COLOR_EMISSIVE); - } - else if (Line=="texture_unit") - { - ss >> Line; - if (Line!="{") - throw DeadlyImportError("empty texture unit!"); - while (Line!="}")//read until the end of the texture_unit - { - ss >> Line; - if (Line=="texture") - { - ss >> Line; - aiString ts(Line.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); - } - }//end of texture unit - } - } - } - }//end of technique - - - } - - - DefaultLogger::get()->info(Line); - //read informations from a custom material: - if (Line=="set") - { - ss >> Line; - if (Line=="$specular")//todo load this values: - { - } - if (Line=="$diffuse") - { - } - if (Line=="$ambient") - { - } - if (Line=="$colormap") - { - ss >> Line; - aiString ts(Line.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0)); - } - if (Line=="$normalmap") - { - ss >> Line; - aiString ts(Line.c_str()); - NewMaterial->AddProperty(&ts, AI_MATKEY_TEXTURE(aiTextureType_NORMALS, 0)); - } - } - }//end of material - } - else {} //this is the wrong material, proceed the file until we reach the next material - } - ss >> Line; - } - - return NewMaterial; -} - - - -}//namespace Ogre -}//namespace Assimp - -#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER diff --git a/3rdparty/assimp/code/OgreXmlHelper.h b/3rdparty/assimp/code/OgreXmlHelper.h deleted file mode 100644 index be72deee..00000000 --- a/3rdparty/assimp/code/OgreXmlHelper.h +++ /dev/null @@ -1,79 +0,0 @@ - -#include "irrXMLWrapper.h" -#include "fast_atof.h" - -namespace Assimp -{ -namespace Ogre -{ - -typedef irr::io::IrrXMLReader XmlReader; - - -//------------Helper Funktion to Get a Attribute Save--------------- -template<typename t> inline t GetAttribute(XmlReader* Reader, std::string Name); - -/* -{ - BOOST_STATIC_ASSERT(false); - return t(); -} -*/ - -template<> inline int GetAttribute<int>(XmlReader* Reader, std::string Name) -{ - const char* Value=Reader->getAttributeValue(Name.c_str()); - if (Value) - return atoi(Value); - else - throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str()); -} - -template<> inline float GetAttribute<float>(XmlReader* Reader, std::string Name) -{ - const char* Value=Reader->getAttributeValue(Name.c_str()); - if (Value) - return fast_atof(Value); - else - throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str()); -} - -template<> inline std::string GetAttribute<std::string>(XmlReader* Reader, std::string Name) -{ - const char* Value=Reader->getAttributeValue(Name.c_str()); - if (Value) - return std::string(Value); - else - throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str()); -} - -template<> inline bool GetAttribute<bool>(XmlReader* Reader, std::string Name) -{ - const char* Value=Reader->getAttributeValue(Name.c_str()); - if (Value) - { - if (Value==std::string("true")) - return true; - else if (Value==std::string("false")) - return false; - else - throw DeadlyImportError(std::string("Bool value has invalid value: "+Name+" / "+Value+" / "+Reader->getNodeName())); - } - else - throw DeadlyImportError(std::string("Attribute "+Name+" does not exist in "+Reader->getNodeName()).c_str()); -} -//__________________________________________________________________ - -inline bool XmlRead(XmlReader* Reader) -{ - do - { - if (!Reader->read()) - return false; - } - while (Reader->getNodeType()!=irr::io::EXN_ELEMENT); - return true; -} - -}//namespace Ogre -}//namespace Assimp diff --git a/3rdparty/assimp/code/OptimizeGraph.cpp b/3rdparty/assimp/code/OptimizeGraph.cpp deleted file mode 100644 index 0529fedd..00000000 --- a/3rdparty/assimp/code/OptimizeGraph.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OptimizeGraph.cpp - * @brief Implementation of the aiProcess_OptimizGraph step - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS - -using namespace Assimp; -#include "OptimizeGraph.h" -#include "ProcessHelper.h" -#include "SceneCombiner.h" - -#define AI_RESERVED_NODE_NAME "$Reserved_And_Evil" - -/* AI_OG_USE_HASHING enables the use of hashing to speed-up std::set lookups. - * The unhashed variant should be faster, except for *very* large data sets - */ -#ifdef AI_OG_USE_HASHING - // Use our standard hashing function to compute the hash -# define AI_OG_GETKEY(str) SuperFastHash(str.data,str.length) -#else - // Otherwise hope that std::string will utilize a static buffer - // for shorter node names. This would avoid endless heap copying. -# define AI_OG_GETKEY(str) std::string(str.data) -#endif - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -OptimizeGraphProcess::OptimizeGraphProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -OptimizeGraphProcess::~OptimizeGraphProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool OptimizeGraphProcess::IsActive( unsigned int pFlags) const -{ - return (0 != (pFlags & aiProcess_OptimizeGraph)); -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties for the postprocessing step -void OptimizeGraphProcess::SetupProperties(const Importer* pImp) -{ - // Get value of AI_CONFIG_PP_OG_EXCLUDE_LIST - std::string tmp = pImp->GetPropertyString(AI_CONFIG_PP_OG_EXCLUDE_LIST,""); - AddLockedNodeList(tmp); -} - -// ------------------------------------------------------------------------------------------------ -// Collect new children -void OptimizeGraphProcess::CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes) -{ - nodes_in += nd->mNumChildren; - - // Process children - std::list<aiNode*> child_nodes; - for (unsigned int i = 0; i < nd->mNumChildren; ++i) { - - CollectNewChildren(nd->mChildren[i],child_nodes); - nd->mChildren[i] = NULL; - } - - // Check whether we need this node; if not we can replace it by our own children (warn, danger of incest). - if (locked.find(AI_OG_GETKEY(nd->mName)) == locked.end() ) { - for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) { - - if (locked.find(AI_OG_GETKEY((*it)->mName)) == locked.end()) { - (*it)->mTransformation = nd->mTransformation * (*it)->mTransformation; - nodes.push_back(*it); - - it = child_nodes.erase(it); - continue; - } - ++it; - } - - if (nd->mNumMeshes || child_nodes.size()) { - nodes.push_back(nd); - } - else { - delete nd; /* bye, node */ - return; - } - } - else { - - // Retain our current position in the hierarchy - nodes.push_back(nd); - - // Now check for possible optimizations in our list of child nodes. join as many as possible - aiNode* join_master = NULL; - aiMatrix4x4 inv; - - const LockedSetType::const_iterator end = locked.end(); - - std::list<aiNode*> join; - for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end();) { - aiNode* child = *it; - if (child->mNumChildren == 0 && locked.find(AI_OG_GETKEY(child->mName)) == end) { - - // There may be no instanced meshes - unsigned int n = 0; - for (; n < child->mNumMeshes;++n) { - if (meshes[child->mMeshes[n]] > 1) { - break; - } - } - if (n == child->mNumMeshes) { - - if (!join_master) { - join_master = child; - inv = join_master->mTransformation; - inv.Inverse(); - } - else { - - child->mTransformation = inv * child->mTransformation ; - - join.push_back(child); - it = child_nodes.erase(it); - continue; - } - } - } - ++it; - } - if (join_master && join.size()) { - join_master->mName.length = sprintf(join_master->mName.data,"$MergedNode_%i",count_merged++); - - unsigned int out_meshes = 0; - for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) { - out_meshes += (*it)->mNumMeshes; - } - - // copy all mesh references in one array - if (out_meshes) { - unsigned int* meshes = new unsigned int[out_meshes+join_master->mNumMeshes], *tmp = meshes; - for (unsigned int n = 0; n < join_master->mNumMeshes;++n) { - *tmp++ = join_master->mMeshes[n]; - } - - for (std::list<aiNode*>::iterator it = join.begin(); it != join.end(); ++it) { - for (unsigned int n = 0; n < (*it)->mNumMeshes; ++n) { - - *tmp = (*it)->mMeshes[n]; - aiMesh* mesh = mScene->mMeshes[*tmp++]; - - // manually move the mesh into the right coordinate system - const aiMatrix3x3 IT = aiMatrix3x3( (*it)->mTransformation ).Inverse().Transpose(); - for (unsigned int a = 0; a < mesh->mNumVertices; ++a) { - - mesh->mVertices[a] *= (*it)->mTransformation; - - if (mesh->HasNormals()) - mesh->mNormals[a] *= IT; - - if (mesh->HasTangentsAndBitangents()) { - mesh->mTangents[a] *= IT; - mesh->mBitangents[a] *= IT; - } - } - } - delete *it; // bye, node - } - delete[] join_master->mMeshes; - join_master->mMeshes = meshes; - join_master->mNumMeshes += out_meshes; - } - } - } - // reassign children if something changed - if (child_nodes.empty() || child_nodes.size() > nd->mNumChildren) { - - delete[] nd->mChildren; - - if (child_nodes.size()) - nd->mChildren = new aiNode*[child_nodes.size()]; - else nd->mChildren = NULL; - } - - nd->mNumChildren = child_nodes.size(); - - aiNode** tmp = nd->mChildren; - for (std::list<aiNode*>::iterator it = child_nodes.begin(); it != child_nodes.end(); ++it) { - aiNode* node = *tmp++ = *it; - node->mParent = nd; - } - - nodes_out += child_nodes.size(); -} - -// ------------------------------------------------------------------------------------------------ -// Execute the postprocessing step on the given scene -void OptimizeGraphProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("OptimizeGraphProcess begin"); - nodes_in = nodes_out = count_merged = 0; - mScene = pScene; - - meshes.resize(pScene->mNumMeshes,0); - FindInstancedMeshes(pScene->mRootNode); - - // build a blacklist of identifiers. If the name of a node matches one of these, we won't touch it - locked.clear(); - for (std::list<std::string>::const_iterator it = locked_nodes.begin(); it != locked_nodes.end(); ++it) { -#ifdef AI_OG_USE_HASHING - locked.insert(SuperFastHash((*it).c_str())); -#else - locked.insert(*it); -#endif - } - - for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) { - for (unsigned int a = 0; a < pScene->mAnimations[i]->mNumChannels; ++a) { - - aiNodeAnim* anim = pScene->mAnimations[i]->mChannels[a]; - locked.insert(AI_OG_GETKEY(anim->mNodeName)); - } - } - - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - for (unsigned int a = 0; a < pScene->mMeshes[i]->mNumBones; ++a) { - - aiBone* bone = pScene->mMeshes[i]->mBones[a]; - locked.insert(AI_OG_GETKEY(bone->mName)); - - // HACK: Meshes referencing bones may not be transformed; we need to look them. - // The easiest way to do this is to increase their reference counters ... - meshes[i] += 2; - } - } - - for (unsigned int i = 0; i < pScene->mNumCameras; ++i) { - aiCamera* cam = pScene->mCameras[i]; - locked.insert(AI_OG_GETKEY(cam->mName)); - } - - for (unsigned int i = 0; i < pScene->mNumLights; ++i) { - aiLight* lgh = pScene->mLights[i]; - locked.insert(AI_OG_GETKEY(lgh->mName)); - } - - // Insert a dummy master node and make it read-only - aiNode* dummy_root = new aiNode(AI_RESERVED_NODE_NAME); - locked.insert(AI_OG_GETKEY(dummy_root->mName)); - - const aiString prev = pScene->mRootNode->mName; - pScene->mRootNode->mParent = dummy_root; - - dummy_root->mChildren = new aiNode*[dummy_root->mNumChildren = 1]; - dummy_root->mChildren[0] = pScene->mRootNode; - - // Do our recursive processing of scenegraph nodes. For each node collect - // a fully new list of children and allow their children to place themselves - // on the same hierarchy layer as their parents. - std::list<aiNode*> nodes; - CollectNewChildren (dummy_root,nodes); - - ai_assert(nodes.size() == 1); - - if (dummy_root->mNumChildren > 1) { - pScene->mRootNode = dummy_root; - - // Keep the dummy node but assign the name of the old root node to it - pScene->mRootNode->mName = prev; - } - else { - - // Remove the dummy root node again. - pScene->mRootNode = dummy_root->mChildren[0]; - - dummy_root->mChildren[0] = NULL; - delete dummy_root; - } - - pScene->mRootNode->mParent = NULL; - if (!DefaultLogger::isNullLogger()) { - if ( nodes_in != nodes_out) { - - char buf[512]; - sprintf(buf,"OptimizeGraphProcess finished; Input nodes: %i, Output nodes: %i",nodes_in,nodes_out); - DefaultLogger::get()->info(buf); - } - else DefaultLogger::get()->debug("OptimizeGraphProcess finished"); - } - meshes.clear(); - locked.clear(); -} - -// ------------------------------------------------------------------------------------------------ -// Buidl a LUT of all instanced meshes -void OptimizeGraphProcess::FindInstancedMeshes (aiNode* pNode) -{ - for (unsigned int i = 0; i < pNode->mNumMeshes;++i) { - ++meshes[pNode->mMeshes[i]]; - } - - for (unsigned int i = 0; i < pNode->mNumChildren; ++i) - FindInstancedMeshes(pNode->mChildren[i]); -} - -#endif // !! ASSIMP_BUILD_NO_OPTIMIZEGRAPH_PROCESS diff --git a/3rdparty/assimp/code/OptimizeGraph.h b/3rdparty/assimp/code/OptimizeGraph.h deleted file mode 100644 index c6d51dfe..00000000 --- a/3rdparty/assimp/code/OptimizeGraph.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OptimizeGraph.h - * @brief Declares a post processing step to optimize the scenegraph - */ -#ifndef AI_OPTIMIZEGRAPHPROCESS_H_INC -#define AI_OPTIMIZEGRAPHPROCESS_H_INC - -#include "BaseProcess.h" -#include "ProcessHelper.h" -#include "../include/aiTypes.h" - -struct aiMesh; -class OptimizeGraphProcessTest; -namespace Assimp { - -// ----------------------------------------------------------------------------- -/** @brief Postprocessing step to optimize the scenegraph - * - * The implementation tries to merge nodes, even if they use different - * transformations. Animations are preserved. - * - * @see aiProcess_OptimizeGraph for a detailed description of the - * algorithm being applied. - */ -class ASSIMP_API OptimizeGraphProcess : public BaseProcess -{ - friend class Importer; - friend class ::OptimizeGraphProcessTest; - -protected: - /** Constructor to be privately used by Importer */ - OptimizeGraphProcess(); - - /** Destructor, private as well */ - ~OptimizeGraphProcess(); - -public: - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - - - // ------------------------------------------------------------------- - /** @brief Add a list of node names to be locked and not modified. - * @param in List of nodes. See #AI_CONFIG_PP_OG_EXCLUDE_LIST for - * format explanations. - */ - inline void AddLockedNodeList(std::string& in) - { - ConvertListToStrings (in,locked_nodes); - } - - // ------------------------------------------------------------------- - /** @brief Add another node to be locked and not modified. - * @param name Name to be locked - */ - inline void AddLockedNode(std::string& name) - { - locked_nodes.push_back(name); - } - - // ------------------------------------------------------------------- - /** @brief Rmeove a node from the list of locked nodes. - * @param name Name to be unlocked - */ - inline void RemoveLockedNode(std::string& name) - { - locked_nodes.remove(name); - } - -protected: - - void CollectNewChildren(aiNode* nd, std::list<aiNode*>& nodes); - void FindInstancedMeshes (aiNode* pNode); - -private: - -#ifdef AI_OG_USE_HASHING - typedef std::set<unsigned int> LockedSetType; -#else - typedef std::set<std::string> LockedSetType; -#endif - - - //! Scene we're working with - aiScene* mScene; - - //! List of locked names. Stored is the hash of the name - LockedSetType locked; - - //! List of nodes to be locked in addition to those with animations, lights or cameras assigned. - std::list<std::string> locked_nodes; - - //! Node counters for logging purposes - unsigned int nodes_in,nodes_out, count_merged; - - //! Reference counters for meshes - std::vector<unsigned int> meshes; -}; - -} // end of namespace Assimp - -#endif // AI_OPTIMIZEGRAPHPROCESS_H_INC diff --git a/3rdparty/assimp/code/OptimizeMeshes.cpp b/3rdparty/assimp/code/OptimizeMeshes.cpp deleted file mode 100644 index ca612739..00000000 --- a/3rdparty/assimp/code/OptimizeMeshes.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OptimizeMeshes.cpp - * @brief Implementation of the aiProcess_OptimizeMeshes step - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS - -using namespace Assimp; -#include "OptimizeMeshes.h" -#include "ProcessHelper.h" -#include "SceneCombiner.h" - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -OptimizeMeshesProcess::OptimizeMeshesProcess() -: pts (false) -, max_verts (0xffffffff) -, max_faces (0xffffffff) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -OptimizeMeshesProcess::~OptimizeMeshesProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool OptimizeMeshesProcess::IsActive( unsigned int pFlags) const -{ - // Our behaviour needs to be different if the SortByPType or SplitLargeMeshes - // steps are active. Thus we need to query their flags here and store the - // information, although we're breaking const-correctness. - // That's a serious design flaw, consider redesign. - if ( 0 != (pFlags & aiProcess_OptimizeMeshes) ) { - pts = (0 != (pFlags & aiProcess_SortByPType)); - max_verts = (0 != (pFlags & aiProcess_SplitLargeMeshes)) ? 0xdeadbeef : 0; - return true; - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties for the postprocessing step -void OptimizeMeshesProcess::SetupProperties(const Importer* pImp) -{ - if (max_verts == 0xdeadbeef /* magic hack */) { - max_faces = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES); - max_verts = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES); - } -} - -// ------------------------------------------------------------------------------------------------ -// Execute step -void OptimizeMeshesProcess::Execute( aiScene* pScene) -{ - const unsigned int num_old = pScene->mNumMeshes; - if (num_old <= 1) { - DefaultLogger::get()->debug("Skipping OptimizeMeshesProcess"); - return; - } - - DefaultLogger::get()->debug("OptimizeMeshesProcess begin"); - mScene = pScene; - - // need to clear persistent members from previous runs - merge_list.clear(); - output.clear(); - - merge_list.reserve(pScene->mNumMeshes); - output.reserve(pScene->mNumMeshes); - - // Prepare lookup tables - meshes.resize(pScene->mNumMeshes); - FindInstancedMeshes(pScene->mRootNode); - if (max_verts == 0xdeadbeef) /* undo the magic hack */ - max_verts = 0xffffffff; - - // ... instanced meshes are immediately processed and added to the output list - for (unsigned int i = 0, n = 0; i < pScene->mNumMeshes;++i) { - meshes[i].vertex_format = GetMeshVFormatUnique(pScene->mMeshes[i]); - - if (meshes[i].instance_cnt > 1 && meshes[i].output_id == 0xffffffff) { - meshes[i].output_id = n++; - output.push_back(mScene->mMeshes[i]); - } - } - - // and process all nodes in the scenegraoh recursively - ProcessNode(pScene->mRootNode); - if (!output.size()) { - throw DeadlyImportError("OptimizeMeshes: No meshes remaining; there's definitely something wrong"); - } - - meshes.clear(); - ai_assert(output.size() <= num_old); - - mScene->mNumMeshes = output.size(); - std::copy(output.begin(),output.end(),mScene->mMeshes); - - if (output.size() != num_old) { - char tmp[512]; - ::sprintf(tmp,"OptimizeMeshesProcess finished. Input meshes: %i, Output meshes: %i",num_old,pScene->mNumMeshes); - DefaultLogger::get()->info(tmp); - } - else DefaultLogger::get()->debug("OptimizeMeshesProcess finished"); -} - -// ------------------------------------------------------------------------------------------------ -// Process meshes for a single node -void OptimizeMeshesProcess::ProcessNode( aiNode* pNode) -{ - for (unsigned int i = 0; i < pNode->mNumMeshes;++i) { - unsigned int& im = pNode->mMeshes[i]; - - if (meshes[im].instance_cnt > 1) { - im = meshes[im].output_id; - } - else { - merge_list.clear(); - unsigned int verts = 0, faces = 0; - - // Find meshes to merge with us - for (unsigned int a = i+1; a < pNode->mNumMeshes;++a) { - register unsigned int am = pNode->mMeshes[a]; - if (meshes[am].instance_cnt == 1 && CanJoin(im,am,verts,faces)) { - - merge_list.push_back(mScene->mMeshes[am]); - verts += mScene->mMeshes[am]->mNumVertices; - faces += mScene->mMeshes[am]->mNumFaces; - - --pNode->mNumMeshes; - for (unsigned int n = a; n < pNode->mNumMeshes; ++n) - pNode->mMeshes[n] = pNode->mMeshes[n+1]; - - --a; - } - } - - // and merge all meshes which we found, replace the old ones - if (!merge_list.empty()) { - merge_list.push_back(mScene->mMeshes[im]); - - aiMesh* out; - SceneCombiner::MergeMeshes(&out,0,merge_list.begin(),merge_list.end()); - output.push_back(out); - } - else { - output.push_back(mScene->mMeshes[im]); - } - im = output.size()-1; - } - } - - - for (unsigned int i = 0; i < pNode->mNumChildren; ++i) - ProcessNode(pNode->mChildren[i]); -} - -// ------------------------------------------------------------------------------------------------ -// Check whether two meshes can be joined -bool OptimizeMeshesProcess::CanJoin ( unsigned int a, unsigned int b, unsigned int verts, unsigned int faces ) -{ - if (meshes[a].vertex_format != meshes[b].vertex_format) - return false; - - aiMesh* ma = mScene->mMeshes[a], *mb = mScene->mMeshes[b]; - - if ((0xffffffff != max_verts && verts+mb->mNumVertices > max_verts) || - (0xffffffff != max_faces && faces+mb->mNumFaces > max_faces)) { - return false; - } - - // Never merge unskinned meshes with skinned meshes - if (ma->mMaterialIndex != mb->mMaterialIndex || ma->HasBones() != mb->HasBones()) - return false; - - // Never merge meshes with different kinds of primitives if SortByPType did already - // do its work. We would destroy everything again ... - if (pts && ma->mPrimitiveTypes != mb->mPrimitiveTypes) - return false; - - // If both meshes are skinned, check whether we have many bones defined in both meshes. - // If yes, we can savely join them. - if (ma->HasBones()) { - // TODO - return false; - } - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Buidl a LUT of all instanced meshes -void OptimizeMeshesProcess::FindInstancedMeshes (aiNode* pNode) -{ - for (unsigned int i = 0; i < pNode->mNumMeshes;++i) - ++meshes[pNode->mMeshes[i]].instance_cnt; - - for (unsigned int i = 0; i < pNode->mNumChildren; ++i) - FindInstancedMeshes(pNode->mChildren[i]); -} - -#endif // !! ASSIMP_BUILD_NO_OPTIMIZEMESHES_PROCESS diff --git a/3rdparty/assimp/code/OptimizeMeshes.h b/3rdparty/assimp/code/OptimizeMeshes.h deleted file mode 100644 index 406e9542..00000000 --- a/3rdparty/assimp/code/OptimizeMeshes.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 OptimizeMeshes.h - * @brief Declares a post processing step to join meshes, if possible - */ -#ifndef AI_OPTIMIZEMESHESPROCESS_H_INC -#define AI_OPTIMIZEMESHESPROCESS_H_INC - -#include "BaseProcess.h" -#include "../include/aiTypes.h" - -struct aiMesh; -class OptimizeMeshesProcessTest; -namespace Assimp { - -// --------------------------------------------------------------------------- -/** @brief Postprocessing step to optimize mesh usage - * - * The implementation looks for meshes that could be joined and joins them. - * Usually this will reduce the number of drawcalls. - * - * @note Instanced meshes are currently not processed. - */ -class ASSIMP_API OptimizeMeshesProcess : public BaseProcess -{ - friend class Importer; - friend class ::OptimizeMeshesProcessTest; - -protected: - /** Constructor to be privately used by Importer */ - OptimizeMeshesProcess(); - - /** Destructor, private as well */ - ~OptimizeMeshesProcess(); - - - /** @brief Internal utility to store additional mesh info - */ - struct MeshInfo - { - MeshInfo() - : instance_cnt (0) - , vertex_format (0) - , output_id (0xffffffff) - {} - - //! Number of times this mesh is referenced - unsigned int instance_cnt; - - //! Vertex format id - unsigned int vertex_format; - - //! Output ID - unsigned int output_id; - }; - -public: - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - - - // ------------------------------------------------------------------- - /** @brief Specify whether you want meshes with different - * primitive types to be merged as well. - * - * IsActive() sets this property automatically to true if the - * aiProcess_SortByPType flag is found. - */ - void EnablePrimitiveTypeSorting(bool enable) { - pts = enable; - } - - // Getter - bool IsPrimitiveTypeSortingEnabled () const { - return pts; - } - - - // ------------------------------------------------------------------- - /** @brief Specify a maximum size of a single output mesh. - * - * If a single input mesh already exceeds this limit, it won't - * be splitted. - * @param verts Maximum number of vertices per mesh - * @param faces Maximum number of faces per mesh - */ - void SetPreferredMeshSizeLimit (unsigned int verts, unsigned int faces) - { - max_verts = verts; - max_faces = faces; - } - - -protected: - - // ------------------------------------------------------------------- - /** @brief Do the actual optimization on all meshes of this node - * @param pNode Node we're working with - */ - void ProcessNode( aiNode* pNode); - - // ------------------------------------------------------------------- - /** @brief Returns true if b can be joined with a - * - * @param verts Number of output verts up to now - * @param faces Number of output faces up to now - */ - bool CanJoin ( unsigned int a, unsigned int b, - unsigned int verts, unsigned int faces ); - - // ------------------------------------------------------------------- - /** @brief Find instanced meshes, for the moment we're excluding - * them from all optimizations - */ - void FindInstancedMeshes (aiNode* pNode); - -private: - - //! Scene we're working with - aiScene* mScene; - - //! Per mesh info - std::vector<MeshInfo> meshes; - - //! Next output mesh - aiMesh* mesh; - - //! Output meshes - std::vector<aiMesh*> output; - - //! @see EnablePrimitiveTypeSorting - mutable bool pts; - - //! @see SetPreferredMeshSizeLimit - mutable unsigned int max_verts,max_faces; - - //! Temporary storage - std::vector<aiMesh*> merge_list; -}; - -} // end of namespace Assimp - -#endif // AI_CALCTANGENTSPROCESS_H_INC diff --git a/3rdparty/assimp/code/ParsingUtils.h b/3rdparty/assimp/code/ParsingUtils.h deleted file mode 100644 index 4cae6519..00000000 --- a/3rdparty/assimp/code/ParsingUtils.h +++ /dev/null @@ -1,181 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ParsingUtils.h - * @brief Defines helper functions for text parsing - */ -#ifndef AI_PARSING_UTILS_H_INC -#define AI_PARSING_UTILS_H_INC - -#include "StringComparison.h" -namespace Assimp { - -// --------------------------------------------------------------------------------- -template <class char_t> -AI_FORCE_INLINE bool IsSpace( const char_t in) -{ - return (in == (char_t)' ' || in == (char_t)'\t'); -} -// --------------------------------------------------------------------------------- -template <class char_t> -AI_FORCE_INLINE bool IsLineEnd( const char_t in) -{ - return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0'); -} -// --------------------------------------------------------------------------------- -template <class char_t> -AI_FORCE_INLINE bool IsSpaceOrNewLine( const char_t in) -{ - return IsSpace<char_t>(in) || IsLineEnd<char_t>(in); -} -// --------------------------------------------------------------------------------- -template <class char_t> -AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) -{ - while (*in == (char_t)' ' || *in == (char_t)'\t')in++; - *out = in; - return !IsLineEnd<char_t>(*in); -} -// --------------------------------------------------------------------------------- -template <class char_t> -AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) -{ - return SkipSpaces<char_t>(*inout,inout); -} -// --------------------------------------------------------------------------------- -template <class char_t> -inline bool SkipLine( const char_t* in, const char_t** out) -{ - while (*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0')in++; - - // files are opened in binary mode. Ergo there are both NL and CR - while (*in == (char_t)'\r' || *in == (char_t)'\n')in++; - *out = in; - return *in != (char_t)'\0'; -} -// --------------------------------------------------------------------------------- -template <class char_t> -inline bool SkipLine( const char_t** inout) -{ - return SkipLine<char_t>(*inout,inout); -} -// --------------------------------------------------------------------------------- -template <class char_t> -inline bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) -{ - while (*in == (char_t)' ' || *in == (char_t)'\t' || - *in == (char_t)'\r' || *in == (char_t)'\n')in++; - *out = in; - return *in != '\0'; -} -// --------------------------------------------------------------------------------- -template <class char_t> -inline bool SkipSpacesAndLineEnd( const char_t** inout) -{ - return SkipSpacesAndLineEnd<char_t>(*inout,inout); -} -// --------------------------------------------------------------------------------- -template <class char_t> -inline bool GetNextLine(const char_t*& buffer, char_t out[4096]) -{ - if ((char_t)'\0' == *buffer)return false; - - char* _out = out; - char* const end = _out+4096; - while (!IsLineEnd( *buffer ) && _out < end) - *_out++ = *buffer++; - *_out = (char_t)'\0'; - - while (IsLineEnd( *buffer ) && '\0' != *buffer)++buffer; - return true; -} -// --------------------------------------------------------------------------------- -template <class char_t> -AI_FORCE_INLINE bool IsNumeric( char_t in) -{ - return ( in >= '0' && in <= '9' ) || '-' == in || '+' == in; -} -// --------------------------------------------------------------------------------- -AI_FORCE_INLINE bool TokenMatch(char*& in, const char* token, unsigned int len) -{ - if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) - { - in += len+1; - return true; - } - return false; -} -// --------------------------------------------------------------------------------- -/** @brief Case-ignoring version of TokenMatch - * @param in Input - * @param token Token to check for - * @param len Number of characters to check - */ -AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len) -{ - if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) - { - in += len+1; - return true; - } - return false; -} -// --------------------------------------------------------------------------------- -AI_FORCE_INLINE bool TokenMatch(const char*& in, const char* token, unsigned int len) -{ - return TokenMatch(const_cast<char*&>(in), token, len); -} -// --------------------------------------------------------------------------------- -AI_FORCE_INLINE void SkipToken(const char*& in) -{ - SkipSpaces(&in); - while (!IsSpaceOrNewLine(*in))++in; -} -// --------------------------------------------------------------------------------- -AI_FORCE_INLINE std::string GetNextToken(const char*& in) -{ - SkipSpacesAndLineEnd(&in); - const char* cur = in; - while (!IsSpaceOrNewLine(*in))++in; - return std::string(cur,(size_t)(in-cur)); -} -} // ! namespace Assimp -#endif // ! AI_PARSING_UTILS_H_INC diff --git a/3rdparty/assimp/code/PlyLoader.cpp b/3rdparty/assimp/code/PlyLoader.cpp deleted file mode 100644 index 2c5dc4c9..00000000 --- a/3rdparty/assimp/code/PlyLoader.cpp +++ /dev/null @@ -1,1050 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 PlyLoader.cpp - * @brief Implementation of the PLY importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER - -// internal headers -#include "PlyLoader.h" -#include "MaterialSystem.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -PLYImporter::PLYImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -PLYImporter::~PLYImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool PLYImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - - if (extension == "ply") - return true; - else if (!extension.length() || checkSig) - { - if (!pIOHandler)return true; - const char* tokens[] = {"ply"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void PLYImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("ply"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void PLYImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open PLY file " + pFile + "."); - } - - // allocate storage and copy the contents of the file to a memory buffer - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - mBuffer = (unsigned char*)&mBuffer2[0]; - - // the beginning of the file must be PLY - magic, magic - if ((mBuffer[0] != 'P' && mBuffer[0] != 'p') || - (mBuffer[1] != 'L' && mBuffer[1] != 'l') || - (mBuffer[2] != 'Y' && mBuffer[2] != 'y')) { - throw DeadlyImportError( "Invalid .ply file: Magic number \'ply\' is no there"); - } - - char* szMe = (char*)&this->mBuffer[3]; - SkipSpacesAndLineEnd(szMe,(const char**)&szMe); - - // determine the format of the file data - PLY::DOM sPlyDom; - if (TokenMatch(szMe,"format",6)) - { - if (TokenMatch(szMe,"ascii",5)) - { - SkipLine(szMe,(const char**)&szMe); - if (!PLY::DOM::ParseInstance(szMe,&sPlyDom)) - throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#1)"); - } - else if (!::strncmp(szMe,"binary_",7)) - { - bool bIsBE = false; - szMe+=7; - - // binary_little_endian - // binary_big_endian -#if (defined AI_BUILD_BIG_ENDIAN) - if ('l' == *szMe || 'L' == *szMe)bIsBE = true; -#else - if ('b' == *szMe || 'B' == *szMe)bIsBE = true; -#endif // ! AI_BUILD_BIG_ENDIAN - - // skip the line, parse the rest of the header and build the DOM - SkipLine(szMe,(const char**)&szMe); - if (!PLY::DOM::ParseInstanceBinary(szMe,&sPlyDom,bIsBE)) - throw DeadlyImportError( "Invalid .ply file: Unable to build DOM (#2)"); - } - else throw DeadlyImportError( "Invalid .ply file: Unknown file format"); - } - else - { - delete[] this->mBuffer; - AI_DEBUG_INVALIDATE_PTR(this->mBuffer); - throw DeadlyImportError( "Invalid .ply file: Missing format specification"); - } - this->pcDOM = &sPlyDom; - - // now load a list of vertices. This must be sucessfull in order to procede - std::vector<aiVector3D> avPositions; - this->LoadVertices(&avPositions,false); - - if (avPositions.empty()) - throw DeadlyImportError( "Invalid .ply file: No vertices found. " - "Unable to parse the data format of the PLY file."); - - // now load a list of normals. - std::vector<aiVector3D> avNormals; - LoadVertices(&avNormals,true); - - // load the face list - std::vector<PLY::Face> avFaces; - LoadFaces(&avFaces); - - // if no face list is existing we assume that the vertex - // list is containing a list of triangles - if (avFaces.empty()) - { - if (avPositions.size() < 3) - { - throw DeadlyImportError( "Invalid .ply file: Not enough " - "vertices to build a proper face list. "); - } - - const unsigned int iNum = (unsigned int)avPositions.size() / 3; - for (unsigned int i = 0; i< iNum;++i) - { - PLY::Face sFace; - sFace.mIndices.push_back((iNum*3)); - sFace.mIndices.push_back((iNum*3)+1); - sFace.mIndices.push_back((iNum*3)+2); - avFaces.push_back(sFace); - } - } - - // now load a list of all materials - std::vector<MaterialHelper*> avMaterials; - LoadMaterial(&avMaterials); - - // now load a list of all vertex color channels - std::vector<aiColor4D> avColors; - avColors.reserve(avPositions.size()); - LoadVertexColor(&avColors); - - // now try to load texture coordinates - std::vector<aiVector2D> avTexCoords; - avTexCoords.reserve(avPositions.size()); - LoadTextureCoordinates(&avTexCoords); - - // now replace the default material in all faces and validate all material indices - ReplaceDefaultMaterial(&avFaces,&avMaterials); - - // now convert this to a list of aiMesh instances - std::vector<aiMesh*> avMeshes; - avMeshes.reserve(avMaterials.size()+1); - ConvertMeshes(&avFaces,&avPositions,&avNormals, - &avColors,&avTexCoords,&avMaterials,&avMeshes); - - if (avMeshes.empty()) - throw DeadlyImportError( "Invalid .ply file: Unable to extract mesh data "); - - // now generate the output scene object. Fill the material list - pScene->mNumMaterials = (unsigned int)avMaterials.size(); - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - pScene->mMaterials[i] = avMaterials[i]; - - // fill the mesh list - pScene->mNumMeshes = (unsigned int)avMeshes.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mMeshes[i] = avMeshes[i]; - - // generate a simple node structure - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; - pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; - - for (unsigned int i = 0; i < pScene->mRootNode->mNumMeshes;++i) - pScene->mRootNode->mMeshes[i] = i; -} - -// ------------------------------------------------------------------------------------------------ -// Split meshes by material IDs -void PLYImporter::ConvertMeshes(std::vector<PLY::Face>* avFaces, - const std::vector<aiVector3D>* avPositions, - const std::vector<aiVector3D>* avNormals, - const std::vector<aiColor4D>* avColors, - const std::vector<aiVector2D>* avTexCoords, - const std::vector<MaterialHelper*>* avMaterials, - std::vector<aiMesh*>* avOut) -{ - ai_assert(NULL != avFaces); - ai_assert(NULL != avPositions); - ai_assert(NULL != avMaterials); - - // split by materials - std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[avMaterials->size()]; - - unsigned int iNum = 0; - for (std::vector<PLY::Face>::const_iterator i = avFaces->begin();i != avFaces->end();++i,++iNum) - aiSplit[(*i).iMaterialIndex].push_back(iNum); - - // now generate submeshes - for (unsigned int p = 0; p < avMaterials->size();++p) - { - if (aiSplit[p].size() != 0) - { - // allocate the mesh object - aiMesh* p_pcOut = new aiMesh(); - p_pcOut->mMaterialIndex = p; - - p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size(); - p_pcOut->mFaces = new aiFace[aiSplit[p].size()]; - - // at first we need to determine the size of the output vector array - unsigned int iNum = 0; - for (unsigned int i = 0; i < aiSplit[p].size();++i) - { - iNum += (unsigned int)(*avFaces)[aiSplit[p][i]].mIndices.size(); - } - p_pcOut->mNumVertices = iNum; - p_pcOut->mVertices = new aiVector3D[iNum]; - - if (!avColors->empty()) - p_pcOut->mColors[0] = new aiColor4D[iNum]; - if (!avTexCoords->empty()) - { - p_pcOut->mNumUVComponents[0] = 2; - p_pcOut->mTextureCoords[0] = new aiVector3D[iNum]; - } - if (!avNormals->empty()) - p_pcOut->mNormals = new aiVector3D[iNum]; - - // add all faces - iNum = 0; - unsigned int iVertex = 0; - for (std::vector<unsigned int>::const_iterator i = aiSplit[p].begin(); - i != aiSplit[p].end();++i,++iNum) - { - p_pcOut->mFaces[iNum].mNumIndices = (unsigned int)(*avFaces)[*i].mIndices.size(); - p_pcOut->mFaces[iNum].mIndices = new unsigned int[p_pcOut->mFaces[iNum].mNumIndices]; - - // build an unique set of vertices/colors for this face - for (unsigned int q = 0; q < p_pcOut->mFaces[iNum].mNumIndices;++q) - { - p_pcOut->mFaces[iNum].mIndices[q] = iVertex; - p_pcOut->mVertices[iVertex] = (*avPositions)[(*avFaces)[*i].mIndices[q]]; - - if (!avColors->empty()) - p_pcOut->mColors[0][iVertex] = (*avColors)[(*avFaces)[*i].mIndices[q]]; - - if (!avTexCoords->empty()) - { - const aiVector2D& vec = (*avTexCoords)[(*avFaces)[*i].mIndices[q]]; - p_pcOut->mTextureCoords[0][iVertex].x = vec.x; - p_pcOut->mTextureCoords[0][iVertex].y = vec.y; - } - - if (!avNormals->empty()) - p_pcOut->mNormals[iVertex] = (*avNormals)[(*avFaces)[*i].mIndices[q]]; - iVertex++; - } - - } - // add the mesh to the output list - avOut->push_back(p_pcOut); - } - } - delete[] aiSplit; // cleanup -} - -// ------------------------------------------------------------------------------------------------ -// Generate a default material if none was specified and apply it to all vanilla faces -void PLYImporter::ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces, - std::vector<MaterialHelper*>* avMaterials) -{ - bool bNeedDefaultMat = false; - - for (std::vector<PLY::Face>::iterator i = avFaces->begin();i != avFaces->end();++i) { - if (0xFFFFFFFF == (*i).iMaterialIndex) { - bNeedDefaultMat = true; - (*i).iMaterialIndex = (unsigned int)avMaterials->size(); - } - else if ((*i).iMaterialIndex >= avMaterials->size() ) { - // clamp the index - (*i).iMaterialIndex = (unsigned int)avMaterials->size()-1; - } - } - - if (bNeedDefaultMat) { - // generate a default material - MaterialHelper* pcHelper = new MaterialHelper(); - - // fill in a default material - int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor3D clr; - clr.b = clr.g = clr.r = 0.6f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - // The face order is absolutely undefined for PLY, so we have to - // use two-sided rendering to be sure it's ok. - const int two_sided = 1; - pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED); - - avMaterials->push_back(pcHelper); - } -} - -// ------------------------------------------------------------------------------------------------ -void PLYImporter::LoadTextureCoordinates(std::vector<aiVector2D>* pvOut) -{ - ai_assert(NULL != pvOut); - - unsigned int aiPositions[2] = {0xFFFFFFFF,0xFFFFFFFF}; - PLY::EDataType aiTypes[2] = {EDT_Char,EDT_Char}; - PLY::ElementInstanceList* pcList = NULL; - unsigned int cnt = 0; - - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Vertex == (*i).eSemantic) - { - pcList = &this->pcDOM->alElementData[_i]; - - // now check whether which normal components are available - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_UTextureCoord == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_VTextureCoord == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - } - } - } - // check whether we have a valid source for the texture coordinates data - if (NULL != pcList && 0 != cnt) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - // convert the vertices to sp floats - aiVector2D vOut; - - if (0xFFFFFFFF != aiPositions[0]) - { - vOut.x = PLY::PropertyInstance::ConvertTo<float>( - (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]); - } - - if (0xFFFFFFFF != aiPositions[1]) - { - vOut.y = PLY::PropertyInstance::ConvertTo<float>( - (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]); - } - // and add them to our nice list - pvOut->push_back(vOut); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Try to extract vertices from the PLY DOM -void PLYImporter::LoadVertices(std::vector<aiVector3D>* pvOut, bool p_bNormals) -{ - ai_assert(NULL != pvOut); - - unsigned int aiPositions[3] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; - PLY::EDataType aiTypes[3] = {EDT_Char,EDT_Char,EDT_Char}; - PLY::ElementInstanceList* pcList = NULL; - unsigned int cnt = 0; - - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Vertex == (*i).eSemantic) - { - pcList = &pcDOM->alElementData[_i]; - - // load normal vectors? - if (p_bNormals) - { - // now check whether which normal components are available - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_XNormal == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_YNormal == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - else if (PLY::EST_ZNormal == (*a).Semantic) - { - cnt++; - aiPositions[2] = _a; - aiTypes[2] = (*a).eType; - } - } - } - // load vertex coordinates - else - { - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_XCoord == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_YCoord == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - else if (PLY::EST_ZCoord == (*a).Semantic) - { - cnt++; - aiPositions[2] = _a; - aiTypes[2] = (*a).eType; - } - if (3 == cnt)break; - } - } - break; - } - } - // check whether we have a valid source for the vertex data - if (NULL != pcList && 0 != cnt) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector<ElementInstance>::const_iterator - i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - // convert the vertices to sp floats - aiVector3D vOut; - - if (0xFFFFFFFF != aiPositions[0]) - { - vOut.x = PLY::PropertyInstance::ConvertTo<float>( - (*i).alProperties[aiPositions[0]].avList.front(),aiTypes[0]); - } - - if (0xFFFFFFFF != aiPositions[1]) - { - vOut.y = PLY::PropertyInstance::ConvertTo<float>( - (*i).alProperties[aiPositions[1]].avList.front(),aiTypes[1]); - } - - if (0xFFFFFFFF != aiPositions[2]) - { - vOut.z = PLY::PropertyInstance::ConvertTo<float>( - (*i).alProperties[aiPositions[2]].avList.front(),aiTypes[2]); - } - - // and add them to our nice list - pvOut->push_back(vOut); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Convert a color component to [0...1] -float PLYImporter::NormalizeColorValue (PLY::PropertyInstance::ValueUnion val, - PLY::EDataType eType) -{ - switch (eType) - { - case EDT_Float: - return val.fFloat; - case EDT_Double: - return (float)val.fDouble; - - case EDT_UChar: - return (float)val.iUInt / (float)0xFF; - case EDT_Char: - return (float)(val.iInt+(0xFF/2)) / (float)0xFF; - case EDT_UShort: - return (float)val.iUInt / (float)0xFFFF; - case EDT_Short: - return (float)(val.iInt+(0xFFFF/2)) / (float)0xFFFF; - case EDT_UInt: - return (float)val.iUInt / (float)0xFFFF; - case EDT_Int: - return ((float)val.iInt / (float)0xFF) + 0.5f; - default: ; - }; - return 0.0f; -} - -// ------------------------------------------------------------------------------------------------ -// Try to extract proper vertex colors from the PLY DOM -void PLYImporter::LoadVertexColor(std::vector<aiColor4D>* pvOut) -{ - ai_assert(NULL != pvOut); - - unsigned int aiPositions[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; - PLY::EDataType aiTypes[4] = {EDT_Char, EDT_Char, EDT_Char, EDT_Char}; // silencing gcc - unsigned int cnt = 0; - PLY::ElementInstanceList* pcList = NULL; - - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Vertex == (*i).eSemantic) - { - pcList = &this->pcDOM->alElementData[_i]; - - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - if (PLY::EST_Red == (*a).Semantic) - { - cnt++; - aiPositions[0] = _a; - aiTypes[0] = (*a).eType; - } - else if (PLY::EST_Green == (*a).Semantic) - { - cnt++; - aiPositions[1] = _a; - aiTypes[1] = (*a).eType; - } - else if (PLY::EST_Blue == (*a).Semantic) - { - cnt++; - aiPositions[2] = _a; - aiTypes[2] = (*a).eType; - } - else if (PLY::EST_Alpha == (*a).Semantic) - { - cnt++; - aiPositions[3] = _a; - aiTypes[3] = (*a).eType; - } - if (4 == cnt)break; - } - break; - } - } - // check whether we have a valid source for the vertex data - if (NULL != pcList && 0 != cnt) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - // convert the vertices to sp floats - aiColor4D vOut; - - if (0xFFFFFFFF != aiPositions[0]) - { - vOut.r = NormalizeColorValue((*i).alProperties[ - aiPositions[0]].avList.front(),aiTypes[0]); - } - - if (0xFFFFFFFF != aiPositions[1]) - { - vOut.g = NormalizeColorValue((*i).alProperties[ - aiPositions[1]].avList.front(),aiTypes[1]); - } - - if (0xFFFFFFFF != aiPositions[2]) - { - vOut.b = NormalizeColorValue((*i).alProperties[ - aiPositions[2]].avList.front(),aiTypes[2]); - } - - // assume 1.0 for the alpha channel ifit is not set - if (0xFFFFFFFF == aiPositions[3])vOut.a = 1.0f; - else - { - vOut.a = NormalizeColorValue((*i).alProperties[ - aiPositions[3]].avList.front(),aiTypes[3]); - } - - // and add them to our nice list - pvOut->push_back(vOut); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Try to extract proper faces from the PLY DOM -void PLYImporter::LoadFaces(std::vector<PLY::Face>* pvOut) -{ - ai_assert(NULL != pvOut); - - PLY::ElementInstanceList* pcList = NULL; - bool bOne = false; - - // index of the vertex index list - unsigned int iProperty = 0xFFFFFFFF; - PLY::EDataType eType = EDT_Char; - bool bIsTristrip = false; - - // index of the material index property - unsigned int iMaterialIndex = 0xFFFFFFFF; - PLY::EDataType eType2 = EDT_Char; - - // serach in the DOM for a face entry - unsigned int _i = 0; - for (std::vector<PLY::Element>::const_iterator i = pcDOM->alElements.begin(); - i != pcDOM->alElements.end();++i,++_i) - { - // face = unique number of vertex indices - if (PLY::EEST_Face == (*i).eSemantic) - { - pcList = &pcDOM->alElementData[_i]; - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if (PLY::EST_VertexIndex == (*a).Semantic) - { - // must be a dynamic list! - if (!(*a).bIsList)continue; - iProperty = _a; - bOne = true; - eType = (*a).eType; - } - else if (PLY::EST_MaterialIndex == (*a).Semantic) - { - if ((*a).bIsList)continue; - iMaterialIndex = _a; - bOne = true; - eType2 = (*a).eType; - } - } - break; - } - // triangle strip - // TODO: triangle strip and material index support??? - else if (PLY::EEST_TriStrip == (*i).eSemantic) - { - // find a list property in this ... - pcList = &this->pcDOM->alElementData[_i]; - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - // must be a dynamic list! - if (!(*a).bIsList)continue; - iProperty = _a; - bOne = true; - bIsTristrip = true; - eType = (*a).eType; - break; - } - break; - } - } - // check whether we have at least one per-face information set - if (pcList && bOne) - { - if (!bIsTristrip) - { - pvOut->reserve(pcList->alInstances.size()); - for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { - PLY::Face sFace; - - // parse the list of vertex indices - if (0xFFFFFFFF != iProperty) - { - const unsigned int iNum = (unsigned int)(*i).alProperties[iProperty].avList.size(); - sFace.mIndices.resize(iNum); - - std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = - (*i).alProperties[iProperty].avList.begin(); - - for (unsigned int a = 0; a < iNum;++a,++p) - { - sFace.mIndices[a] = PLY::PropertyInstance::ConvertTo<unsigned int>(*p,eType); - } - } - - // parse the material index - if (0xFFFFFFFF != iMaterialIndex) - { - sFace.iMaterialIndex = PLY::PropertyInstance::ConvertTo<unsigned int>( - (*i).alProperties[iMaterialIndex].avList.front(),eType2); - } - pvOut->push_back(sFace); - } - } - else // triangle strips - { - // normally we have only one triangle strip instance where - // a value of -1 indicates a restart of the strip - bool flip = false; - for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) { - const std::vector<PLY::PropertyInstance::ValueUnion>& quak = (*i).alProperties[iProperty].avList; - pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); - - int aiTable[2] = {-1,-1}; - for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin();a != quak.end();++a) { - const int p = PLY::PropertyInstance::ConvertTo<int>(*a,eType); - - if (-1 == p) { - // restart the strip ... - aiTable[0] = aiTable[1] = -1; - flip = false; - continue; - } - if (-1 == aiTable[0]) { - aiTable[0] = p; - continue; - } - if (-1 == aiTable[1]) { - aiTable[1] = p; - continue; - } - - pvOut->push_back(PLY::Face()); - PLY::Face& sFace = pvOut->back(); - sFace.mIndices[0] = aiTable[0]; - sFace.mIndices[1] = aiTable[1]; - sFace.mIndices[2] = p; - if ((flip = !flip)) { - std::swap(sFace.mIndices[0],sFace.mIndices[1]); - } - - aiTable[0] = aiTable[1]; - aiTable[1] = p; - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Get a RGBA color in [0...1] range -void PLYImporter::GetMaterialColor(const std::vector<PLY::PropertyInstance>& avList, - unsigned int aiPositions[4], - PLY::EDataType aiTypes[4], - aiColor4D* clrOut) -{ - ai_assert(NULL != clrOut); - - if (0xFFFFFFFF == aiPositions[0])clrOut->r = 0.0f; - else - { - clrOut->r = NormalizeColorValue(avList[ - aiPositions[0]].avList.front(),aiTypes[0]); - } - - if (0xFFFFFFFF == aiPositions[1])clrOut->g = 0.0f; - else - { - clrOut->g = NormalizeColorValue(avList[ - aiPositions[1]].avList.front(),aiTypes[1]); - } - - if (0xFFFFFFFF == aiPositions[2])clrOut->b = 0.0f; - else - { - clrOut->b = NormalizeColorValue(avList[ - aiPositions[2]].avList.front(),aiTypes[2]); - } - - // assume 1.0 for the alpha channel ifit is not set - if (0xFFFFFFFF == aiPositions[3])clrOut->a = 1.0f; - else - { - clrOut->a = NormalizeColorValue(avList[ - aiPositions[3]].avList.front(),aiTypes[3]); - } -} - -// ------------------------------------------------------------------------------------------------ -// Extract a material from the PLY DOM -void PLYImporter::LoadMaterial(std::vector<MaterialHelper*>* pvOut) -{ - ai_assert(NULL != pvOut); - - // diffuse[4], specular[4], ambient[4] - // rgba order - unsigned int aaiPositions[3][4] = { - - {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, - {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, - {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}, - }; - - PLY::EDataType aaiTypes[3][4] = { - {EDT_Char,EDT_Char,EDT_Char,EDT_Char}, - {EDT_Char,EDT_Char,EDT_Char,EDT_Char}, - {EDT_Char,EDT_Char,EDT_Char,EDT_Char} - }; - PLY::ElementInstanceList* pcList = NULL; - - unsigned int iPhong = 0xFFFFFFFF; - PLY::EDataType ePhong = EDT_Char; - - unsigned int iOpacity = 0xFFFFFFFF; - PLY::EDataType eOpacity = EDT_Char; - - // serach in the DOM for a vertex entry - unsigned int _i = 0; - for (std::vector<PLY::Element>::const_iterator i = this->pcDOM->alElements.begin(); - i != this->pcDOM->alElements.end();++i,++_i) - { - if (PLY::EEST_Material == (*i).eSemantic) - { - pcList = &this->pcDOM->alElementData[_i]; - - // now check whether which coordinate sets are available - unsigned int _a = 0; - for (std::vector<PLY::Property>::const_iterator - a = (*i).alProperties.begin(); - a != (*i).alProperties.end();++a,++_a) - { - if ((*a).bIsList)continue; - - // pohng specularity ----------------------------------- - if (PLY::EST_PhongPower == (*a).Semantic) - { - iPhong = _a; - ePhong = (*a).eType; - } - - // general opacity ----------------------------------- - if (PLY::EST_Opacity == (*a).Semantic) - { - iOpacity = _a; - eOpacity = (*a).eType; - } - - // diffuse color channels ----------------------------------- - if (PLY::EST_DiffuseRed == (*a).Semantic) - { - aaiPositions[0][0] = _a; - aaiTypes[0][0] = (*a).eType; - } - else if (PLY::EST_DiffuseGreen == (*a).Semantic) - { - aaiPositions[0][1] = _a; - aaiTypes[0][1] = (*a).eType; - } - else if (PLY::EST_DiffuseBlue == (*a).Semantic) - { - aaiPositions[0][2] = _a; - aaiTypes[0][2] = (*a).eType; - } - else if (PLY::EST_DiffuseAlpha == (*a).Semantic) - { - aaiPositions[0][3] = _a; - aaiTypes[0][3] = (*a).eType; - } - // specular color channels ----------------------------------- - else if (PLY::EST_SpecularRed == (*a).Semantic) - { - aaiPositions[1][0] = _a; - aaiTypes[1][0] = (*a).eType; - } - else if (PLY::EST_SpecularGreen == (*a).Semantic) - { - aaiPositions[1][1] = _a; - aaiTypes[1][1] = (*a).eType; - } - else if (PLY::EST_SpecularBlue == (*a).Semantic) - { - aaiPositions[1][2] = _a; - aaiTypes[1][2] = (*a).eType; - } - else if (PLY::EST_SpecularAlpha == (*a).Semantic) - { - aaiPositions[1][3] = _a; - aaiTypes[1][3] = (*a).eType; - } - // ambient color channels ----------------------------------- - else if (PLY::EST_AmbientRed == (*a).Semantic) - { - aaiPositions[2][0] = _a; - aaiTypes[2][0] = (*a).eType; - } - else if (PLY::EST_AmbientGreen == (*a).Semantic) - { - aaiPositions[2][1] = _a; - aaiTypes[2][1] = (*a).eType; - } - else if (PLY::EST_AmbientBlue == (*a).Semantic) - { - aaiPositions[2][2] = _a; - aaiTypes[2][2] = (*a).eType; - } - else if (PLY::EST_AmbientAlpha == (*a).Semantic) - { - aaiPositions[2][3] = _a; - aaiTypes[2][3] = (*a).eType; - } - } - break; - } - } - // check whether we have a valid source for the material data - if (NULL != pcList) { - for (std::vector<ElementInstance>::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) { - aiColor4D clrOut; - MaterialHelper* pcHelper = new MaterialHelper(); - - // build the diffuse material color - GetMaterialColor((*i).alProperties,aaiPositions[0],aaiTypes[0],&clrOut); - pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_DIFFUSE); - - // build the specular material color - GetMaterialColor((*i).alProperties,aaiPositions[1],aaiTypes[1],&clrOut); - pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_SPECULAR); - - // build the ambient material color - GetMaterialColor((*i).alProperties,aaiPositions[2],aaiTypes[2],&clrOut); - pcHelper->AddProperty<aiColor4D>(&clrOut,1,AI_MATKEY_COLOR_AMBIENT); - - // handle phong power and shading mode - int iMode; - if (0xFFFFFFFF != iPhong) { - float fSpec = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),ePhong); - - // if shininess is 0 (and the pow() calculation would therefore always - // become 1, not depending on the angle), use gouraud lighting - if (fSpec) { - // scale this with 15 ... hopefully this is correct - fSpec *= 15; - pcHelper->AddProperty<float>(&fSpec, 1, AI_MATKEY_SHININESS); - - iMode = (int)aiShadingMode_Phong; - } - else iMode = (int)aiShadingMode_Gouraud; - } - else iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - // handle opacity - if (0xFFFFFFFF != iOpacity) { - float fOpacity = PLY::PropertyInstance::ConvertTo<float>((*i).alProperties[iPhong].avList.front(),eOpacity); - pcHelper->AddProperty<float>(&fOpacity, 1, AI_MATKEY_OPACITY); - } - - // The face order is absolutely undefined for PLY, so we have to - // use two-sided rendering to be sure it's ok. - const int two_sided = 1; - pcHelper->AddProperty(&two_sided,1,AI_MATKEY_TWOSIDED); - - // add the newly created material instance to the list - pvOut->push_back(pcHelper); - } - } -} - -#endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/3rdparty/assimp/code/PlyLoader.h b/3rdparty/assimp/code/PlyLoader.h deleted file mode 100644 index 3cdfb5e1..00000000 --- a/3rdparty/assimp/code/PlyLoader.h +++ /dev/null @@ -1,174 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 PLYLoader.h - * @brief Declaration of the .ply importer class. - */ -#ifndef AI_PLYLOADER_H_INCLUDED -#define AI_PLYLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" - -struct aiNode; - -#include "PlyParser.h" - -namespace Assimp { -class MaterialHelper; - -using namespace PLY; - -// --------------------------------------------------------------------------- -/** Importer class to load the stanford PLY file format -*/ -class PLYImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - PLYImporter(); - - /** Destructor, private as well */ - ~PLYImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - - - // ------------------------------------------------------------------- - /** Extract vertices from the DOM - */ - void LoadVertices(std::vector<aiVector3D>* pvOut, - bool p_bNormals = false); - - // ------------------------------------------------------------------- - /** Extract vertex color channels from the DOM - */ - void LoadVertexColor(std::vector<aiColor4D>* pvOut); - - // ------------------------------------------------------------------- - /** Extract texture coordinate channels from the DOM - */ - void LoadTextureCoordinates(std::vector<aiVector2D>* pvOut); - - // ------------------------------------------------------------------- - /** Extract a face list from the DOM - */ - void LoadFaces(std::vector<PLY::Face>* pvOut); - - // ------------------------------------------------------------------- - /** Extract a material list from the DOM - */ - void LoadMaterial(std::vector<MaterialHelper*>* pvOut); - - - // ------------------------------------------------------------------- - /** Validate material indices, replace default material identifiers - */ - void ReplaceDefaultMaterial(std::vector<PLY::Face>* avFaces, - std::vector<MaterialHelper*>* avMaterials); - - - // ------------------------------------------------------------------- - /** Convert all meshes into our ourer representation - */ - void ConvertMeshes(std::vector<PLY::Face>* avFaces, - const std::vector<aiVector3D>* avPositions, - const std::vector<aiVector3D>* avNormals, - const std::vector<aiColor4D>* avColors, - const std::vector<aiVector2D>* avTexCoords, - const std::vector<MaterialHelper*>* avMaterials, - std::vector<aiMesh*>* avOut); - - - // ------------------------------------------------------------------- - /** Static helper to parse a color from four single channels in - */ - static void GetMaterialColor( - const std::vector<PLY::PropertyInstance>& avList, - unsigned int aiPositions[4], - PLY::EDataType aiTypes[4], - aiColor4D* clrOut); - - - // ------------------------------------------------------------------- - /** Static helper to parse a color channel value. The input value - * is normalized to 0-1. - */ - static float NormalizeColorValue ( - PLY::PropertyInstance::ValueUnion val, - PLY::EDataType eType); - - - /** Buffer to hold the loaded file */ - unsigned char* mBuffer; - - /** Document object model representation extracted from the file */ - PLY::DOM* pcDOM; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_INC diff --git a/3rdparty/assimp/code/PlyParser.cpp b/3rdparty/assimp/code/PlyParser.cpp deleted file mode 100644 index d0e3fa0f..00000000 --- a/3rdparty/assimp/code/PlyParser.cpp +++ /dev/null @@ -1,919 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 PLY parser class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_PLY_IMPORTER - -#include "PlyLoader.h" -#include "fast_atof.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -PLY::EDataType PLY::Property::ParseDataType(const char* pCur,const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - PLY::EDataType eOut = PLY::EDT_INVALID; - - if (TokenMatch(pCur,"char",4) || - TokenMatch(pCur,"int8",4)) - { - eOut = PLY::EDT_Char; - } - else if (TokenMatch(pCur,"uchar",5) || - TokenMatch(pCur,"uint8",5)) - { - eOut = PLY::EDT_UChar; - } - else if (TokenMatch(pCur,"short",5) || - TokenMatch(pCur,"int16",5)) - { - eOut = PLY::EDT_Short; - } - else if (TokenMatch(pCur,"ushort",6) || - TokenMatch(pCur,"uint16",6)) - { - eOut = PLY::EDT_UShort; - } - else if (TokenMatch(pCur,"int32",5) || TokenMatch(pCur,"int",3)) - { - eOut = PLY::EDT_Int; - } - else if (TokenMatch(pCur,"uint32",6) || TokenMatch(pCur,"uint",4)) - { - eOut = PLY::EDT_UInt; - } - else if (TokenMatch(pCur,"float",5) || TokenMatch(pCur,"float32",7)) - { - eOut = PLY::EDT_Float; - } - else if (TokenMatch(pCur,"double64",8) || TokenMatch(pCur,"double",6) || - TokenMatch(pCur,"float64",7)) - { - eOut = PLY::EDT_Double; - } - if (PLY::EDT_INVALID == eOut) - { - DefaultLogger::get()->info("Found unknown data type in PLY file. This is OK"); - } - *pCurOut = pCur; - return eOut; -} - -// ------------------------------------------------------------------------------------------------ -PLY::ESemantic PLY::Property::ParseSemantic(const char* pCur,const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - - PLY::ESemantic eOut = PLY::EST_INVALID; - if (TokenMatch(pCur,"red",3)) - { - eOut = PLY::EST_Red; - } - else if (TokenMatch(pCur,"green",5)) - { - eOut = PLY::EST_Green; - } - else if (TokenMatch(pCur,"blue",4)) - { - eOut = PLY::EST_Blue; - } - else if (TokenMatch(pCur,"alpha",5)) - { - eOut = PLY::EST_Alpha; - } - else if (TokenMatch(pCur,"vertex_index",12) || TokenMatch(pCur,"vertex_indices",14)) - { - eOut = PLY::EST_VertexIndex; - } - else if (TokenMatch(pCur,"material_index",14)) - { - eOut = PLY::EST_MaterialIndex; - } - else if (TokenMatch(pCur,"ambient_red",11)) - { - eOut = PLY::EST_AmbientRed; - } - else if (TokenMatch(pCur,"ambient_green",13)) - { - eOut = PLY::EST_AmbientGreen; - } - else if (TokenMatch(pCur,"ambient_blue",12)) - { - eOut = PLY::EST_AmbientBlue; - } - else if (TokenMatch(pCur,"ambient_alpha",13)) - { - eOut = PLY::EST_AmbientAlpha; - } - else if (TokenMatch(pCur,"diffuse_red",11)) - { - eOut = PLY::EST_DiffuseRed; - } - else if (TokenMatch(pCur,"diffuse_green",13)) - { - eOut = PLY::EST_DiffuseGreen; - } - else if (TokenMatch(pCur,"diffuse_blue",12)) - { - eOut = PLY::EST_DiffuseBlue; - } - else if (TokenMatch(pCur,"diffuse_alpha",13)) - { - eOut = PLY::EST_DiffuseAlpha; - } - else if (TokenMatch(pCur,"specular_red",12)) - { - eOut = PLY::EST_SpecularRed; - } - else if (TokenMatch(pCur,"specular_green",14)) - { - eOut = PLY::EST_SpecularGreen; - } - else if (TokenMatch(pCur,"specular_blue",13)) - { - eOut = PLY::EST_SpecularBlue; - } - else if (TokenMatch(pCur,"specular_alpha",14)) - { - eOut = PLY::EST_SpecularAlpha; - } - else if (TokenMatch(pCur,"opacity",7)) - { - eOut = PLY::EST_Opacity; - } - else if (TokenMatch(pCur,"specular_power",6)) - { - eOut = PLY::EST_PhongPower; - } - else if (TokenMatch(pCur,"r",1)) - { - eOut = PLY::EST_Red; - } - else if (TokenMatch(pCur,"g",1)) - { - eOut = PLY::EST_Green; - } - else if (TokenMatch(pCur,"b",1)) - { - eOut = PLY::EST_Blue; - } - // NOTE: Blender3D exports texture coordinates as s,t tuples - else if (TokenMatch(pCur,"u",1) || TokenMatch(pCur,"s",1) || TokenMatch(pCur,"tx",2)) - { - eOut = PLY::EST_UTextureCoord; - } - else if (TokenMatch(pCur,"v",1) || TokenMatch(pCur,"t",1) || TokenMatch(pCur,"ty",2)) - { - eOut = PLY::EST_VTextureCoord; - } - else if (TokenMatch(pCur,"x",1)) - { - eOut = PLY::EST_XCoord; - } - else if (TokenMatch(pCur,"y",1)) - { - eOut = PLY::EST_YCoord; - } - else if (TokenMatch(pCur,"z",1)) - { - eOut = PLY::EST_ZCoord; - } - else if (TokenMatch(pCur,"nx",2)) - { - eOut = PLY::EST_XNormal; - } - else if (TokenMatch(pCur,"ny",2)) - { - eOut = PLY::EST_YNormal; - } - else if (TokenMatch(pCur,"nz",2)) - { - eOut = PLY::EST_ZNormal; - } - else - { - DefaultLogger::get()->info("Found unknown property semantic in file. This is ok"); - SkipLine(&pCur); - } - *pCurOut = pCur; - return eOut; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::Property::ParseProperty (const char* pCur, - const char** pCurOut, - PLY::Property* pOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - - // Forms supported: - // "property float x" - // "property list uchar int vertex_index" - *pCurOut = pCur; - - // skip leading spaces - if (!SkipSpaces(pCur,&pCur))return false; - - // skip the "property" string at the beginning - if (!TokenMatch(pCur,"property",8)) - { - // seems not to be a valid property entry - return false; - } - // get next word - if (!SkipSpaces(pCur,&pCur))return false; - if (TokenMatch(pCur,"list",4)) - { - pOut->bIsList = true; - - // seems to be a list. - if (EDT_INVALID == (pOut->eFirstType = PLY::Property::ParseDataType(pCur, &pCur))) - { - // unable to parse list size data type - SkipLine(pCur,&pCur); - *pCurOut = pCur; - return false; - } - if (!SkipSpaces(pCur,&pCur))return false; - if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur))) - { - // unable to parse list data type - SkipLine(pCur,&pCur); - *pCurOut = pCur; - return false; - } - } - else - { - if (EDT_INVALID == (pOut->eType = PLY::Property::ParseDataType(pCur, &pCur))) - { - // unable to parse data type. Skip the property - SkipLine(pCur,&pCur); - *pCurOut = pCur; - return false; - } - } - - if (!SkipSpaces(pCur,&pCur))return false; - const char* szCur = pCur; - pOut->Semantic = PLY::Property::ParseSemantic(pCur, &pCur); - - if (PLY::EST_INVALID == pOut->Semantic) - { - // store the name of the semantic - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - - DefaultLogger::get()->info("Found unknown semantic in PLY file. This is OK"); - pOut->szName = std::string(szCur,iDiff); - } - - SkipSpacesAndLineEnd(pCur,&pCur); - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -PLY::EElementSemantic PLY::Element::ParseSemantic(const char* pCur, - const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - PLY::EElementSemantic eOut = PLY::EEST_INVALID; - if (TokenMatch(pCur,"vertex",6)) - { - eOut = PLY::EEST_Vertex; - } - else if (TokenMatch(pCur,"face",4)) - { - eOut = PLY::EEST_Face; - } -#if 0 - // TODO: maybe implement this? - else if (TokenMatch(pCur,"range_grid",10)) - { - eOut = PLY::EEST_Face; - } -#endif - else if (TokenMatch(pCur,"tristrips",9)) - { - eOut = PLY::EEST_TriStrip; - } - else if (TokenMatch(pCur,"edge",4)) - { - eOut = PLY::EEST_Edge; - } - else if (TokenMatch(pCur,"material",8)) - { - eOut = PLY::EEST_Material; - } - *pCurOut = pCur; - return eOut; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::Element::ParseElement (const char* pCur, - const char** pCurOut, - PLY::Element* pOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pOut); - - // Example format: "element vertex 8" - *pCurOut = pCur; - - // skip leading spaces - if (!SkipSpaces(&pCur))return false; - - // skip the "element" string at the beginning - if (!TokenMatch(pCur,"element",7)) - { - // seems not to be a valid property entry - return false; - } - // get next word - if (!SkipSpaces(&pCur))return false; - - // parse the semantic of the element - const char* szCur = pCur; - pOut->eSemantic = PLY::Element::ParseSemantic(pCur,&pCur); - if (PLY::EEST_INVALID == pOut->eSemantic) - { - // if the exact semantic can't be determined, just store - // the original string identifier - uintptr_t iDiff = (uintptr_t)pCur - (uintptr_t)szCur; - pOut->szName = std::string(szCur,iDiff); - } - - if (!SkipSpaces(&pCur))return false; - - //parse the number of occurences of this element - pOut->NumOccur = strtol10(pCur,&pCur); - - // go to the next line - SkipSpacesAndLineEnd(pCur,&pCur); - - // now parse all properties of the element - while (true) - { - // skip all comments - PLY::DOM::SkipComments(pCur,&pCur); - - PLY::Property prop; - if (!PLY::Property::ParseProperty(pCur,&pCur,&prop))break; - pOut->alProperties.push_back(prop); - } - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::SkipComments (const char* pCur, - const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - *pCurOut = pCur; - - // skip spaces - if (!SkipSpaces(pCur,&pCur))return false; - - if (TokenMatch(pCur,"comment",7)) - { - SkipLine(pCur,&pCur); - SkipComments(pCur,&pCur); - *pCurOut = pCur; - return true; - } - *pCurOut = pCur; - return false; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseHeader (const char* pCur,const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - DefaultLogger::get()->debug("PLY::DOM::ParseHeader() begin"); - - // after ply and format line - *pCurOut = pCur; - - // parse all elements - while (true) - { - // skip all comments - PLY::DOM::SkipComments(pCur,&pCur); - - PLY::Element out; - if (PLY::Element::ParseElement(pCur,&pCur,&out)) - { - // add the element to the list of elements - alElements.push_back(out); - } - else if (TokenMatch(pCur,"end_header",10)) - { - // we have reached the end of the header - break; - } - else - { - // ignore unknown header elements - SkipLine(&pCur); - } - } - SkipSpacesAndLineEnd(pCur,&pCur); - *pCurOut = pCur; - - DefaultLogger::get()->debug("PLY::DOM::ParseHeader() succeeded"); - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceLists ( - const char* pCur, - const char** pCurOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() begin"); - *pCurOut = pCur; - - alElementData.resize(alElements.size()); - - std::vector<PLY::Element>::const_iterator i = alElements.begin(); - std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin(); - - // parse all element instances - for (;i != alElements.end();++i,++a) - { - (*a).alInstances.resize((*i).NumOccur); - PLY::ElementInstanceList::ParseInstanceList(pCur,&pCur,&(*i),&(*a)); - } - - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceLists() succeeded"); - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseElementInstanceListsBinary ( - const char* pCur, - const char** pCurOut, - bool p_bBE) -{ - ai_assert(NULL != pCur && NULL != pCurOut); - - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() begin"); - *pCurOut = pCur; - - alElementData.resize(alElements.size()); - - std::vector<PLY::Element>::const_iterator i = alElements.begin(); - std::vector<PLY::ElementInstanceList>::iterator a = alElementData.begin(); - - // parse all element instances - for (;i != alElements.end();++i,++a) - { - (*a).alInstances.resize((*i).NumOccur); - PLY::ElementInstanceList::ParseInstanceListBinary(pCur,&pCur,&(*i),&(*a),p_bBE); - } - - DefaultLogger::get()->debug("PLY::DOM::ParseElementInstanceListsBinary() succeeded"); - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseInstanceBinary (const char* pCur,DOM* p_pcOut,bool p_bBE) -{ - ai_assert(NULL != pCur && NULL != p_pcOut); - - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() begin"); - - if (!p_pcOut->ParseHeader(pCur,&pCur)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); - return false; - } - if (!p_pcOut->ParseElementInstanceListsBinary(pCur,&pCur,p_bBE)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() failure"); - return false; - } - DefaultLogger::get()->debug("PLY::DOM::ParseInstanceBinary() succeeded"); - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::DOM::ParseInstance (const char* pCur,DOM* p_pcOut) -{ - ai_assert(NULL != pCur); - ai_assert(NULL != p_pcOut); - - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() begin"); - - - if (!p_pcOut->ParseHeader(pCur,&pCur)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); - return false; - } - if (!p_pcOut->ParseElementInstanceLists(pCur,&pCur)) - { - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() failure"); - return false; - } - DefaultLogger::get()->debug("PLY::DOM::ParseInstance() succeeded"); - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstanceList::ParseInstanceList ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstanceList* p_pcOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); - - if (EEST_INVALID == pcElement->eSemantic || pcElement->alProperties.empty()) - { - // if the element has an unknown semantic we can skip all lines - // However, there could be comments - for (unsigned int i = 0; i < pcElement->NumOccur;++i) - { - PLY::DOM::SkipComments(pCur,&pCur); - SkipLine(pCur,&pCur); - } - } - else - { - // be sure to have enough storage - for (unsigned int i = 0; i < pcElement->NumOccur;++i) - { - PLY::DOM::SkipComments(pCur,&pCur); - PLY::ElementInstance::ParseInstance(pCur, &pCur,pcElement, - &p_pcOut->alInstances[i]); - } - } - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstanceList::ParseInstanceListBinary ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstanceList* p_pcOut, - bool p_bBE /* = false */) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); - - // we can add special handling code for unknown element semantics since - // we can't skip it as a whole block (we don't know its exact size - // due to the fact that lists could be contained in the property list - // of the unknown element) - for (unsigned int i = 0; i < pcElement->NumOccur;++i) - { - PLY::ElementInstance::ParseInstanceBinary(pCur, &pCur,pcElement, - &p_pcOut->alInstances[i], p_bBE); - } - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstance ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstance* p_pcOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); - - if (!SkipSpaces(pCur, &pCur))return false; - - // allocate enough storage - p_pcOut->alProperties.resize(pcElement->alProperties.size()); - - std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin(); - std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); - for (;i != p_pcOut->alProperties.end();++i,++a) - { - if (!(PLY::PropertyInstance::ParseInstance(pCur, &pCur,&(*a),&(*i)))) - { - DefaultLogger::get()->warn("Unable to parse property instance. " - "Skipping this element instance"); - - // skip the rest of the instance - SkipLine(pCur, &pCur); - - PLY::PropertyInstance::ValueUnion v = PLY::PropertyInstance::DefaultValue((*a).eType); - (*i).avList.push_back(v); - } - } - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::ElementInstance::ParseInstanceBinary ( - const char* pCur, - const char** pCurOut, - const PLY::Element* pcElement, - PLY::ElementInstance* p_pcOut, - bool p_bBE /* = false */) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != pcElement && NULL != p_pcOut); - - // allocate enough storage - p_pcOut->alProperties.resize(pcElement->alProperties.size()); - - std::vector<PLY::PropertyInstance>::iterator i = p_pcOut->alProperties.begin(); - std::vector<PLY::Property>::const_iterator a = pcElement->alProperties.begin(); - for (;i != p_pcOut->alProperties.end();++i,++a) - { - if (!(PLY::PropertyInstance::ParseInstanceBinary(pCur, &pCur,&(*a),&(*i),p_bBE))) - { - DefaultLogger::get()->warn("Unable to parse binary property instance. " - "Skipping this element instance"); - - (*i).avList.push_back(PLY::PropertyInstance::DefaultValue((*a).eType)); - } - } - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseInstance (const char* pCur,const char** pCurOut, - const PLY::Property* prop, PLY::PropertyInstance* p_pcOut) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut); - - *pCurOut = pCur; - - // skip spaces at the beginning - if (!SkipSpaces(pCur, &pCur))return false; - - if (prop->bIsList) - { - // parse the number of elements in the list - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eFirstType,&v); - - // convert to unsigned int - unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType); - - // parse all list elements - p_pcOut->avList.resize(iNum); - for (unsigned int i = 0; i < iNum;++i) - { - if (!SkipSpaces(pCur, &pCur))return false; - PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&p_pcOut->avList[i]); - } - } - else - { - // parse the property - PLY::PropertyInstance::ValueUnion v; - - PLY::PropertyInstance::ParseValue(pCur, &pCur,prop->eType,&v); - p_pcOut->avList.push_back(v); - } - SkipSpacesAndLineEnd(pCur, &pCur); - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseInstanceBinary ( - const char* pCur, - const char** pCurOut, - const PLY::Property* prop, - PLY::PropertyInstance* p_pcOut, - bool p_bBE) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != prop && NULL != p_pcOut); - - if (prop->bIsList) - { - // parse the number of elements in the list - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eFirstType,&v,p_bBE); - - // convert to unsigned int - unsigned int iNum = PLY::PropertyInstance::ConvertTo<unsigned int>(v,prop->eFirstType); - - // parse all list elements - p_pcOut->avList.resize(iNum); - for (unsigned int i = 0; i < iNum;++i){ - PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&p_pcOut->avList[i],p_bBE); - } - } - else - { - // parse the property - PLY::PropertyInstance::ValueUnion v; - PLY::PropertyInstance::ParseValueBinary(pCur, &pCur,prop->eType,&v,p_bBE); - p_pcOut->avList.push_back(v); - } - *pCurOut = pCur; - return true; -} - -// ------------------------------------------------------------------------------------------------ -PLY::PropertyInstance::ValueUnion PLY::PropertyInstance::DefaultValue( - PLY::EDataType eType) -{ - PLY::PropertyInstance::ValueUnion out; - - switch (eType) - { - case EDT_Float: - out.fFloat = 0.f; - return out; - - case EDT_Double: - out.fDouble = 0.; - return out; - - default: ; - }; - out.iUInt = 0; - return out; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseValue( - const char* pCur, - const char** pCurOut, - PLY::EDataType eType, - PLY::PropertyInstance::ValueUnion* out) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != out); - - register bool ret = true; - *pCurOut = pCur; - switch (eType) - { - case EDT_UInt: - case EDT_UShort: - case EDT_UChar: - - out->iUInt = (uint32_t)strtol10(pCur, &pCur); - break; - - case EDT_Int: - case EDT_Short: - case EDT_Char: - - out->iInt = (int32_t)strtol10s(pCur, &pCur); - break; - - case EDT_Float: - - pCur = fast_atof_move(pCur,out->fFloat); - break; - - case EDT_Double: - - float f; - pCur = fast_atof_move(pCur,f); - out->fDouble = (double)f; - break; - - default: - ret = false; - } - *pCurOut = pCur; - return ret; -} - -// ------------------------------------------------------------------------------------------------ -bool PLY::PropertyInstance::ParseValueBinary( - const char* pCur, - const char** pCurOut, - PLY::EDataType eType, - PLY::PropertyInstance::ValueUnion* out, - bool p_bBE) -{ - ai_assert(NULL != pCur && NULL != pCurOut && NULL != out); - - register bool ret = true; - switch (eType) - { - case EDT_UInt: - out->iUInt = (uint32_t)*((uint32_t*)pCur); - pCur += 4; - - // Swap endianess - if (p_bBE)ByteSwap::Swap((int32_t*)&out->iUInt); - break; - - case EDT_UShort: - { - int16_t i = *((uint16_t*)pCur); - - // Swap endianess - if (p_bBE)ByteSwap::Swap(&i); - out->iUInt = (uint32_t)i; - pCur += 2; - break; - } - - case EDT_UChar: - { - out->iUInt = (uint32_t)(*((uint8_t*)pCur)); - pCur ++; - break; - } - - case EDT_Int: - out->iInt = *((int32_t*)pCur); - pCur += 4; - - // Swap endianess - if (p_bBE)ByteSwap::Swap(&out->iInt); - break; - - case EDT_Short: - { - int16_t i = *((int16_t*)pCur); - - // Swap endianess - if (p_bBE)ByteSwap::Swap(&i); - out->iInt = (int32_t)i; - pCur += 2; - break; - } - - case EDT_Char: - out->iInt = (int32_t)*((int8_t*)pCur); - pCur ++; - break; - - case EDT_Float: - { - out->fFloat = *((float*)pCur); - - // Swap endianess - if (p_bBE)ByteSwap::Swap((int32_t*)&out->fFloat); - pCur += 4; - break; - } - case EDT_Double: - { - out->fDouble = *((double*)pCur); - - // Swap endianess - if (p_bBE)ByteSwap::Swap((int64_t*)&out->fDouble); - pCur += 8; - break; - } - default: - ret = false; - } - *pCurOut = pCur; - return ret; -} - -#endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER diff --git a/3rdparty/assimp/code/PlyParser.h b/3rdparty/assimp/code/PlyParser.h deleted file mode 100644 index 5b95442a..00000000 --- a/3rdparty/assimp/code/PlyParser.h +++ /dev/null @@ -1,501 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the helper data structures for importing PLY files */ -#ifndef AI_PLYFILEHELPER_H_INC -#define AI_PLYFILEHELPER_H_INC - - -#include "ParsingUtils.h" - - -namespace Assimp -{ - -// http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/ -// http://w3.impa.br/~lvelho/outgoing/sossai/old/ViHAP_D4.4.2_PLY_format_v1.1.pdf -// http://www.okino.com/conv/exp_ply.htm -namespace PLY -{ - - -// --------------------------------------------------------------------------------- -/* -name type number of bytes ---------------------------------------- -char character 1 -uchar unsigned character 1 -short short integer 2 -ushort unsigned short integer 2 -int integer 4 -uint unsigned integer 4 -float single-precision float 4 -double double-precision float 8 - -int8 -int16 -uint8 ... forms are also used -*/ -enum EDataType -{ - EDT_Char = 0x0u, - EDT_UChar, - EDT_Short, - EDT_UShort, - EDT_Int, - EDT_UInt, - EDT_Float, - EDT_Double, - - // Marks invalid entries - EDT_INVALID -}; - -// --------------------------------------------------------------------------------- -/** \brief Specifies semantics for PLY element properties - * - * Semantics define the usage of a property, e.g. x coordinate -*/ -enum ESemantic -{ - //! vertex position x coordinate - EST_XCoord = 0x0u, - //! vertex position x coordinate - EST_YCoord, - //! vertex position x coordinate - EST_ZCoord, - - //! vertex normal x coordinate - EST_XNormal, - //! vertex normal y coordinate - EST_YNormal, - //! vertex normal z coordinate - EST_ZNormal, - - //! u texture coordinate - EST_UTextureCoord, - //! v texture coordinate - EST_VTextureCoord, - - //! vertex colors, red channel - EST_Red, - //! vertex colors, green channel - EST_Green, - //! vertex colors, blue channel - EST_Blue, - //! vertex colors, alpha channel - EST_Alpha, - - //! vertex index list - EST_VertexIndex, - - //! texture index - EST_TextureIndex, - - //! texture coordinates (stored as element of a face) - EST_TextureCoordinates, - - //! material index - EST_MaterialIndex, - - //! ambient color, red channel - EST_AmbientRed, - //! ambient color, green channel - EST_AmbientGreen, - //! ambient color, blue channel - EST_AmbientBlue, - //! ambient color, alpha channel - EST_AmbientAlpha, - - //! diffuse color, red channel - EST_DiffuseRed, - //! diffuse color, green channel - EST_DiffuseGreen, - //! diffuse color, blue channel - EST_DiffuseBlue, - //! diffuse color, alpha channel - EST_DiffuseAlpha, - - //! specular color, red channel - EST_SpecularRed, - //! specular color, green channel - EST_SpecularGreen, - //! specular color, blue channel - EST_SpecularBlue, - //! specular color, alpha channel - EST_SpecularAlpha, - - //! specular power for phong shading - EST_PhongPower, - - //! opacity between 0 and 1 - EST_Opacity, - - //! Marks invalid entries - EST_INVALID -}; - -// --------------------------------------------------------------------------------- -/** \brief Specifies semantics for PLY elements - * - * Semantics define the usage of an element, e.g. vertex or material -*/ -enum EElementSemantic -{ - //! The element is a vertex - EEST_Vertex = 0x0u, - - //! The element is a face description (index table) - EEST_Face, - - //! The element is a tristrip description (index table) - EEST_TriStrip, - - //! The element is an edge description (ignored) - EEST_Edge, - - //! The element is a material description - EEST_Material, - - //! Marks invalid entries - EEST_INVALID -}; - -// --------------------------------------------------------------------------------- -/** \brief Helper class for a property in a PLY file. - * - * This can e.g. be a part of the vertex declaration - */ -class Property -{ -public: - - //! Default constructor - Property() - : eType (EDT_Int), bIsList(false), eFirstType(EDT_UChar) - {} - - //! Data type of the property - EDataType eType; - - //! Semantical meaning of the property - ESemantic Semantic; - - //! Of the semantic of the property could not be parsed: - //! Contains the semantic specified in the file - std::string szName; - - //! Specifies whether the data type is a list where - //! the first element specifies the size of the list - bool bIsList; - EDataType eFirstType; - - // ------------------------------------------------------------------- - //! Parse a property from a string. The end of the - //! string is either '\n', '\r' or '\0'. Return valie is false - //! if the input string is NOT a valid property (E.g. does - //! not start with the "property" keyword) - static bool ParseProperty (const char* pCur, const char** pCurOut, - Property* pOut); - - // ------------------------------------------------------------------- - //! Parse a data type from a string - static EDataType ParseDataType(const char* pCur,const char** pCurOut); - - // ------------------------------------------------------------------- - //! Parse a semantic from a string - static ESemantic ParseSemantic(const char* pCur,const char** pCurOut); -}; - -// --------------------------------------------------------------------------------- -/** \brief Helper class for an element in a PLY file. - * - * This can e.g. be the vertex declaration. Elements contain a - * well-defined number of properties. - */ -class Element -{ -public: - - //! Default constructor - Element() - : eSemantic (EEST_INVALID) - , NumOccur(0) - {} - - //! List of properties assigned to the element - //! std::vector to support operator[] - std::vector<Property> alProperties; - - //! Semantic of the element - EElementSemantic eSemantic; - - //! Of the semantic of the element could not be parsed: - //! Contains the semantic specified in the file - std::string szName; - - //! How many times will the element occur? - unsigned int NumOccur; - - - // ------------------------------------------------------------------- - //! Parse an element from a string. - //! The function will parse all properties contained in the - //! element, too. - static bool ParseElement (const char* pCur, const char** pCurOut, - Element* pOut); - - // ------------------------------------------------------------------- - //! Parse a semantic from a string - static EElementSemantic ParseSemantic(const char* pCur, - const char** pCurOut); -}; - -// --------------------------------------------------------------------------------- -/** \brief Instance of a property in a PLY file - */ -class PropertyInstance -{ -public: - - //! Default constructor - PropertyInstance () - {} - - union ValueUnion - { - - //! uInt32 representation of the property. All - // uint types are automatically converted to uint32 - uint32_t iUInt; - - //! Int32 representation of the property. All - // int types are automatically converted to int32 - int32_t iInt; - - //! Float32 representation of the property - float fFloat; - - //! Float64 representation of the property - double fDouble; - - }; - - // ------------------------------------------------------------------- - //! List of all values parsed. Contains only one value - // for non-list properties - std::vector<ValueUnion> avList; - - // ------------------------------------------------------------------- - //! Parse a property instance - static bool ParseInstance (const char* pCur,const char** pCurOut, - const Property* prop, PropertyInstance* p_pcOut); - - // ------------------------------------------------------------------- - //! Parse a property instance in binary format - static bool ParseInstanceBinary (const char* pCur,const char** pCurOut, - const Property* prop, PropertyInstance* p_pcOut,bool p_bBE); - - // ------------------------------------------------------------------- - //! Get the default value for a given data type - static ValueUnion DefaultValue(EDataType eType); - - // ------------------------------------------------------------------- - //! Parse a value - static bool ParseValue(const char* pCur,const char** pCurOut, - EDataType eType,ValueUnion* out); - - // ------------------------------------------------------------------- - //! Parse a binary value - static bool ParseValueBinary(const char* pCur,const char** pCurOut, - EDataType eType,ValueUnion* out,bool p_bBE); - - // ------------------------------------------------------------------- - //! Convert a property value to a given type TYPE - template <typename TYPE> - static TYPE ConvertTo(ValueUnion v, EDataType eType); -}; - -// --------------------------------------------------------------------------------- -/** \brief Class for an element instance in a PLY file - */ -class ElementInstance -{ -public: - - //! Default constructor - ElementInstance () - {} - - //! List of all parsed properties - std::vector< PropertyInstance > alProperties; - - // ------------------------------------------------------------------- - //! Parse an element instance - static bool ParseInstance (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstance* p_pcOut); - - // ------------------------------------------------------------------- - //! Parse a binary element instance - static bool ParseInstanceBinary (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstance* p_pcOut,bool p_bBE); -}; - -// --------------------------------------------------------------------------------- -/** \brief Class for an element instance list in a PLY file - */ -class ElementInstanceList -{ -public: - - //! Default constructor - ElementInstanceList () - {} - - //! List of all element instances - std::vector< ElementInstance > alInstances; - - // ------------------------------------------------------------------- - //! Parse an element instance list - static bool ParseInstanceList (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstanceList* p_pcOut); - - // ------------------------------------------------------------------- - //! Parse a binary element instance list - static bool ParseInstanceListBinary (const char* pCur,const char** pCurOut, - const Element* pcElement, ElementInstanceList* p_pcOut,bool p_bBE); -}; -// --------------------------------------------------------------------------------- -/** \brief Class to represent the document object model of an ASCII or binary - * (both little and big-endian) PLY file - */ -class DOM -{ -public: - - //! Default constructor - DOM() - {} - - - //! Contains all elements of the file format - std::vector<Element> alElements; - //! Contains the real data of each element's instance list - std::vector<ElementInstanceList> alElementData; - - //! Parse the DOM for a PLY file. The input string is assumed - //! to be terminated with zero - static bool ParseInstance (const char* pCur,DOM* p_pcOut); - static bool ParseInstanceBinary (const char* pCur, - DOM* p_pcOut,bool p_bBE); - - //! Skip all comment lines after this - static bool SkipComments (const char* pCur,const char** pCurOut); - -private: - - // ------------------------------------------------------------------- - //! Handle the file header and read all element descriptions - bool ParseHeader (const char* pCur,const char** pCurOut); - - // ------------------------------------------------------------------- - //! Read in all element instance lists - bool ParseElementInstanceLists (const char* pCur,const char** pCurOut); - - // ------------------------------------------------------------------- - //! Read in all element instance lists for a binary file format - bool ParseElementInstanceListsBinary (const char* pCur, - const char** pCurOut,bool p_bBE); -}; - -// --------------------------------------------------------------------------------- -/** \brief Helper class to represent a loaded PLY face - */ -class Face -{ -public: - - Face() - : iMaterialIndex(0xFFFFFFFF) - { - // set all indices to zero by default - mIndices.resize(3,0); - } - -public: - - //! List of vertex indices - std::vector<unsigned int> mIndices; - - //! Material index - unsigned int iMaterialIndex; -}; - -// --------------------------------------------------------------------------------- -template <typename TYPE> -inline TYPE PLY::PropertyInstance::ConvertTo( - PLY::PropertyInstance::ValueUnion v, PLY::EDataType eType) -{ - switch (eType) - { - case EDT_Float: - return (TYPE)v.fFloat; - case EDT_Double: - return (TYPE)v.fDouble; - - case EDT_UInt: - case EDT_UShort: - case EDT_UChar: - return (TYPE)v.iUInt; - - case EDT_Int: - case EDT_Short: - case EDT_Char: - return (TYPE)v.iInt; - default: ; - }; - return (TYPE)0; -} - -} // Namespace PLY -} // Namespace AssImp - -#endif // !! include guard diff --git a/3rdparty/assimp/code/PretransformVertices.cpp b/3rdparty/assimp/code/PretransformVertices.cpp deleted file mode 100644 index cd97b4a6..00000000 --- a/3rdparty/assimp/code/PretransformVertices.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 PretransformVertices.cpp - * @brief Implementation of the "PretransformVertices" post processing step -*/ - -#include "AssimpPCH.h" -#include "PretransformVertices.h" -#include "ProcessHelper.h" -#include "SceneCombiner.h" - -using namespace Assimp; - -// some array offsets -#define AI_PTVS_VERTEX 0x0 -#define AI_PTVS_FACE 0x1 - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -PretransformVertices::PretransformVertices() -: configKeepHierarchy (false) -{ -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -PretransformVertices::~PretransformVertices() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool PretransformVertices::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_PreTransformVertices) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Setup import configuration -void PretransformVertices::SetupProperties(const Importer* pImp) -{ - // Get the current value of AI_CONFIG_PP_PTV_KEEP_HIERARCHY and AI_CONFIG_PP_PTV_NORMALIZE - configKeepHierarchy = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_KEEP_HIERARCHY,0)); - configNormalize = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_NORMALIZE,0)); -} - -// ------------------------------------------------------------------------------------------------ -// Count the number of nodes -unsigned int PretransformVertices::CountNodes( aiNode* pcNode ) -{ - unsigned int iRet = 1; - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) - { - iRet += CountNodes(pcNode->mChildren[i]); - } - return iRet; -} - -// ------------------------------------------------------------------------------------------------ -// Get a bitwise combination identifying the vertex format of a mesh -unsigned int PretransformVertices::GetMeshVFormat(aiMesh* pcMesh) -{ - // the vertex format is stored in aiMesh::mBones for later retrieval. - // there isn't a good reason to compute it a few hundred times - // from scratch. The pointer is unused as animations are lost - // during PretransformVertices. - if (pcMesh->mBones) - return (unsigned int)(uint64_t)pcMesh->mBones; - - - const unsigned int iRet = GetMeshVFormatUnique(pcMesh); - - // store the value for later use - pcMesh->mBones = (aiBone**)(uint64_t)iRet; - return iRet; -} - -// ------------------------------------------------------------------------------------------------ -// Count the number of vertices in the whole scene and a given -// material index -void PretransformVertices::CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, - unsigned int iVFormat, unsigned int* piFaces, unsigned int* piVertices) -{ - for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; - if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) - { - *piVertices += pcMesh->mNumVertices; - *piFaces += pcMesh->mNumFaces; - } - } - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) - { - CountVerticesAndFaces(pcScene,pcNode->mChildren[i],iMat, - iVFormat,piFaces,piVertices); - } -} - -// ------------------------------------------------------------------------------------------------ -// Collect vertex/face data -void PretransformVertices::CollectData( aiScene* pcScene, aiNode* pcNode, unsigned int iMat, - unsigned int iVFormat, aiMesh* pcMeshOut, - unsigned int aiCurrent[2], unsigned int* num_refs) -{ - // No need to multiply if there's no transformation - const bool identity = pcNode->mTransformation.IsIdentity(); - for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[ pcNode->mMeshes[i] ]; - if (iMat == pcMesh->mMaterialIndex && iVFormat == GetMeshVFormat(pcMesh)) - { - // Decrement mesh reference counter - unsigned int& num_ref = num_refs[pcNode->mMeshes[i]]; - ai_assert(0 != num_ref); - --num_ref; - - if (identity) { - // copy positions without modifying them - ::memcpy(pcMeshOut->mVertices + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mVertices, - pcMesh->mNumVertices * sizeof(aiVector3D)); - - if (iVFormat & 0x2) { - // copy normals without modifying them - ::memcpy(pcMeshOut->mNormals + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mNormals, - pcMesh->mNumVertices * sizeof(aiVector3D)); - } - if (iVFormat & 0x4) - { - // copy tangents without modifying them - ::memcpy(pcMeshOut->mTangents + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mTangents, - pcMesh->mNumVertices * sizeof(aiVector3D)); - // copy bitangents without modifying them - ::memcpy(pcMeshOut->mBitangents + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mBitangents, - pcMesh->mNumVertices * sizeof(aiVector3D)); - } - } - else - { - // copy positions, transform them to worldspace - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMeshOut->mVertices[aiCurrent[AI_PTVS_VERTEX]+n] = pcNode->mTransformation * pcMesh->mVertices[n]; - } - aiMatrix4x4 mWorldIT = pcNode->mTransformation; - mWorldIT.Inverse().Transpose(); - - // TODO: implement Inverse() for aiMatrix3x3 - aiMatrix3x3 m = aiMatrix3x3(mWorldIT); - - if (iVFormat & 0x2) - { - // copy normals, transform them to worldspace - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMeshOut->mNormals[aiCurrent[AI_PTVS_VERTEX]+n] = - m * pcMesh->mNormals[n]; - } - } - if (iVFormat & 0x4) - { - // copy tangents and bitangents, transform them to worldspace - for (unsigned int n = 0; n < pcMesh->mNumVertices;++n) { - pcMeshOut->mTangents [aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mTangents[n]; - pcMeshOut->mBitangents[aiCurrent[AI_PTVS_VERTEX]+n] = m * pcMesh->mBitangents[n]; - } - } - } - unsigned int p = 0; - while (iVFormat & (0x100 << p)) - { - // copy texture coordinates - memcpy(pcMeshOut->mTextureCoords[p] + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mTextureCoords[p], - pcMesh->mNumVertices * sizeof(aiVector3D)); - ++p; - } - p = 0; - while (iVFormat & (0x1000000 << p)) - { - // copy vertex colors - memcpy(pcMeshOut->mColors[p] + aiCurrent[AI_PTVS_VERTEX], - pcMesh->mColors[p], - pcMesh->mNumVertices * sizeof(aiColor4D)); - ++p; - } - // now we need to copy all faces. since we will delete the source mesh afterwards, - // we don't need to reallocate the array of indices except if this mesh is - // referenced multiple times. - for (unsigned int planck = 0;planck < pcMesh->mNumFaces;++planck) - { - aiFace& f_src = pcMesh->mFaces[planck]; - aiFace& f_dst = pcMeshOut->mFaces[aiCurrent[AI_PTVS_FACE]+planck]; - - const unsigned int num_idx = f_src.mNumIndices; - - f_dst.mNumIndices = num_idx; - - unsigned int* pi; - if (!num_ref) { /* if last time the mesh is referenced -> no reallocation */ - pi = f_dst.mIndices = f_src.mIndices; - - // offset all vertex indices - for (unsigned int hahn = 0; hahn < num_idx;++hahn){ - pi[hahn] += aiCurrent[AI_PTVS_VERTEX]; - } - } - else { - pi = f_dst.mIndices = new unsigned int[num_idx]; - - // copy and offset all vertex indices - for (unsigned int hahn = 0; hahn < num_idx;++hahn){ - pi[hahn] = f_src.mIndices[hahn] + aiCurrent[AI_PTVS_VERTEX]; - } - } - - // Update the mPrimitiveTypes member of the mesh - switch (pcMesh->mFaces[planck].mNumIndices) - { - case 0x1: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 0x2: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 0x3: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - pcMeshOut->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - }; - } - aiCurrent[AI_PTVS_VERTEX] += pcMesh->mNumVertices; - aiCurrent[AI_PTVS_FACE] += pcMesh->mNumFaces; - } - } - - // append all children of us - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) { - CollectData(pcScene,pcNode->mChildren[i],iMat, - iVFormat,pcMeshOut,aiCurrent,num_refs); - } -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all vertex formats that occur for a given material index -// The output list contains duplicate elements -void PretransformVertices::GetVFormatList( aiScene* pcScene, unsigned int iMat, - std::list<unsigned int>& aiOut) -{ - for (unsigned int i = 0; i < pcScene->mNumMeshes;++i) - { - aiMesh* pcMesh = pcScene->mMeshes[ i ]; - if (iMat == pcMesh->mMaterialIndex) { - aiOut.push_back(GetMeshVFormat(pcMesh)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Compute the absolute transformation matrices of each node -void PretransformVertices::ComputeAbsoluteTransform( aiNode* pcNode ) -{ - if (pcNode->mParent) { - pcNode->mTransformation = pcNode->mParent->mTransformation*pcNode->mTransformation; - } - - for (unsigned int i = 0;i < pcNode->mNumChildren;++i) { - ComputeAbsoluteTransform(pcNode->mChildren[i]); - } -} - -// ------------------------------------------------------------------------------------------------ -// Apply the node transformation to a mesh -void PretransformVertices::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat) -{ - // Check whether we need to transform the coordinates at all - if (!mat.IsIdentity()) { - - if (mesh->HasPositions()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mVertices[i] = mat * mesh->mVertices[i]; - } - } - if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) { - aiMatrix4x4 mWorldIT = mat; - mWorldIT.Inverse().Transpose(); - - // TODO: implement Inverse() for aiMatrix3x3 - aiMatrix3x3 m = aiMatrix3x3(mWorldIT); - - if (mesh->HasNormals()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mNormals[i] = m * mesh->mNormals[i]; - } - } - if (mesh->HasTangentsAndBitangents()) { - for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { - mesh->mTangents[i] = m * mesh->mTangents[i]; - mesh->mBitangents[i] = m * mesh->mBitangents[i]; - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Simple routine to build meshes in worldspace, no further optimization -void PretransformVertices::BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in, - unsigned int numIn, aiNode* node) -{ - // NOTE: - // aiMesh::mNumBones store original source mesh, or 0xffffffff if not a copy - // aiMesh::mBones store reference to abs. transform we multiplied with - - // process meshes - for (unsigned int i = 0; i < node->mNumMeshes;++i) { - aiMesh* mesh = in[node->mMeshes[i]]; - - // check whether we can operate on this mesh - if (!mesh->mBones || *reinterpret_cast<aiMatrix4x4*>(mesh->mBones) == node->mTransformation) { - // yes, we can. - mesh->mBones = reinterpret_cast<aiBone**> (&node->mTransformation); - mesh->mNumBones = 0xffffffff; - } - else { - - // try to find us in the list of newly created meshes - for (unsigned int n = 0; n < out.size(); ++n) { - aiMesh* ctz = out[n]; - if (ctz->mNumBones == node->mMeshes[i] && *reinterpret_cast<aiMatrix4x4*>(ctz->mBones) == node->mTransformation) { - - // ok, use this one. Update node mesh index - node->mMeshes[i] = numIn + n; - } - } - if (node->mMeshes[i] < numIn) { - // Worst case. Need to operate on a full copy of the mesh - DefaultLogger::get()->info("PretransformVertices: Copying mesh due to mismatching transforms"); - aiMesh* ntz; - - const unsigned int tmp = mesh->mNumBones; // - mesh->mNumBones = 0; - SceneCombiner::Copy(&ntz,mesh); - mesh->mNumBones = tmp; - - ntz->mNumBones = node->mMeshes[i]; - ntz->mBones = reinterpret_cast<aiBone**> (&node->mTransformation); - - out.push_back(ntz); - } - } - } - - // call children - for (unsigned int i = 0; i < node->mNumChildren;++i) - BuildWCSMeshes(out,in,numIn,node->mChildren[i]); -} - -// ------------------------------------------------------------------------------------------------ -// Reset transformation matrices to identity -void PretransformVertices::MakeIdentityTransform(aiNode* nd) -{ - nd->mTransformation = aiMatrix4x4(); - - // call children - for (unsigned int i = 0; i < nd->mNumChildren;++i) - MakeIdentityTransform(nd->mChildren[i]); -} - -// ------------------------------------------------------------------------------------------------ -// Build reference counters for all meshes -void PretransformVertices::BuildMeshRefCountArray(aiNode* nd, unsigned int * refs) -{ - for (unsigned int i = 0; i< nd->mNumMeshes;++i) - refs[nd->mMeshes[i]]++; - - // call children - for (unsigned int i = 0; i < nd->mNumChildren;++i) - BuildMeshRefCountArray(nd->mChildren[i],refs); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void PretransformVertices::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("PretransformVerticesProcess begin"); - - // Return immediately if we have no meshes - if (!pScene->mNumMeshes) - return; - - const unsigned int iOldMeshes = pScene->mNumMeshes; - const unsigned int iOldAnimationChannels = pScene->mNumAnimations; - const unsigned int iOldNodes = CountNodes(pScene->mRootNode); - - // first compute absolute transformation matrices for all nodes - ComputeAbsoluteTransform(pScene->mRootNode); - - // Delete aiMesh::mBones for all meshes. The bones are - // removed during this step and we need the pointer as - // temporary storage - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) { - aiMesh* mesh = pScene->mMeshes[i]; - - for (unsigned int a = 0; a < mesh->mNumBones;++a) - delete mesh->mBones[a]; - - delete[] mesh->mBones; - mesh->mBones = NULL; - } - - // now build a list of output meshes - std::vector<aiMesh*> apcOutMeshes; - - // Keep scene hierarchy? It's an easy job in this case ... - // we go on and transform all meshes, if one is referenced by nodes - // with different absolute transformations a depth copy of the mesh - // is required. - if ( configKeepHierarchy ) { - - // Hack: store the matrix we're transforming a mesh with in aiMesh::mBones - BuildWCSMeshes(apcOutMeshes,pScene->mMeshes,pScene->mNumMeshes, pScene->mRootNode); - - // ... if new meshes have been generated, append them to the end of the scene - if (apcOutMeshes.size() > 0) { - aiMesh** npp = new aiMesh*[pScene->mNumMeshes + apcOutMeshes.size()]; - - memcpy(npp,pScene->mMeshes,sizeof(aiMesh*)*pScene->mNumMeshes); - memcpy(npp+pScene->mNumMeshes,&apcOutMeshes[0],sizeof(aiMesh*)*apcOutMeshes.size()); - - pScene->mNumMeshes += apcOutMeshes.size(); - delete[] pScene->mMeshes; pScene->mMeshes = npp; - } - - // now iterate through all meshes and transform them to worldspace - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) { - ApplyTransform(pScene->mMeshes[i],*reinterpret_cast<aiMatrix4x4*>( pScene->mMeshes[i]->mBones )); - - // prevent improper destruction - pScene->mMeshes[i]->mBones = NULL; - pScene->mMeshes[i]->mNumBones = 0; - } - } - else { - - apcOutMeshes.reserve(pScene->mNumMaterials<<1u); - std::list<unsigned int> aiVFormats; - - std::vector<unsigned int> s(pScene->mNumMeshes,0); - BuildMeshRefCountArray(pScene->mRootNode,&s[0]); - - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - // get the list of all vertex formats for this material - aiVFormats.clear(); - GetVFormatList(pScene,i,aiVFormats); - aiVFormats.sort(); - aiVFormats.unique(); - for (std::list<unsigned int>::const_iterator j = aiVFormats.begin();j != aiVFormats.end();++j) { - unsigned int iVertices = 0; - unsigned int iFaces = 0; - CountVerticesAndFaces(pScene,pScene->mRootNode,i,*j,&iFaces,&iVertices); - if (0 != iFaces && 0 != iVertices) - { - apcOutMeshes.push_back(new aiMesh()); - aiMesh* pcMesh = apcOutMeshes.back(); - pcMesh->mNumFaces = iFaces; - pcMesh->mNumVertices = iVertices; - pcMesh->mFaces = new aiFace[iFaces]; - pcMesh->mVertices = new aiVector3D[iVertices]; - pcMesh->mMaterialIndex = i; - if ((*j) & 0x2)pcMesh->mNormals = new aiVector3D[iVertices]; - if ((*j) & 0x4) - { - pcMesh->mTangents = new aiVector3D[iVertices]; - pcMesh->mBitangents = new aiVector3D[iVertices]; - } - iFaces = 0; - while ((*j) & (0x100 << iFaces)) - { - pcMesh->mTextureCoords[iFaces] = new aiVector3D[iVertices]; - if ((*j) & (0x10000 << iFaces))pcMesh->mNumUVComponents[iFaces] = 3; - else pcMesh->mNumUVComponents[iFaces] = 2; - iFaces++; - } - iFaces = 0; - while ((*j) & (0x1000000 << iFaces)) - pcMesh->mColors[iFaces++] = new aiColor4D[iVertices]; - - // fill the mesh ... - unsigned int aiTemp[2] = {0,0}; - CollectData(pScene,pScene->mRootNode,i,*j,pcMesh,aiTemp,&s[0]); - } - } - } - - // now delete all meshes in the scene and build a new mesh list - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - aiMesh* mesh = pScene->mMeshes[i]; - mesh->mNumBones = 0; - mesh->mBones = NULL; - - // we're reusing the face index arrays. avoid destruction - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { - mesh->mFaces[a].mNumIndices = 0; - mesh->mFaces[a].mIndices = NULL; - } - - delete mesh; - - // Invalidate the contents of the old mesh array. We will most - // likely have less output meshes now, so the last entries of - // the mesh array are not overridden. We set them to NULL to - // make sure the developer gets notified when his application - // attempts to access these fields ... - mesh = NULL; - } - - // If no meshes are referenced in the node graph it is possible that we get no output meshes. - if (apcOutMeshes.empty()) { - throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by nodes"); - } - else - { - // It is impossible that we have more output meshes than - // input meshes, so we can easily reuse the old mesh array - pScene->mNumMeshes = (unsigned int)apcOutMeshes.size(); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - pScene->mMeshes[i] = apcOutMeshes[i]; - } - } - - // remove all animations from the scene - for (unsigned int i = 0; i < pScene->mNumAnimations;++i) - delete pScene->mAnimations[i]; - delete[] pScene->mAnimations; - - pScene->mAnimations = NULL; - pScene->mNumAnimations = 0; - - // --- we need to keep all cameras and lights - for (unsigned int i = 0; i < pScene->mNumCameras;++i) - { - aiCamera* cam = pScene->mCameras[i]; - const aiNode* nd = pScene->mRootNode->FindNode(cam->mName); - ai_assert(NULL != nd); - - // multiply all properties of the camera with the absolute - // transformation of the corresponding node - cam->mPosition = nd->mTransformation * cam->mPosition; - cam->mLookAt = aiMatrix3x3( nd->mTransformation ) * cam->mLookAt; - cam->mUp = aiMatrix3x3( nd->mTransformation ) * cam->mUp; - } - - for (unsigned int i = 0; i < pScene->mNumLights;++i) - { - aiLight* l = pScene->mLights[i]; - const aiNode* nd = pScene->mRootNode->FindNode(l->mName); - ai_assert(NULL != nd); - - // multiply all properties of the camera with the absolute - // transformation of the corresponding node - l->mPosition = nd->mTransformation * l->mPosition; - l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection; - } - - if ( !configKeepHierarchy ) { - - // now delete all nodes in the scene and build a new - // flat node graph with a root node and some level 1 children - delete pScene->mRootNode; - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("<dummy_root>"); - - if (1 == pScene->mNumMeshes && !pScene->mNumLights && !pScene->mNumCameras) - { - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - } - else - { - pScene->mRootNode->mNumChildren = pScene->mNumMeshes+pScene->mNumLights+pScene->mNumCameras; - aiNode** nodes = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; - - // generate mesh nodes - for (unsigned int i = 0; i < pScene->mNumMeshes;++i,++nodes) - { - aiNode* pcNode = *nodes = new aiNode(); - pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ::sprintf(pcNode->mName.data,"mesh_%i",i); - - // setup mesh indices - pcNode->mNumMeshes = 1; - pcNode->mMeshes = new unsigned int[1]; - pcNode->mMeshes[0] = i; - } - // generate light nodes - for (unsigned int i = 0; i < pScene->mNumLights;++i,++nodes) - { - aiNode* pcNode = *nodes = new aiNode(); - pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ::sprintf(pcNode->mName.data,"light_%i",i); - pScene->mLights[i]->mName = pcNode->mName; - } - // generate camera nodes - for (unsigned int i = 0; i < pScene->mNumCameras;++i,++nodes) - { - aiNode* pcNode = *nodes = new aiNode(); - pcNode->mParent = pScene->mRootNode; - pcNode->mName.length = ::sprintf(pcNode->mName.data,"cam_%i",i); - pScene->mCameras[i]->mName = pcNode->mName; - } - } - } - else { - // ... and finally set the transformation matrix of all nodes to identity - MakeIdentityTransform(pScene->mRootNode); - } - - if (configNormalize) { - // compute the boundary of all meshes - aiVector3D min,max; - MinMaxChooser<aiVector3D> ()(min,max); - - for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { - aiMesh* m = pScene->mMeshes[a]; - for (unsigned int i = 0; i < m->mNumVertices;++i) { - min = std::min(m->mVertices[i],min); - max = std::max(m->mVertices[i],max); - } - } - - // find the dominant axis - aiVector3D d = max-min; - const float div = std::max(d.x,std::max(d.y,d.z))*0.5f; - - d = min+d*0.5f; - for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) { - aiMesh* m = pScene->mMeshes[a]; - for (unsigned int i = 0; i < m->mNumVertices;++i) { - m->mVertices[i] = (m->mVertices[i]-d)/div; - } - } - } - - // print statistics - if (!DefaultLogger::isNullLogger()) - { - char buffer[4096]; - - DefaultLogger::get()->debug("PretransformVerticesProcess finished"); - - sprintf(buffer,"Removed %i nodes and %i animation channels (%i output nodes)", - iOldNodes,iOldAnimationChannels,CountNodes(pScene->mRootNode)); - DefaultLogger::get()->info(buffer); - - sprintf(buffer,"Kept %i lights and %i cameras", - pScene->mNumLights,pScene->mNumCameras); - DefaultLogger::get()->info(buffer); - - sprintf(buffer,"Moved %i meshes to WCS (number of output meshes: %i)", - iOldMeshes,pScene->mNumMeshes); - DefaultLogger::get()->info(buffer); - } -} - diff --git a/3rdparty/assimp/code/PretransformVertices.h b/3rdparty/assimp/code/PretransformVertices.h deleted file mode 100644 index df2d8450..00000000 --- a/3rdparty/assimp/code/PretransformVertices.h +++ /dev/null @@ -1,166 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 PretransformVertices.h - * @brief Defines a post processing step to pretransform all - * vertices in the scenegraph - */ -#ifndef AI_PRETRANSFORMVERTICES_H_INC -#define AI_PRETRANSFORMVERTICES_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class PretransformVerticesTest; -namespace Assimp { - -// --------------------------------------------------------------------------- -/** The PretransformVertices pretransforms all vertices in the nodegraph - * and removes the whole graph. The output is a list of meshes, one for - * each material. -*/ -class ASSIMP_API PretransformVertices : public BaseProcess -{ - friend class Importer; - friend class ::PretransformVerticesTest; - -protected: - /** Constructor to be privately used by Importer */ - PretransformVertices (); - - /** Destructor, private as well */ - ~PretransformVertices (); - -public: - - // ------------------------------------------------------------------- - // Check whether step is active - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - // Execute step on a given scene - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - // Setup import settings - void SetupProperties(const Importer* pImp); - - - // ------------------------------------------------------------------- - /** @brief Toggle the 'keep hierarchy' option - * @param d hm ... difficult to guess what this means, hu!? - */ - void KeepHierarchy(bool d) { - configKeepHierarchy = d; - } - - // ------------------------------------------------------------------- - /** @brief Check whether 'keep hierarchy' is currently enabled. - * @return ... - */ - bool IsHierarchyKept() const { - return configKeepHierarchy; - } - -private: - - // ------------------------------------------------------------------- - // Count the number of nodes - unsigned int CountNodes( aiNode* pcNode ); - - // ------------------------------------------------------------------- - // Get a bitwise combination identifying the vertex format of a mesh - unsigned int GetMeshVFormat(aiMesh* pcMesh); - - // ------------------------------------------------------------------- - // Count the number of vertices in the whole scene and a given - // material index - void CountVerticesAndFaces( aiScene* pcScene, aiNode* pcNode, - unsigned int iMat, - unsigned int iVFormat, - unsigned int* piFaces, - unsigned int* piVertices); - - // ------------------------------------------------------------------- - // Collect vertex/face data - void CollectData( aiScene* pcScene, aiNode* pcNode, - unsigned int iMat, - unsigned int iVFormat, - aiMesh* pcMeshOut, - unsigned int aiCurrent[2], - unsigned int* num_refs); - - // ------------------------------------------------------------------- - // Get a list of all vertex formats that occur for a given material - // The output list contains duplicate elements - void GetVFormatList( aiScene* pcScene, unsigned int iMat, - std::list<unsigned int>& aiOut); - - // ------------------------------------------------------------------- - // Compute the absolute transformation matrices of each node - void ComputeAbsoluteTransform( aiNode* pcNode ); - - // ------------------------------------------------------------------- - // Simple routine to build meshes in worldspace, no further optimization - void BuildWCSMeshes(std::vector<aiMesh*>& out, aiMesh** in, - unsigned int numIn, aiNode* node); - - // ------------------------------------------------------------------- - // Apply the node transformation to a mesh - void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat); - - // ------------------------------------------------------------------- - // Reset transformation matrices to identity - void MakeIdentityTransform(aiNode* nd); - - // ------------------------------------------------------------------- - // Build reference counters for all meshes - void BuildMeshRefCountArray(aiNode* nd, unsigned int * refs); - - - - //! Configuration option: keep scene hierarchy as long as possible - bool configKeepHierarchy, configNormalize; - -}; - -} // end of namespace Assimp - -#endif // !!AI_GENFACENORMALPROCESS_H_INC diff --git a/3rdparty/assimp/code/ProcessHelper.h b/3rdparty/assimp/code/ProcessHelper.h deleted file mode 100644 index 4e8b1dec..00000000 --- a/3rdparty/assimp/code/ProcessHelper.h +++ /dev/null @@ -1,564 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef AI_PROCESS_HELPER_H_INCLUDED -#define AI_PROCESS_HELPER_H_INCLUDED - -#include "../include/aiPostProcess.h" - -#include "SpatialSort.h" -#include "BaseProcess.h" -#include "ParsingUtils.h" - -// ------------------------------------------------------------------------------- -// Some extensions to std namespace. Mainly std::min and std::max for all -// flat data types in the aiScene. They're used to quickly determine the -// min/max bounds of data arrays. -#ifdef __cplusplus -namespace std { - - // std::min for aiVector3D - inline ::aiVector3D min (const ::aiVector3D& a, const ::aiVector3D& b) { - return ::aiVector3D (min(a.x,b.x),min(a.y,b.y),min(a.z,b.z)); - } - - // std::max for aiVector3D - inline ::aiVector3D max (const ::aiVector3D& a, const ::aiVector3D& b) { - return ::aiVector3D (max(a.x,b.x),max(a.y,b.y),max(a.z,b.z)); - } - - // std::min for aiColor4D - inline ::aiColor4D min (const ::aiColor4D& a, const ::aiColor4D& b) { - return ::aiColor4D (min(a.r,b.r),min(a.g,b.g),min(a.b,b.b),min(a.a,b.a)); - } - - // std::max for aiColor4D - inline ::aiColor4D max (const ::aiColor4D& a, const ::aiColor4D& b) { - return ::aiColor4D (max(a.r,b.r),max(a.g,b.g),max(a.b,b.b),max(a.a,b.a)); - } - - // std::min for aiQuaternion - inline ::aiQuaternion min (const ::aiQuaternion& a, const ::aiQuaternion& b) { - return ::aiQuaternion (min(a.w,b.w),min(a.x,b.x),min(a.y,b.y),min(a.z,b.z)); - } - - // std::max for aiQuaternion - inline ::aiQuaternion max (const ::aiQuaternion& a, const ::aiQuaternion& b) { - return ::aiQuaternion (max(a.w,b.w),max(a.x,b.x),max(a.y,b.y),max(a.z,b.z)); - } - - // std::min for aiVectorKey - inline ::aiVectorKey min (const ::aiVectorKey& a, const ::aiVectorKey& b) { - return ::aiVectorKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue)); - } - - // std::max for aiVectorKey - inline ::aiVectorKey max (const ::aiVectorKey& a, const ::aiVectorKey& b) { - return ::aiVectorKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue)); - } - - // std::min for aiQuatKey - inline ::aiQuatKey min (const ::aiQuatKey& a, const ::aiQuatKey& b) { - return ::aiQuatKey (min(a.mTime,b.mTime),min(a.mValue,b.mValue)); - } - - // std::max for aiQuatKey - inline ::aiQuatKey max (const ::aiQuatKey& a, const ::aiQuatKey& b) { - return ::aiQuatKey (max(a.mTime,b.mTime),max(a.mValue,b.mValue)); - } - - // std::min for aiVertexWeight - inline ::aiVertexWeight min (const ::aiVertexWeight& a, const ::aiVertexWeight& b) { - return ::aiVertexWeight (min(a.mVertexId,b.mVertexId),min(a.mWeight,b.mWeight)); - } - - // std::max for aiVertexWeight - inline ::aiVertexWeight max (const ::aiVertexWeight& a, const ::aiVertexWeight& b) { - return ::aiVertexWeight (max(a.mVertexId,b.mVertexId),max(a.mWeight,b.mWeight)); - } - -} // end namespace std -#endif // !! C++ - -namespace Assimp { - -// ------------------------------------------------------------------------------- -// Start points for ArrayBounds<T> for all supported Ts -template <typename T> -struct MinMaxChooser; - -template <> struct MinMaxChooser<float> { - void operator ()(float& min,float& max) { - max = -10e10f; - min = 10e10f; -}}; -template <> struct MinMaxChooser<double> { - void operator ()(double& min,double& max) { - max = -10e10; - min = 10e10; -}}; -template <> struct MinMaxChooser<unsigned int> { - void operator ()(unsigned int& min,unsigned int& max) { - max = 0; - min = (1u<<(sizeof(unsigned int)*8-1)); -}}; - -template <> struct MinMaxChooser<aiVector3D> { - void operator ()(aiVector3D& min,aiVector3D& max) { - max = aiVector3D(-10e10f,-10e10f,-10e10f); - min = aiVector3D( 10e10f, 10e10f, 10e10f); -}}; -template <> struct MinMaxChooser<aiColor4D> { - void operator ()(aiColor4D& min,aiColor4D& max) { - max = aiColor4D(-10e10f,-10e10f,-10e10f,-10e10f); - min = aiColor4D( 10e10f, 10e10f, 10e10f, 10e10f); -}}; - -template <> struct MinMaxChooser<aiQuaternion> { - void operator ()(aiQuaternion& min,aiQuaternion& max) { - max = aiQuaternion(-10e10f,-10e10f,-10e10f,-10e10f); - min = aiQuaternion( 10e10f, 10e10f, 10e10f, 10e10f); -}}; - -template <> struct MinMaxChooser<aiVectorKey> { - void operator ()(aiVectorKey& min,aiVectorKey& max) { - MinMaxChooser<double>()(min.mTime,max.mTime); - MinMaxChooser<aiVector3D>()(min.mValue,max.mValue); -}}; -template <> struct MinMaxChooser<aiQuatKey> { - void operator ()(aiQuatKey& min,aiQuatKey& max) { - MinMaxChooser<double>()(min.mTime,max.mTime); - MinMaxChooser<aiQuaternion>()(min.mValue,max.mValue); -}}; - -template <> struct MinMaxChooser<aiVertexWeight> { - void operator ()(aiVertexWeight& min,aiVertexWeight& max) { - MinMaxChooser<unsigned int>()(min.mVertexId,max.mVertexId); - MinMaxChooser<float>()(min.mWeight,max.mWeight); -}}; - -// ------------------------------------------------------------------------------- -/** @brief Find the min/max values of an array of Ts - * @param in Input array - * @param size Numebr of elements to process - * @param[out] min minimum value - * @param[out] max maximum value - */ -template <typename T> -inline void ArrayBounds(const T* in, unsigned int size, T& min, T& max) -{ - MinMaxChooser<T> ()(min,max); - for (unsigned int i = 0; i < size;++i) { - min = std::min(in[i],min); - max = std::max(in[i],max); - } -} - -// ------------------------------------------------------------------------------- -/** @brief Extract single strings from a list of identifiers - * @param in Input string list. - * @param out Receives a list of clean output strings - * @sdee #AI_CONFIG_PP_OG_EXCLUDE_LIST - */ -inline void ConvertListToStrings(const std::string& in, std::list<std::string>& out) -{ - const char* s = in.c_str(); - while (*s) { - SkipSpacesAndLineEnd(&s); - if (*s == '\'') { - const char* base = ++s; - while (*s != '\'') { - ++s; - if (*s == '\0') { - DefaultLogger::get()->error("ConvertListToString: String list is ill-formatted"); - return; - } - } - out.push_back(std::string(base,(size_t)(s-base))); - ++s; - } - else { - out.push_back(GetNextToken(s)); - } - } -} - -// ------------------------------------------------------------------------------- -/** @brief Compute the newell normal of a polygon regardless of its shape - * - * @param out Receives the output normal - * @param num Number of input vertices - * @param x X data source. x[ofs_x*n] is the n'th element. - * @param y Y data source. y[ofs_y*n] is the y'th element - * @param z Z data source. z[ofs_z*n] is the z'th element - * - * @note The data arrays must have storage for at least num+2 elements. Using - * this method is much faster than the 'other' NewellNormal() - */ -template <int ofs_x, int ofs_y, int ofs_z> -inline void NewellNormal (aiVector3D& out, int num, float* x, float* y, float* z) -{ - // Duplicate the first two vertices at the end - x[(num+0)*ofs_x] = x[0]; - x[(num+1)*ofs_x] = x[ofs_x]; - - y[(num+0)*ofs_y] = y[0]; - y[(num+1)*ofs_y] = y[ofs_y]; - - z[(num+0)*ofs_z] = z[0]; - z[(num+1)*ofs_z] = z[ofs_z]; - - float sum_xy = 0.0, sum_yz = 0.0, sum_zx = 0.0; - - float *xptr = x +ofs_x, *xlow = x, *xhigh = x + ofs_x*2; - float *yptr = y +ofs_y, *ylow = y, *yhigh = y + ofs_y*2; - float *zptr = z +ofs_z, *zlow = z, *zhigh = z + ofs_z*2; - - for (int tmp=0; tmp < num; tmp++) { - sum_xy += (*xptr) * ( (*yhigh) - (*ylow) ); - sum_yz += (*yptr) * ( (*zhigh) - (*zlow) ); - sum_zx += (*zptr) * ( (*xhigh) - (*xlow) ); - - xptr += ofs_x; - xlow += ofs_x; - xhigh += ofs_x; - - yptr += ofs_y; - ylow += ofs_y; - yhigh += ofs_y; - - zptr += ofs_z; - zlow += ofs_z; - zhigh += ofs_z; - } - out = aiVector3D(sum_yz,sum_zx,sum_xy); -} - -#if 0 -// ------------------------------------------------------------------------------- -/** @brief Compute newell normal of a polgon regardless of its shape - * - * @param out Receives the output normal - * @param data Input vertices - * @param idx Index buffer - * @param num Number of indices - */ -inline void NewellNormal (aiVector3D& out, const aiVector3D* data, unsigned int* idx, unsigned int num ) -{ - // TODO: intended to be used in GenNormals. -} -#endif - -// ------------------------------------------------------------------------------- -/** Little helper function to calculate the quadratic difference - * of two colours. - * @param pColor1 First color - * @param pColor2 second color - * @return Quadratic color difference - */ -inline float GetColorDifference( const aiColor4D& pColor1, const aiColor4D& pColor2) -{ - const aiColor4D c (pColor1.r - pColor2.r, pColor1.g - pColor2.g, - pColor1.b - pColor2.b, pColor1.a - pColor2.a); - - return c.r*c.r + c.g*c.g + c.b*c.b + c.a*c.a; -} - -// ------------------------------------------------------------------------------- -/** @brief Compute the AABB of a mesh after applying a given transform - * @param mesh Input mesh - * @param[out] min Receives minimum transformed vertex - * @param[out] max Receives maximum transformed vertex - * @param m Transformation matrix to be applied - */ -inline void FindAABBTransformed (const aiMesh* mesh, aiVector3D& min, aiVector3D& max, - const aiMatrix4x4& m) -{ - min = aiVector3D (10e10f, 10e10f, 10e10f); - max = aiVector3D (-10e10f,-10e10f,-10e10f); - for (unsigned int i = 0;i < mesh->mNumVertices;++i) - { - const aiVector3D v = m * mesh->mVertices[i]; - min = std::min(v,min); - max = std::max(v,max); - } -} - -// ------------------------------------------------------------------------------- -/** @brief Helper function to determine the 'real' center of a mesh - * - * That is the center of its axis-aligned bounding box. - * @param mesh Input mesh - * @param[out] min Minimum vertex of the mesh - * @param[out] max maximum vertex of the mesh - * @param[out] out Center point - */ -inline void FindMeshCenter (aiMesh* mesh, aiVector3D& out, aiVector3D& min, aiVector3D& max) -{ - ArrayBounds(mesh->mVertices,mesh->mNumVertices, min,max); - out = min + (max-min)*0.5f; -} - -// ------------------------------------------------------------------------------- -// Helper function to determine the 'real' center of a mesh after applying a given transform -inline void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, aiVector3D& min, - aiVector3D& max, const aiMatrix4x4& m) -{ - FindAABBTransformed(mesh,min,max,m); - out = min + (max-min)*0.5f; -} - -// ------------------------------------------------------------------------------- -// Helper function to determine the 'real' center of a mesh -inline void FindMeshCenter (aiMesh* mesh, aiVector3D& out) -{ - aiVector3D min,max; - FindMeshCenter(mesh,out,min,max); -} - -// ------------------------------------------------------------------------------- -// Helper function to determine the 'real' center of a mesh after applying a given transform -inline void FindMeshCenterTransformed (aiMesh* mesh, aiVector3D& out, - const aiMatrix4x4& m) -{ - aiVector3D min,max; - FindMeshCenterTransformed(mesh,out,min,max,m); -} - -// ------------------------------------------------------------------------------- -// Compute a good epsilon value for position comparisons on a mesh -inline float ComputePositionEpsilon(const aiMesh* pMesh) -{ - const float epsilon = 1e-4f; - - // calculate the position bounds so we have a reliable epsilon to check position differences against - aiVector3D minVec, maxVec; - ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,minVec,maxVec); - return (maxVec - minVec).Length() * epsilon; -} - -// ------------------------------------------------------------------------------- -// Compute a good epsilon value for position comparisons on a array of meshes -inline float ComputePositionEpsilon(const aiMesh* const* pMeshes, size_t num) -{ - const float epsilon = 1e-4f; - - // calculate the position bounds so we have a reliable epsilon to check position differences against - aiVector3D minVec, maxVec, mi, ma; - MinMaxChooser<aiVector3D>()(minVec,maxVec); - - for (size_t a = 0; a < num; ++a) { - const aiMesh* pMesh = pMeshes[a]; - ArrayBounds(pMesh->mVertices,pMesh->mNumVertices,mi,ma); - - minVec = std::min(minVec,mi); - maxVec = std::max(maxVec,ma); - } - return (maxVec - minVec).Length() * epsilon; -} - -// ------------------------------------------------------------------------------- -// Compute an unique value for the vertex format of a mesh -inline unsigned int GetMeshVFormatUnique(aiMesh* pcMesh) -{ - ai_assert(NULL != pcMesh); - - // FIX: the hash may never be 0. Otherwise a comparison against - // nullptr could be successful - unsigned int iRet = 1; - - // normals - if (pcMesh->HasNormals())iRet |= 0x2; - // tangents and bitangents - if (pcMesh->HasTangentsAndBitangents())iRet |= 0x4; - -#ifdef BOOST_STATIC_ASSERT - BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_COLOR_SETS); - BOOST_STATIC_ASSERT(8 >= AI_MAX_NUMBER_OF_TEXTURECOORDS); -#endif - - // texture coordinates - unsigned int p = 0; - while (pcMesh->HasTextureCoords(p)) - { - iRet |= (0x100 << p); - if (3 == pcMesh->mNumUVComponents[p]) - iRet |= (0x10000 << p); - - ++p; - } - // vertex colors - p = 0; - while (pcMesh->HasVertexColors(p))iRet |= (0x1000000 << p++); - return iRet; -} - -typedef std::pair <unsigned int,float> PerVertexWeight; -typedef std::vector <PerVertexWeight> VertexWeightTable; - -// ------------------------------------------------------------------------------- -// Compute a per-vertex bone weight table -// please .... delete result with operator delete[] ... -inline VertexWeightTable* ComputeVertexBoneWeightTable(aiMesh* pMesh) -{ - if (!pMesh || !pMesh->mNumVertices || !pMesh->mNumBones) - return NULL; - - VertexWeightTable* avPerVertexWeights = new VertexWeightTable[pMesh->mNumVertices]; - for (unsigned int i = 0; i < pMesh->mNumBones;++i) - { - aiBone* bone = pMesh->mBones[i]; - for (unsigned int a = 0; a < bone->mNumWeights;++a) { - const aiVertexWeight& weight = bone->mWeights[a]; - avPerVertexWeights[weight.mVertexId].push_back( - std::pair<unsigned int,float>(i,weight.mWeight)); - } - } - return avPerVertexWeights; -} - -// ------------------------------------------------------------------------------- -// Get a string for a given aiTextureType -inline const char* TextureTypeToString(aiTextureType in) -{ - switch (in) - { - case aiTextureType_NONE: - return "n/a"; - case aiTextureType_DIFFUSE: - return "Diffuse"; - case aiTextureType_SPECULAR: - return "Specular"; - case aiTextureType_AMBIENT: - return "Ambient"; - case aiTextureType_EMISSIVE: - return "Emissive"; - case aiTextureType_OPACITY: - return "Opacity"; - case aiTextureType_NORMALS: - return "Normals"; - case aiTextureType_HEIGHT: - return "Height"; - case aiTextureType_SHININESS: - return "Shininess"; - case aiTextureType_DISPLACEMENT: - return "Displacement"; - case aiTextureType_LIGHTMAP: - return "Lightmap"; - case aiTextureType_REFLECTION: - return "Reflection"; - case aiTextureType_UNKNOWN: - return "Unknown"; - default: - return "HUGE ERROR. Expect BSOD (linux guys: kernel panic ...)."; - } -} - -// ------------------------------------------------------------------------------- -// Get a string for a given aiTextureMapping -inline const char* MappingTypeToString(aiTextureMapping in) -{ - switch (in) - { - case aiTextureMapping_UV: - return "UV"; - case aiTextureMapping_BOX: - return "Box"; - case aiTextureMapping_SPHERE: - return "Sphere"; - case aiTextureMapping_CYLINDER: - return "Cylinder"; - case aiTextureMapping_PLANE: - return "Plane"; - case aiTextureMapping_OTHER: - return "Other"; - default: - return "HUGE ERROR. Expect BSOD (linux guys: kernel panic ...)."; - } -} - -// ------------------------------------------------------------------------------- -// Utility postprocess step to share the spatial sort tree between -// all steps which use it to speedup its computations. -class ComputeSpatialSortProcess : public BaseProcess -{ - bool IsActive( unsigned int pFlags) const - { - return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace | - aiProcess_GenNormals | aiProcess_JoinIdenticalVertices)); - } - - void Execute( aiScene* pScene) - { - typedef std::pair<SpatialSort, float> _Type; - DefaultLogger::get()->debug("Generate spatially-sorted vertex cache"); - - std::vector<_Type>* p = new std::vector<_Type>(pScene->mNumMeshes); - std::vector<_Type>::iterator it = p->begin(); - - for (unsigned int i = 0; i < pScene->mNumMeshes; ++i, ++it) { - aiMesh* mesh = pScene->mMeshes[i]; - _Type& blubb = *it; - blubb.first.Fill(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D)); - blubb.second = ComputePositionEpsilon(mesh); - } - - shared->AddProperty(AI_SPP_SPATIAL_SORT,p); - } -}; - -// ------------------------------------------------------------------------------- -// ... and the same again to cleanup the whole stuff -class DestroySpatialSortProcess : public BaseProcess -{ - bool IsActive( unsigned int pFlags) const - { - return NULL != shared && 0 != (pFlags & (aiProcess_CalcTangentSpace | - aiProcess_GenNormals | aiProcess_JoinIdenticalVertices)); - } - - void Execute( aiScene* pScene) - { - shared->RemoveProperty(AI_SPP_SPATIAL_SORT); - } -}; - -} // ! namespace Assimp -#endif // !! AI_PROCESS_HELPER_H_INCLUDED diff --git a/3rdparty/assimp/code/Profiler.h b/3rdparty/assimp/code/Profiler.h deleted file mode 100644 index 74fed429..00000000 --- a/3rdparty/assimp/code/Profiler.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Profiler.h - * @brief Utility to measure the respective runtime of each import step - */ -#ifndef INCLUDED_PROFILER_H -#define INCLUDED_PROFILER_H - -#include "boost/timer.hpp" - -#include "../include/DefaultLogger.h" -#include "TinyFormatter.h" - -namespace Assimp { - namespace Profiling { - - using namespace Formatter; - - -// ------------------------------------------------------------------------------------------------ -/** Simple wrapper around boost::timer to simplify reporting. Timings are automatically - * dumped to the log file. - */ -class Profiler -{ - -public: - - Profiler() {} - -public: - - /** Start a named timer */ - void BeginRegion(const std::string& region) { - regions[region] = boost::timer(); - DefaultLogger::get()->debug((format("START `"),region,"`")); - } - - - /** End a specific named timer and write its end time to the log */ - void EndRegion(const std::string& region) { - RegionMap::const_iterator it = regions.find(region); - if (it == regions.end()) { - return; - } - - DefaultLogger::get()->debug((format("END `"),region,"`, dt= ",(*it).second.elapsed()," s")); - } - -private: - - typedef std::map<std::string,boost::timer> RegionMap; - RegionMap regions; -}; - - } -} - -#endif diff --git a/3rdparty/assimp/code/Q3BSPFileData.h b/3rdparty/assimp/code/Q3BSPFileData.h deleted file mode 100644 index eb3ae828..00000000 --- a/3rdparty/assimp/code/Q3BSPFileData.h +++ /dev/null @@ -1,228 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ -#ifndef ASSIMP_Q3BSPFILEDATA_H_INC -#define ASSIMP_Q3BSPFILEDATA_H_INC - -#include <vector> - -namespace Assimp -{ -namespace Q3BSP -{ - -static const unsigned int CE_BSP_LIGHTMAPWIDTH = 128; -static const unsigned int CE_BSP_LIGHTMAPHEIGHT = 128; - -static const unsigned int CE_BSP_LIGHTMAPSIZE = 128*128*3; ///< = 128( width ) * 128 ( height ) * 3 ( channels / RGB ). -static const int VERION_Q3LEVEL = 46; ///< Supported version. - -/// Geometric type enumeration -enum Q3BSPGeoType -{ - Polygon = 1, - Patch, - TriangleMesh, - Billboard -}; - -/// Integer vector. -struct ceVec3i -{ - int x, y, z; - ceVec3i(): x( 0 ), y( 0 ), z( 0 ) { /* empty */ } - ceVec3i( int iX, int iY=0, int iZ=0) : x( iX ), y( iY ), z( iZ ) { /* empty */ } -}; - -/// Fileheader -struct sQ3BSPHeader -{ - char strID[ 4 ]; //!< Should be "IBSP" - int iVersion; //!< 46 for standard levels -}; - -/// Descripes an entry. -struct sQ3BSPLump -{ - int iOffset; ///< Offset from startpointer of file - int iSize; ///< Size fo part -}; - -struct vec2f -{ - float x,y; -}; - -struct vec3f -{ - float x, y, z; -}; - -/// Vertex of a Q3 level -struct sQ3BSPVertex -{ - vec3f vPosition; ///< Position of vertex - vec2f vTexCoord; ///< (u,v) Texturecoordinate of detailtexture - vec2f vLightmap; ///< (u,v) Texturecoordinate of lightmap - vec3f vNormal; ///< vertex normale - unsigned char bColor[ 4 ]; ///< Color in RGBA -}; - -/// A face in bsp format info -struct sQ3BSPFace -{ - int iTextureID; ///< Index in texture array - int iEffect; ///< Index in effectarray (-1 = no effect) - int iType; ///< 1=Polygon, 2=Patch, 3=Mesh, 4=Billboard - int iVertexIndex; ///< Start index of polygon - int iNumOfVerts; ///< Number of vertices - int iFaceVertexIndex; ///< Index of first mesh vertex - int iNumOfFaceVerts; ///< Anzahl der Meshvertices - int iLightmapID; ///< Index to the lightmap array - int iLMapCorner[ 2 ]; ///< Die Ecke der Lightmap in der Textur - int iLMapSize[ 2 ]; ///< Size of the lightmap stored on the texture - vec3f vLMapPos; ///< 3D-Ursprung der Lightmap - vec3f vLMapVecs[ 2 ]; ///< 3D-s-t-Vektoren - vec3f vNormal; ///< Polygonnormale - int patchWidth, patchHeight; ///< bezier patch -}; - -/// A quake3 texture name. -struct sQ3BSPTexture -{ - char strName[ 64 ]; ///< Name of the texture without extention - int iFlags; ///< Not used - int iContents; ///< Not used -}; - -/// A lightmap of the level, size 128 x 128, RGB components. -struct sQ3BSPLightmap -{ - unsigned char bLMapData[ CE_BSP_LIGHTMAPSIZE ]; - sQ3BSPLightmap() - { - memset(bLMapData, 0, CE_BSP_LIGHTMAPSIZE ); - } -}; - -struct SubPatch -{ - std::vector<size_t> indices; - int lightmapID; -}; - -enum eLumps -{ - kEntities = 0, - kTextures, - kPlanes, - kNodes, - kLeafs, - kLeafFaces, - kLeafBrushes, - kModels, - kBrushes, - kBrushSides, - kVertices, - kMeshVerts, - kShaders, - kFaces, - kLightmaps, - kLightVolumes, - kVisData, - kMaxLumps -}; - -struct Q3BSPModel -{ - std::vector<unsigned char> m_Data; - std::vector<sQ3BSPLump*> m_Lumps; - std::vector<sQ3BSPVertex*> m_Vertices; - std::vector<sQ3BSPFace*> m_Faces; - std::vector<int> m_Indices; - std::vector<sQ3BSPTexture*> m_Textures; - std::vector<sQ3BSPLightmap*> m_Lightmaps; - std::vector<char> m_EntityData; - std::string m_ModelName; - - Q3BSPModel() : - m_Data(), - m_Lumps(), - m_Vertices(), - m_Faces(), - m_Indices(), - m_Textures(), - m_Lightmaps(), - m_EntityData(), - m_ModelName( "" ) - { - // empty - } - - ~Q3BSPModel() - { - for ( unsigned int i=0; i<m_Lumps.size(); i++ ) - if ( NULL != m_Lumps[i] ) - delete m_Lumps[i]; - - for ( unsigned int i=0; i<m_Vertices.size(); i++ ) - if ( NULL != m_Vertices[ i ] ) - delete m_Vertices[ i ]; - for ( unsigned int i=0; i<m_Faces.size(); i++ ) - if ( NULL != m_Faces[ i ] ) - delete m_Faces[ i ]; - for ( unsigned int i=0; i<m_Textures.size(); i++ ) - if ( NULL != m_Textures[ i ] ) - delete m_Textures[ i ]; - for ( unsigned int i=0; i<m_Lightmaps.size(); i++ ) - if ( NULL != m_Lightmaps[ i ] ) - delete m_Lightmaps[ i ]; - - m_Lumps.clear(); - m_Vertices.clear(); - m_Faces.clear(); - m_Textures.clear(); - m_Lightmaps.clear(); - } -}; - -} // Namespace Q3BSP -} // Namespace Assimp - -#endif // ASSIMP_Q3BSPFILEDATA_H_INC diff --git a/3rdparty/assimp/code/Q3BSPFileImporter.cpp b/3rdparty/assimp/code/Q3BSPFileImporter.cpp deleted file mode 100644 index dab913fb..00000000 --- a/3rdparty/assimp/code/Q3BSPFileImporter.cpp +++ /dev/null @@ -1,731 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ---------------------------------------------------------------------------------------------------- -*/ -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER - -//#include <windows.h> -#include "DefaultIOSystem.h" -#include "Q3BSPFileImporter.h" -#include "Q3BSPZipArchive.h" -#include "Q3BSPFileParser.h" -#include "Q3BSPFileData.h" - -#ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include <zlib.h> -#else -# include "../contrib/zlib/zlib.h" -#endif - -#include "../include/aiTypes.h" -#include "../include/aiMesh.h" -#include <vector> - -namespace Assimp -{ - -using namespace Q3BSP; - -static const std::string Q3BSPExtention = "pk3"; - -// ------------------------------------------------------------------------------------------------ -// Local fnction to create a material keyname. -static void createKey( int id1, int id2, std::string &rKey ) -{ - std::stringstream str; - str << id1 << "." << id2; - rKey = str.str(); -} - -// ------------------------------------------------------------------------------------------------ -// Local function to extract the texture ids from a material keyname. -static void extractIds( const std::string &rKey, int &rId1, int &rId2 ) -{ - rId1 = -1; - rId2 = -1; - if ( rKey.empty() ) - return; - - std::string::size_type pos = rKey.find( "." ); - if ( std::string::npos == pos ) - return; - - std::string tmp1 = rKey.substr( 0, pos ); - std::string tmp2 = rKey.substr( pos + 1, rKey.size() - pos - 1 ); - rId1 = atoi( tmp1.c_str() ); - rId2 = atoi( tmp2.c_str() ); -} - -// ------------------------------------------------------------------------------------------------ -// Local helper fuction to normalize filenames. -static void normalizePathName( const std::string &rPath, std::string &rNormalizedPath ) -{ - rNormalizedPath = ""; - if ( rPath.empty() ) - return; - -#ifdef _WIN32 - std::string sep = "\\"; -#else - std::string sep = "/"; -#endif - - static const unsigned int numDelimiters = 2; - const char delimiters[ numDelimiters ] = { '/', '\\' }; - rNormalizedPath = rPath; - for ( unsigned int i=0; i<numDelimiters; i++ ) - { - for ( size_t j=0; j<rNormalizedPath.size(); j++ ) - { - if ( rNormalizedPath[j] == delimiters[ i ] ) - { - rNormalizedPath[ j ] = sep[ 0 ]; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Constructor. -Q3BSPFileImporter::Q3BSPFileImporter() : - m_pCurrentMesh( NULL ), - m_pCurrentFace( NULL ), - m_MaterialLookupMap(), - mTextures() -{ - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -Q3BSPFileImporter::~Q3BSPFileImporter() -{ - // For lint - m_pCurrentMesh = NULL; - m_pCurrentFace = NULL; - - // Clear face-to-material map - for ( FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); - ++it ) - { - const std::string matName = (*it).first; - if ( matName.empty() ) - { - continue; - } - - std::vector<Q3BSP::sQ3BSPFace*> *pCurFaceArray = (*it).second; - if ( NULL != pCurFaceArray ) - { - delete pCurFaceArray; - } - } - m_MaterialLookupMap.clear(); -} - -// ------------------------------------------------------------------------------------------------ -// Returns true, if the loader can read this. -bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* pIOHandler, bool checkSig ) const -{ - bool isBSPData = false; - if ( checkSig ) - isBSPData = SimpleExtensionCheck( rFile, Q3BSPExtention.c_str() ); - - return isBSPData; -} - -// ------------------------------------------------------------------------------------------------ -// Adds extensions. -void Q3BSPFileImporter::GetExtensionList( std::set<std::string>& extensions ) -{ - extensions.insert( Q3BSPExtention ); -} - -// ------------------------------------------------------------------------------------------------ -// Import method. -void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene* pScene, IOSystem* pIOHandler) -{ - Q3BSPZipArchive Archive( rFile ); - if ( !Archive.isOpen() ) - { - throw new DeadlyImportError( "Failed to open file " + rFile + "." ); - } - - std::string archiveName( "" ), mapName( "" ); - separateMapName( rFile, archiveName, mapName ); - - if ( mapName.empty() ) - { - if ( !findFirstMapInArchive( Archive, mapName ) ) - { - return; - } - } - - Q3BSPFileParser fileParser( mapName, &Archive ); - Q3BSPModel *pBSPModel = fileParser.getModel(); - if ( NULL != pBSPModel ) - { - CreateDataFromImport( pBSPModel, pScene, &Archive ); - } -} - -// ------------------------------------------------------------------------------------------------ -// Separates the map name from the import name. -void Q3BSPFileImporter::separateMapName( const std::string &rImportName, std::string &rArchiveName, - std::string &rMapName ) -{ - rArchiveName = ""; - rMapName = ""; - if ( rImportName.empty() ) - return; - - std::string::size_type pos = rImportName.rfind( "," ); - if ( std::string::npos == pos ) - { - rArchiveName = rImportName; - return; - } - - rArchiveName = rImportName.substr( 0, pos ); - rMapName = rImportName.substr( pos, rImportName.size() - pos - 1 ); -} - -// ------------------------------------------------------------------------------------------------ -// Returns the first map in the map archive. -bool Q3BSPFileImporter::findFirstMapInArchive( Q3BSPZipArchive &rArchive, std::string &rMapName ) -{ - rMapName = ""; - std::vector<std::string> fileList; - rArchive.getFileList( fileList ); - if ( fileList.empty() ) - return false; - - for ( std::vector<std::string>::iterator it = fileList.begin(); it != fileList.end(); - ++it ) - { - std::string::size_type pos = (*it).find( "maps/" ); - if ( std::string::npos != pos ) - { - std::string::size_type extPos = (*it).find( ".bsp" ); - if ( std::string::npos != extPos ) - { - rMapName = *it; - return true; - } - } - } - - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Creates the assimp specific data. -void Q3BSPFileImporter::CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - Q3BSPZipArchive *pArchive ) -{ - if ( NULL == pModel || NULL == pScene ) - return; - - pScene->mRootNode = new aiNode; - if ( !pModel->m_ModelName.empty() ) - { - pScene->mRootNode->mName.Set( pModel->m_ModelName ); - } - - // Create the face to material relation map - createMaterialMap( pModel ); - - // Create all nodes - CreateNodes( pModel, pScene, pScene->mRootNode ); - - // Create the assigned materials - createMaterials( pModel, pScene, pArchive ); -} - -// ------------------------------------------------------------------------------------------------ -// Creates all assimp nodes. -void Q3BSPFileImporter::CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - aiNode *pParent ) -{ - ai_assert( NULL != pModel ); - if ( NULL == pModel ) - { - return; - } - - unsigned int matIdx = 0; - std::vector<aiMesh*> MeshArray; - std::vector<aiNode*> NodeArray; - for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it ) - { - std::vector<Q3BSP::sQ3BSPFace*> *pArray = (*it).second; - size_t numVerts = countData( *pArray ); - if ( 0 != numVerts ) - { - aiMesh* pMesh = new aiMesh; - aiNode *pNode = CreateTopology( pModel, matIdx, *pArray, pMesh ); - if ( NULL != pNode ) - { - NodeArray.push_back( pNode ); - MeshArray.push_back( pMesh ); - } - else - { - delete pMesh; - } - } - matIdx++; - } - - pScene->mNumMeshes = MeshArray.size(); - if ( pScene->mNumMeshes > 0 ) - { - pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; - for ( size_t i = 0; i < MeshArray.size(); i++ ) - { - aiMesh *pMesh = MeshArray[ i ]; - if ( NULL != pMesh ) - { - pScene->mMeshes[ i ] = pMesh; - } - } - } - - pParent->mNumChildren = MeshArray.size(); - pParent->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren ]; - for ( size_t i=0; i<NodeArray.size(); i++ ) - { - aiNode *pNode = NodeArray[ i ]; - pNode->mParent = pParent; - pParent->mChildren[ i ] = pNode; - pParent->mChildren[ i ]->mMeshes[ 0 ] = i; - } -} - -// ------------------------------------------------------------------------------------------------ -// Creates the topology. -aiNode *Q3BSPFileImporter::CreateTopology( const Q3BSP::Q3BSPModel *pModel, - unsigned int materialIdx, - std::vector<sQ3BSPFace*> &rArray, - aiMesh* pMesh ) -{ - size_t numVerts = countData( rArray ); - if ( 0 == numVerts ) - { - return NULL; - } - - size_t numFaces = countFaces( rArray ); - if ( 0 == numFaces ) - { - return NULL; - } - - size_t numTriangles = countTriangles( rArray ); - pMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - pMesh->mFaces = new aiFace[ numTriangles ]; - pMesh->mNumFaces = numTriangles; - - pMesh->mNumVertices = numVerts; - pMesh->mVertices = new aiVector3D[ numVerts ]; - pMesh->mNormals = new aiVector3D[ numVerts ]; - pMesh->mTextureCoords[ 0 ] = new aiVector3D[ numVerts ]; - pMesh->mTextureCoords[ 1 ] = new aiVector3D[ numVerts ]; - pMesh->mMaterialIndex = materialIdx; - - unsigned int faceIdx = 0; - unsigned int vertIdx = 0; - pMesh->mNumUVComponents[ 0 ] = 2; - pMesh->mNumUVComponents[ 1 ] = 2; - for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); ++it ) - { - Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - ai_assert( NULL != pQ3BSPFace ); - if ( NULL == pQ3BSPFace ) - { - continue; - } - - if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) - { - if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) - { - createTriangleTopology( pModel, pQ3BSPFace, pMesh, faceIdx, vertIdx ); - } - } - } - - aiNode *pNode = new aiNode; - pNode->mNumMeshes = 1; - pNode->mMeshes = new unsigned int[ 1 ]; - - return pNode; -} - -// ------------------------------------------------------------------------------------------------ -// Creates the triangle topology from a face array. -void Q3BSPFileImporter::createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, - Q3BSP::sQ3BSPFace *pQ3BSPFace, - aiMesh* pMesh, - unsigned int &rFaceIdx, - unsigned int &rVertIdx ) -{ - ai_assert( rFaceIdx < pMesh->mNumFaces ); - - m_pCurrentFace = getNextFace( pMesh, rFaceIdx ); - ai_assert( NULL != m_pCurrentFace ); - if ( NULL == m_pCurrentFace ) - { - return; - } - - m_pCurrentFace->mNumIndices = 3; - m_pCurrentFace->mIndices = new unsigned int[ m_pCurrentFace->mNumIndices ]; - - size_t idx = 0; - for ( size_t i = 0; i < (size_t) pQ3BSPFace->iNumOfFaceVerts; i++ ) - { - const size_t index = pQ3BSPFace->iVertexIndex + pModel->m_Indices[ pQ3BSPFace->iFaceVertexIndex + i ]; - ai_assert( index < pModel->m_Vertices.size() ); - if ( index >= pModel->m_Vertices.size() ) - { - continue; - } - - sQ3BSPVertex *pVertex = pModel->m_Vertices[ index ]; - ai_assert( NULL != pVertex ); - if ( NULL == pVertex ) - { - continue; - } - - pMesh->mVertices[ rVertIdx ].Set( pVertex->vPosition.x, pVertex->vPosition.y, pVertex->vPosition.z ); - pMesh->mNormals[ rVertIdx ].Set( pVertex->vNormal.x, pVertex->vNormal.y, pVertex->vNormal.z ); - - pMesh->mTextureCoords[ 0 ][ rVertIdx ].Set( pVertex->vTexCoord.x, pVertex->vTexCoord.y, 0.0f ); - pMesh->mTextureCoords[ 1 ][ rVertIdx ].Set( pVertex->vLightmap.x, pVertex->vLightmap.y, 0.0f ); - - m_pCurrentFace->mIndices[ idx ] = rVertIdx; - rVertIdx++; - - idx++; - if ( idx > 2 ) - { - idx = 0; - m_pCurrentFace = getNextFace( pMesh, rFaceIdx ); - if ( NULL != m_pCurrentFace ) - { - m_pCurrentFace->mNumIndices = 3; - m_pCurrentFace->mIndices = new unsigned int[ 3 ]; - } - } - } - rFaceIdx--; -} - -// ------------------------------------------------------------------------------------------------ -// Creates all referenced materials. -void Q3BSPFileImporter::createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - Q3BSPZipArchive *pArchive ) -{ - if ( m_MaterialLookupMap.empty() ) - { - return; - } - - pScene->mMaterials = new aiMaterial*[ m_MaterialLookupMap.size() ]; - size_t texIdx( 0 ); - aiString aiMatName; - int textureId( -1 ), lightmapId( -1 ); - for ( FaceMapIt it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); - ++it ) - { - const std::string matName = (*it).first; - if ( matName.empty() ) - { - continue; - } - - aiMatName.Set( matName ); - Assimp::MaterialHelper *pMatHelper = new Assimp::MaterialHelper; - pMatHelper->AddProperty( &aiMatName, AI_MATKEY_NAME ); - - extractIds( matName, textureId, lightmapId ); - - // Adding the texture - if ( -1 != textureId ) - { - sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; - if ( NULL != pTexture ) - { - std::string tmp( "*" ), texName( "" ); - tmp += pTexture->strName; - tmp += ".jpg"; - normalizePathName( tmp, texName ); - - if ( !importTextureFromArchive( pModel, pArchive, pScene, pMatHelper, textureId ) ) - { - } - } - - } - if ( -1 != lightmapId ) - { - importLightmap( pModel, pScene, pMatHelper, lightmapId ); - } - pScene->mMaterials[ pScene->mNumMaterials ] = pMatHelper; - pScene->mNumMaterials++; - } - pScene->mNumTextures = mTextures.size(); - pScene->mTextures = new aiTexture*[ pScene->mNumTextures ]; - std::copy( mTextures.begin(), mTextures.end(), pScene->mTextures ); -} - -// ------------------------------------------------------------------------------------------------ -// Counts the number of referenced vertices. -size_t Q3BSPFileImporter::countData( const std::vector<sQ3BSPFace*> &rArray ) const -{ - size_t numVerts = 0; - for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); - ++it ) - { - sQ3BSPFace *pQ3BSPFace = *it; - if ( pQ3BSPFace->iType == Polygon || pQ3BSPFace->iType == TriangleMesh ) - { - Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - ai_assert( NULL != pQ3BSPFace ); - numVerts += pQ3BSPFace->iNumOfFaceVerts; - } - } - - return numVerts; -} - -// ------------------------------------------------------------------------------------------------ -// Counts the faces with vertices. -size_t Q3BSPFileImporter::countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const -{ - size_t numFaces = 0; - for ( std::vector<sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); - ++it ) - { - Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - if ( pQ3BSPFace->iNumOfFaceVerts > 0 ) - { - numFaces++; - } - } - - return numFaces; -} - -// ------------------------------------------------------------------------------------------------ -// Counts the number of triangles in a Q3-facearray. -size_t Q3BSPFileImporter::countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const -{ - size_t numTriangles = 0; - for ( std::vector<Q3BSP::sQ3BSPFace*>::const_iterator it = rArray.begin(); it != rArray.end(); - ++it ) - { - const Q3BSP::sQ3BSPFace *pQ3BSPFace = *it; - if ( NULL != pQ3BSPFace ) - { - numTriangles += pQ3BSPFace->iNumOfFaceVerts / 3; - } - } - - return numTriangles; -} - -// ------------------------------------------------------------------------------------------------ -// Creates the faces-to-material map. -void Q3BSPFileImporter::createMaterialMap( const Q3BSP::Q3BSPModel *pModel ) -{ - std::string key( "" ); - std::vector<sQ3BSPFace*> *pCurFaceArray = NULL; - for ( size_t idx = 0; idx < pModel->m_Faces.size(); idx++ ) - { - Q3BSP::sQ3BSPFace *pQ3BSPFace = pModel->m_Faces[ idx ]; - const int texId = pQ3BSPFace->iTextureID; - const int lightMapId = pQ3BSPFace->iLightmapID; - createKey( texId, lightMapId, key ); - FaceMapIt it = m_MaterialLookupMap.find( key ); - if ( m_MaterialLookupMap.end() == it ) - { - pCurFaceArray = new std::vector<Q3BSP::sQ3BSPFace*>; - m_MaterialLookupMap[ key ] = pCurFaceArray; - } - else - { - pCurFaceArray = (*it).second; - } - ai_assert( NULL != pCurFaceArray ); - if ( NULL != pCurFaceArray ) - { - pCurFaceArray->push_back( pQ3BSPFace ); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Returns the next face. -aiFace *Q3BSPFileImporter::getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx ) -{ - aiFace *pFace = NULL; - if ( rFaceIdx < pMesh->mNumFaces ) - { - pFace = &pMesh->mFaces[ rFaceIdx ]; - rFaceIdx++; - } - else - { - pFace = NULL; - } - - return pFace; -} - -// ------------------------------------------------------------------------------------------------ -// Imports a texture file. -bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, - Q3BSP::Q3BSPZipArchive *pArchive, aiScene* pScene, - Assimp::MaterialHelper *pMatHelper, int textureId ) -{ - if ( NULL == pArchive || NULL == pArchive || NULL == pMatHelper ) - { - return false; - } - - if ( textureId < 0 || textureId >= static_cast<int>( pModel->m_Textures.size() ) ) - { - return false; - } - - bool res = true; - sQ3BSPTexture *pTexture = pModel->m_Textures[ textureId ]; - if ( NULL == pTexture ) - return false; - - std::string textureName = pTexture->strName; - textureName += ".jpg"; - if ( pArchive->Exists( textureName.c_str() ) ) - { - IOStream *pTextureStream = pArchive->Open( textureName.c_str() ); - if ( NULL != pTextureStream ) - { - size_t texSize = pTextureStream->FileSize(); - aiTexture *pTexture = new aiTexture; - pTexture->mHeight = 0; - pTexture->mWidth = texSize; - unsigned char *pData = new unsigned char[ pTexture->mWidth ]; - size_t readSize = pTextureStream->Read( pData, sizeof( unsigned char ), pTexture->mWidth ); - ai_assert( readSize == pTexture->mWidth ); - pTexture->pcData = reinterpret_cast<aiTexel*>( pData ); - pTexture->achFormatHint[ 0 ] = 'j'; - pTexture->achFormatHint[ 1 ] = 'p'; - pTexture->achFormatHint[ 2 ] = 'g'; - pTexture->achFormatHint[ 2 ] = '\0'; - res = true; - - aiString name; - name.data[ 0 ] = '*'; - name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() ); - - pArchive->Close( pTextureStream ); - - pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); - mTextures.push_back( pTexture ); - } - } - - return res; -} - -// ------------------------------------------------------------------------------------------------ -// Imports a lightmap file. -bool Q3BSPFileImporter::importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, - Assimp::MaterialHelper *pMatHelper, int lightmapId ) -{ - if ( NULL == pModel || NULL == pScene || NULL == pMatHelper ) - { - return false; - } - - if ( lightmapId < 0 || lightmapId >= static_cast<int>( pModel->m_Lightmaps.size() ) ) - { - return false; - } - - sQ3BSPLightmap *pLightMap = pModel->m_Lightmaps[ lightmapId ]; - if ( NULL == pLightMap ) - { - return false; - } - - aiTexture *pTexture = new aiTexture; - pTexture->mHeight = 0; - pTexture->mWidth = CE_BSP_LIGHTMAPWIDTH * CE_BSP_LIGHTMAPHEIGHT; - - unsigned char *pData = new unsigned char[ pTexture->mWidth ]; - pTexture->pcData = reinterpret_cast<aiTexel*>( pData ); - - pTexture->achFormatHint[ 0 ] = 'b'; - pTexture->achFormatHint[ 1 ] = 'm'; - pTexture->achFormatHint[ 2 ] = 'p'; - pTexture->achFormatHint[ 3 ] = '\0'; - - memcpy( pTexture->pcData, pLightMap->bLMapData, pTexture->mWidth ); - - aiString name; - name.data[ 0 ] = '*'; - name.length = 1 + ASSIMP_itoa10( name.data + 1, MAXLEN-1, mTextures.size() ); - - pMatHelper->AddProperty( &name,AI_MATKEY_TEXTURE_LIGHTMAP( 1 ) ); - mTextures.push_back( pTexture ); - - return true; -} - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Assimp - -#endif // ASSIMP_BUILD_NO_Q3BSP_IMPORTER diff --git a/3rdparty/assimp/code/Q3BSPFileImporter.h b/3rdparty/assimp/code/Q3BSPFileImporter.h deleted file mode 100644 index fa2e215a..00000000 --- a/3rdparty/assimp/code/Q3BSPFileImporter.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ -#ifndef ASSIMP_Q3BSPFILEIMPORTER_H_INC -#define ASSIMP_Q3BSPFILEIMPORTER_H_INC - -#include "BaseImporter.h" - -struct aiMesh; - -namespace Assimp -{ -namespace Q3BSP -{ - -class Q3BSPZipArchive; -struct Q3BSPModel; -struct sQ3BSPFace; - -} - -/** Loader to import BSP-levels from a PK3 archive or from a unpacked BSP-level. - */ -class Q3BSPFileImporter : BaseImporter -{ - friend class Importer; - -protected: - /// @brief Default constructor. - Q3BSPFileImporter(); - - /// @brief Destructor. - ~Q3BSPFileImporter(); - -public: - /// @brief Returns whether the class can handle the format of the given file. - /// @remark See BaseImporter::CanRead() for details. - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const; - -private: - typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*> FaceMap; - typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator FaceMapIt; - typedef std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator FaceMapConstIt; - - void GetExtensionList(std::set<std::string>& extensions); - void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); - void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName ); - bool findFirstMapInArchive( Q3BSP::Q3BSPZipArchive &rArchive, std::string &rMapName ); - void CreateDataFromImport( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive ); - void CreateNodes( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, aiNode *pParent ); - aiNode *CreateTopology( const Q3BSP::Q3BSPModel *pModel, unsigned int materialIdx, - std::vector<Q3BSP::sQ3BSPFace*> &rArray, aiMesh* pMesh ); - void createTriangleTopology( const Q3BSP::Q3BSPModel *pModel, Q3BSP::sQ3BSPFace *pQ3BSPFace, aiMesh* pMesh, unsigned int &rFaceIdx, - unsigned int &rVertIdx ); - void createMaterials( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Q3BSP::Q3BSPZipArchive *pArchive ); - size_t countData( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; - size_t countFaces( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; - size_t countTriangles( const std::vector<Q3BSP::sQ3BSPFace*> &rArray ) const; - void createMaterialMap( const Q3BSP::Q3BSPModel *pModel); - aiFace *getNextFace( aiMesh *pMesh, unsigned int &rFaceIdx ); - bool importTextureFromArchive( const Q3BSP::Q3BSPModel *pModel, Q3BSP::Q3BSPZipArchive *pArchive, aiScene* pScene, - Assimp::MaterialHelper *pMatHelper, int textureId ); - bool importLightmap( const Q3BSP::Q3BSPModel *pModel, aiScene* pScene, Assimp::MaterialHelper *pMatHelper, int lightmapId ); - -private: - aiMesh *m_pCurrentMesh; - aiFace *m_pCurrentFace; - FaceMap m_MaterialLookupMap; - std::vector<aiTexture*> mTextures; -}; - -} // Namespace Assimp - -#endif // ASSIMP_Q3BSPFILEIMPORTER_H_INC diff --git a/3rdparty/assimp/code/Q3BSPFileParser.cpp b/3rdparty/assimp/code/Q3BSPFileParser.cpp deleted file mode 100644 index 09411ca5..00000000 --- a/3rdparty/assimp/code/Q3BSPFileParser.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ -#include "AssimpPCH.h" -#include "Q3BSPFileParser.h" -#include "DefaultIOSystem.h" -#include "Q3BSPFileData.h" -#include "Q3BSPZipArchive.h" -#include <vector> - -namespace Assimp -{ - -using namespace Q3BSP; - -// ------------------------------------------------------------------------------------------------ -Q3BSPFileParser::Q3BSPFileParser( const std::string &rMapName, Q3BSPZipArchive *pZipArchive ) : - m_sOffset( 0 ), - m_Data(), - m_pModel( NULL ), - m_pZipArchive( pZipArchive ) -{ - ai_assert( NULL != m_pZipArchive ); - ai_assert( !rMapName.empty() ); - - if ( !readData( rMapName ) ) - return; - - m_pModel = new Q3BSPModel; - m_pModel->m_ModelName = rMapName; - if ( !parseFile() ) - { - delete m_pModel; - m_pModel = NULL; - } -} - -// ------------------------------------------------------------------------------------------------ -Q3BSPFileParser::~Q3BSPFileParser() -{ - delete m_pModel; - m_pModel = NULL; -} - -// ------------------------------------------------------------------------------------------------ -Q3BSP::Q3BSPModel *Q3BSPFileParser::getModel() const -{ - return m_pModel; -} - -// ------------------------------------------------------------------------------------------------ -bool Q3BSPFileParser::readData( const std::string &rMapName ) -{ - if ( !m_pZipArchive->Exists( rMapName.c_str() ) ) - return false; - - IOStream *pMapFile = m_pZipArchive->Open( rMapName.c_str() ); - if ( NULL == pMapFile ) - return false; - - const size_t size = pMapFile->FileSize(); - m_Data.resize( size ); - - const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size ); - if ( readSize != size ) - { - m_Data.clear(); - return false; - } - m_pZipArchive->Close( pMapFile ); - - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool Q3BSPFileParser::parseFile() -{ - if ( m_Data.empty() ) - { - return false; - } - - if ( !validateFormat() ) - { - return false; - } - - // Imports the dictionary of the level - getLumps(); - - // Conunt data and prepare model data - countLumps(); - - // Read in Vertices - getVertices(); - - // Read in Indices - getIndices(); - - // Read Faces - getFaces(); - - // Read Textures - getTextures(); - - // Read Lightmaps - getLightMaps(); - - // Load the entities - getEntities(); - - return true; -} - -// ------------------------------------------------------------------------------------------------ -bool Q3BSPFileParser::validateFormat() -{ - sQ3BSPHeader *pHeader = (sQ3BSPHeader*) &m_Data[ 0 ]; - m_sOffset += sizeof( sQ3BSPHeader ); - - // Version and identify string validation - if (pHeader->strID[ 0 ] != 'I' || pHeader->strID[ 1 ] != 'B' || pHeader->strID[ 2 ] != 'S' - || pHeader->strID[ 3 ] != 'P') - { - return false; - } - - return true; -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getLumps() -{ - size_t Offset = m_sOffset; - m_pModel->m_Lumps.resize( kMaxLumps ); - for ( size_t idx=0; idx < kMaxLumps; idx++ ) - { - sQ3BSPLump *pLump = new sQ3BSPLump; - memcpy( pLump, &m_Data[ Offset ], sizeof( sQ3BSPLump ) ); - Offset += sizeof( sQ3BSPLump ); - m_pModel->m_Lumps[ idx ] = pLump; - } -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::countLumps() -{ - m_pModel->m_Vertices.resize( m_pModel->m_Lumps[ kVertices ]->iSize / sizeof( sQ3BSPVertex ) ); - m_pModel->m_Indices.resize( m_pModel->m_Lumps[ kMeshVerts ]->iSize / sizeof( int ) ); - m_pModel->m_Faces.resize( m_pModel->m_Lumps[ kFaces ]->iSize / sizeof( sQ3BSPFace ) ); - m_pModel->m_Textures.resize( m_pModel->m_Lumps[ kTextures ]->iSize / sizeof( sQ3BSPTexture ) ); - m_pModel->m_Lightmaps.resize( m_pModel->m_Lumps[ kLightmaps ]->iSize / sizeof( sQ3BSPLightmap ) ); -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getVertices() -{ - size_t Offset = m_pModel->m_Lumps[ kVertices ]->iOffset; - for ( size_t idx = 0; idx < m_pModel->m_Vertices.size(); idx++ ) - { - sQ3BSPVertex *pVertex = new sQ3BSPVertex; - memcpy( pVertex, &m_Data[ Offset ], sizeof( sQ3BSPVertex ) ); - Offset += sizeof( sQ3BSPVertex ); - m_pModel->m_Vertices[ idx ] = pVertex; - } -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getIndices() -{ - ai_assert( NULL != m_pModel ); - - sQ3BSPLump *lump = m_pModel->m_Lumps[ kMeshVerts ]; - size_t Offset = (size_t) lump->iOffset; - const size_t nIndices = lump->iSize / sizeof( int ); - m_pModel->m_Indices.resize( nIndices ); - memcpy( &m_pModel->m_Indices[ 0 ], &m_Data[ Offset ], lump->iSize ); -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getFaces() -{ - ai_assert( NULL != m_pModel ); - - size_t Offset = m_pModel->m_Lumps[ kFaces ]->iOffset; - for ( size_t idx = 0; idx < m_pModel->m_Faces.size(); idx++ ) - { - sQ3BSPFace *pFace = new sQ3BSPFace; - memcpy( pFace, &m_Data[ Offset ], sizeof( sQ3BSPFace ) ); - m_pModel->m_Faces[ idx ] = pFace; - Offset += sizeof( sQ3BSPFace ); - } -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getTextures() -{ - ai_assert( NULL != m_pModel ); - - size_t Offset = m_pModel->m_Lumps[ kTextures ]->iOffset; - for ( size_t idx=0; idx < m_pModel->m_Textures.size(); idx++ ) - { - sQ3BSPTexture *pTexture = new sQ3BSPTexture; - memcpy( pTexture, &m_Data[ Offset ], sizeof(sQ3BSPTexture) ); - m_pModel->m_Textures[ idx ] = pTexture; - Offset += sizeof(sQ3BSPTexture); - } -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getLightMaps() -{ - ai_assert( NULL != m_pModel ); - - size_t Offset = m_pModel->m_Lumps[kLightmaps]->iOffset; - for ( size_t idx=0; idx < m_pModel->m_Lightmaps.size(); idx++ ) - { - sQ3BSPLightmap *pLightmap = new sQ3BSPLightmap; - memcpy( pLightmap, &m_Data[ Offset ], sizeof( sQ3BSPLightmap ) ); - Offset += sizeof( sQ3BSPLightmap ); - m_pModel->m_Lightmaps[ idx ] = pLightmap; - } -} - -// ------------------------------------------------------------------------------------------------ -void Q3BSPFileParser::getEntities() -{ - int size = m_pModel->m_Lumps[ kEntities ]->iSize; - m_pModel->m_EntityData.resize( size ); - size_t Offset = m_pModel->m_Lumps[ kEntities ]->iOffset; - memcpy( &m_pModel->m_EntityData[ 0 ], &m_Data[ Offset ], sizeof( char ) * size ); -} - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Assimp diff --git a/3rdparty/assimp/code/Q3BSPFileParser.h b/3rdparty/assimp/code/Q3BSPFileParser.h deleted file mode 100644 index a049dc29..00000000 --- a/3rdparty/assimp/code/Q3BSPFileParser.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef ASSIMP_Q3BSPFILEPARSER_H_INC -#define ASSIMP_Q3BSPFILEPARSER_H_INC - -#include "BaseImporter.h" -#include <string> - -namespace Assimp -{ -namespace Q3BSP -{ - -class Q3BSPZipArchive; -struct Q3BSPModel; -class ZipFile; - -} - -// ------------------------------------------------------------------- -// ------------------------------------------------------------------- -class Q3BSPFileParser -{ -public: - Q3BSPFileParser( const std::string &rMapName, Q3BSP::Q3BSPZipArchive *pZipArchive ); - ~Q3BSPFileParser(); - Q3BSP::Q3BSPModel *getModel() const; - -protected: - bool readData(const std::string &rMapName); - bool parseFile(); - bool validateFormat(); - void getLumps(); - void countLumps(); - void getVertices(); - void getIndices(); - void getFaces(); - void getTextures(); - void getLightMaps(); - void getEntities(); - -private: - size_t m_sOffset; - std::vector<char> m_Data; - Q3BSP::Q3BSPModel *m_pModel; - Q3BSP::Q3BSPZipArchive *m_pZipArchive; -}; - -} // Namespace Assimp - -#endif // ASSIMP_Q3BSPFILEPARSER_H_INC diff --git a/3rdparty/assimp/code/Q3BSPZipArchive.cpp b/3rdparty/assimp/code/Q3BSPZipArchive.cpp deleted file mode 100644 index 76a4156f..00000000 --- a/3rdparty/assimp/code/Q3BSPZipArchive.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#include "Q3BSPZipArchive.h" -#include <algorithm> -#include <cassert> - -namespace Assimp -{ -namespace Q3BSP -{ - -// ------------------------------------------------------------------------------------------------ -// Constructor. -Q3BSPZipArchive::Q3BSPZipArchive( const std::string& rFile ) : - m_ZipFileHandle( NULL ), - m_FileList(), - m_bDirty( true ) -{ - if ( !rFile.empty() ) - { - m_ZipFileHandle = unzOpen( rFile.c_str() ); - if ( NULL != m_ZipFileHandle ) - { - mapArchive(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. -Q3BSPZipArchive::~Q3BSPZipArchive() -{ - if ( NULL != m_ZipFileHandle ) - { - unzClose( m_ZipFileHandle ); - } - m_ZipFileHandle = NULL; - m_FileList.clear(); -} - -// ------------------------------------------------------------------------------------------------ -// Returns true, if the archive is already open. -bool Q3BSPZipArchive::isOpen() const -{ - return ( NULL != m_ZipFileHandle ); -} - -// ------------------------------------------------------------------------------------------------ -// Returns true, if the filename is part of the archive. -bool Q3BSPZipArchive::Exists( const char* pFile ) const -{ - ai_assert( NULL != pFile ); - if ( NULL == pFile ) - { - return false; - } - - std::string rFile( pFile ); - std::vector<std::string>::const_iterator it = std::find( m_FileList.begin(), m_FileList.end(), rFile ); - if ( m_FileList.end() == it ) - { - return false; - } - - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Returns the separator delimiter. -char Q3BSPZipArchive::getOsSeparator() const -{ - return '/'; -} - -// ------------------------------------------------------------------------------------------------ -// Opens a file, which is part of the archive. -IOStream *Q3BSPZipArchive::Open( const char* pFile, const char* pMode ) -{ - ai_assert( NULL != pFile ); - - std::string rItem( pFile ); - std::vector<std::string>::iterator it = std::find( m_FileList.begin(), m_FileList.end(), rItem ); - if ( m_FileList.end() == it ) - return NULL; - - ZipFile *pZipFile = new ZipFile( *it, m_ZipFileHandle ); - m_ArchiveMap[ rItem ] = pZipFile; - - return pZipFile; -} - -// ------------------------------------------------------------------------------------------------ -// Close a filestream. -void Q3BSPZipArchive::Close( IOStream *pFile ) -{ - ai_assert( NULL != pFile ); - - std::map<std::string, IOStream*>::iterator it; - for ( it = m_ArchiveMap.begin(); it != m_ArchiveMap.end(); ++it ) - { - if ( (*it).second == pFile ) - { - ZipFile *pZipFile = reinterpret_cast<ZipFile*>( (*it).second ); - delete pZipFile; - m_ArchiveMap.erase( it ); - break; - } - } -} -// ------------------------------------------------------------------------------------------------ -// Returns the file-list of the archive. -void Q3BSPZipArchive::getFileList( std::vector<std::string> &rFileList ) -{ - rFileList = m_FileList; -} - -// ------------------------------------------------------------------------------------------------ -// Maps the archive content. -bool Q3BSPZipArchive::mapArchive() -{ - if ( NULL == m_ZipFileHandle ) - return false; - - if ( !m_bDirty ) - return true; - - if ( !m_FileList.empty() ) - m_FileList.resize( 0 ); - - // At first ensure file is already open - if ( UNZ_OK == unzGoToFirstFile( m_ZipFileHandle ) ) - { - char filename[ FileNameSize ]; - unzGetCurrentFileInfo( m_ZipFileHandle, NULL, filename, FileNameSize, NULL, 0, NULL, 0 ); - m_FileList.push_back( filename ); - unzCloseCurrentFile( m_ZipFileHandle ); - - // Loop over all files - while ( unzGoToNextFile( m_ZipFileHandle ) != UNZ_END_OF_LIST_OF_FILE ) - { - char filename[ FileNameSize ]; - unzGetCurrentFileInfo( m_ZipFileHandle, NULL, filename, FileNameSize, NULL, 0, NULL, 0 ); - m_FileList.push_back( filename ); - unzCloseCurrentFile( m_ZipFileHandle ); - } - } - - std::sort( m_FileList.begin(), m_FileList.end() ); - m_bDirty = false; - - return true; -} - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Q3BSP -} // Namespace Assimp diff --git a/3rdparty/assimp/code/Q3BSPZipArchive.h b/3rdparty/assimp/code/Q3BSPZipArchive.h deleted file mode 100644 index d924e88a..00000000 --- a/3rdparty/assimp/code/Q3BSPZipArchive.h +++ /dev/null @@ -1,182 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ -#ifndef AI_Q3BSP_ZIPARCHIVE_H_INC -#define AI_Q3BSP_ZIPARCHIVE_H_INC - -#include "../contrib/unzip/unzip.h" -#include "../include/IOStream.h" -#include "../include/IOSystem.h" -#include <string> -#include <vector> -#include <map> -#include <cassert> - -namespace Assimp -{ -namespace Q3BSP -{ - -// ------------------------------------------------------------------------------------------------ -/// \class ZipFile -/// \ingroup Assimp::Q3BSP -/// -/// \brief -// ------------------------------------------------------------------------------------------------ -class ZipFile : public IOStream -{ -public: - ZipFile( const std::string &rFileName, unzFile zipFile ) : - m_Name( rFileName ), - m_zipFile( zipFile ) - { - ai_assert( NULL != m_zipFile ); - } - - ~ZipFile() - { - m_zipFile = NULL; - } - - size_t Read(void* pvBuffer, size_t pSize, size_t pCount ) - { - size_t bytes_read = 0; - if ( NULL == m_zipFile ) - return bytes_read; - - // search file and place file pointer there - if ( unzLocateFile( m_zipFile, m_Name.c_str(), 0 ) == UNZ_OK ) - { - // get file size, etc. - unz_file_info fileInfo; - unzGetCurrentFileInfo( m_zipFile, &fileInfo, 0, 0, 0, 0, 0, 0 ); - const size_t size = pSize * pCount; - assert( size <= fileInfo.uncompressed_size ); - - // The file has EXACTLY the size of uncompressed_size. In C - // you need to mark the last character with '\0', so add - // another character - unzOpenCurrentFile( m_zipFile ); - bytes_read = unzReadCurrentFile( m_zipFile, pvBuffer, fileInfo.uncompressed_size); - if ( bytes_read < 0 || bytes_read != static_cast<size_t>( fileInfo.uncompressed_size ) ) - { - return 0; - } - size_t filesize = fileInfo.uncompressed_size; - unzCloseCurrentFile( m_zipFile ); - } - return bytes_read; - } - - size_t Write(const void* pvBuffer, size_t pSize, size_t pCount) - { - return 0; - } - - size_t FileSize() const - { - if ( NULL == m_zipFile ) - return 0; - if ( unzLocateFile( m_zipFile, m_Name.c_str(), 0 ) == UNZ_OK ) - { - unz_file_info fileInfo; - unzGetCurrentFileInfo( m_zipFile, &fileInfo, 0, 0, 0, 0, 0, 0 ); - return fileInfo.uncompressed_size; - } - return 0; - } - - aiReturn Seek(size_t pOffset, aiOrigin pOrigin) - { - return aiReturn_FAILURE; - } - - size_t Tell() const - { - return 0; - } - - void Flush() - { - // empty - } - -private: - std::string m_Name; - unzFile m_zipFile; -}; - -// ------------------------------------------------------------------------------------------------ -/// \class Q3BSPZipArchive -/// \ingroup Assimp::Q3BSP -/// -/// \brief IMplements a zip archive like the WinZip archives. Will be also used to import data -/// from a P3K archive ( Quake level format ). -// ------------------------------------------------------------------------------------------------ -class Q3BSPZipArchive : public Assimp::IOSystem -{ -public: - static const unsigned int FileNameSize = 256; - -public: - Q3BSPZipArchive( const std::string & rFile ); - ~Q3BSPZipArchive(); - bool Exists( const char* pFile) const; - char getOsSeparator() const; - IOStream* Open(const char* pFile, const char* pMode = "rb"); - void Close( IOStream* pFile); - bool isOpen() const; - void getFileList( std::vector<std::string> &rFileList ); - -private: - bool mapArchive(); - -private: - unzFile m_ZipFileHandle; - std::map<std::string, IOStream*> m_ArchiveMap; - std::vector<std::string> m_FileList; - bool m_bDirty; -}; - -// ------------------------------------------------------------------------------------------------ - -} // Namespace Q3BSP -} // Namespace Assimp - -#endif // AI_Q3BSP_ZIPARCHIVE_H_INC diff --git a/3rdparty/assimp/code/Q3DLoader.cpp b/3rdparty/assimp/code/Q3DLoader.cpp deleted file mode 100644 index 05c4a2ac..00000000 --- a/3rdparty/assimp/code/Q3DLoader.cpp +++ /dev/null @@ -1,600 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Q3DLoader.cpp - * @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" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -Q3DImporter::Q3DImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -Q3DImporter::~Q3DImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// 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; -} - -// ------------------------------------------------------------------------------------------------ -void Q3DImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("q3o"); - extensions.insert("q3s"); -} - -// ------------------------------------------------------------------------------------------------ -// 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 = 0xffffffff; - } - } - } - - // 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"); - - register 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 fucking 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(); - MaterialHelper* mat = new MaterialHelper(); - 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); -#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; - } -} - -#endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER diff --git a/3rdparty/assimp/code/Q3DLoader.h b/3rdparty/assimp/code/Q3DLoader.h deleted file mode 100644 index fef4eac3..00000000 --- a/3rdparty/assimp/code/Q3DLoader.h +++ /dev/null @@ -1,135 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Q3DLoader.h - * @brief Declaration of the Q3D importer class. - */ -#ifndef AI_Q3DLOADER_H_INCLUDED -#define AI_Q3DLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" -#include <vector> - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Importer class for the Quick3D Object and Scene formats. -*/ -class Q3DImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - Q3DImporter(); - - /** Destructor, private as well */ - ~Q3DImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - - struct Material - { - Material() - : diffuse (0.6f,0.6f,0.6f) - , transparency (0.f) - , texIdx (0xffffffff) - {} - - aiString name; - aiColor3D ambient, diffuse, specular; - float transparency; - - unsigned int texIdx; - }; - - struct Face - { - Face(unsigned int s) - : indices (s) - , uvindices (s) - , mat (0) - { - } - - std::vector<unsigned int> indices; - std::vector<unsigned int> uvindices; - unsigned int mat; - }; - - struct Mesh - { - - std::vector<aiVector3D> verts; - std::vector<aiVector3D> normals; - std::vector<aiVector3D> uv; - std::vector<Face> faces; - - uint32_t prevUVIdx; - }; -}; - -} // end of namespace Assimp - -#endif // AI_Q3DIMPORTER_H_IN diff --git a/3rdparty/assimp/code/RawLoader.cpp b/3rdparty/assimp/code/RawLoader.cpp deleted file mode 100644 index df5daba8..00000000 --- a/3rdparty/assimp/code/RawLoader.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 RawLoader.cpp - * @brief Implementation of the RAW importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER - -// internal headers -#include "RawLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -RAWImporter::RAWImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -RAWImporter::~RAWImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool RAWImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - return SimpleExtensionCheck(pFile,"raw"); -} - -// ------------------------------------------------------------------------------------------------ -// Get the list of all supported file extensions -void RAWImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("raw"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void RAWImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open RAW file " + pFile + "."); - } - - // allocate storage and copy the contents of the file to a memory buffer - // (terminate it with zero) - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - const char* buffer = &mBuffer2[0]; - - // list of groups loaded from the file - std::vector< GroupInformation > outGroups(1,GroupInformation("<default>")); - std::vector< GroupInformation >::iterator curGroup = outGroups.begin(); - - // now read all lines - char line[4096]; - while (GetNextLine(buffer,line)) - { - // if the line starts with a non-numeric identifier, it marks - // the beginning of a new group - const char* sz = line;SkipSpaces(&sz); - if (IsLineEnd(*sz))continue; - if (!IsNumeric(*sz)) - { - const char* sz2 = sz; - while (!IsSpaceOrNewLine(*sz2))++sz2; - const unsigned int length = (unsigned int)(sz2-sz); - - // find an existing group with this name - for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); - it != end;++it) - { - if (length == (*it).name.length() && !::strcmp(sz,(*it).name.c_str())) - { - curGroup = it;sz2 = NULL; - break; - } - } - if (sz2) - { - outGroups.push_back(GroupInformation(std::string(sz,length))); - curGroup = outGroups.end()-1; - } - } - else - { - // there can be maximally 12 floats plus an extra texture file name - float data[12]; - unsigned int num; - for (num = 0; num < 12;++num) - { - if (!SkipSpaces(&sz) || !IsNumeric(*sz))break; - sz = fast_atof_move(sz,data[num]); - } - if (num != 12 && num != 9) - { - DefaultLogger::get()->error("A line may have either 9 or 12 floats and an optional texture"); - continue; - } - - MeshInformation* output = NULL; - - const char* sz2 = sz; - unsigned int length; - if (!IsLineEnd(*sz)) - { - while (!IsSpaceOrNewLine(*sz2))++sz2; - length = (unsigned int)(sz2-sz); - } - else if (9 == num) - { - sz = "%default%"; - length = 9; - } - else - { - sz = ""; - length = 0; - } - - // search in the list of meshes whether we have one with this texture - for (std::vector< MeshInformation >::iterator it = (*curGroup).meshes.begin(), - end = (*curGroup).meshes.end(); it != end; ++it) - { - if (length == (*it).name.length() && (length ? !::strcmp(sz,(*it).name.c_str()) : true)) - { - output = &(*it); - break; - } - } - // if we don't have the mesh, create it - if (!output) - { - (*curGroup).meshes.push_back(MeshInformation(std::string(sz,length))); - output = &((*curGroup).meshes.back()); - } - if (12 == num) - { - aiColor4D v(data[0],data[1],data[2],1.0f); - output->colors.push_back(v); - output->colors.push_back(v); - output->colors.push_back(v); - - output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); - output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); - output->vertices.push_back(aiVector3D(data[9],data[10],data[11])); - } - else - { - output->vertices.push_back(aiVector3D(data[0],data[1],data[2])); - output->vertices.push_back(aiVector3D(data[3],data[4],data[5])); - output->vertices.push_back(aiVector3D(data[6],data[7],data[8])); - } - } - } - - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mName.Set("<RawRoot>"); - - // count the number of valid groups - // (meshes can't be empty) - for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); - it != end;++it) - { - if (!(*it).meshes.empty()) - { - ++pScene->mRootNode->mNumChildren; - pScene->mNumMeshes += (unsigned int)(*it).meshes.size(); - } - } - - if (!pScene->mNumMeshes) - { - throw DeadlyImportError("RAW: No meshes loaded. The file seems to be corrupt or empty."); - } - - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - aiNode** cc; - if (1 == pScene->mRootNode->mNumChildren) - { - cc = &pScene->mRootNode; - pScene->mRootNode->mNumChildren = 0; - } - else cc = pScene->mRootNode->mChildren = new aiNode*[pScene->mRootNode->mNumChildren]; - - pScene->mNumMaterials = pScene->mNumMeshes; - aiMaterial** mats = pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; - - unsigned int meshIdx = 0; - for (std::vector< GroupInformation >::iterator it = outGroups.begin(), end = outGroups.end(); - it != end;++it) - { - if ((*it).meshes.empty())continue; - - aiNode* node; - if (pScene->mRootNode->mNumChildren) - { - node = *cc = new aiNode(); - node->mParent = pScene->mRootNode; - } - else node = *cc;++cc; - node->mName.Set((*it).name); - - // add all meshes - node->mNumMeshes = (unsigned int)(*it).meshes.size(); - unsigned int* pi = node->mMeshes = new unsigned int[ node->mNumMeshes ]; - for (std::vector< MeshInformation >::iterator it2 = (*it).meshes.begin(), - end2 = (*it).meshes.end(); it2 != end2; ++it2) - { - ai_assert(!(*it2).vertices.empty()); - - // allocate the mesh - *pi++ = meshIdx; - aiMesh* mesh = pScene->mMeshes[meshIdx] = new aiMesh(); - mesh->mMaterialIndex = meshIdx++; - - mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - - // allocate storage for the vertex components and copy them - mesh->mNumVertices = (unsigned int)(*it2).vertices.size(); - mesh->mVertices = new aiVector3D[ mesh->mNumVertices ]; - ::memcpy(mesh->mVertices,&(*it2).vertices[0],sizeof(aiVector3D)*mesh->mNumVertices); - - if ((*it2).colors.size()) - { - ai_assert((*it2).colors.size() == mesh->mNumVertices); - - mesh->mColors[0] = new aiColor4D[ mesh->mNumVertices ]; - ::memcpy(mesh->mColors[0],&(*it2).colors[0],sizeof(aiColor4D)*mesh->mNumVertices); - } - - // generate triangles - ai_assert(0 == mesh->mNumVertices % 3); - aiFace* fc = mesh->mFaces = new aiFace[ mesh->mNumFaces = mesh->mNumVertices/3 ]; - aiFace* const fcEnd = fc + mesh->mNumFaces; - unsigned int n = 0; - while (fc != fcEnd) - { - aiFace& f = *fc++; - f.mIndices = new unsigned int[f.mNumIndices = 3]; - for (unsigned int m = 0; m < 3;++m) - f.mIndices[m] = n++; - } - - // generate a material for the mesh - MaterialHelper* mat = new MaterialHelper(); - - aiColor4D clr(1.0f,1.0f,1.0f,1.0f); - if ("%default%" == (*it2).name) // a gray default material - { - clr.r = clr.g = clr.b = 0.6f; - } - else if ((*it2).name.length() > 0) // a texture - { - aiString s; - s.Set((*it2).name); - mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - mat->AddProperty<aiColor4D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - *mats++ = mat; - } - } -} - -#endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER diff --git a/3rdparty/assimp/code/RawLoader.h b/3rdparty/assimp/code/RawLoader.h deleted file mode 100644 index 47a4a5aa..00000000 --- a/3rdparty/assimp/code/RawLoader.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 RAWLoader.h - * @brief Declaration of the RAW importer class. - */ -#ifndef AI_RAWLOADER_H_INCLUDED -#define AI_RAWLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" -#include <vector> - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Importer class for the PovRay RAW triangle format -*/ -class RAWImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - RAWImporter(); - - /** Destructor, private as well */ - ~RAWImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - - struct MeshInformation - { - MeshInformation(const std::string& _name) - : name(_name) - { - vertices.reserve(100); - colors.reserve(100); - } - - std::string name; - - std::vector<aiVector3D> vertices; - std::vector<aiColor4D> colors; - }; - - struct GroupInformation - { - GroupInformation(const std::string& _name) - : name(_name) - { - meshes.reserve(10); - } - - std::string name; - std::vector<MeshInformation> meshes; - }; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_IN diff --git a/3rdparty/assimp/code/RemoveComments.cpp b/3rdparty/assimp/code/RemoveComments.cpp deleted file mode 100644 index b69c04c0..00000000 --- a/3rdparty/assimp/code/RemoveComments.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 RemoveComments.cpp - * @brief Defines the CommentRemover utility class - */ - -#include "AssimpPCH.h" -#include "RemoveComments.h" -#include "ParsingUtils.h" - -namespace Assimp { - -// ------------------------------------------------------------------------------------------------ -// Remove line comments from a file -void CommentRemover::RemoveLineComments(const char* szComment, - char* szBuffer, char chReplacement /* = ' ' */) -{ - // validate parameters - ai_assert(NULL != szComment && NULL != szBuffer && *szComment); - - const size_t len = strlen(szComment); - while (*szBuffer) { - - // skip over quotes - if (*szBuffer == '\"' || *szBuffer == '\'') - while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\''); - - if (!strncmp(szBuffer,szComment,len)) { - while (!IsLineEnd(*szBuffer)) - *szBuffer++ = chReplacement; - } - ++szBuffer; - } -} - -// ------------------------------------------------------------------------------------------------ -// Remove multi-line comments from a file -void CommentRemover::RemoveMultiLineComments(const char* szCommentStart, - const char* szCommentEnd,char* szBuffer, - char chReplacement) -{ - // validate parameters - ai_assert(NULL != szCommentStart && NULL != szCommentEnd && - NULL != szBuffer && *szCommentStart && *szCommentEnd); - - const size_t len = strlen(szCommentEnd); - const size_t len2 = strlen(szCommentStart); - - while (*szBuffer) { - // skip over quotes - if (*szBuffer == '\"' || *szBuffer == '\'') - while (*szBuffer++ && *szBuffer != '\"' && *szBuffer != '\''); - - if (!strncmp(szBuffer,szCommentStart,len2)) { - while (*szBuffer) { - if (!::strncmp(szBuffer,szCommentEnd,len)) { - for (unsigned int i = 0; i < len;++i) - *szBuffer++ = chReplacement; - - break; - } - *szBuffer++ = chReplacement; - } - continue; - } - ++szBuffer; - } -} - -} // !! Assimp diff --git a/3rdparty/assimp/code/RemoveComments.h b/3rdparty/assimp/code/RemoveComments.h deleted file mode 100644 index 54899527..00000000 --- a/3rdparty/assimp/code/RemoveComments.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Declares a helper class, "CommentRemover", which can be - * used to remove comments (single and multi line) from a text file. - */ -#ifndef AI_REMOVE_COMMENTS_H_INC -#define AI_REMOVE_COMMENTS_H_INC - -#include "../include/aiAssert.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** \brief Helper class to remove single and multi line comments from a file - * - * Some mesh formats like MD5 have comments that are quite similar - * to those in C or C++ so this code has been moved to a separate - * module. - */ -class ASSIMP_API CommentRemover -{ - // class cannot be instanced - CommentRemover() {} - -public: - - //! Remove single-line comments. The end of a line is - //! expected to be either NL or CR or NLCR. - //! \param szComment The start sequence of the comment, e.g. "//" - //! \param szBuffer Buffer to work with - //! \param chReplacement Character to be used as replacement - //! for commented lines. By default this is ' ' - static void RemoveLineComments(const char* szComment, - char* szBuffer, char chReplacement = ' '); - - //! Remove multi-line comments. The end of a line is - //! expected to be either NL or CR or NLCR. Multi-line comments - //! may not be nested (as in C). - //! \param szCommentStart The start sequence of the comment, e.g. "/*" - //! \param szCommentEnd The end sequence of the comment, e.g. "*/" - //! \param szBuffer Buffer to work with - //! \param chReplacement Character to be used as replacement - //! for commented lines. By default this is ' ' - static void RemoveMultiLineComments(const char* szCommentStart, - const char* szCommentEnd,char* szBuffer, - char chReplacement = ' '); -}; -} // ! Assimp - -#endif // !! AI_REMOVE_COMMENTS_H_INC diff --git a/3rdparty/assimp/code/RemoveRedundantMaterials.cpp b/3rdparty/assimp/code/RemoveRedundantMaterials.cpp deleted file mode 100644 index 73931ea9..00000000 --- a/3rdparty/assimp/code/RemoveRedundantMaterials.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 RemoveRedundantMaterials.cpp - * @brief Implementation of the "RemoveRedundantMaterials" post processing step -*/ - -// internal headers -#include "AssimpPCH.h" -#include "RemoveRedundantMaterials.h" -#include "ParsingUtils.h" -#include "ProcessHelper.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -RemoveRedundantMatsProcess::RemoveRedundantMatsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -RemoveRedundantMatsProcess::~RemoveRedundantMatsProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool RemoveRedundantMatsProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_RemoveRedundantMaterials) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Setup import properties -void RemoveRedundantMatsProcess::SetupProperties(const Importer* pImp) -{ - // Get value of AI_CONFIG_PP_RRM_EXCLUDE_LIST - configFixedMaterials = pImp->GetPropertyString(AI_CONFIG_PP_RRM_EXCLUDE_LIST,""); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void RemoveRedundantMatsProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("RemoveRedundantMatsProcess begin"); - - unsigned int iCnt = 0, unreferenced = 0; - if (pScene->mNumMaterials) - { - // Find out which materials are referenced by meshes - std::vector<bool> abReferenced(pScene->mNumMaterials,false); - for (unsigned int i = 0;i < pScene->mNumMeshes;++i) - abReferenced[pScene->mMeshes[i]->mMaterialIndex] = true; - - // If a list of materials to be excluded was given, match the list with - // our imported materials and 'salt' all positive matches to ensure that - // we get unique hashes later. - if (configFixedMaterials.length()) { - - std::list<std::string> strings; - ConvertListToStrings(configFixedMaterials,strings); - - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - aiMaterial* mat = pScene->mMaterials[i]; - - aiString name; - mat->Get(AI_MATKEY_NAME,name); - - if (name.length) { - std::list<std::string>::const_iterator it = std::find(strings.begin(), strings.end(), name.data); - if (it != strings.end()) { - - // Our brilliant 'salt': A single material property with ~ as first - // character to mark it as internal and temporary. - const int dummy = 1; - ((MaterialHelper*)mat)->AddProperty(&dummy,1,"~RRM.UniqueMaterial",0,0); - - // Keep this material even if no mesh references it - abReferenced[i] = true; - DefaultLogger::get()->debug(std::string("Found positive match in exclusion list: \'") + name.data + "\'"); - } - } - } - } - - - // TODO: reimplement this algorithm to work in-place - - unsigned int* aiMappingTable = new unsigned int[pScene->mNumMaterials]; - unsigned int iNewNum = 0; - - // Iterate through all materials and calculate a hash for them - // store all hashes in a list and so a quick search whether - // we do already have a specific hash. This allows us to - // determine which materials are identical. - uint32_t* aiHashes; - aiHashes = new uint32_t[pScene->mNumMaterials]; - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) - { - // if the material is not referenced ... remove it - if (!abReferenced[i]) { - ++unreferenced; - continue; - } - - uint32_t me = aiHashes[i] = ((MaterialHelper*)pScene->mMaterials[i])->ComputeHash(); - for (unsigned int a = 0; a < i;++a) - { - if (me == aiHashes[a]) { - ++iCnt; - me = 0; - aiMappingTable[i] = aiMappingTable[a]; - delete pScene->mMaterials[i]; - break; - } - } - if (me) { - aiMappingTable[i] = iNewNum++; - } - } - if (iCnt) { - // build an output material list - aiMaterial** ppcMaterials = new aiMaterial*[iNewNum]; - ::memset(ppcMaterials,0,sizeof(void*)*iNewNum); - for (unsigned int p = 0; p < pScene->mNumMaterials;++p) - { - // if the material is not referenced ... remove it - if (!abReferenced[p]) - continue; - - // generate new names for all modified materials - const unsigned int idx = aiMappingTable[p]; - if (ppcMaterials[idx]) - { - aiString sz; - sz.length = ::sprintf(sz.data,"JoinedMaterial_#%i",p); - ((MaterialHelper*)ppcMaterials[idx])->AddProperty(&sz,AI_MATKEY_NAME); - } - else ppcMaterials[idx] = pScene->mMaterials[p]; - } - // update all material indices - for (unsigned int p = 0; p < pScene->mNumMeshes;++p) { - aiMesh* mesh = pScene->mMeshes[p]; - mesh->mMaterialIndex = aiMappingTable[mesh->mMaterialIndex]; - } - // delete the old material list - delete[] pScene->mMaterials; - pScene->mMaterials = ppcMaterials; - pScene->mNumMaterials = iNewNum; - } - // delete temporary storage - delete[] aiHashes; - delete[] aiMappingTable; - } - if (!iCnt)DefaultLogger::get()->debug("RemoveRedundantMatsProcess finished "); - else - { - char szBuffer[128]; // should be sufficiently large - ::sprintf(szBuffer,"RemoveRedundantMatsProcess finished. %i redundant and %i unused materials", - iCnt,unreferenced); - DefaultLogger::get()->info(szBuffer); - } -} diff --git a/3rdparty/assimp/code/RemoveRedundantMaterials.h b/3rdparty/assimp/code/RemoveRedundantMaterials.h deleted file mode 100644 index 65bbf2cf..00000000 --- a/3rdparty/assimp/code/RemoveRedundantMaterials.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 RemoveRedundantMaterials.h - * @brief Defines a post processing step to remove redundant materials - */ -#ifndef AI_REMOVEREDUNDANTMATERIALS_H_INC -#define AI_REMOVEREDUNDANTMATERIALS_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class RemoveRedundantMatsTest; -namespace Assimp { - -// --------------------------------------------------------------------------- -/** RemoveRedundantMatsProcess: Postprocessing steo to remove redundant - * materials from the imported scene. - */ -class ASSIMP_API RemoveRedundantMatsProcess : public BaseProcess -{ - friend class Importer; - friend class ::RemoveRedundantMatsTest; // grant the unit test full access to us - -protected: - /** Constructor to be privately used by Importer */ - RemoveRedundantMatsProcess(); - - /** Destructor, private as well */ - ~RemoveRedundantMatsProcess(); - -public: - // ------------------------------------------------------------------- - // Check whether step is active - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - // Execute step on a given scene - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - // Setup import settings - void SetupProperties(const Importer* pImp); - - - // ------------------------------------------------------------------- - /** @brief Set list of fixed (unmutable) materials - * @param fixed See #AI_CONFIG_PP_RRM_EXCLUDE_LIST - */ - void SetFixedMaterialsString(const std::string& fixed = "") { - configFixedMaterials = fixed; - } - - // ------------------------------------------------------------------- - /** @brief Get list of fixed (unmutable) materials - * @return See #AI_CONFIG_PP_RRM_EXCLUDE_LIST - */ - const std::string& GetFixedMaterialsString() const { - return configFixedMaterials; - } - -private: - - //! Configuration option: list of all fixed materials - std::string configFixedMaterials; -}; - -} // end of namespace Assimp - -#endif // !!AI_REMOVEREDUNDANTMATERIALS_H_INC diff --git a/3rdparty/assimp/code/RemoveVCProcess.cpp b/3rdparty/assimp/code/RemoveVCProcess.cpp deleted file mode 100644 index 2d5b60e3..00000000 --- a/3rdparty/assimp/code/RemoveVCProcess.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 post processing step to remove - * any parts of the mesh structure from the imported data. -*/ - -#include "AssimpPCH.h" -#include "RemoveVCProcess.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -RemoveVCProcess::RemoveVCProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -RemoveVCProcess::~RemoveVCProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool RemoveVCProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_RemoveComponent) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Small helper function to delete all elements in a T** aray using delete -template <typename T> -inline void ArrayDelete(T**& in, unsigned int& num) -{ - for (unsigned int i = 0; i < num; ++i) - delete in[i]; - - delete[] in; - in = NULL; - num = 0; -} - -#if 0 -// ------------------------------------------------------------------------------------------------ -// Updates the node graph - removes all nodes which have the "remove" flag set and the -// "don't remove" flag not set. Nodes with meshes are never deleted. -bool UpdateNodeGraph(aiNode* node,std::list<aiNode*>& childsOfParent,bool root) -{ - register bool b = false; - - std::list<aiNode*> mine; - for (unsigned int i = 0; i < node->mNumChildren;++i) - { - if (UpdateNodeGraph(node->mChildren[i],mine,false)) - b = true; - } - - // somewhat tricky ... mNumMeshes must be originally 0 and MSB2 may not be set, - // so we can do a simple comparison against MSB here - if (!root && AI_RC_UINT_MSB == node->mNumMeshes ) - { - // this node needs to be removed - if (node->mNumChildren) - { - childsOfParent.insert(childsOfParent.end(),mine.begin(),mine.end()); - - // set all children to NULL to make sure they are not deleted when we delete ourself - for (unsigned int i = 0; i < node->mNumChildren;++i) - node->mChildren[i] = NULL; - } - b = true; - delete node; - } - else - { - AI_RC_UNMASK(node->mNumMeshes); - childsOfParent.push_back(node); - - if (b) - { - // reallocate the array of our children here - node->mNumChildren = (unsigned int)mine.size(); - aiNode** const children = new aiNode*[mine.size()]; - aiNode** ptr = children; - - for (std::list<aiNode*>::iterator it = mine.begin(), end = mine.end(); - it != end; ++it) - { - *ptr++ = *it; - } - delete[] node->mChildren; - node->mChildren = children; - return false; - } - } - return b; -} -#endif - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void RemoveVCProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("RemoveVCProcess begin"); - bool bHas = false; //,bMasked = false; - - mScene = pScene; - - // handle animations - if ( configDeleteFlags & aiComponent_ANIMATIONS) - { - - bHas = true; - ArrayDelete(pScene->mAnimations,pScene->mNumAnimations); - } - - // handle textures - if ( configDeleteFlags & aiComponent_TEXTURES) - { - bHas = true; - ArrayDelete(pScene->mTextures,pScene->mNumTextures); - } - - // handle materials - if ( configDeleteFlags & aiComponent_MATERIALS && pScene->mNumMaterials) - { - bHas = true; - for (unsigned int i = 1;i < pScene->mNumMaterials;++i) - delete pScene->mMaterials[i]; - - pScene->mNumMaterials = 1; - MaterialHelper* helper = (MaterialHelper*) pScene->mMaterials[0]; - ai_assert(NULL != helper); - helper->Clear(); - - // gray - aiColor3D clr(0.6f,0.6f,0.6f); - helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - - // add a small ambient color value - clr = aiColor3D(0.05f,0.05f,0.05f); - helper->AddProperty(&clr,1,AI_MATKEY_COLOR_AMBIENT); - - aiString s; - s.Set("Dummy_MaterialsRemoved"); - helper->AddProperty(&s,AI_MATKEY_NAME); - } - - // handle light sources - if ( configDeleteFlags & aiComponent_LIGHTS) - { - bHas = true; - ArrayDelete(pScene->mLights,pScene->mNumLights); - } - - // handle camneras - if ( configDeleteFlags & aiComponent_CAMERAS) - { - bHas = true; - ArrayDelete(pScene->mCameras,pScene->mNumCameras); - } - - // handle meshes - if (configDeleteFlags & aiComponent_MESHES) - { - bHas = true; - ArrayDelete(pScene->mMeshes,pScene->mNumMeshes); - } - else - { - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { - if ( ProcessMesh( pScene->mMeshes[a])) - bHas = true; - } - } - - - // now check whether the result is still a full scene - if (!pScene->mNumMeshes || !pScene->mNumMaterials) - { - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - DefaultLogger::get()->debug("Setting AI_SCENE_FLAGS_INCOMPLETE flag"); - - // If we have no meshes anymore we should also clear another flag ... - if (!pScene->mNumMeshes) - pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; - } - - if (bHas)DefaultLogger::get()->info("RemoveVCProcess finished. Data structure cleanup has been done."); - else DefaultLogger::get()->debug("RemoveVCProcess finished. Nothing to be done ..."); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties for the step -void RemoveVCProcess::SetupProperties(const Importer* pImp) -{ - configDeleteFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,0x0); - if (!configDeleteFlags) - { - DefaultLogger::get()->warn("RemoveVCProcess: AI_CONFIG_PP_RVC_FLAGS is zero."); - } -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -bool RemoveVCProcess::ProcessMesh(aiMesh* pMesh) -{ - bool ret = false; - - // if all materials have been deleted let the material - // index of the mesh point to the created default material - if ( configDeleteFlags & aiComponent_MATERIALS) - pMesh->mMaterialIndex = 0; - - // handle normals - if (configDeleteFlags & aiComponent_NORMALS && pMesh->mNormals) - { - delete[] pMesh->mNormals; - pMesh->mNormals = NULL; - ret = true; - } - - // handle tangents and bitangents - if (configDeleteFlags & aiComponent_TANGENTS_AND_BITANGENTS && pMesh->mTangents) - { - delete[] pMesh->mTangents; - pMesh->mTangents = NULL; - - delete[] pMesh->mBitangents; - pMesh->mBitangents = NULL; - ret = true; - } - - // handle texture coordinates - register bool b = (0 != (configDeleteFlags & aiComponent_TEXCOORDS)); - for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++real) - { - if (!pMesh->mTextureCoords[i])break; - if (configDeleteFlags & aiComponent_TEXCOORDSn(real) || b) - { - delete pMesh->mTextureCoords[i]; - pMesh->mTextureCoords[i] = NULL; - ret = true; - - if (!b) - { - // collapse the rest of the array - for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) - pMesh->mTextureCoords[a-1] = pMesh->mTextureCoords[a]; - - pMesh->mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS-1] = NULL; - continue; - } - } - ++i; - } - - // handle vertex colors - b = (0 != (configDeleteFlags & aiComponent_COLORS)); - for (unsigned int i = 0, real = 0; real < AI_MAX_NUMBER_OF_COLOR_SETS; ++real) - { - if (!pMesh->mColors[i])break; - if (configDeleteFlags & aiComponent_COLORSn(i) || b) - { - delete pMesh->mColors[i]; - pMesh->mColors[i] = NULL; - ret = true; - - if (!b) - { - // collapse the rest of the array - for (unsigned int a = i+1; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) - pMesh->mColors[a-1] = pMesh->mColors[a]; - - pMesh->mColors[AI_MAX_NUMBER_OF_COLOR_SETS-1] = NULL; - continue; - } - } - ++i; - } - - // handle bones - if (configDeleteFlags & aiComponent_BONEWEIGHTS && pMesh->mBones) - { - ArrayDelete(pMesh->mBones,pMesh->mNumBones); - ret = true; - } - return ret; -} diff --git a/3rdparty/assimp/code/RemoveVCProcess.h b/3rdparty/assimp/code/RemoveVCProcess.h deleted file mode 100644 index 43693f63..00000000 --- a/3rdparty/assimp/code/RemoveVCProcess.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to remove specific parts of the scene */ -#ifndef AI_REMOVEVCPROCESS_H_INCLUDED -#define AI_REMOVEVCPROCESS_H_INCLUDED - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class RemoveVCProcessTest; -namespace Assimp { - -// --------------------------------------------------------------------------- -/** RemoveVCProcess: Class to exclude specific parts of the data structure - * from further processing by removing them, -*/ -class ASSIMP_API RemoveVCProcess : public BaseProcess -{ - friend class Importer; - friend class ::RemoveVCProcessTest; - -protected: - /** Constructor to be privately used by Importer */ - RemoveVCProcess(); - - /** Destructor, private as well */ - ~RemoveVCProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - virtual void SetupProperties(const Importer* pImp); - - // ------------------------------------------------------------------- - /** Manually setup the configuration flags for the step - * - * @param Bitwise combintion of the #aiComponent enumerated values. - */ - void SetDeleteFlags(unsigned int f) - { - configDeleteFlags = f; - } - - // ------------------------------------------------------------------- - /** Query the current configuration. - */ - unsigned int GetDeleteFlags() const - { - return configDeleteFlags; - } - -private: - - bool ProcessMesh (aiMesh* pcMesh); - - /** Configuration flag - */ - unsigned int configDeleteFlags; - - /** The scene we're working with - */ - aiScene* mScene; -}; - -} // end of namespace Assimp - -#endif // !!AI_REMOVEVCPROCESS_H_INCLUDED diff --git a/3rdparty/assimp/code/SGSpatialSort.cpp b/3rdparty/assimp/code/SGSpatialSort.cpp deleted file mode 100644 index 705dafc9..00000000 --- a/3rdparty/assimp/code/SGSpatialSort.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 helper class to quickly find -vertices close to a given position. Special implementation for -the 3ds loader handling smooth groups correctly */ - -#include "AssimpPCH.h" -#include "SGSpatialSort.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -SGSpatialSort::SGSpatialSort() -{ - // define the reference plane. We choose some arbitrary vector away from all basic axises - // in the hope that no model spreads all its vertices along this plane. - mPlaneNormal.Set( 0.8523f, 0.34321f, 0.5736f); - mPlaneNormal.Normalize(); -} -// ------------------------------------------------------------------------------------------------ -// Destructor -SGSpatialSort::~SGSpatialSort() -{ - // nothing to do here, everything destructs automatically -} -// ------------------------------------------------------------------------------------------------ -void SGSpatialSort::Add(const aiVector3D& vPosition, unsigned int index, - unsigned int smoothingGroup) -{ - // store position by index and distance - float distance = vPosition * mPlaneNormal; - mPositions.push_back( Entry( index, vPosition, - distance, smoothingGroup)); -} -// ------------------------------------------------------------------------------------------------ -void SGSpatialSort::Prepare() -{ - // now sort the array ascending by distance. - std::sort( this->mPositions.begin(), this->mPositions.end()); -} -// ------------------------------------------------------------------------------------------------ -// Returns an iterator for all positions close to the given position. -void SGSpatialSort::FindPositions( const aiVector3D& pPosition, - uint32_t pSG, - float pRadius, - std::vector<unsigned int>& poResults, - bool exactMatch /*= false*/) const -{ - float dist = pPosition * mPlaneNormal; - float minDist = dist - pRadius, maxDist = dist + pRadius; - - // clear the array in this strange fashion because a simple clear() would also deallocate - // the array which we want to avoid - poResults.erase( poResults.begin(), poResults.end()); - - // quick check for positions outside the range - if ( mPositions.size() == 0) - return; - if ( maxDist < mPositions.front().mDistance) - return; - if ( minDist > mPositions.back().mDistance) - return; - - // do a binary search for the minimal distance to start the iteration there - unsigned int index = (unsigned int)mPositions.size() / 2; - unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4; - while ( binaryStepSize > 1) - { - if ( mPositions[index].mDistance < minDist) - index += binaryStepSize; - else - index -= binaryStepSize; - - binaryStepSize /= 2; - } - - // depending on the direction of the last step we need to single step a bit back or forth - // to find the actual beginning element of the range - while ( index > 0 && mPositions[index].mDistance > minDist) - index--; - while ( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist) - index++; - - // Mow start iterating from there until the first position lays outside of the distance range. - // Add all positions inside the distance range within the given radius to the result aray - - float squareEpsilon = pRadius * pRadius; - std::vector<Entry>::const_iterator it = mPositions.begin() + index; - std::vector<Entry>::const_iterator end = mPositions.end(); - - if (exactMatch) - { - while ( it->mDistance < maxDist) - { - if ((it->mPosition - pPosition).SquareLength() < squareEpsilon && it->mSmoothGroups == pSG) - { - poResults.push_back( it->mIndex); - } - ++it; - if ( end == it )break; - } - } - else - { - // if the given smoothing group is 0, we'll return all surrounding vertices - if (!pSG) - { - while ( it->mDistance < maxDist) - { - if ((it->mPosition - pPosition).SquareLength() < squareEpsilon) - poResults.push_back( it->mIndex); - ++it; - if ( end == it)break; - } - } - else while ( it->mDistance < maxDist) - { - if ((it->mPosition - pPosition).SquareLength() < squareEpsilon && - (it->mSmoothGroups & pSG || !it->mSmoothGroups)) - { - poResults.push_back( it->mIndex); - } - ++it; - if ( end == it)break; - } - } -} - - diff --git a/3rdparty/assimp/code/SGSpatialSort.h b/3rdparty/assimp/code/SGSpatialSort.h deleted file mode 100644 index e657ae3a..00000000 --- a/3rdparty/assimp/code/SGSpatialSort.h +++ /dev/null @@ -1,139 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -/** Small helper classes to optimise finding vertizes close to a given location - */ -#ifndef AI_D3DSSPATIALSORT_H_INC -#define AI_D3DSSPATIALSORT_H_INC - -#include <vector> -#include "../include/aiTypes.h" - -namespace Assimp { - -// ---------------------------------------------------------------------------------- -/** Specialized version of SpatialSort to support smoothing groups - * This is used in by the 3DS, ASE and LWO loaders. 3DS and ASE share their - * normal computation code in SmoothingGroups.inl, the LWO loader has its own - * implementation to handle all details of its file format correctly. - */ -// ---------------------------------------------------------------------------------- -class SGSpatialSort -{ -public: - - SGSpatialSort(); - - // ------------------------------------------------------------------- - /** Construction from a given face array, handling smoothing groups - * properly - */ - SGSpatialSort(const std::vector<aiVector3D>& vPositions); - - // ------------------------------------------------------------------- - /** Add a vertex to the spatial sort - * @param vPosition Vertex position to be added - * @param index Index of the vrtex - * @param smoothingGroup SmoothingGroup for this vertex - */ - void Add(const aiVector3D& vPosition, unsigned int index, - unsigned int smoothingGroup); - - // ------------------------------------------------------------------- - /** Prepare the spatial sorter for use. This step runs in O(logn) - */ - void Prepare(); - - /** Destructor */ - ~SGSpatialSort(); - - // ------------------------------------------------------------------- - /** Returns an iterator for all positions close to the given position. - * @param pPosition The position to look for vertices. - * @param pSG Only included vertices with at least one shared smooth group - * @param pRadius Maximal distance from the position a vertex may have - * to be counted in. - * @param poResults The container to store the indices of the found - * positions. Will be emptied by the call so it may contain anything. - * @param exactMatch Specifies whether smoothing groups are bit masks - * (false) or integral values (true). In the latter case, a vertex - * cannot belong to more than one smoothing group. - * @return An iterator to iterate over all vertices in the given area. - */ - // ------------------------------------------------------------------- - void FindPositions( const aiVector3D& pPosition, uint32_t pSG, - float pRadius, std::vector<unsigned int>& poResults, - bool exactMatch = false) const; - -protected: - /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */ - aiVector3D mPlaneNormal; - - // ------------------------------------------------------------------- - /** An entry in a spatially sorted position array. Consists of a - * vertex index, its position and its precalculated distance from - * the reference plane */ - // ------------------------------------------------------------------- - struct Entry - { - unsigned int mIndex; ///< The vertex referred by this entry - aiVector3D mPosition; ///< Position - uint32_t mSmoothGroups; - float mDistance; ///< Distance of this vertex to the sorting plane - - Entry() { /** intentionally not initialized.*/ } - Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance,uint32_t pSG) - : - mIndex( pIndex), - mPosition( pPosition), - mSmoothGroups (pSG), - mDistance( pDistance) - { } - - bool operator < (const Entry& e) const { return mDistance < e.mDistance; } - }; - - // all positions, sorted by distance to the sorting plane - std::vector<Entry> mPositions; -}; - -} // end of namespace Assimp - -#endif // AI_SPATIALSORT_H_INC diff --git a/3rdparty/assimp/code/SMDLoader.cpp b/3rdparty/assimp/code/SMDLoader.cpp deleted file mode 100644 index 234582c9..00000000 --- a/3rdparty/assimp/code/SMDLoader.cpp +++ /dev/null @@ -1,1129 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 SMDLoader.cpp - * @brief Implementation of the SMD importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER - -// internal headers -#include "SMDLoader.h" -#include "fast_atof.h" -#include "SkeletonMeshBuilder.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -SMDImporter::SMDImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -SMDImporter::~SMDImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool SMDImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool) const -{ - // fixme: auto format detection - return SimpleExtensionCheck(pFile,"smd","vta"); -} - -// ------------------------------------------------------------------------------------------------ -// Get a list of all supported file extensions -void SMDImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("smd"); - extensions.insert("vta"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup configuration properties -void SMDImporter::SetupProperties(const Importer* pImp) -{ - // The - // AI_CONFIG_IMPORT_SMD_KEYFRAME option overrides the - // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option. - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_SMD_KEYFRAME,0xffffffff); - if(0xffffffff == configFrameID) { - configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0); - } -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void SMDImporter::InternReadFile( - const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if( file.get() == NULL) { - throw DeadlyImportError( "Failed to open SMD/VTA file " + pFile + "."); - } - - iFileSize = (unsigned int)file->FileSize(); - - // Allocate storage and copy the contents of the file to a memory buffer - this->pScene = pScene; - - std::vector<char> buff(iFileSize+1); - TextFileToBuffer(file.get(),buff); - mBuffer = &buff[0]; - - iSmallestFrame = (1 << 31); - bHasUVs = true; - iLineNumber = 1; - - // Reserve enough space for ... hm ... 10 textures - aszTextures.reserve(10); - - // Reserve enough space for ... hm ... 1000 triangles - asTriangles.reserve(1000); - - // Reserve enough space for ... hm ... 20 bones - asBones.reserve(20); - - - // parse the file ... - ParseFile(); - - // If there are no triangles it seems to be an animation SMD, - // containing only the animation skeleton. - if (asTriangles.empty()) - { - if (asBones.empty()) - { - throw DeadlyImportError("SMD: No triangles and no bones have " - "been found in the file. This file seems to be invalid."); - } - - // Set the flag in the scene structure which indicates - // that there is nothing than an animation skeleton - pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - - if (!asBones.empty()) - { - // Check whether all bones have been initialized - for (std::vector<SMD::Bone>::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if (!(*i).mName.length()) - { - DefaultLogger::get()->warn("SMD: Not all bones have been initialized"); - break; - } - } - - // now fix invalid time values and make sure the animation starts at frame 0 - FixTimeValues(); - - // compute absolute bone transformation matrices - // ComputeAbsoluteBoneTransformations(); - } - - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) - { - // create output meshes - CreateOutputMeshes(); - - // build an output material list - CreateOutputMaterials(); - } - - // build the output animation - CreateOutputAnimations(); - - // build output nodes (bones are added as empty dummy nodes) - CreateOutputNodes(); - - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) - { - SkeletonMeshBuilder skeleton(pScene); - } -} -// ------------------------------------------------------------------------------------------------ -// Write an error message with line number to the log file -void SMDImporter::LogErrorNoThrow(const char* msg) -{ - char szTemp[1024]; - sprintf(szTemp,"Line %i: %s",iLineNumber,msg); - DefaultLogger::get()->error(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -// Write a warning with line number to the log file -void SMDImporter::LogWarning(const char* msg) -{ - char szTemp[1024]; - ai_assert(strlen(msg) < 1000); - DefaultLogger::get()->warn(szTemp); -} - -// ------------------------------------------------------------------------------------------------ -// Fix invalid time values in the file -void SMDImporter::FixTimeValues() -{ - double dDelta = (double)iSmallestFrame; - double dMax = 0.0f; - for (std::vector<SMD::Bone>::iterator - iBone = asBones.begin(); - iBone != asBones.end();++iBone) - { - for (std::vector<SMD::Bone::Animation::MatrixKey>::iterator - iKey = (*iBone).sAnim.asKeys.begin(); - iKey != (*iBone).sAnim.asKeys.end();++iKey) - { - (*iKey).dTime -= dDelta; - dMax = std::max(dMax, (*iKey).dTime); - } - } - dLengthOfAnim = dMax; -} - -// ------------------------------------------------------------------------------------------------ -// create output meshes -void SMDImporter::CreateOutputMeshes() -{ - if (aszTextures.empty()) - aszTextures.push_back(std::string()); - - // we need to sort all faces by their material index - // in opposition to other loaders we can be sure that each - // material is at least used once. - pScene->mNumMeshes = (unsigned int) aszTextures.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - - typedef std::vector<unsigned int> FaceList; - FaceList* aaiFaces = new FaceList[pScene->mNumMeshes]; - - // approximate the space that will be required - unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes; - iNum += iNum >> 1; - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - aaiFaces[i].reserve(iNum); - - - // collect all faces - iNum = 0; - for (std::vector<SMD::Face>::const_iterator - iFace = asTriangles.begin(); - iFace != asTriangles.end();++iFace,++iNum) - { - if (0xffffffff == (*iFace).iTexture)aaiFaces[(*iFace).iTexture].push_back( 0 ); - else if ((*iFace).iTexture >= aszTextures.size()) - { - DefaultLogger::get()->error("[SMD/VTA] Material index overflow in face"); - aaiFaces[(*iFace).iTexture].push_back((unsigned int)aszTextures.size()-1); - } - else aaiFaces[(*iFace).iTexture].push_back(iNum); - } - - // now create the output meshes - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - aiMesh*& pcMesh = pScene->mMeshes[i] = new aiMesh(); - ai_assert(!aaiFaces[i].empty()); // should not be empty ... - - pcMesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - pcMesh->mNumVertices = (unsigned int)aaiFaces[i].size()*3; - pcMesh->mNumFaces = (unsigned int)aaiFaces[i].size(); - pcMesh->mMaterialIndex = i; - - // storage for bones - typedef std::pair<unsigned int,float> TempWeightListEntry; - typedef std::vector< TempWeightListEntry > TempBoneWeightList; - - TempBoneWeightList* aaiBones = new TempBoneWeightList[asBones.size()](); - - // try to reserve enough memory without wasting too much - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - aaiBones[iBone].reserve(pcMesh->mNumVertices/asBones.size()); - } - - // allocate storage - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - aiVector3D* pcNormals = pcMesh->mNormals = new aiVector3D[pcMesh->mNumVertices]; - aiVector3D* pcVerts = pcMesh->mVertices = new aiVector3D[pcMesh->mNumVertices]; - - aiVector3D* pcUVs = NULL; - if (bHasUVs) - { - pcUVs = pcMesh->mTextureCoords[0] = new aiVector3D[pcMesh->mNumVertices]; - pcMesh->mNumUVComponents[0] = 2; - } - - iNum = 0; - for (unsigned int iFace = 0; iFace < pcMesh->mNumFaces;++iFace) - { - pcMesh->mFaces[iFace].mIndices = new unsigned int[3]; - pcMesh->mFaces[iFace].mNumIndices = 3; - - // fill the vertices - unsigned int iSrcFace = aaiFaces[i][iFace]; - SMD::Face& face = asTriangles[iSrcFace]; - - *pcVerts++ = face.avVertices[0].pos; - *pcVerts++ = face.avVertices[1].pos; - *pcVerts++ = face.avVertices[2].pos; - - // fill the normals - *pcNormals++ = face.avVertices[0].nor; - *pcNormals++ = face.avVertices[1].nor; - *pcNormals++ = face.avVertices[2].nor; - - // fill the texture coordinates - if (pcUVs) - { - *pcUVs++ = face.avVertices[0].uv; - *pcUVs++ = face.avVertices[1].uv; - *pcUVs++ = face.avVertices[2].uv; - } - - for (unsigned int iVert = 0; iVert < 3;++iVert) - { - float fSum = 0.0f; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) - { - TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; - - // FIX: The second check is here just to make sure we won't - // assign more than one weight to a single vertex index - if (pairval.first >= asBones.size() || - pairval.first == face.avVertices[iVert].iParentNode) - { - DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. " - "The bone index will be ignored, the weight will be assigned " - "to the vertex' parent node"); - continue; - } - aaiBones[pairval.first].push_back(TempWeightListEntry(iNum,pairval.second)); - fSum += pairval.second; - } - // ****************************************************************** - // If the sum of all vertex weights is not 1.0 we must assign - // the rest to the vertex' parent node. Well, at least the doc says - // we should ... - // FIX: We use 0.975 as limit, floating-point inaccuracies seem to - // be very strong in some SMD exporters. Furthermore it is possible - // that the parent of a vertex is 0xffffffff (if the corresponding - // entry in the file was unreadable) - // ****************************************************************** - if (fSum < 0.975f && face.avVertices[iVert].iParentNode != 0xffffffff) - { - if (face.avVertices[iVert].iParentNode >= asBones.size()) - { - DefaultLogger::get()->error("[SMD/VTA] Bone index overflow. " - "The index of the vertex parent bone is invalid. " - "The remaining weights will be normalized to 1.0"); - - if (fSum) - { - fSum = 1 / fSum; - for (unsigned int iBone = 0;iBone < face.avVertices[iVert].aiBoneLinks.size();++iBone) - { - TempWeightListEntry& pairval = face.avVertices[iVert].aiBoneLinks[iBone]; - if (pairval.first >= asBones.size())continue; - aaiBones[pairval.first].back().second *= fSum; - } - } - } - else - { - aaiBones[face.avVertices[iVert].iParentNode].push_back( - TempWeightListEntry(iNum,1.0f-fSum)); - } - } - pcMesh->mFaces[iFace].mIndices[iVert] = iNum++; - } - } - - // now build all bones of the mesh - iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - if (!aaiBones[iBone].empty())++iNum; - - if (false && iNum) - { - pcMesh->mNumBones = iNum; - pcMesh->mBones = new aiBone*[pcMesh->mNumBones]; - iNum = 0; - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - if (aaiBones[iBone].empty())continue; - aiBone*& bone = pcMesh->mBones[iNum] = new aiBone(); - - bone->mNumWeights = (unsigned int)aaiBones[iBone].size(); - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - bone->mOffsetMatrix = asBones[iBone].mOffsetMatrix; - bone->mName.Set( asBones[iBone].mName ); - - asBones[iBone].bIsUsed = true; - - for (unsigned int iWeight = 0; iWeight < bone->mNumWeights;++iWeight) - { - bone->mWeights[iWeight].mVertexId = aaiBones[iBone][iWeight].first; - bone->mWeights[iWeight].mWeight = aaiBones[iBone][iWeight].second; - } - ++iNum; - } - } - delete[] aaiBones; - } - delete[] aaiFaces; -} - -// ------------------------------------------------------------------------------------------------ -// add bone child nodes -void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent) -{ - ai_assert(NULL != pcNode && 0 == pcNode->mNumChildren && NULL == pcNode->mChildren); - - // first count ... - for (unsigned int i = 0; i < asBones.size();++i) - { - SMD::Bone& bone = asBones[i]; - if (bone.iParent == iParent)++pcNode->mNumChildren; - } - - // now allocate the output array - pcNode->mChildren = new aiNode*[pcNode->mNumChildren]; - - // and fill all subnodes - unsigned int qq = 0; - for (unsigned int i = 0; i < asBones.size();++i) - { - SMD::Bone& bone = asBones[i]; - if (bone.iParent != iParent)continue; - - aiNode* pc = pcNode->mChildren[qq++] = new aiNode(); - pc->mName.Set(bone.mName); - - // store the local transformation matrix of the bind pose - pc->mTransformation = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrix; - pc->mParent = pcNode; - - // add children to this node, too - AddBoneChildren(pc,i); - } -} - -// ------------------------------------------------------------------------------------------------ -// create output nodes -void SMDImporter::CreateOutputNodes() -{ - pScene->mRootNode = new aiNode(); - if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) - { - // create one root node that renders all meshes - 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; - } - - // now add all bones as dummy sub nodes to the graph - // AddBoneChildren(pScene->mRootNode,(uint32_t)-1); - - // if we have only one bone we can even remove the root node - if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE && - 1 == pScene->mRootNode->mNumChildren) - { - aiNode* pcOldRoot = pScene->mRootNode; - pScene->mRootNode = pcOldRoot->mChildren[0]; - pcOldRoot->mChildren[0] = NULL; - delete pcOldRoot; - - pScene->mRootNode->mParent = NULL; - } - else - { - ::strcpy(pScene->mRootNode->mName.data, "<SMD_root>"); - pScene->mRootNode->mName.length = 10; - } -} - -// ------------------------------------------------------------------------------------------------ -// create output animations -void SMDImporter::CreateOutputAnimations() -{ - unsigned int iNumBones = 0; - for (std::vector<SMD::Bone>::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if ((*i).bIsUsed)++iNumBones; - } - if (!iNumBones) - { - // just make sure this case doesn't occur ... (it could occur - // if the file was invalid) - return; - } - - pScene->mNumAnimations = 1; - pScene->mAnimations = new aiAnimation*[1]; - aiAnimation*& anim = pScene->mAnimations[0] = new aiAnimation(); - - anim->mDuration = dLengthOfAnim; - anim->mNumChannels = iNumBones; - anim->mTicksPerSecond = 25.0; // FIXME: is this correct? - - aiNodeAnim** pp = anim->mChannels = new aiNodeAnim*[anim->mNumChannels]; - - // now build valid keys - unsigned int a = 0; - for (std::vector<SMD::Bone>::const_iterator - i = asBones.begin(); - i != asBones.end();++i) - { - if (!(*i).bIsUsed)continue; - - aiNodeAnim* p = pp[a] = new aiNodeAnim(); - - // copy the name of the bone - p->mNodeName.Set( i->mName); - - p->mNumRotationKeys = (unsigned int) (*i).sAnim.asKeys.size(); - if (p->mNumRotationKeys) - { - p->mNumPositionKeys = p->mNumRotationKeys; - aiVectorKey* pVecKeys = p->mPositionKeys = new aiVectorKey[p->mNumRotationKeys]; - aiQuatKey* pRotKeys = p->mRotationKeys = new aiQuatKey[p->mNumRotationKeys]; - - for (std::vector<SMD::Bone::Animation::MatrixKey>::const_iterator - qq = (*i).sAnim.asKeys.begin(); - qq != (*i).sAnim.asKeys.end(); ++qq) - { - pRotKeys->mTime = pVecKeys->mTime = (*qq).dTime; - - // compute the rotation quaternion from the euler angles - pRotKeys->mValue = aiQuaternion( (*qq).vRot.x, (*qq).vRot.y, (*qq).vRot.z ); - pVecKeys->mValue = (*qq).vPos; - - ++pVecKeys; ++pRotKeys; - } - } - ++a; - - // there are no scaling keys ... - } -} - -// ------------------------------------------------------------------------------------------------ -void SMDImporter::ComputeAbsoluteBoneTransformations() -{ - // For each bone: determine the key with the lowest time value - // theoretically the SMD format should have all keyframes - // in order. However, I've seen a file where this wasn't true. - for (unsigned int i = 0; i < asBones.size();++i) - { - SMD::Bone& bone = asBones[i]; - - uint32_t iIndex = 0; - double dMin = 10e10; - for (unsigned int i = 0; i < bone.sAnim.asKeys.size();++i) - { - double d = std::min(bone.sAnim.asKeys[i].dTime,dMin); - if (d < dMin) - { - dMin = d; - iIndex = i; - } - } - bone.sAnim.iFirstTimeKey = iIndex; - } - - unsigned int iParent = 0; - while (iParent < asBones.size()) - { - for (unsigned int iBone = 0; iBone < asBones.size();++iBone) - { - SMD::Bone& bone = asBones[iBone]; - - if (iParent == bone.iParent) - { - SMD::Bone& parentBone = asBones[iParent]; - - - uint32_t iIndex = bone.sAnim.iFirstTimeKey; - const aiMatrix4x4& mat = bone.sAnim.asKeys[iIndex].matrix; - aiMatrix4x4& matOut = bone.sAnim.asKeys[iIndex].matrixAbsolute; - - // The same for the parent bone ... - iIndex = parentBone.sAnim.iFirstTimeKey; - const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrixAbsolute; - - // Compute the absolute transformation matrix - matOut = mat * mat2; - } - } - ++iParent; - } - - // Store the inverse of the absolute transformation matrix - // of the first key as bone offset matrix - for (iParent = 0; iParent < asBones.size();++iParent) - { - SMD::Bone& bone = asBones[iParent]; - bone.mOffsetMatrix = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute; - bone.mOffsetMatrix.Inverse(); - } -} - -// ------------------------------------------------------------------------------------------------ -// create output materials -void SMDImporter::CreateOutputMaterials() -{ - pScene->mNumMaterials = (unsigned int)aszTextures.size(); - pScene->mMaterials = new aiMaterial*[std::max(1u, pScene->mNumMaterials)]; - - for (unsigned int iMat = 0; iMat < pScene->mNumMaterials;++iMat) - { - MaterialHelper* pcMat = new MaterialHelper(); - pScene->mMaterials[iMat] = pcMat; - - aiString szName; - szName.length = (size_t)::sprintf(szName.data,"Texture_%i",iMat); - pcMat->AddProperty(&szName,AI_MATKEY_NAME); - - if (aszTextures[iMat].length()) - { - ::strcpy(szName.data, aszTextures[iMat].c_str() ); - szName.length = aszTextures[iMat].length(); - pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - } - - // create a default material if necessary - if (0 == pScene->mNumMaterials) - { - pScene->mNumMaterials = 1; - - MaterialHelper* pcHelper = new MaterialHelper(); - pScene->mMaterials[0] = pcHelper; - - int iMode = (int)aiShadingMode_Gouraud; - pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); - - aiColor3D clr; - clr.b = clr.g = clr.r = 0.7f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE); - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR); - - clr.b = clr.g = clr.r = 0.05f; - pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT); - - aiString szName; - szName.Set(AI_DEFAULT_MATERIAL_NAME); - pcHelper->AddProperty(&szName,AI_MATKEY_NAME); - } -} - -// ------------------------------------------------------------------------------------------------ -// Parse the file -void SMDImporter::ParseFile() -{ - const char* szCurrent = mBuffer; - - // read line per line ... - while (true) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; - - // "version <n> \n", <n> should be 1 for hl and hl² SMD files - if (TokenMatch(szCurrent,"version",7)) - { - if(!SkipSpaces(szCurrent,&szCurrent)) break; - if (1 != strtol10(szCurrent,&szCurrent)) - { - DefaultLogger::get()->warn("SMD.version is not 1. This " - "file format is not known. Continuing happily ..."); - } - continue; - } - // "nodes\n" - Starts the node section - if (TokenMatch(szCurrent,"nodes",5)) - { - ParseNodesSection(szCurrent,&szCurrent); - continue; - } - // "triangles\n" - Starts the triangle section - if (TokenMatch(szCurrent,"triangles",9)) - { - ParseTrianglesSection(szCurrent,&szCurrent); - continue; - } - // "vertexanimation\n" - Starts the vertex animation section - if (TokenMatch(szCurrent,"vertexanimation",15)) - { - bHasUVs = false; - ParseVASection(szCurrent,&szCurrent); - continue; - } - // "skeleton\n" - Starts the skeleton section - if (TokenMatch(szCurrent,"skeleton",8)) - { - ParseSkeletonSection(szCurrent,&szCurrent); - continue; - } - SkipLine(szCurrent,&szCurrent); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -unsigned int SMDImporter::GetTextureIndex(const std::string& filename) -{ - unsigned int iIndex = 0; - for (std::vector<std::string>::const_iterator - i = aszTextures.begin(); - i != aszTextures.end();++i,++iIndex) - { - // case-insensitive ... it's a path - if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str()))return iIndex; - } - iIndex = (unsigned int)aszTextures.size(); - aszTextures.push_back(filename); - return iIndex; -} - -// ------------------------------------------------------------------------------------------------ -// Parse the nodes section of the file -void SMDImporter::ParseNodesSection(const char* szCurrent, - const char** szCurrentOut) -{ - while (true) - { - // "end\n" - Ends the nodes section - if (0 == ASSIMP_strincmp(szCurrent,"end",3) && - IsSpaceOrNewLine(*(szCurrent+3))) - { - szCurrent += 4; - break; - } - ParseNodeInfo(szCurrent,&szCurrent); - } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// Parse the triangles section of the file -void SMDImporter::ParseTrianglesSection(const char* szCurrent, - const char** szCurrentOut) -{ - // Parse a triangle, parse another triangle, parse the next triangle ... - // and so on until we reach a token that looks quite similar to "end" - while (true) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; - - // "end\n" - Ends the triangles section - if (TokenMatch(szCurrent,"end",3)) - break; - ParseTriangle(szCurrent,&szCurrent); - } - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - *szCurrentOut = szCurrent; -} -// ------------------------------------------------------------------------------------------------ -// Parse the vertex animation section of the file -void SMDImporter::ParseVASection(const char* szCurrent, - const char** szCurrentOut) -{ - unsigned int iCurIndex = 0; - while (true) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; - - // "end\n" - Ends the "vertexanimation" section - if (TokenMatch(szCurrent,"end",3)) - break; - - // "time <n>\n" - if (TokenMatch(szCurrent,"time",4)) - { - // NOTE: The doc says that time values COULD be negative ... - // NOTE2: this is the shape key -> valve docs - int iTime = 0; - if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime)break; - SkipLine(szCurrent,&szCurrent); - } - else - { - if(0 == iCurIndex) - { - asTriangles.push_back(SMD::Face()); - } - if (++iCurIndex == 3)iCurIndex = 0; - ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true); - } - } - - if (iCurIndex != 2 && !asTriangles.empty()) - { - // we want to no degenerates, so throw this triangle away - asTriangles.pop_back(); - } - - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - *szCurrentOut = szCurrent; -} -// ------------------------------------------------------------------------------------------------ -// Parse the skeleton section of the file -void SMDImporter::ParseSkeletonSection(const char* szCurrent, - const char** szCurrentOut) -{ - int iTime = 0; - while (true) - { - if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break; - - // "end\n" - Ends the skeleton section - if (TokenMatch(szCurrent,"end",3)) - break; - - // "time <n>\n" - Specifies the current animation frame - else if (TokenMatch(szCurrent,"time",4)) - { - // NOTE: The doc says that time values COULD be negative ... - if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break; - - iSmallestFrame = std::min(iSmallestFrame,iTime); - SkipLine(szCurrent,&szCurrent); - } - else ParseSkeletonElement(szCurrent,&szCurrent,iTime); - } - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -#define SMDI_PARSE_RETURN { \ - SkipLine(szCurrent,&szCurrent); \ - *szCurrentOut = szCurrent; \ - return; \ -} -// ------------------------------------------------------------------------------------------------ -// Parse a node line -void SMDImporter::ParseNodeInfo(const char* szCurrent, - const char** szCurrentOut) -{ - unsigned int iBone = 0; - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone) || !SkipSpaces(szCurrent,&szCurrent)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone index"); - SMDI_PARSE_RETURN; - } - // add our bone to the list - if (iBone >= asBones.size())asBones.resize(iBone+1); - SMD::Bone& bone = asBones[iBone]; - - bool bQuota = true; - if ('\"' != *szCurrent) - { - LogWarning("Bone name is expcted to be enclosed in " - "double quotation marks. "); - bQuota = false; - } - else ++szCurrent; - - const char* szEnd = szCurrent; - while (true) - { - if (bQuota && '\"' == *szEnd) - { - iBone = (unsigned int)(szEnd - szCurrent); - ++szEnd; - break; - } - else if (IsSpaceOrNewLine(*szEnd)) - { - iBone = (unsigned int)(szEnd - szCurrent); - break; - } - else if (!(*szEnd)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone name"); - SMDI_PARSE_RETURN; - } - ++szEnd; - } - bone.mName = std::string(szCurrent,iBone); - szCurrent = szEnd; - - // the only negative bone parent index that could occur is -1 AFAIK - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)bone.iParent)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone parent index. Assuming -1"); - SMDI_PARSE_RETURN; - } - - // go to the beginning of the next line - SMDI_PARSE_RETURN; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a skeleton element -void SMDImporter::ParseSkeletonElement(const char* szCurrent, - const char** szCurrentOut,int iTime) -{ - aiVector3D vPos; - aiVector3D vRot; - - unsigned int iBone = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iBone)) - { - DefaultLogger::get()->error("Unexpected EOF/EOL while parsing bone index"); - SMDI_PARSE_RETURN; - } - if (iBone >= asBones.size()) - { - LogErrorNoThrow("Bone index in skeleton section is out of range"); - SMDI_PARSE_RETURN; - } - SMD::Bone& bone = asBones[iBone]; - - bone.sAnim.asKeys.push_back(SMD::Bone::Animation::MatrixKey()); - SMD::Bone::Animation::MatrixKey& key = bone.sAnim.asKeys.back(); - - key.dTime = (double)iTime; - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.x)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.y)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vPos.z)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.pos.z"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.x)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.y)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vRot.z)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing bone.rot.z"); - SMDI_PARSE_RETURN; - } - // build the transformation matrix of the key - key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z); - { - aiMatrix4x4 mTemp; - mTemp.a4 = vPos.x; - mTemp.b4 = vPos.y; - mTemp.c4 = vPos.z; - key.matrix = key.matrix * mTemp; - } - - // go to the beginning of the next line - SMDI_PARSE_RETURN; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a triangle -void SMDImporter::ParseTriangle(const char* szCurrent, - const char** szCurrentOut) -{ - asTriangles.push_back(SMD::Face()); - SMD::Face& face = asTriangles.back(); - - if(!SkipSpaces(szCurrent,&szCurrent)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing a triangle"); - return; - } - - // read the texture file name - const char* szLast = szCurrent; - while (!IsSpaceOrNewLine(*szCurrent++)); - - // ... and get the index that belongs to this file name - face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast)); - - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - - // load three vertices - for (unsigned int iVert = 0; iVert < 3;++iVert) - { - ParseVertex(szCurrent,&szCurrent, - face.avVertices[iVert]); - } - *szCurrentOut = szCurrent; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a float -bool SMDImporter::ParseFloat(const char* szCurrent, - const char** szCurrentOut, float& out) -{ - if(!SkipSpaces(&szCurrent)) - return false; - - *szCurrentOut = fast_atof_move(szCurrent,out); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Parse an unsigned int -bool SMDImporter::ParseUnsignedInt(const char* szCurrent, - const char** szCurrentOut, unsigned int& out) -{ - if(!SkipSpaces(&szCurrent)) - return false; - - out = strtol10(szCurrent,szCurrentOut); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a signed int -bool SMDImporter::ParseSignedInt(const char* szCurrent, - const char** szCurrentOut, int& out) -{ - if(!SkipSpaces(&szCurrent)) - return false; - - out = strtol10s(szCurrent,szCurrentOut); - return true; -} - -// ------------------------------------------------------------------------------------------------ -// Parse a vertex -void SMDImporter::ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, - bool bVASection /*= false*/) -{ - if (SkipSpaces(&szCurrent) && IsLineEnd(*szCurrent)) - { - SkipSpacesAndLineEnd(szCurrent,&szCurrent); - return ParseVertex(szCurrent,szCurrentOut,vertex,bVASection); - } - if(!ParseSignedInt(szCurrent,&szCurrent,(int&)vertex.iParentNode)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.parent"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.x)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.y)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.pos.z)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.pos.z"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.x)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.y)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.y"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.nor.z)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.nor.z"); - SMDI_PARSE_RETURN; - } - - if (bVASection)SMDI_PARSE_RETURN; - - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.x)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.x"); - SMDI_PARSE_RETURN; - } - if(!ParseFloat(szCurrent,&szCurrent,(float&)vertex.uv.y)) - { - LogErrorNoThrow("Unexpected EOF/EOL while parsing vertex.uv.y"); - SMDI_PARSE_RETURN; - } - - // now read the number of bones affecting this vertex - // all elements from now are fully optional, we don't need them - unsigned int iSize = 0; - if(!ParseUnsignedInt(szCurrent,&szCurrent,iSize))SMDI_PARSE_RETURN; - vertex.aiBoneLinks.resize(iSize,std::pair<unsigned int, float>(0,0.0f)); - - for (std::vector<std::pair<unsigned int, float> >::iterator - i = vertex.aiBoneLinks.begin(); - i != vertex.aiBoneLinks.end();++i) - { - if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first)) - SMDI_PARSE_RETURN; - if(!ParseFloat(szCurrent,&szCurrent,(*i).second)) - SMDI_PARSE_RETURN; - } - - // go to the beginning of the next line - SMDI_PARSE_RETURN; -} - -#endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER diff --git a/3rdparty/assimp/code/SMDLoader.h b/3rdparty/assimp/code/SMDLoader.h deleted file mode 100644 index 9b4ac8da..00000000 --- a/3rdparty/assimp/code/SMDLoader.h +++ /dev/null @@ -1,420 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 SMDLoader.h - * @brief Defintion of the Valve SMD file format - */ - -#ifndef AI_SMDLOADER_H_INCLUDED -#define AI_SMDLOADER_H_INCLUDED - -// internal headers -#include "BaseImporter.h" -#include "ParsingUtils.h" - -// public Assimp headers -#include "../include/aiTypes.h" -#include "../include/aiTexture.h" -#include "../include/aiAnim.h" -#include "../include/aiMaterial.h" -struct aiNode; - -// STL headers -#include <vector> - -namespace Assimp { -class MaterialHelper; - -namespace SMD { - -// --------------------------------------------------------------------------- -/** Data structure for a vertex in a SMD file -*/ -struct Vertex -{ - Vertex() : iParentNode(0xffffffff) - {} - - //! Vertex position, normal and texture coordinate - aiVector3D pos,nor,uv; - - //! Vertex parent node - unsigned int iParentNode; - - //! Links to bones: pair.first is the bone index, - //! pair.second is the vertex weight. - //! WARN: The remaining weight (to reach 1.0f) is assigned - //! to the parent node/bone - std::vector<std::pair<unsigned int, float> > aiBoneLinks; -}; - -// --------------------------------------------------------------------------- -/** Data structure for a face in a SMD file -*/ -struct Face -{ - Face() : iTexture(0x0) - {} - - //! Texture index for the face - unsigned int iTexture; - - //! The three vertices of the face - Vertex avVertices[3]; -}; - -// --------------------------------------------------------------------------- -/** Data structure for a bone in a SMD file -*/ -struct Bone -{ - //! Default constructor - Bone() : iParent(0xffffffff), bIsUsed(false) - { - } - - //! Destructor - ~Bone() - { - } - - //! Name of the bone - std::string mName; - - //! Parent of the bone - uint32_t iParent; - - //! Animation of the bone - struct Animation - { - //! Public default constructor - Animation() - { - asKeys.reserve(20); - } - - //! Data structure for a matrix key - struct MatrixKey - { - //! Matrix at this time - aiMatrix4x4 matrix; - - //! Absolute transformation matrix - aiMatrix4x4 matrixAbsolute; - - //! Position - aiVector3D vPos; - - //! Rotation (euler angles) - aiVector3D vRot; - - //! Current time. may be negative, this - //! will be fixed later - double dTime; - }; - - //! Index of the key with the smallest time value - uint32_t iFirstTimeKey; - - //! Array of matrix keys - std::vector<MatrixKey> asKeys; - - } sAnim; - - //! Offset matrix of the bone - aiMatrix4x4 mOffsetMatrix; - - //! true if the bone is referenced by at least one mesh - bool bIsUsed; -}; - -} //! namespace SMD - -// --------------------------------------------------------------------------- -/** Used to load Half-life 1 and 2 SMD models -*/ -class SMDImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - SMDImporter(); - - /** Destructor, private as well */ - ~SMDImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - - // ------------------------------------------------------------------- - /** Called prior to ReadFile(). - * The function is a request to the importer to update its configuration - * basing on the Importer's configuration property list. - */ - void SetupProperties(const Importer* pImp); - -protected: - - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -protected: - - // ------------------------------------------------------------------- - /** Parse the SMD file and create the output scene - */ - void ParseFile(); - - // ------------------------------------------------------------------- - /** Parse the triangles section of the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseTrianglesSection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse the vertex animation section in VTA files - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseVASection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse the nodes section of the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseNodesSection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse the skeleton section of the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives a pointer to the heading line of - * the next section (or to EOF) - */ - void ParseSkeletonSection(const char* szCurrent, - const char** szCurrentOut); - - // ------------------------------------------------------------------- - /** Parse a single triangle in the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives the output cursor position - */ - void ParseTriangle(const char* szCurrent, - const char** szCurrentOut); - - - // ------------------------------------------------------------------- - /** Parse a single vertex in the SMD file - * \param szCurrent Current position in the file. Points to the first - * data line of the section. - * \param szCurrentOut Receives the output cursor position - * \param vertex Vertex to be filled - */ - void ParseVertex(const char* szCurrent, - const char** szCurrentOut, SMD::Vertex& vertex, - bool bVASection = false); - - // ------------------------------------------------------------------- - /** Get the index of a texture. If the texture was not yet known - * it will be added to the internal texture list. - * \param filename Name of the texture - * \return Value texture index - */ - unsigned int GetTextureIndex(const std::string& filename); - - // ------------------------------------------------------------------- - /** Computes absolute bone transformations - * All output transformations are in worldspace. - */ - void ComputeAbsoluteBoneTransformations(); - - - // ------------------------------------------------------------------- - /** Parse a line in the skeleton section - */ - void ParseSkeletonElement(const char* szCurrent, - const char** szCurrentOut,int iTime); - - // ------------------------------------------------------------------- - /** Parse a line in the nodes section - */ - void ParseNodeInfo(const char* szCurrent, - const char** szCurrentOut); - - - // ------------------------------------------------------------------- - /** Parse a floating-point value - */ - bool ParseFloat(const char* szCurrent, - const char** szCurrentOut, float& out); - - // ------------------------------------------------------------------- - /** Parse an unsigned integer. There may be no sign! - */ - bool ParseUnsignedInt(const char* szCurrent, - const char** szCurrentOut, unsigned int& out); - - // ------------------------------------------------------------------- - /** Parse a signed integer. Signs (+,-) are handled. - */ - bool ParseSignedInt(const char* szCurrent, - const char** szCurrentOut, int& out); - - // ------------------------------------------------------------------- - /** Fix invalid time values in the file - */ - void FixTimeValues(); - - // ------------------------------------------------------------------- - /** Add all children of a bone as subnodes to a node - * \param pcNode Parent node - * \param iParent Parent bone index - */ - void AddBoneChildren(aiNode* pcNode, uint32_t iParent); - - // ------------------------------------------------------------------- - /** Build output meshes/materials/nodes/animations - */ - void CreateOutputMeshes(); - void CreateOutputNodes(); - void CreateOutputAnimations(); - void CreateOutputMaterials(); - - - // ------------------------------------------------------------------- - /** Print a log message together with the current line number - */ - void LogErrorNoThrow(const char* msg); - void LogWarning(const char* msg); - - - // ------------------------------------------------------------------- - inline bool SkipLine( const char* in, const char** out) - { - Assimp::SkipLine(in,out); - ++iLineNumber; - return true; - } - // ------------------------------------------------------------------- - inline bool SkipSpacesAndLineEnd( const char* in, const char** out) - { - ++iLineNumber; - return Assimp::SkipSpacesAndLineEnd(in,out); - } - -private: - - /** Configuration option: frame to be loaded */ - unsigned int configFrameID; - - /** Buffer to hold the loaded file */ - const char* mBuffer; - - /** Output scene to be filled - */ - aiScene* pScene; - - /** Size of the input file in bytes - */ - unsigned int iFileSize; - - /** Array of textures found in the file - */ - std::vector<std::string> aszTextures; - - /** Array of triangles found in the file - */ - std::vector<SMD::Face> asTriangles; - - /** Array of bones found in the file - */ - std::vector<SMD::Bone> asBones; - - /** Smallest frame index found in the skeleton - */ - int iSmallestFrame; - - /** Length of the whole animation, in frames - */ - double dLengthOfAnim; - - /** Do we have texture coordinates? - */ - bool bHasUVs; - - /** Current line numer - */ - unsigned int iLineNumber; - -}; - -} // end of namespace Assimp - -#endif // AI_SMDIMPORTER_H_INC diff --git a/3rdparty/assimp/code/STLLoader.cpp b/3rdparty/assimp/code/STLLoader.cpp deleted file mode 100644 index 894124f2..00000000 --- a/3rdparty/assimp/code/STLLoader.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 STL importer class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_STL_IMPORTER - -// internal headers -#include "STLLoader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -STLImporter::STLImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -STLImporter::~STLImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool STLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - const std::string extension = GetExtension(pFile); - - if (extension == "stl") - return true; - else if (!extension.length() || checkSig) { - if (!pIOHandler) - return true; - const char* tokens[] = {"STL","solid"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,2); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void STLImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("stl"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void STLImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); - - // Check whether we can read from the file - if ( file.get() == NULL) { - throw DeadlyImportError( "Failed to open STL file " + pFile + "."); - } - - fileSize = (unsigned int)file->FileSize(); - - // allocate storage and copy the contents of the file to a memory buffer - // (terminate it with zero) - std::vector<char> mBuffer2; - TextFileToBuffer(file.get(),mBuffer2); - - this->pScene = pScene; - this->mBuffer = &mBuffer2[0]; - - // the default vertex color is white - clrColorDefault.r = clrColorDefault.g = clrColorDefault.b = clrColorDefault.a = 1.0f; - - // allocate one mesh - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - aiMesh* pMesh = pScene->mMeshes[0] = new aiMesh(); - pMesh->mMaterialIndex = 0; - - // allocate a single node - pScene->mRootNode = new aiNode(); - pScene->mRootNode->mNumMeshes = 1; - pScene->mRootNode->mMeshes = new unsigned int[1]; - pScene->mRootNode->mMeshes[0] = 0; - - bool bMatClr = false; - - // check whether the file starts with 'solid' - - // in this case we can simply assume it IS a text file. finished. - if (!::strncmp(mBuffer,"solid",5)) { - LoadASCIIFile(); - } - else bMatClr = LoadBinaryFile(); - - // now copy faces - pMesh->mFaces = new aiFace[pMesh->mNumFaces]; - for (unsigned int i = 0, p = 0; i < pMesh->mNumFaces;++i) { - - aiFace& face = pMesh->mFaces[i]; - face.mIndices = new unsigned int[face.mNumIndices = 3]; - for (unsigned int o = 0; o < 3;++o,++p) { - face.mIndices[o] = p; - } - } - - // create a single default material - everything white, as we have vertex colors - MaterialHelper* pcMat = new MaterialHelper(); - aiString s; - s.Set(AI_DEFAULT_MATERIAL_NAME); - pcMat->AddProperty(&s, AI_MATKEY_NAME); - - aiColor4D clrDiffuse(1.0f,1.0f,1.0f,1.0f); - if (bMatClr) { - clrDiffuse = clrColorDefault; - } - pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_DIFFUSE); - pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_SPECULAR); - clrDiffuse = aiColor4D(0.05f,0.05f,0.05f,1.0f); - pcMat->AddProperty(&clrDiffuse,1,AI_MATKEY_COLOR_AMBIENT); - - pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = pcMat; -} -// ------------------------------------------------------------------------------------------------ -// Read an ASCII STL file -void STLImporter::LoadASCIIFile() -{ - aiMesh* pMesh = pScene->mMeshes[0]; - - const char* sz = mBuffer + 5; // skip the "solid" - SkipSpaces(&sz); - const char* szMe = sz; - while (!::IsSpaceOrNewLine(*sz)) { - sz++; - } - - size_t temp; - // setup the name of the node - if ((temp = (size_t)(sz-szMe))) { - - pScene->mRootNode->mName.length = temp; - memcpy(pScene->mRootNode->mName.data,szMe,temp); - pScene->mRootNode->mName.data[temp] = '\0'; - } - else pScene->mRootNode->mName.Set("<STL_ASCII>"); - - // try to guess how many vertices we could have - // assume we'll need 160 bytes for each face - pMesh->mNumVertices = ( pMesh->mNumFaces = fileSize / 160 ) * 3; - pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - - unsigned int curFace = 0, curVertex = 3; - while (true) - { - // go to the next token - if (!SkipSpacesAndLineEnd(&sz)) - { - // seems we're finished although there was no end marker - DefaultLogger::get()->warn("STL: unexpected EOF. \'endsolid\' keyword was expected"); - break; - } - // facet normal -0.13 -0.13 -0.98 - if (!strncmp(sz,"facet",5) && IsSpaceOrNewLine(*(sz+5))) { - - if (3 != curVertex) { - DefaultLogger::get()->warn("STL: A new facet begins but the old is not yet complete"); - } - if (pMesh->mNumFaces == curFace) { - // need to resize the arrays, our size estimate was wrong - unsigned int iNeededSize = (unsigned int)(sz-mBuffer) / pMesh->mNumFaces; - if (iNeededSize <= 160)iNeededSize >>= 1; // prevent endless looping - unsigned int add = (unsigned int)((mBuffer+fileSize)-sz) / iNeededSize; - add += add >> 3; // add 12.5% as buffer - iNeededSize = (pMesh->mNumFaces + add)*3; - aiVector3D* pv = new aiVector3D[iNeededSize]; - memcpy(pv,pMesh->mVertices,pMesh->mNumVertices*sizeof(aiVector3D)); - delete[] pMesh->mVertices; - pMesh->mVertices = pv; - pv = new aiVector3D[iNeededSize]; - memcpy(pv,pMesh->mNormals,pMesh->mNumVertices*sizeof(aiVector3D)); - delete[] pMesh->mNormals; - pMesh->mNormals = pv; - - pMesh->mNumVertices = iNeededSize; - pMesh->mNumFaces += add; - } - aiVector3D* vn = &pMesh->mNormals[curFace++*3]; - - sz += 6; - curVertex = 0; - SkipSpaces(&sz); - if (strncmp(sz,"normal",6)) { - DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found"); - } - else - { - sz += 7; - SkipSpaces(&sz); - sz = fast_atof_move(sz, (float&)vn->x ); - SkipSpaces(&sz); - sz = fast_atof_move(sz, (float&)vn->y ); - SkipSpaces(&sz); - sz = fast_atof_move(sz, (float&)vn->z ); - *(vn+1) = *vn; - *(vn+2) = *vn; - } - } - // vertex 1.50000 1.50000 0.00000 - else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) - { - if (3 == curVertex) { - DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found"); - } - else - { - sz += 7; - SkipSpaces(&sz); - aiVector3D* vn = &pMesh->mVertices[(curFace-1)*3 + curVertex++]; - sz = fast_atof_move(sz, (float&)vn->x ); - SkipSpaces(&sz); - sz = fast_atof_move(sz, (float&)vn->y ); - SkipSpaces(&sz); - sz = fast_atof_move(sz, (float&)vn->z ); - } - } - else if (!::strncmp(sz,"endsolid",8)) { - // finished! - break; - } - // else skip the whole identifier - else while (!::IsSpaceOrNewLine(*sz)) { - ++sz; - } - } - - if (!curFace) { - pMesh->mNumFaces = 0; - throw DeadlyImportError("STL: ASCII file is empty or invalid; no data loaded"); - } - pMesh->mNumFaces = curFace; - pMesh->mNumVertices = curFace*3; - // we are finished! -} - -// ------------------------------------------------------------------------------------------------ -// Read a binary STL file -bool STLImporter::LoadBinaryFile() -{ - // skip the first 80 bytes - if (fileSize < 84) { - throw DeadlyImportError("STL: file is too small for the header"); - } - bool bIsMaterialise = false; - - // search for an occurence of "COLOR=" in the header - const char* sz2 = (const char*)mBuffer; - const char* const szEnd = sz2+80; - while (sz2 < szEnd) { - - if ('C' == *sz2++ && 'O' == *sz2++ && 'L' == *sz2++ && - 'O' == *sz2++ && 'R' == *sz2++ && '=' == *sz2++) { - - // read the default vertex color for facets - bIsMaterialise = true; - DefaultLogger::get()->info("STL: Taking code path for Materialise files"); - clrColorDefault.r = (*sz2++) / 255.0f; - clrColorDefault.g = (*sz2++) / 255.0f; - clrColorDefault.b = (*sz2++) / 255.0f; - clrColorDefault.a = (*sz2++) / 255.0f; - break; - } - } - const unsigned char* sz = (const unsigned char*)mBuffer + 80; - - // now read the number of facets - aiMesh* pMesh = pScene->mMeshes[0]; - pScene->mRootNode->mName.Set("<STL_BINARY>"); - - pMesh->mNumFaces = *((uint32_t*)sz); - sz += 4; - - if (fileSize < 84 + pMesh->mNumFaces*50) { - throw DeadlyImportError("STL: file is too small to hold all facets"); - } - - if (!pMesh->mNumFaces) { - throw DeadlyImportError("STL: file is empty. There are no facets defined"); - } - - pMesh->mNumVertices = pMesh->mNumFaces*3; - - aiVector3D* vp,*vn; - vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; - vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - - for (unsigned int i = 0; i < pMesh->mNumFaces;++i) { - - // NOTE: Blender sometimes writes empty normals ... this is not - // our fault ... the RemoveInvalidData helper step should fix that - *vn = *((aiVector3D*)sz); - sz += sizeof(aiVector3D); - *(vn+1) = *vn; - *(vn+2) = *vn; - vn += 3; - - *vp++ = *((aiVector3D*)sz); - sz += sizeof(aiVector3D); - - *vp++ = *((aiVector3D*)sz); - sz += sizeof(aiVector3D); - - *vp++ = *((aiVector3D*)sz); - sz += sizeof(aiVector3D); - - uint16_t color = *((uint16_t*)sz); - sz += 2; - - if (color & (1 << 15)) - { - // seems we need to take the color - if (!pMesh->mColors[0]) - { - pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; - for (unsigned int i = 0; i <pMesh->mNumVertices;++i) - *pMesh->mColors[0]++ = this->clrColorDefault; - pMesh->mColors[0] -= pMesh->mNumVertices; - - DefaultLogger::get()->info("STL: Mesh has vertex colors"); - } - aiColor4D* clr = &pMesh->mColors[0][pMesh->mNumFaces*3]; - clr->a = 1.0f; - if (bIsMaterialise) // fuck, this is reversed - { - clr->r = (color & 0x31u) / 31.0f; - clr->g = ((color & (0x31u<<5))>>5u) / 31.0f; - clr->b = ((color & (0x31u<<10))>>10u) / 31.0f; - } - else - { - clr->b = (color & 0x31u) / 31.0f; - clr->g = ((color & (0x31u<<5))>>5u) / 31.0f; - clr->r = ((color & (0x31u<<10))>>10u) / 31.0f; - } - // assign the color to all vertices of the face - *(clr+1) = *clr; - *(clr+2) = *clr; - } - } - if (bIsMaterialise && !pMesh->mColors[0]) - { - // use the color as diffuse material color - return true; - } - return false; -} - -#endif // !! ASSIMP_BUILD_NO_STL_IMPORTER diff --git a/3rdparty/assimp/code/STLLoader.h b/3rdparty/assimp/code/STLLoader.h deleted file mode 100644 index edd0b2a9..00000000 --- a/3rdparty/assimp/code/STLLoader.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 STLLoader.h - * Declaration of the STL importer class. - */ -#ifndef AI_STLLOADER_H_INCLUDED -#define AI_STLLOADER_H_INCLUDED - -#include "BaseImporter.h" -#include "../include/aiTypes.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** Importer class for the sterolithography STL file format -*/ -class STLImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - STLImporter(); - - /** Destructor, private as well */ - ~STLImporter(); - -public: - - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. - */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - - // ------------------------------------------------------------------- - /** Loads a binary .stl file - * @return true if the default vertex color must be used as material color - */ - bool LoadBinaryFile(); - - // ------------------------------------------------------------------- - /** Loads a ASCII text .stl file - */ - void LoadASCIIFile(); - -protected: - - /** Buffer to hold the loaded file */ - const char* mBuffer; - - /** Size of the file, in bytes */ - unsigned int fileSize; - - /** Output scene */ - aiScene* pScene; - - /** Default vertex color */ - aiColor4D clrColorDefault; -}; - -} // end of namespace Assimp - -#endif // AI_3DSIMPORTER_H_IN diff --git a/3rdparty/assimp/code/SceneCombiner.cpp b/3rdparty/assimp/code/SceneCombiner.cpp deleted file mode 100644 index 72ffc111..00000000 --- a/3rdparty/assimp/code/SceneCombiner.cpp +++ /dev/null @@ -1,1133 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Implements Assimp::SceneCombiner. This is a smart utility - * class that combines multiple scenes, meshes, ... into one. Currently - * these utilities are used by the IRR and LWS loaders and the - * OptimizeGraph step. - */ -// ---------------------------------------------------------------------------- -#include "AssimpPCH.h" -#include "SceneCombiner.h" -#include "fast_atof.h" -#include "Hash.h" -#include "time.h" - -namespace Assimp { - -// ------------------------------------------------------------------------------------------------ -// Add a prefix to a string -inline void PrefixString(aiString& string,const char* prefix, unsigned int len) -{ - // If the string is already prefixed, we won't prefix it a second time - if (string.length >= 1 && string.data[0] == '$') - return; - - if (len+string.length>=MAXLEN-1) { - DefaultLogger::get()->debug("Can't add an unique prefix because the string is too long"); - ai_assert(false); - return; - } - - // Add the prefix - ::memmove(string.data+len,string.data,string.length+1); - ::memcpy (string.data, prefix, len); - - // And update the string's length - string.length += len; -} - -// ------------------------------------------------------------------------------------------------ -// Add node identifiers to a hashing set -void SceneCombiner::AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes) -{ - // Add node name to hashing set if it is non-empty - empty nodes are allowed - // and they can't have any anims assigned so its absolutely safe to duplicate them. - if (node->mName.length) { - hashes.insert( SuperFastHash(node->mName.data,node->mName.length) ); - } - - // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - AddNodeHashes(node->mChildren[i],hashes); -} - -// ------------------------------------------------------------------------------------------------ -// Add a name prefix to all nodes in a hierarchy -void SceneCombiner::AddNodePrefixes(aiNode* node, const char* prefix, unsigned int len) -{ - ai_assert(NULL != prefix); - PrefixString(node->mName,prefix,len); - - // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - AddNodePrefixes(node->mChildren[i],prefix,len); -} - -// ------------------------------------------------------------------------------------------------ -// Search for matching names -bool SceneCombiner::FindNameMatch(const aiString& name, std::vector<SceneHelper>& input, unsigned int cur) -{ - const unsigned int hash = SuperFastHash(name.data, name.length); - - // Check whether we find a positive match in one of the given sets - for (unsigned int i = 0; i < input.size(); ++i) { - - if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { - return true; - } - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Add a name prefix to all nodes in a hierarchy if a hash match is found -void SceneCombiner::AddNodePrefixesChecked(aiNode* node, const char* prefix, unsigned int len, - std::vector<SceneHelper>& input, unsigned int cur) -{ - ai_assert(NULL != prefix); - const unsigned int hash = SuperFastHash(node->mName.data,node->mName.length); - - // Check whether we find a positive match in one of the given sets - for (unsigned int i = 0; i < input.size(); ++i) { - - if (cur != i && input[i].hashes.find(hash) != input[i].hashes.end()) { - PrefixString(node->mName,prefix,len); - break; - } - } - - // Process all children recursively - for (unsigned int i = 0; i < node->mNumChildren;++i) - AddNodePrefixesChecked(node->mChildren[i],prefix,len,input,cur); -} - -// ------------------------------------------------------------------------------------------------ -// Add an offset to all mesh indices in a node graph -void SceneCombiner::OffsetNodeMeshIndices (aiNode* node, unsigned int offset) -{ - for (unsigned int i = 0; i < node->mNumMeshes;++i) - node->mMeshes[i] += offset; - - for (unsigned int i = 0; i < node->mNumChildren;++i) - OffsetNodeMeshIndices(node->mChildren[i],offset); -} - -// ------------------------------------------------------------------------------------------------ -// Merges two scenes. Currently only used by the LWS loader. -void SceneCombiner::MergeScenes(aiScene** _dest,std::vector<aiScene*>& src, - unsigned int flags) -{ - ai_assert(NULL != _dest); - - // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it - if (src.empty()) - { - if (*_dest) - { - (*_dest)->~aiScene(); - SceneCombiner::CopySceneFlat(_dest,src[0]); - } - else *_dest = src[0]; - return; - } - if (*_dest)(*_dest)->~aiScene(); - else *_dest = new aiScene(); - - // Create a dummy scene to serve as master for the others - aiScene* master = new aiScene(); - master->mRootNode = new aiNode(); - master->mRootNode->mName.Set("<MergeRoot>"); - - std::vector<AttachmentInfo> srcList (src.size()); - for (unsigned int i = 0; i < srcList.size();++i) { - srcList[i] = AttachmentInfo(src[i],master->mRootNode); - } - - // 'master' will be deleted afterwards - MergeScenes (_dest, master, srcList, flags); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::AttachToGraph (aiNode* attach, std::vector<NodeAttachmentInfo>& srcList) -{ - unsigned int cnt; - for (cnt = 0; cnt < attach->mNumChildren;++cnt) - AttachToGraph(attach->mChildren[cnt],srcList); - - cnt = 0; - for (std::vector<NodeAttachmentInfo>::iterator it = srcList.begin(); - it != srcList.end(); ++it) - { - if ((*it).attachToNode == attach && !(*it).resolved) - ++cnt; - } - - if (cnt) { - aiNode** n = new aiNode*[cnt+attach->mNumChildren]; - if (attach->mNumChildren) { - ::memcpy(n,attach->mChildren,sizeof(void*)*attach->mNumChildren); - delete[] attach->mChildren; - } - attach->mChildren = n; - - n += attach->mNumChildren; - attach->mNumChildren += cnt; - - for (unsigned int i = 0; i < srcList.size();++i) { - NodeAttachmentInfo& att = srcList[i]; - if (att.attachToNode == attach && !att.resolved) { - *n = att.node; - (**n).mParent = attach; - ++n; - - // mark this attachment as resolved - att.resolved = true; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::AttachToGraph ( aiScene* master, - std::vector<NodeAttachmentInfo>& src) -{ - ai_assert(NULL != master); - AttachToGraph(master->mRootNode,src); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::MergeScenes(aiScene** _dest, aiScene* master, - std::vector<AttachmentInfo>& srcList, - unsigned int flags) -{ - ai_assert(NULL != _dest); - - // if _dest points to NULL allocate a new scene. Otherwise clear the old and reuse it - if (srcList.empty()) - { - if (*_dest) - { - (*_dest)->~aiScene(); - SceneCombiner::CopySceneFlat(_dest,master); - } - else *_dest = master; - return; - } - if (*_dest)(*_dest)->~aiScene(); - else *_dest = new aiScene(); - - aiScene* dest = *_dest; - - std::vector<SceneHelper> src (srcList.size()+1); - src[0].scene = master; - for (unsigned int i = 0; i < srcList.size();++i) { - src[i+1] = SceneHelper( srcList[i].scene ); - } - - // this helper array specifies which scenes are duplicates of others - std::vector<unsigned int> duplicates(src.size(),0xffffffff); - - // this helper array is used as lookup table several times - std::vector<unsigned int> offset(src.size()); - - // Find duplicate scenes - for (unsigned int i = 0; i < src.size();++i) - { - if (duplicates[i] != i && duplicates[i] != 0xffffffff)continue; - duplicates[i] = i; - for ( unsigned int a = i+1; a < src.size(); ++a) - { - if (src[i].scene == src[a].scene) - duplicates[a] = i; - } - } - - // Generate unique names for all named stuff? - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) - { -#if 0 - // Construct a proper random number generator - boost::mt19937 rng( ); - boost::uniform_int<> dist(1u,1 << 24u); - boost::variate_generator<boost::mt19937&, boost::uniform_int<> > rndGen(rng, dist); -#endif - for (unsigned int i = 1; i < src.size();++i) - { - //if (i != duplicates[i]) - //{ - // // duplicate scenes share the same UID - // ::strcpy( src[i].id, src[duplicates[i]].id ); - // src[i].idlen = src[duplicates[i]].idlen; - - // continue; - //} - - src[i].idlen = ::sprintf(src[i].id,"$%.6X$_",i); - - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - - // Compute hashes for all identifiers in this scene and store them - // in a sorted table (for convenience I'm using std::set). We hash - // just the node and animation channel names, all identifiers except - // the material names should be caught by doing this. - AddNodeHashes(src[i]->mRootNode,src[i].hashes); - - for (unsigned int a = 0; a < src[i]->mNumAnimations;++a) { - aiAnimation* anim = src[i]->mAnimations[a]; - src[i].hashes.insert(SuperFastHash(anim->mName.data,anim->mName.length)); - } - } - } - } - - unsigned int cnt; - - // First find out how large the respective output arrays must be - for ( unsigned int n = 0; n < src.size();++n ) - { - SceneHelper* cur = &src[n]; - - if (n == duplicates[n] || flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) { - dest->mNumTextures += (*cur)->mNumTextures; - dest->mNumMaterials += (*cur)->mNumMaterials; - dest->mNumMeshes += (*cur)->mNumMeshes; - } - - dest->mNumLights += (*cur)->mNumLights; - dest->mNumCameras += (*cur)->mNumCameras; - dest->mNumAnimations += (*cur)->mNumAnimations; - - // Combine the flags of all scenes - // We need to process them flag-by-flag here to get correct results - // dest->mFlags ; //|= (*cur)->mFlags; - if ((*cur)->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { - dest->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT; - } - } - - // generate the output texture list + an offset table for all texture indices - if (dest->mNumTextures) - { - aiTexture** pip = dest->mTextures = new aiTexture*[dest->mNumMaterials]; - cnt = 0; - for ( unsigned int n = 0; n < src.size();++n ) - { - SceneHelper* cur = &src[n]; - for (unsigned int i = 0; i < (*cur)->mNumTextures;++i) - { - if (n != duplicates[n]) - { - if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) - Copy(pip,(*cur)->mTextures[i]); - - else continue; - } - else *pip = (*cur)->mTextures[i]; - ++pip; - } - - offset[n] = cnt; - cnt = (unsigned int)(pip - dest->mTextures); - } - } - - // generate the output material list + an offset table for all material indices - if (dest->mNumMaterials) - { - aiMaterial** pip = dest->mMaterials = new aiMaterial*[dest->mNumMaterials]; - cnt = 0; - for ( unsigned int n = 0; n < src.size();++n ) { - SceneHelper* cur = &src[n]; - for (unsigned int i = 0; i < (*cur)->mNumMaterials;++i) - { - if (n != duplicates[n]) - { - if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) - Copy(pip,(*cur)->mMaterials[i]); - - else continue; - } - else *pip = (*cur)->mMaterials[i]; - - if ((*cur)->mNumTextures != dest->mNumTextures) { - // We need to update all texture indices of the mesh. So we need to search for - // a material property called '$tex.file' - - for (unsigned int a = 0; a < (*pip)->mNumProperties;++a) - { - aiMaterialProperty* prop = (*pip)->mProperties[a]; - if (!strncmp(prop->mKey.data,"$tex.file",9)) - { - // Check whether this texture is an embedded texture. - // In this case the property looks like this: *<n>, - // where n is the index of the texture. - aiString& s = *((aiString*)prop->mData); - if ('*' == s.data[0]) { - // Offset the index and write it back .. - const unsigned int idx = strtol10(&s.data[1]) + offset[n]; - ASSIMP_itoa10(&s.data[1],sizeof(s.data)-1,idx); - } - } - - // Need to generate new, unique material names? - else if (!::strcmp( prop->mKey.data,"$mat.name" ) && flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES) - { - aiString* pcSrc = (aiString*) prop->mData; - PrefixString(*pcSrc, (*cur).id, (*cur).idlen); - } - } - } - ++pip; - } - - offset[n] = cnt; - cnt = (unsigned int)(pip - dest->mMaterials); - } - } - - // generate the output mesh list + again an offset table for all mesh indices - if (dest->mNumMeshes) - { - aiMesh** pip = dest->mMeshes = new aiMesh*[dest->mNumMeshes]; - cnt = 0; - for ( unsigned int n = 0; n < src.size();++n ) - { - SceneHelper* cur = &src[n]; - for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) - { - if (n != duplicates[n]) { - if ( flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) - Copy(pip, (*cur)->mMeshes[i]); - - else continue; - } - else *pip = (*cur)->mMeshes[i]; - - // update the material index of the mesh - (*pip)->mMaterialIndex += offset[n]; - ++pip; - } - - // reuse the offset array - store now the mesh offset in it - offset[n] = cnt; - cnt = (unsigned int)(pip - dest->mMeshes); - } - } - - std::vector <NodeAttachmentInfo> nodes; - nodes.reserve(srcList.size()); - - // ---------------------------------------------------------------------------- - // Now generate the output node graph. We need to make those - // names in the graph that are referenced by anims or lights - // or cameras unique. So we add a prefix to them ... $<rand>_ - // We could also use a counter, but using a random value allows us to - // use just one prefix if we are joining multiple scene hierarchies recursively. - // Chances are quite good we don't collide, so we try that ... - // ---------------------------------------------------------------------------- - - // Allocate space for light sources, cameras and animations - aiLight** ppLights = dest->mLights = (dest->mNumLights - ? new aiLight*[dest->mNumLights] : NULL); - - aiCamera** ppCameras = dest->mCameras = (dest->mNumCameras - ? new aiCamera*[dest->mNumCameras] : NULL); - - aiAnimation** ppAnims = dest->mAnimations = (dest->mNumAnimations - ? new aiAnimation*[dest->mNumAnimations] : NULL); - - for ( int n = src.size()-1; n >= 0 ;--n ) /* !!! important !!! */ - { - SceneHelper* cur = &src[n]; - aiNode* node; - - // To offset or not to offset, this is the question - if (n != (int)duplicates[n]) - { - // Get full scenegraph copy - Copy( &node, (*cur)->mRootNode ); - OffsetNodeMeshIndices(node,offset[duplicates[n]]); - - if (flags & AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY) { - // (note:) they are already 'offseted' by offset[duplicates[n]] - OffsetNodeMeshIndices(node,offset[n] - offset[duplicates[n]]); - } - } - else // if (n == duplicates[n]) - { - node = (*cur)->mRootNode; - OffsetNodeMeshIndices(node,offset[n]); - } - if (n) // src[0] is the master node - nodes.push_back(NodeAttachmentInfo( node,srcList[n-1].attachToNode,n )); - - // add name prefixes? - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { - - // or the whole scenegraph - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - AddNodePrefixesChecked(node,(*cur).id,(*cur).idlen,src,n); - } - else AddNodePrefixes(node,(*cur).id,(*cur).idlen); - - // meshes - for (unsigned int i = 0; i < (*cur)->mNumMeshes;++i) { - aiMesh* mesh = (*cur)->mMeshes[i]; - - // rename all bones - for (unsigned int a = 0; a < mesh->mNumBones;++a) { - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch(mesh->mBones[a]->mName,src,n)) - continue; - } - PrefixString(mesh->mBones[a]->mName,(*cur).id,(*cur).idlen); - } - } - } - - // -------------------------------------------------------------------- - // Copy light sources - for (unsigned int i = 0; i < (*cur)->mNumLights;++i,++ppLights) - { - if (n != (int)duplicates[n]) // duplicate scene? - { - Copy(ppLights, (*cur)->mLights[i]); - } - else *ppLights = (*cur)->mLights[i]; - - - // Add name prefixes? - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppLights)->mName,src,n)) - continue; - } - - PrefixString((*ppLights)->mName,(*cur).id,(*cur).idlen); - } - } - - // -------------------------------------------------------------------- - // Copy cameras - for (unsigned int i = 0; i < (*cur)->mNumCameras;++i,++ppCameras) { - if (n != (int)duplicates[n]) // duplicate scene? - { - Copy(ppCameras, (*cur)->mCameras[i]); - } - else *ppCameras = (*cur)->mCameras[i]; - - // Add name prefixes? - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppCameras)->mName,src,n)) - continue; - } - - PrefixString((*ppCameras)->mName,(*cur).id,(*cur).idlen); - } - } - - // -------------------------------------------------------------------- - // Copy animations - for (unsigned int i = 0; i < (*cur)->mNumAnimations;++i,++ppAnims) { - if (n != (int)duplicates[n]) // duplicate scene? - { - Copy(ppAnims, (*cur)->mAnimations[i]); - } - else *ppAnims = (*cur)->mAnimations[i]; - - // Add name prefixes? - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES) { - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppAnims)->mName,src,n)) - continue; - } - - PrefixString((*ppAnims)->mName,(*cur).id,(*cur).idlen); - - // don't forget to update all node animation channels - for (unsigned int a = 0; a < (*ppAnims)->mNumChannels;++a) { - if (flags & AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY) { - if (!FindNameMatch((*ppAnims)->mChannels[a]->mNodeName,src,n)) - continue; - } - - PrefixString((*ppAnims)->mChannels[a]->mNodeName,(*cur).id,(*cur).idlen); - } - } - } - } - - // Now build the output graph - AttachToGraph ( master, nodes); - dest->mRootNode = master->mRootNode; - - // Check whether we succeeded at building the output graph - for (std::vector <NodeAttachmentInfo> ::iterator it = nodes.begin(); - it != nodes.end(); ++it) - { - if (!(*it).resolved) { - if (flags & AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS) { - // search for this attachment point in all other imported scenes, too. - for ( unsigned int n = 0; n < src.size();++n ) { - if (n != (*it).src_idx) { - AttachToGraph(src[n].scene,nodes); - if ((*it).resolved) - break; - } - } - } - if (!(*it).resolved) { - DefaultLogger::get()->error(std::string("SceneCombiner: Failed to resolve attachment ") - + (*it).node->mName.data + " " + (*it).attachToNode->mName.data); - } - } - } - - // now delete all input scenes. Make sure duplicate scenes aren't - // deleted more than one time - for ( unsigned int n = 0; n < src.size();++n ) { - if (n != duplicates[n]) // duplicate scene? - continue; - - aiScene* deleteMe = src[n].scene; - - // We need to delete the arrays before the destructor is called - - // we are reusing the array members - delete[] deleteMe->mMeshes; deleteMe->mMeshes = NULL; - delete[] deleteMe->mCameras; deleteMe->mCameras = NULL; - delete[] deleteMe->mLights; deleteMe->mLights = NULL; - delete[] deleteMe->mMaterials; deleteMe->mMaterials = NULL; - delete[] deleteMe->mAnimations; deleteMe->mAnimations = NULL; - - deleteMe->mRootNode = NULL; - - // Now we can safely delete the scene - delete deleteMe; - } - - // Check flags - if (!dest->mNumMeshes || !dest->mNumMaterials) { - dest->mFlags |= AI_SCENE_FLAGS_INCOMPLETE; - } - - // We're finished -} - -// ------------------------------------------------------------------------------------------------ -// Build a list of unique bones -void SceneCombiner::BuildUniqueBoneList(std::list<BoneWithHash>& asBones, - std::vector<aiMesh*>::const_iterator it, - std::vector<aiMesh*>::const_iterator end) -{ - unsigned int iOffset = 0; - for (; it != end;++it) { - for (unsigned int l = 0; l < (*it)->mNumBones;++l) { - aiBone* p = (*it)->mBones[l]; - uint32_t itml = SuperFastHash(p->mName.data,(unsigned int)p->mName.length); - - std::list<BoneWithHash>::iterator it2 = asBones.begin(); - std::list<BoneWithHash>::iterator end2 = asBones.end(); - - for (;it2 != end2;++it2) { - if ((*it2).first == itml) { - (*it2).pSrcBones.push_back(BoneSrcIndex(p,iOffset)); - break; - } - } - if (end2 == it2) { - // need to begin a new bone entry - asBones.push_back(BoneWithHash()); - BoneWithHash& btz = asBones.back(); - - // setup members - btz.first = itml; - btz.second = &p->mName; - btz.pSrcBones.push_back(BoneSrcIndex(p,iOffset)); - } - } - iOffset += (*it)->mNumVertices; - } -} - -// ------------------------------------------------------------------------------------------------ -// Merge a list of bones -void SceneCombiner::MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it, - std::vector<aiMesh*>::const_iterator end) -{ - ai_assert(NULL != out && !out->mNumBones); - - // find we need to build an unique list of all bones. - // we work with hashes to make the comparisons MUCH faster, - // at least if we have many bones. - std::list<BoneWithHash> asBones; - BuildUniqueBoneList(asBones, it,end); - - // now create the output bones - out->mNumBones = 0; - out->mBones = new aiBone*[asBones.size()]; - - for (std::list<BoneWithHash>::const_iterator it = asBones.begin(),end = asBones.end(); it != end;++it) { - // Allocate a bone and setup it's name - aiBone* pc = out->mBones[out->mNumBones++] = new aiBone(); - pc->mName = aiString( *((*it).second )); - - std::vector< BoneSrcIndex >::const_iterator wend = (*it).pSrcBones.end(); - - // Loop through all bones to be joined for this bone - for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) { - pc->mNumWeights += (*wmit).first->mNumWeights; - - // NOTE: different offset matrices for bones with equal names - // are - at the moment - not handled correctly. - if (wmit != (*it).pSrcBones.begin() && pc->mOffsetMatrix != (*wmit).first->mOffsetMatrix) { - DefaultLogger::get()->warn("Bones with equal names but different offset matrices can't be joined at the moment"); - continue; - } - pc->mOffsetMatrix = (*wmit).first->mOffsetMatrix; - } - - // Allocate the vertex weight array - aiVertexWeight* avw = pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - - // And copy the final weights - adjust the vertex IDs by the - // face index offset of the coresponding mesh. - for (std::vector< BoneSrcIndex >::const_iterator wmit = (*it).pSrcBones.begin(); wmit != wend; ++wmit) { - aiBone* pip = (*wmit).first; - for (unsigned int mp = 0; mp < pip->mNumWeights;++mp,++avw) { - const aiVertexWeight& vfi = pip->mWeights[mp]; - avw->mWeight = vfi.mWeight; - avw->mVertexId = vfi.mVertexId + (*wmit).second; - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Merge a list of meshes -void SceneCombiner::MergeMeshes(aiMesh** _out,unsigned int flags, - std::vector<aiMesh*>::const_iterator begin, - std::vector<aiMesh*>::const_iterator end) -{ - ai_assert(NULL != _out); - - if (begin == end) { - *_out = NULL; // no meshes ... - return; - } - - // Allocate the output mesh - aiMesh* out = *_out = new aiMesh(); - out->mMaterialIndex = (*begin)->mMaterialIndex; - - // Find out how much output storage we'll need - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - out->mNumVertices += (*it)->mNumVertices; - out->mNumFaces += (*it)->mNumFaces; - out->mNumBones += (*it)->mNumBones; - - // combine primitive type flags - out->mPrimitiveTypes |= (*it)->mPrimitiveTypes; - } - - if (out->mNumVertices) { - aiVector3D* pv2; - - // copy vertex positions - if ((**begin).HasPositions()) { - - pv2 = out->mVertices = new aiVector3D[out->mNumVertices]; - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - if ((*it)->mVertices) { - ::memcpy(pv2,(*it)->mVertices,(*it)->mNumVertices*sizeof(aiVector3D)); - } - else DefaultLogger::get()->warn("JoinMeshes: Positions expected but input mesh contains no positions"); - pv2 += (*it)->mNumVertices; - } - } - // copy normals - if ((**begin).HasNormals()) { - - pv2 = out->mNormals = new aiVector3D[out->mNumVertices]; - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - if ((*it)->mNormals) { - ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); - } - else DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals"); - pv2 += (*it)->mNumVertices; - } - } - // copy tangents and bitangents - if ((**begin).HasTangentsAndBitangents()) { - - pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; - aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; - - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - if ((*it)->mTangents) { - ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); - ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); - } - else DefaultLogger::get()->warn("JoinMeshes: Tangents expected but input mesh contains no tangents"); - pv2 += (*it)->mNumVertices; - pv2b += (*it)->mNumVertices; - } - } - // copy texture coordinates - unsigned int n = 0; - while ((**begin).HasTextureCoords(n)) { - out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n]; - - pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices]; - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - - if ((*it)->mTextureCoords[n]) { - ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); - } - else DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs"); - pv2 += (*it)->mNumVertices; - } - ++n; - } - // copy vertex colors - n = 0; - while ((**begin).HasVertexColors(n)) { - aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - - if ((*it)->mColors[n]) { - ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); - } - else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs"); - pv2 += (*it)->mNumVertices; - } - ++n; - } - } - - if (out->mNumFaces) // just for safety - { - // copy faces - out->mFaces = new aiFace[out->mNumFaces]; - aiFace* pf2 = out->mFaces; - - unsigned int ofs = 0; - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) { - for (unsigned int m = 0; m < (*it)->mNumFaces;++m,++pf2) { - aiFace& face = (*it)->mFaces[m]; - pf2->mNumIndices = face.mNumIndices; - pf2->mIndices = face.mIndices; - - if (ofs) { - // add the offset to the vertex - for (unsigned int q = 0; q < face.mNumIndices; ++q) - face.mIndices[q] += ofs; - } - face.mIndices = NULL; - } - ofs += (*it)->mNumVertices; - } - } - - // bones - as this is quite lengthy, I moved the code to a separate function - if (out->mNumBones) - MergeBones(out,begin,end); - - // delete all source meshes - for (std::vector<aiMesh*>::const_iterator it = begin; it != end;++it) - delete *it; -} - -// ------------------------------------------------------------------------------------------------ -template <typename Type> -inline void CopyPtrArray (Type**& dest, Type** src, unsigned int num) -{ - if (!num) - { - dest = NULL; - return; - } - dest = new Type*[num]; - for (unsigned int i = 0; i < num;++i) - SceneCombiner::Copy(&dest[i],src[i]); -} - -// ------------------------------------------------------------------------------------------------ -template <typename Type> -inline void GetArrayCopy (Type*& dest, unsigned int num ) -{ - if (!dest)return; - Type* old = dest; - - dest = new Type[num]; - ::memcpy(dest, old, sizeof(Type) * num); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::CopySceneFlat(aiScene** _dest,aiScene* src) -{ - // reuse the old scene or allocate a new? - if (*_dest)(*_dest)->~aiScene(); - else *_dest = new aiScene(); - - ::memcpy(*_dest,src,sizeof(aiScene)); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::CopyScene(aiScene** _dest,aiScene* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiScene* dest = *_dest = new aiScene(); - - // copy animations - dest->mNumAnimations = src->mNumAnimations; - CopyPtrArray(dest->mAnimations,src->mAnimations, - dest->mNumAnimations); - - // copy textures - dest->mNumTextures = src->mNumTextures; - CopyPtrArray(dest->mTextures,src->mTextures, - dest->mNumTextures); - - // copy materials - dest->mNumMaterials = src->mNumMaterials; - CopyPtrArray(dest->mMaterials,src->mMaterials, - dest->mNumMaterials); - - // copy lights - dest->mNumLights = src->mNumLights; - CopyPtrArray(dest->mLights,src->mLights, - dest->mNumLights); - - // copy cameras - dest->mNumCameras = src->mNumCameras; - CopyPtrArray(dest->mCameras,src->mCameras, - dest->mNumCameras); - - // copy meshes - dest->mNumMeshes = src->mNumMeshes; - CopyPtrArray(dest->mMeshes,src->mMeshes, - dest->mNumMeshes); - - // now - copy the root node of the scene (deep copy, too) - Copy( &dest->mRootNode, src->mRootNode); - - // and keep the flags ... - dest->mFlags = src->mFlags; -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiMesh** _dest, const aiMesh* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiMesh* dest = *_dest = new aiMesh(); - - // get a flat copy - ::memcpy(dest,src,sizeof(aiMesh)); - - // and reallocate all arrays - GetArrayCopy( dest->mVertices, dest->mNumVertices ); - GetArrayCopy( dest->mNormals , dest->mNumVertices ); - GetArrayCopy( dest->mTangents, dest->mNumVertices ); - GetArrayCopy( dest->mBitangents, dest->mNumVertices ); - - unsigned int n = 0; - while (dest->HasTextureCoords(n)) - GetArrayCopy( dest->mTextureCoords[n++], dest->mNumVertices ); - - n = 0; - while (dest->HasVertexColors(n)) - GetArrayCopy( dest->mColors[n++], dest->mNumVertices ); - - // make a deep copy of all bones - CopyPtrArray(dest->mBones,dest->mBones,dest->mNumBones); - - // make a deep copy of all faces - GetArrayCopy(dest->mFaces,dest->mNumFaces); - for (unsigned int i = 0; i < dest->mNumFaces;++i) - { - aiFace& f = dest->mFaces[i]; - GetArrayCopy(f.mIndices,f.mNumIndices); - } -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiMaterial** _dest, const aiMaterial* src) -{ - ai_assert(NULL != _dest && NULL != src); - - MaterialHelper* dest = (MaterialHelper*) ( *_dest = new MaterialHelper() ); - dest->mNumAllocated = src->mNumAllocated; - dest->mNumProperties = src->mNumProperties; - dest->mProperties = new aiMaterialProperty* [dest->mNumAllocated]; - - for (unsigned int i = 0; i < dest->mNumProperties;++i) - { - aiMaterialProperty* prop = dest->mProperties[i] = new aiMaterialProperty(); - aiMaterialProperty* sprop = src->mProperties[i]; - - prop->mDataLength = sprop->mDataLength; - prop->mData = new char[prop->mDataLength]; - ::memcpy(prop->mData,sprop->mData,prop->mDataLength); - - prop->mIndex = sprop->mIndex; - prop->mSemantic = sprop->mSemantic; - prop->mKey = sprop->mKey; - prop->mType = sprop->mType; - } -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiTexture** _dest, const aiTexture* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiTexture* dest = *_dest = new aiTexture(); - - // get a flat copy - ::memcpy(dest,src,sizeof(aiTexture)); - - // and reallocate all arrays. We must do it manually here - const char* old = (const char*)dest->pcData; - if (old) - { - unsigned int cpy; - if (!dest->mHeight)cpy = dest->mWidth; - else cpy = dest->mHeight * dest->mWidth * sizeof(aiTexel); - - if (!cpy) - { - dest->pcData = NULL; - return; - } - // the cast is legal, the aiTexel c'tor does nothing important - dest->pcData = (aiTexel*) new char[cpy]; - ::memcpy(dest->pcData, old, cpy); - } -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiAnimation** _dest, const aiAnimation* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiAnimation* dest = *_dest = new aiAnimation(); - - // get a flat copy - ::memcpy(dest,src,sizeof(aiAnimation)); - - // and reallocate all arrays - CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels ); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiNodeAnim** _dest, const aiNodeAnim* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiNodeAnim* dest = *_dest = new aiNodeAnim(); - - // get a flat copy - ::memcpy(dest,src,sizeof(aiNodeAnim)); - - // and reallocate all arrays - GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys ); - GetArrayCopy( dest->mScalingKeys, dest->mNumScalingKeys ); - GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys ); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiCamera** _dest,const aiCamera* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiCamera* dest = *_dest = new aiCamera(); - - // get a flat copy, that's already OK - ::memcpy(dest,src,sizeof(aiCamera)); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiLight** _dest, const aiLight* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiLight* dest = *_dest = new aiLight(); - - // get a flat copy, that's already OK - ::memcpy(dest,src,sizeof(aiLight)); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiBone** _dest, const aiBone* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiBone* dest = *_dest = new aiBone(); - - // get a flat copy - ::memcpy(dest,src,sizeof(aiBone)); - - // and reallocate all arrays - GetArrayCopy( dest->mWeights, dest->mNumWeights ); -} - -// ------------------------------------------------------------------------------------------------ -void SceneCombiner::Copy (aiNode** _dest, const aiNode* src) -{ - ai_assert(NULL != _dest && NULL != src); - - aiNode* dest = *_dest = new aiNode(); - - // get a flat copy - ::memcpy(dest,src,sizeof(aiNode)); - - // and reallocate all arrays - GetArrayCopy( dest->mMeshes, dest->mNumMeshes ); - CopyPtrArray( dest->mChildren, src->mChildren,dest->mNumChildren); -} - - -} diff --git a/3rdparty/assimp/code/SceneCombiner.h b/3rdparty/assimp/code/SceneCombiner.h deleted file mode 100644 index a8fd43cb..00000000 --- a/3rdparty/assimp/code/SceneCombiner.h +++ /dev/null @@ -1,365 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Declares a helper class, "SceneCombiner" providing various - * utilities to merge scenes. - */ -#ifndef AI_SCENE_COMBINER_H_INC -#define AI_SCENE_COMBINER_H_INC - -#include "../include/aiAssert.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** \brief Helper data structure for SceneCombiner. - * - * Describes to which node a scene must be attached to. - */ -struct AttachmentInfo -{ - AttachmentInfo() - : scene (NULL) - , attachToNode (NULL) - {} - - AttachmentInfo(aiScene* _scene, aiNode* _attachToNode) - : scene (_scene) - , attachToNode (_attachToNode) - {} - - aiScene* scene; - aiNode* attachToNode; -}; - -// --------------------------------------------------------------------------- -struct NodeAttachmentInfo -{ - NodeAttachmentInfo() - : node (NULL) - , attachToNode (NULL) - , resolved (false) - , src_idx (0xffffffff) - {} - - NodeAttachmentInfo(aiNode* _scene, aiNode* _attachToNode,size_t idx) - : node (_scene) - , attachToNode (_attachToNode) - , resolved (false) - , src_idx (idx) - {} - - aiNode* node; - aiNode* attachToNode; - bool resolved; - size_t src_idx; -}; - -// --------------------------------------------------------------------------- -/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES - * Generate unique names for all named scene items - */ -#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES 0x1 - -/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES - * Generate unique names for materials, too. - * This is not absolutely required to pass the validation. - */ -#define AI_INT_MERGE_SCENE_GEN_UNIQUE_MATNAMES 0x2 - -/** @def AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY - * Use deep copies of duplicate scenes - */ -#define AI_INT_MERGE_SCENE_DUPLICATES_DEEP_CPY 0x4 - -/** @def AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS - * If attachment nodes are not found in the given master scene, - * search the other imported scenes for them in an any order. - */ -#define AI_INT_MERGE_SCENE_RESOLVE_CROSS_ATTACHMENTS 0x8 - -/** @def AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY - * Can be combined with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES. - * Unique names are generated, but only if this is absolutely - * required to avoid name conflicts. - */ -#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10 - - -typedef std::pair<aiBone*,unsigned int> BoneSrcIndex; - -// --------------------------------------------------------------------------- -/** @brief Helper data structure for SceneCombiner::MergeBones. - */ -struct BoneWithHash : public std::pair<uint32_t,aiString*> { - std::vector<BoneSrcIndex> pSrcBones; -}; - - -// --------------------------------------------------------------------------- -/** @brief Utility for SceneCombiner - */ -struct SceneHelper -{ - SceneHelper () - : scene (NULL) - , idlen (0) - { - id[0] = 0; - } - - SceneHelper (aiScene* _scene) - : scene (_scene) - , idlen (0) - { - id[0] = 0; - } - - AI_FORCE_INLINE aiScene* operator-> () const - { - return scene; - } - - // scene we're working on - aiScene* scene; - - // prefix to be added to all identifiers in the scene ... - char id [32]; - - // and its strlen() - unsigned int idlen; - - // hash table to quickly check whether a name is contained in the scene - std::set<unsigned int> hashes; -}; - -// --------------------------------------------------------------------------- -/** \brief Static helper class providing various utilities to merge two - * scenes. It is intended as internal utility and NOT for use by - * applications. - * - * The class is currently being used by various postprocessing steps - * and loaders (ie. LWS). - */ -class ASSIMP_API SceneCombiner -{ - // class cannot be instanced - SceneCombiner() {} - -public: - - // ------------------------------------------------------------------- - /** Merges two or more scenes. - * - * @param dest Receives a pointer to the destination scene. If the - * pointer doesn't point to NULL when the function is called, the - * existing scene is cleared and refilled. - * @param src Non-empty list of scenes to be merged. The function - * deletes the input scenes afterwards. There may be duplicate scenes. - * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above - */ - static void MergeScenes(aiScene** dest,std::vector<aiScene*>& src, - unsigned int flags = 0); - - - // ------------------------------------------------------------------- - /** Merges two or more scenes and attaches all sceenes to a specific - * position in the node graph of the masteer scene. - * - * @param dest Receives a pointer to the destination scene. If the - * pointer doesn't point to NULL when the function is called, the - * existing scene is cleared and refilled. - * @param master Master scene. It will be deleted afterwards. All - * other scenes will be inserted in its node graph. - * @param src Non-empty list of scenes to be merged along with their - * corresponding attachment points in the master scene. The function - * deletes the input scenes afterwards. There may be duplicate scenes. - * @param flags Combination of the AI_INT_MERGE_SCENE flags defined above - */ - static void MergeScenes(aiScene** dest, aiScene* master, - std::vector<AttachmentInfo>& src, - unsigned int flags = 0); - - - // ------------------------------------------------------------------- - /** Merges two or more meshes - * - * The meshes should have equal vertex formats. Only components - * that are provided by ALL meshes will be present in the output mesh. - * An exception is made for VColors - they are set to black. The - * meshes should have the same material indices, too. The output - * material index is always the material index of the first mesh. - * - * @param dest Destination mesh. Must be empty. - * @param flags Currently no parameters - * @param begin First mesh to be processed - * @param end Points to the mesh after the last mesh to be processed - */ - static void MergeMeshes(aiMesh** dest,unsigned int flags, - std::vector<aiMesh*>::const_iterator begin, - std::vector<aiMesh*>::const_iterator end); - - - // ------------------------------------------------------------------- - /** Merges two or more bones - * - * @param out Mesh to receive the output bone list - * @param flags Currently no parameters - * @param begin First mesh to be processed - * @param end Points to the mesh after the last mesh to be processed - */ - static void MergeBones(aiMesh* out,std::vector<aiMesh*>::const_iterator it, - std::vector<aiMesh*>::const_iterator end); - - - // ------------------------------------------------------------------- - /** Builds a list of uniquely named bones in a mesh list - * - * @param asBones Receives the output list - * @param it First mesh to be processed - * @param end Last mesh to be processed - */ - static void BuildUniqueBoneList(std::list<BoneWithHash>& asBones, - std::vector<aiMesh*>::const_iterator it, - std::vector<aiMesh*>::const_iterator end); - - // ------------------------------------------------------------------- - /** Add a name prefix to all nodes in a scene. - * - * @param Current node. This function is called recursively. - * @param prefix Prefix to be added to all nodes - * @param len STring length - */ - static void AddNodePrefixes(aiNode* node, const char* prefix, - unsigned int len); - - // ------------------------------------------------------------------- - /** Add an offset to all mesh indices in a node graph - * - * @param Current node. This function is called recursively. - * @param offset Offset to be added to all mesh indices - */ - static void OffsetNodeMeshIndices (aiNode* node, unsigned int offset); - - // ------------------------------------------------------------------- - /** Attach a list of node graphs to well-defined nodes in a master - * graph. This is a helper for MergeScenes() - * - * @param master Master scene - * @param srcList List of source scenes along with their attachment - * points. If an attachment point is NULL (or does not exist in - * the master graph), a scene is attached to the root of the master - * graph (as an additional child node) - * @duplicates List of duplicates. If elem[n] == n the scene is not - * a duplicate. Otherwise elem[n] links scene n to its first occurence. - */ - static void AttachToGraph ( aiScene* master, - std::vector<NodeAttachmentInfo>& srcList); - - static void AttachToGraph (aiNode* attach, - std::vector<NodeAttachmentInfo>& srcList); - - - // ------------------------------------------------------------------- - /** Get a deep copy of a scene - * - * @param dest Receives a pointer to the destination scene - * @param src Source scene - remains unmodified. - */ - static void CopyScene(aiScene** dest,aiScene* source); - - - // ------------------------------------------------------------------- - /** Get a flat copy of a scene - * - * Only the first hierarchy layer is copied. All pointer members of - * aiScene are shared by source and destination scene. If the - * pointer doesn't point to NULL when the function is called, the - * existing scene is cleared and refilled. - * @param dest Receives a pointer to the destination scene - * @param src Source scene - remains unmodified. - */ - static void CopySceneFlat(aiScene** dest,aiScene* source); - - - // ------------------------------------------------------------------- - /** Get a deep copy of a mesh - * - * @param dest Receives a pointer to the destination mesh - * @param src Source mesh - remains unmodified. - */ - static void Copy (aiMesh** dest, const aiMesh* src); - - // similar to Copy(): - static void Copy (aiMaterial** dest, const aiMaterial* src); - static void Copy (aiTexture** dest, const aiTexture* src); - static void Copy (aiAnimation** dest, const aiAnimation* src); - static void Copy (aiCamera** dest, const aiCamera* src); - static void Copy (aiBone** dest, const aiBone* src); - static void Copy (aiLight** dest, const aiLight* src); - static void Copy (aiNodeAnim** dest, const aiNodeAnim* src); - - // recursive, of course - static void Copy (aiNode** dest, const aiNode* src); - - -private: - - // ------------------------------------------------------------------- - // Same as AddNodePrefixes, but with an additional check - static void AddNodePrefixesChecked(aiNode* node, const char* prefix, - unsigned int len, - std::vector<SceneHelper>& input, - unsigned int cur); - - // ------------------------------------------------------------------- - // Add node identifiers to a hashing set - static void AddNodeHashes(aiNode* node, std::set<unsigned int>& hashes); - - - // ------------------------------------------------------------------- - // Search for duplicate names - static bool FindNameMatch(const aiString& name, - std::vector<SceneHelper>& input, unsigned int cur); -}; - -} - -#endif // !! AI_SCENE_COMBINER_H_INC diff --git a/3rdparty/assimp/code/ScenePreprocessor.cpp b/3rdparty/assimp/code/ScenePreprocessor.cpp deleted file mode 100644 index e7a83c51..00000000 --- a/3rdparty/assimp/code/ScenePreprocessor.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#include "ScenePreprocessor.h" - -using namespace Assimp; - -// --------------------------------------------------------------------------------------------- -void ScenePreprocessor::ProcessScene () -{ - ai_assert(scene != NULL); - - // Process all meshes - for (unsigned int i = 0; i < scene->mNumMeshes;++i) - ProcessMesh(scene->mMeshes[i]); - - // - nothing to do for nodes for the moment - // - nothing to do for textures for the moment - // - nothing to do for lights for the moment - // - nothing to do for cameras for the moment - - // Process all animations - for (unsigned int i = 0; i < scene->mNumAnimations;++i) - ProcessAnimation(scene->mAnimations[i]); - - // Generate a default material if none was specified - if (!scene->mNumMaterials && scene->mNumMeshes) { - scene->mMaterials = new aiMaterial*[2]; - MaterialHelper* helper; - - aiString name; - - // Check whether there are meshes with at least one set of uv coordinates ... add a dummy texture for them - // meshes without texture coordinates receive a boring gray default material. - unsigned int mat0 = 0xffffffff, mat1 = 0xffffffff; - for (unsigned int i = 0; i < scene->mNumMeshes;++i) { - if (scene->mMeshes[i]->mTextureCoords[0]) { - - if (mat0 == 0xffffffff) { - - scene->mMaterials[scene->mNumMaterials] = helper = new MaterialHelper(); - name.Set("$texture.png"); - helper->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(0)); - - name.Set(AI_DEFAULT_TEXTURED_MATERIAL_NAME); - helper->AddProperty(&name,AI_MATKEY_NAME); - - mat0 = scene->mNumMaterials++; - DefaultLogger::get()->debug("ScenePreprocessor: Adding textured material \'" AI_DEFAULT_TEXTURED_MATERIAL_NAME "\'"); - } - scene->mMeshes[i]->mMaterialIndex = mat0; - } - else - { - if (mat1 == 0xffffffff) { - - scene->mMaterials[scene->mNumMaterials] = helper = new MaterialHelper(); - aiColor3D clr(0.6f,0.6f,0.6f); - helper->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); - - // setup the default name - name.Set(AI_DEFAULT_MATERIAL_NAME); - helper->AddProperty(&name,AI_MATKEY_NAME); - - mat1 = scene->mNumMaterials++; - DefaultLogger::get()->debug("ScenePreprocessor: Adding grey material \'" AI_DEFAULT_MATERIAL_NAME "\'"); - } - scene->mMeshes[i]->mMaterialIndex = mat1; - } - } - } -} - -// --------------------------------------------------------------------------------------------- -void ScenePreprocessor::ProcessMesh (aiMesh* mesh) -{ - // If aiMesh::mNumUVComponents is *not* set assign the default value of 2 - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - if (!mesh->mTextureCoords[i]) - mesh->mNumUVComponents[i] = 0; - - else { - if ( !mesh->mNumUVComponents[i]) - mesh->mNumUVComponents[i] = 2; - - aiVector3D* p = mesh->mTextureCoords[i], *end = p+mesh->mNumVertices; - - // Ensure unsued components are zeroed. This will make 1D texture channels work - // as if they were 2D channels .. just in case an application doesn't handle - // this case - if (2 == mesh->mNumUVComponents[i]) { - for (; p != end; ++p) - p->z = 0.f; - } - else if (1 == mesh->mNumUVComponents[i]) { - for (; p != end; ++p) - p->z = p->y = 0.f; - } - else if (3 == mesh->mNumUVComponents[i]) { - - // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element - for (; p != end; ++p) { - if (p->z != 0) - break; - } - if (p == end) { - DefaultLogger::get()->warn("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D."); - mesh->mNumUVComponents[i] = 2; - } - } - } - } - - // If the information which primitive types are there in the - // mesh is currently not available, compute it. - if (!mesh->mPrimitiveTypes) { - for (unsigned int a = 0; a < mesh->mNumFaces; ++a) { - aiFace& face = mesh->mFaces[a]; - switch (face.mNumIndices) - { - case 3u: - mesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - - case 2u: - mesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - - case 1u: - mesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - - default: - mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - break; - } - } - } - - // If tangents and normals are given but no bitangents compute them - if (mesh->mTangents && mesh->mNormals && !mesh->mBitangents) { - - mesh->mBitangents = new aiVector3D[mesh->mNumVertices]; - for (unsigned int i = 0; i < mesh->mNumVertices;++i) { - mesh->mBitangents[i] = mesh->mNormals[i] ^ mesh->mTangents[i]; - } - } -} - -// --------------------------------------------------------------------------------------------- -void ScenePreprocessor::ProcessAnimation (aiAnimation* anim) -{ - double first = 10e10, last = -10e10; - for (unsigned int i = 0; i < anim->mNumChannels;++i) { - aiNodeAnim* channel = anim->mChannels[i]; - - /* If the exact duration of the animation is not given - * compute it now. - */ - if (anim->mDuration == -1.) { - - // Position keys - for (unsigned int i = 0; i < channel->mNumPositionKeys;++i) { - aiVectorKey& key = channel->mPositionKeys[i]; - first = std::min (first, key.mTime); - last = std::max (last, key.mTime); - } - - // Scaling keys - for (unsigned int i = 0; i < channel->mNumScalingKeys;++i) { - aiVectorKey& key = channel->mScalingKeys[i]; - first = std::min (first, key.mTime); - last = std::max (last, key.mTime); - } - - // Rotation keys - for (unsigned int i = 0; i < channel->mNumRotationKeys;++i) { - aiQuatKey& key = channel->mRotationKeys[i]; - first = std::min (first, key.mTime); - last = std::max (last, key.mTime); - } - } - - /* Check whether the animation channel has no rotation - * or position tracks. In this case we generate a dummy - * track from the information we have in the transformation - * matrix of the corresponding node. - */ - if (!channel->mNumRotationKeys || !channel->mNumPositionKeys || !channel->mNumScalingKeys) { - // Find the node that belongs to this animation - aiNode* node = scene->mRootNode->FindNode(channel->mNodeName); - if (node) // ValidateDS will complain later if 'node' is NULL - { - // Decompose the transformation matrix of the node - aiVector3D scaling, position; - aiQuaternion rotation; - - node->mTransformation.Decompose(scaling, rotation,position); - - // No rotation keys? Generate a dummy track - if (!channel->mNumRotationKeys) { - channel->mNumRotationKeys = 1; - channel->mRotationKeys = new aiQuatKey[1]; - aiQuatKey& q = channel->mRotationKeys[0]; - - q.mTime = 0.; - q.mValue = rotation; - - DefaultLogger::get()->debug("ScenePreprocessor: Dummy rotation track has been generated"); - } - - // No scaling keys? Generate a dummy track - if (!channel->mNumScalingKeys) { - channel->mNumScalingKeys = 1; - channel->mScalingKeys = new aiVectorKey[1]; - aiVectorKey& q = channel->mScalingKeys[0]; - - q.mTime = 0.; - q.mValue = scaling; - - DefaultLogger::get()->debug("ScenePreprocessor: Dummy scaling track has been generated"); - } - - // No position keys? Generate a dummy track - if (!channel->mNumPositionKeys) { - channel->mNumPositionKeys = 1; - channel->mPositionKeys = new aiVectorKey[1]; - aiVectorKey& q = channel->mPositionKeys[0]; - - q.mTime = 0.; - q.mValue = position; - - DefaultLogger::get()->debug("ScenePreprocessor: Dummy position track has been generated"); - } - } - } - } - - if (anim->mDuration == -1.) { - DefaultLogger::get()->debug("ScenePreprocessor: Setting animation duration"); - anim->mDuration = last - std::min( first, 0. ); - } -} diff --git a/3rdparty/assimp/code/ScenePreprocessor.h b/3rdparty/assimp/code/ScenePreprocessor.h deleted file mode 100644 index 86254469..00000000 --- a/3rdparty/assimp/code/ScenePreprocessor.h +++ /dev/null @@ -1,116 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to search all meshes for - degenerated faces */ -#ifndef AI_SCENE_PREPROCESSOR_H_INC -#define AI_SCENE_PREPROCESSOR_H_INC - -class ScenePreprocessorTest; -namespace Assimp { - -// ---------------------------------------------------------------------------------- -/** ScenePreprocessor: Preprocess a scene before any post-processing - * steps are executed. - * - * The step computes data that needn't necessarily be provided by the - * importer, such as aiMesh::mPrimitiveTypes. -*/ -// ---------------------------------------------------------------------------------- -class ASSIMP_API ScenePreprocessor -{ - // Make ourselves a friend of the corresponding test unit. - friend class ::ScenePreprocessorTest; -public: - - // ---------------------------------------------------------------- - /** Default c'tpr. Use SetScene() to assign a scene to the object. - */ - ScenePreprocessor() - : scene (NULL) - {} - - /** Constructs the object and assigns a specific scene to it - */ - ScenePreprocessor(aiScene* _scene) - : scene (_scene) - {} - - // ---------------------------------------------------------------- - /** Assign a (new) scene to the object. - * - * One 'SceneProcessor' can be used for multiple scenes. - * Call ProcessScene to have the scene preprocessed. - * @param sc Scene to be processed. - */ - void SetScene (aiScene* sc) { - scene = sc; - } - - // ---------------------------------------------------------------- - /** Preprocess the current scene - */ - void ProcessScene (); - -protected: - - // ---------------------------------------------------------------- - /** Preprocess an animation in the scene - * @param anim Anim to be preprocessed. - */ - void ProcessAnimation (aiAnimation* anim); - - - // ---------------------------------------------------------------- - /** Preprocess a mesh in the scene - * @param mesh Mesh to be preprocessed. - */ - void ProcessMesh (aiMesh* mesh); - -protected: - - //! Scene we're currently working on - aiScene* scene; -}; - - -} // ! end namespace Assimp - -#endif // include guard diff --git a/3rdparty/assimp/code/SkeletonMeshBuilder.cpp b/3rdparty/assimp/code/SkeletonMeshBuilder.cpp deleted file mode 100644 index 9e42270b..00000000 --- a/3rdparty/assimp/code/SkeletonMeshBuilder.cpp +++ /dev/null @@ -1,267 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 SkeletonMeshBuilder.cpp - * @brief Implementation of a little class to construct a dummy mesh for a skeleton - */ - -#include "AssimpPCH.h" -#include "../include/aiScene.h" -#include "SkeletonMeshBuilder.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// The constructor processes the given scene and adds a mesh there. -SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly) -{ - // nothing to do if there's mesh data already present at the scene - if ( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL) - return; - - if (!root) - root = pScene->mRootNode; - - mKnobsOnly = bKnobsOnly; - - // build some faces around each node - CreateGeometry( root ); - - // create a mesh to hold all the generated faces - pScene->mNumMeshes = 1; - pScene->mMeshes = new aiMesh*[1]; - pScene->mMeshes[0] = CreateMesh(); - // and install it at the root node - root->mNumMeshes = 1; - root->mMeshes = new unsigned int[1]; - root->mMeshes[0] = 0; - - // create a dummy material for the mesh - pScene->mNumMaterials = 1; - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = CreateMaterial(); -} - -// ------------------------------------------------------------------------------------------------ -// Recursively builds a simple mesh representation for the given node -void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode) -{ - // add a joint entry for the node. - const unsigned int vertexStartIndex = mVertices.size(); - - // now build the geometry. - if ( pNode->mNumChildren > 0 && !mKnobsOnly) - { - // If the node has children, we build little pointers to each of them - for ( unsigned int a = 0; a < pNode->mNumChildren; a++) - { - // find a suitable coordinate system - const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation; - aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4); - float distanceToChild = childpos.Length(); - if ( distanceToChild < 0.0001f) - continue; - aiVector3D up = aiVector3D( childpos).Normalize(); - - aiVector3D orth( 1.0f, 0.0f, 0.0f); - if ( fabs( orth * up) > 0.99f) - orth.Set( 0.0f, 1.0f, 0.0f); - - aiVector3D front = (up ^ orth).Normalize(); - aiVector3D side = (front ^ up).Normalize(); - - unsigned int localVertexStart = mVertices.size(); - mVertices.push_back( -front * distanceToChild * 0.1f); - mVertices.push_back( childpos); - mVertices.push_back( -side * distanceToChild * 0.1f); - mVertices.push_back( -side * distanceToChild * 0.1f); - mVertices.push_back( childpos); - mVertices.push_back( front * distanceToChild * 0.1f); - mVertices.push_back( front * distanceToChild * 0.1f); - mVertices.push_back( childpos); - mVertices.push_back( side * distanceToChild * 0.1f); - mVertices.push_back( side * distanceToChild * 0.1f); - mVertices.push_back( childpos); - mVertices.push_back( -front * distanceToChild * 0.1f); - - mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2)); - mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5)); - mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8)); - mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11)); - } - } - else - { - // if the node has no children, it's an end node. Put a little knob there instead - aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4); - float sizeEstimate = ownpos.Length() * 0.18f; - - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate)); - - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate)); - mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f)); - mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate)); - mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f)); - - mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2)); - mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5)); - mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8)); - mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11)); - mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14)); - mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17)); - mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20)); - mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23)); - } - - unsigned int numVertices = mVertices.size() - vertexStartIndex; - if ( numVertices > 0) - { - // create a bone affecting all the newly created vertices - aiBone* bone = new aiBone; - mBones.push_back( bone); - bone->mName = pNode->mName; - - // calculate the bone offset matrix by concatenating the inverse transformations of all parents - bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse(); - for ( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent) - bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix; - - // add all the vertices to the bone's influences - bone->mNumWeights = numVertices; - bone->mWeights = new aiVertexWeight[numVertices]; - for ( unsigned int a = 0; a < numVertices; a++) - bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0f); - - // HACK: (thom) transform all vertices to the bone's local space. Should be done before adding - // them to the array, but I'm tired now and I'm annoyed. - aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse(); - for ( unsigned int a = vertexStartIndex; a < mVertices.size(); a++) - mVertices[a] = boneToMeshTransform * mVertices[a]; - } - - // and finally recurse into the children list - for ( unsigned int a = 0; a < pNode->mNumChildren; a++) - CreateGeometry( pNode->mChildren[a]); -} - -// ------------------------------------------------------------------------------------------------ -// Creates the mesh from the internally accumulated stuff and returns it. -aiMesh* SkeletonMeshBuilder::CreateMesh() -{ - aiMesh* mesh = new aiMesh(); - - // add points - mesh->mNumVertices = mVertices.size(); - mesh->mVertices = new aiVector3D[mesh->mNumVertices]; - std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices); - - mesh->mNormals = new aiVector3D[mesh->mNumVertices]; - - // add faces - mesh->mNumFaces = mFaces.size(); - mesh->mFaces = new aiFace[mesh->mNumFaces]; - for ( unsigned int a = 0; a < mesh->mNumFaces; a++) - { - const Face& inface = mFaces[a]; - aiFace& outface = mesh->mFaces[a]; - outface.mNumIndices = 3; - outface.mIndices = new unsigned int[3]; - outface.mIndices[0] = inface.mIndices[0]; - outface.mIndices[1] = inface.mIndices[1]; - outface.mIndices[2] = inface.mIndices[2]; - - // Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize - // the skeleton, so it's good if there's a visual difference to the rest of the geometry - aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^ - (mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]])); - - if (nor.Length() < 1e-5f) /* ensure that FindInvalidData won't remove us ...*/ - nor = aiVector3D(1.f,0.f,0.f); - - for (unsigned int n = 0; n < 3; ++n) - mesh->mNormals[inface.mIndices[n]] = nor; - } - - // add the bones - mesh->mNumBones = mBones.size(); - mesh->mBones = new aiBone*[mesh->mNumBones]; - std::copy( mBones.begin(), mBones.end(), mesh->mBones); - - // default - mesh->mMaterialIndex = 0; - - return mesh; -} - -// ------------------------------------------------------------------------------------------------ -// Creates a dummy material and returns it. -aiMaterial* SkeletonMeshBuilder::CreateMaterial() -{ - Assimp::MaterialHelper* matHelper = new Assimp::MaterialHelper; - - // Name - aiString matName( std::string( "SkeletonMaterial")); - matHelper->AddProperty( &matName, AI_MATKEY_NAME); - - // Prevent backface culling - const int no_cull = 1; - matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED); - - return matHelper; -} diff --git a/3rdparty/assimp/code/SkeletonMeshBuilder.h b/3rdparty/assimp/code/SkeletonMeshBuilder.h deleted file mode 100644 index 2575d072..00000000 --- a/3rdparty/assimp/code/SkeletonMeshBuilder.h +++ /dev/null @@ -1,122 +0,0 @@ -/** Helper class to construct a dummy mesh for file formats containing only motion data */ - -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 SkeletonMeshBuilder.h - * Declares SkeletonMeshBuilder, a tiny utility to build dummy meshes - * for animation skeletons. - */ - -#ifndef AI_SKELETONMESHBUILDER_H_INC -#define AI_SKELETONMESHBUILDER_H_INC - -#include <vector> -#include "../include/aiMesh.h" - -struct aiScene; -struct aiNode; - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** - * This little helper class constructs a dummy mesh for a given scene - * the resembles the node hierarchy. This is useful for file formats - * that don't carry any mesh data but only animation data. - */ -class ASSIMP_API SkeletonMeshBuilder -{ -public: - - // ------------------------------------------------------------------- - /** The constructor processes the given scene and adds a mesh there. - * - * Does nothing if the scene already has mesh data. - * @param pScene The scene for which a skeleton mesh should be constructed. - * @param root The node to start with. NULL is the scene root - * @param bKnobsOnly Set this to true if you don't want the connectors - * between the knobs representing the nodes. - */ - SkeletonMeshBuilder( aiScene* pScene, aiNode* root = NULL, - bool bKnobsOnly = false); - -protected: - - // ------------------------------------------------------------------- - /** Recursively builds a simple mesh representation for the given node - * and also creates a joint for the node that affects this part of - * the mesh. - * @param pNode The node to build geometry for. - */ - void CreateGeometry( const aiNode* pNode); - - // ------------------------------------------------------------------- - /** Creates the mesh from the internally accumulated stuff and returns it. - */ - aiMesh* CreateMesh(); - - // ------------------------------------------------------------------- - /** Creates a dummy material and returns it. */ - aiMaterial* CreateMaterial(); - -protected: - /** space to assemble the mesh data: points */ - std::vector<aiVector3D> mVertices; - - /** faces */ - struct Face - { - unsigned int mIndices[3]; - Face(); - Face( unsigned int p0, unsigned int p1, unsigned int p2) - { mIndices[0] = p0; mIndices[1] = p1; mIndices[2] = p2; } - }; - std::vector<Face> mFaces; - - /** bones */ - std::vector<aiBone*> mBones; - - bool mKnobsOnly; -}; - -} // end of namespace Assimp - -#endif // AI_SKELETONMESHBUILDER_H_INC diff --git a/3rdparty/assimp/code/SmoothingGroups.h b/3rdparty/assimp/code/SmoothingGroups.h deleted file mode 100644 index 50535820..00000000 --- a/3rdparty/assimp/code/SmoothingGroups.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the helper data structures for importing 3DS files. -http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */ - -#ifndef AI_SMOOTHINGGROUPS_H_INC -#define AI_SMOOTHINGGROUPS_H_INC - -// --------------------------------------------------------------------------- -/** Helper structure representing a face with smoothing groups assigned */ -struct FaceWithSmoothingGroup -{ - FaceWithSmoothingGroup() : iSmoothGroup(0) - { - // let the rest uninitialized for performance - in release builds. - // in debug builds set all indices to a common magic value -#ifdef _DEBUG - this->mIndices[0] = 0xffffffff; - this->mIndices[1] = 0xffffffff; - this->mIndices[2] = 0xffffffff; -#endif - } - - - //! Indices. .3ds is using uint16. However, after - //! an unique vrtex set has been generated it might - //! be an index becomes > 2^16 - uint32_t mIndices[3]; - - //! specifies to which smoothing group the face belongs to - uint32_t iSmoothGroup; -}; - -// --------------------------------------------------------------------------- -/** Helper structure representing a mesh whose faces have smoothing - groups assigned. This allows us to reuse the code for normal computations - from smoothings groups for several loaders (3DS, ASE). All of them - use face structures which inherit from #FaceWithSmoothingGroup, - but as they add extra members and need to be copied by value we - need to use a template here. - */ -template <class T> -struct MeshWithSmoothingGroups -{ - //! Vertex positions - std::vector<aiVector3D> mPositions; - - //! Face lists - std::vector<T> mFaces; - - //! List of normal vectors - std::vector<aiVector3D> mNormals; -}; - -// --------------------------------------------------------------------------- -/** Computes normal vectors for the mesh - */ -template <class T> -void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh); - - -// include implementations -#include "SmoothingGroups.inl" - -#endif // !! AI_SMOOTHINGGROUPS_H_INC diff --git a/3rdparty/assimp/code/SmoothingGroups.inl b/3rdparty/assimp/code/SmoothingGroups.inl deleted file mode 100644 index 10eb7d25..00000000 --- a/3rdparty/assimp/code/SmoothingGroups.inl +++ /dev/null @@ -1,138 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Generation of normal vectors basing on smoothing groups */ - -#ifndef AI_SMOOTHINGGROUPS_INL_INCLUDED -#define AI_SMOOTHINGGROUPS_INL_INCLUDED - -// internal headers -#include "SGSpatialSort.h" - -// CRT header -#include <algorithm> - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -template <class T> -void ComputeNormalsWithSmoothingsGroups(MeshWithSmoothingGroups<T>& sMesh) -{ - // First generate face normals - sMesh.mNormals.resize(sMesh.mPositions.size(),aiVector3D()); - for ( unsigned int a = 0; a < sMesh.mFaces.size(); a++) - { - T& face = sMesh.mFaces[a]; - - aiVector3D* pV1 = &sMesh.mPositions[face.mIndices[0]]; - aiVector3D* pV2 = &sMesh.mPositions[face.mIndices[1]]; - aiVector3D* pV3 = &sMesh.mPositions[face.mIndices[2]]; - - aiVector3D pDelta1 = *pV2 - *pV1; - aiVector3D pDelta2 = *pV3 - *pV1; - aiVector3D vNor = pDelta1 ^ pDelta2; - - for (unsigned int c = 0; c < 3;++c) - sMesh.mNormals[face.mIndices[c]] = vNor; - } - - // calculate the position bounds so we have a reliable epsilon to check position differences against - aiVector3D minVec( 1e10f, 1e10f, 1e10f), maxVec( -1e10f, -1e10f, -1e10f); - for ( unsigned int a = 0; a < sMesh.mPositions.size(); a++) - { - minVec.x = std::min( minVec.x, sMesh.mPositions[a].x); - minVec.y = std::min( minVec.y, sMesh.mPositions[a].y); - minVec.z = std::min( minVec.z, sMesh.mPositions[a].z); - maxVec.x = std::max( maxVec.x, sMesh.mPositions[a].x); - maxVec.y = std::max( maxVec.y, sMesh.mPositions[a].y); - maxVec.z = std::max( maxVec.z, sMesh.mPositions[a].z); - } - const float posEpsilon = (maxVec - minVec).Length() * 1e-5f; - std::vector<aiVector3D> avNormals; - avNormals.resize(sMesh.mNormals.size()); - - // now generate the spatial sort tree - SGSpatialSort sSort; - for ( typename std::vector<T>::iterator i = sMesh.mFaces.begin(); - i != sMesh.mFaces.end();++i) - { - for (unsigned int c = 0; c < 3;++c) - sSort.Add(sMesh.mPositions[(*i).mIndices[c]],(*i).mIndices[c],(*i).iSmoothGroup); - } - sSort.Prepare(); - - std::vector<bool> vertexDone(sMesh.mPositions.size(),false); - for ( typename std::vector<T>::iterator i = sMesh.mFaces.begin(); - i != sMesh.mFaces.end();++i) - { - std::vector<unsigned int> poResult; - for (unsigned int c = 0; c < 3;++c) - { - register unsigned int idx = (*i).mIndices[c]; - if (vertexDone[idx])continue; - - sSort.FindPositions(sMesh.mPositions[idx],(*i).iSmoothGroup, - posEpsilon,poResult); - - aiVector3D vNormals; - for (std::vector<unsigned int>::const_iterator - a = poResult.begin(); - a != poResult.end();++a) - { - vNormals += sMesh.mNormals[(*a)]; - } - vNormals.Normalize(); - - // write back into all affected normals - for (std::vector<unsigned int>::const_iterator - a = poResult.begin(); - a != poResult.end();++a) - { - idx = *a; - avNormals [idx] = vNormals; - vertexDone[idx] = true; - } - } - } - sMesh.mNormals = avNormals; -} - -#endif // !! AI_SMOOTHINGGROUPS_INL_INCLUDED diff --git a/3rdparty/assimp/code/SortByPTypeProcess.cpp b/3rdparty/assimp/code/SortByPTypeProcess.cpp deleted file mode 100644 index 613245ff..00000000 --- a/3rdparty/assimp/code/SortByPTypeProcess.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 DeterminePTypeHelperProcess and - * SortByPTypeProcess post-process steps. -*/ - -#include "AssimpPCH.h" - -// internal headers -#include "ProcessHelper.h" -#include "SortByPTypeProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -SortByPTypeProcess::SortByPTypeProcess() -{ - configRemoveMeshes = 0; -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -SortByPTypeProcess::~SortByPTypeProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool SortByPTypeProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_SortByPType) != 0; -} - -// ------------------------------------------------------------------------------------------------ -void SortByPTypeProcess::SetupProperties(const Importer* pImp) -{ - configRemoveMeshes = pImp->GetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,0); -} - -// ------------------------------------------------------------------------------------------------ -// Update changed meshes in all nodes -void UpdateNodes(const std::vector<unsigned int>& replaceMeshIndex, aiNode* node) -{ -// std::vector<unsigned int>::const_iterator it; - - if (node->mNumMeshes) - { - unsigned int newSize = 0; - for (unsigned int m = 0; m< node->mNumMeshes; ++m) - { - unsigned int add = node->mMeshes[m]<<2; - for (unsigned int i = 0; i < 4;++i) - { - if (0xffffffff != replaceMeshIndex[add+i])++newSize; - } - } - if (!newSize) - { - delete[] node->mMeshes; - node->mNumMeshes = 0; - node->mMeshes = NULL; - } - else - { - // Try to reuse the old array if possible - unsigned int* newMeshes = (newSize > node->mNumMeshes - ? new unsigned int[newSize] : node->mMeshes); - - for (unsigned int m = 0; m< node->mNumMeshes; ++m) - { - unsigned int add = node->mMeshes[m]<<2; - for (unsigned int i = 0; i < 4;++i) - { - if (0xffffffff != replaceMeshIndex[add+i]) - *newMeshes++ = replaceMeshIndex[add+i]; - } - } - if (newSize > node->mNumMeshes) - delete[] node->mMeshes; - - node->mMeshes = newMeshes-(node->mNumMeshes = newSize); - } - } - - // call all subnodes recursively - for (unsigned int m = 0; m < node->mNumChildren; ++m) - UpdateNodes(replaceMeshIndex,node->mChildren[m]); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void SortByPTypeProcess::Execute( aiScene* pScene) -{ - if (!pScene->mNumMeshes) - { - DefaultLogger::get()->debug("SortByPTypeProcess skipped, there are no meshes"); - return; - } - - DefaultLogger::get()->debug("SortByPTypeProcess begin"); - - unsigned int aiNumMeshesPerPType[4] = {0,0,0,0}; - - std::vector<aiMesh*> outMeshes; - outMeshes.reserve(pScene->mNumMeshes<<1u); - - bool bAnyChanges = false; - - std::vector<unsigned int> replaceMeshIndex(pScene->mNumMeshes*4,0xffffffff); - std::vector<unsigned int>::iterator meshIdx = replaceMeshIndex.begin(); - for (unsigned int i = 0; i < pScene->mNumMeshes;++i) - { - aiMesh* mesh = pScene->mMeshes[i]; - ai_assert(0 != mesh->mPrimitiveTypes); - - // if there's just one primitive type in the mesh there's nothing to do for us - unsigned int num = 0; - if (mesh->mPrimitiveTypes & aiPrimitiveType_POINT) - { - ++aiNumMeshesPerPType[0]; - ++num; - } - if (mesh->mPrimitiveTypes & aiPrimitiveType_LINE) - { - ++aiNumMeshesPerPType[1]; - ++num; - } - if (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE) - { - ++aiNumMeshesPerPType[2]; - ++num; - } - if (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON) - { - ++aiNumMeshesPerPType[3]; - ++num; - } - - if (1 == num) - { - if (!(configRemoveMeshes & mesh->mPrimitiveTypes)) - { - *meshIdx = (unsigned int) outMeshes.size(); - outMeshes.push_back(mesh); - } - else bAnyChanges = true; - - meshIdx += 4; - continue; - } - bAnyChanges = true; - - // reuse our current mesh arrays for the submesh - // with the largest numer of primitives - unsigned int aiNumPerPType[4] = {0,0,0,0}; - aiFace* pFirstFace = mesh->mFaces; - aiFace* const pLastFace = pFirstFace + mesh->mNumFaces; - - unsigned int numPolyVerts = 0; - for (;pFirstFace != pLastFace; ++pFirstFace) - { - if (pFirstFace->mNumIndices <= 3) - ++aiNumPerPType[pFirstFace->mNumIndices-1]; - else - { - ++aiNumPerPType[3]; - numPolyVerts += pFirstFace-> mNumIndices; - } - } - - VertexWeightTable* avw = ComputeVertexBoneWeightTable(mesh); - for (unsigned int real = 0; real < 4; ++real,++meshIdx) - { - if ( !aiNumPerPType[real] || configRemoveMeshes & (1u << real)) - { - continue; - } - - *meshIdx = (unsigned int) outMeshes.size(); - outMeshes.push_back(new aiMesh()); - aiMesh* out = outMeshes.back(); - - // the name carries the adjacency information between the meshes - out->mName = mesh->mName; - - // copy data members - out->mPrimitiveTypes = 1u << real; - out->mMaterialIndex = mesh->mMaterialIndex; - - // allocate output storage - out->mNumFaces = aiNumPerPType[real]; - aiFace* outFaces = out->mFaces = new aiFace[out->mNumFaces]; - - out->mNumVertices = (3 == real ? numPolyVerts : out->mNumFaces * (real+1)); - - aiVector3D *vert(NULL), *nor(NULL), *tan(NULL), *bit(NULL); - aiVector3D *uv [AI_MAX_NUMBER_OF_TEXTURECOORDS]; - aiColor4D *cols [AI_MAX_NUMBER_OF_COLOR_SETS]; - - if (mesh->mVertices) - vert = out->mVertices = new aiVector3D[out->mNumVertices]; - - if (mesh->mNormals) - nor = out->mNormals = new aiVector3D[out->mNumVertices]; - - if (mesh->mTangents) - { - tan = out->mTangents = new aiVector3D[out->mNumVertices]; - bit = out->mBitangents = new aiVector3D[out->mNumVertices]; - } - - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - { - if (mesh->mTextureCoords[i]) - uv[i] = out->mTextureCoords[i] = new aiVector3D[out->mNumVertices]; - else uv[i] = NULL; - - out->mNumUVComponents[i] = mesh->mNumUVComponents[i]; - } - - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS;++i) - { - if (mesh->mColors[i]) - cols[i] = out->mColors[i] = new aiColor4D[out->mNumVertices]; - else cols[i] = NULL; - } - - typedef std::vector< aiVertexWeight > TempBoneInfo; - std::vector< TempBoneInfo > tempBones(mesh->mNumBones); - - // try to guess how much storage we'll need - for (unsigned int q = 0; q < mesh->mNumBones;++q) - { - tempBones[q].reserve(mesh->mBones[q]->mNumWeights / (num-1)); - } - - unsigned int outIdx = 0; - for (unsigned int m = 0; m < mesh->mNumFaces; ++m) - { - aiFace& in = mesh->mFaces[m]; - if ((real == 3 && in.mNumIndices <= 3) || (real != 3 && in.mNumIndices != real+1)) - { - continue; - } - - outFaces->mNumIndices = in.mNumIndices; - outFaces->mIndices = in.mIndices; - - for (unsigned int q = 0; q < in.mNumIndices; ++q) - { - register unsigned int idx = in.mIndices[q]; - - // process all bones of this index - if (avw) - { - VertexWeightTable& tbl = avw[idx]; - for (VertexWeightTable::const_iterator it = tbl.begin(), end = tbl.end(); - it != end; ++it) - { - tempBones[ (*it).first ].push_back( aiVertexWeight(outIdx, (*it).second) ); - } - } - - if (vert) - { - *vert++ = mesh->mVertices[idx]; - //mesh->mVertices[idx].x = get_qnan(); - } - if (nor )*nor++ = mesh->mNormals[idx]; - if (tan ) - { - *tan++ = mesh->mTangents[idx]; - *bit++ = mesh->mBitangents[idx]; - } - - for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++pp) - { - if (!uv[pp])break; - *uv[pp]++ = mesh->mTextureCoords[pp][idx]; - } - - for (unsigned int pp = 0; pp < AI_MAX_NUMBER_OF_COLOR_SETS; ++pp) - { - if (!cols[pp])break; - *cols[pp]++ = mesh->mColors[pp][idx]; - } - - in.mIndices[q] = outIdx++; - } - - in.mIndices = NULL; - ++outFaces; - } - ai_assert(outFaces == out->mFaces + out->mNumFaces); - - // now generate output bones - for (unsigned int q = 0; q < mesh->mNumBones;++q) - if (!tempBones[q].empty())++out->mNumBones; - - if (out->mNumBones) - { - out->mBones = new aiBone*[out->mNumBones]; - for (unsigned int q = 0, real = 0; q < mesh->mNumBones;++q) - { - TempBoneInfo& in = tempBones[q]; - if (in.empty())continue; - - aiBone* srcBone = mesh->mBones[q]; - aiBone* bone = out->mBones[real] = new aiBone(); - - bone->mName = srcBone->mName; - bone->mOffsetMatrix = srcBone->mOffsetMatrix; - - bone->mNumWeights = (unsigned int)in.size(); - bone->mWeights = new aiVertexWeight[bone->mNumWeights]; - - ::memcpy(bone->mWeights,&in[0],bone->mNumWeights*sizeof(aiVertexWeight)); - - ++real; - } - } - } - - // delete the per-vertex bone weights table - delete[] avw; - - // delete the input mesh - delete mesh; - } - - if (outMeshes.empty()) - { - // This should not occur - throw DeadlyImportError("No meshes remaining"); - } - - // If we added at least one mesh process all nodes in the node - // graph and update their respective mesh indices. - if (bAnyChanges) - { - UpdateNodes(replaceMeshIndex,pScene->mRootNode); - } - - if (outMeshes.size() != pScene->mNumMeshes) - { - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)outMeshes.size(); - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]; - } - ::memcpy(pScene->mMeshes,&outMeshes[0],pScene->mNumMeshes*sizeof(void*)); - - if (!DefaultLogger::isNullLogger()) - { - char buffer[1024]; - ::sprintf(buffer,"Points: %i%s, Lines: %i%s, Triangles: %i%s, Polygons: %i%s (Meshes, X = removed)", - aiNumMeshesPerPType[0], (configRemoveMeshes & aiPrimitiveType_POINT ? "X" : ""), - aiNumMeshesPerPType[1], (configRemoveMeshes & aiPrimitiveType_LINE ? "X" : ""), - aiNumMeshesPerPType[2], (configRemoveMeshes & aiPrimitiveType_TRIANGLE ? "X" : ""), - aiNumMeshesPerPType[3], (configRemoveMeshes & aiPrimitiveType_POLYGON ? "X" : "")); - DefaultLogger::get()->info(buffer); - DefaultLogger::get()->debug("SortByPTypeProcess finished"); - } -} - diff --git a/3rdparty/assimp/code/SortByPTypeProcess.h b/3rdparty/assimp/code/SortByPTypeProcess.h deleted file mode 100644 index 539df299..00000000 --- a/3rdparty/assimp/code/SortByPTypeProcess.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to sort meshes by the types - of primitives they contain */ -#ifndef AI_SORTBYPTYPEPROCESS_H_INC -#define AI_SORTBYPTYPEPROCESS_H_INC - -#include "BaseProcess.h" -#include "../include/aiMesh.h" - -class SortByPTypeProcessTest; -namespace Assimp { - - -// --------------------------------------------------------------------------- -/** SortByPTypeProcess: Sorts meshes by the types of primitives they contain. - * A mesh with 5 lines, 3 points and 145 triangles would be split in 3 - * submeshes. -*/ -class ASSIMP_API SortByPTypeProcess : public BaseProcess -{ - friend class Importer; - friend class ::SortByPTypeProcessTest; // grant the unit test full access to us - -protected: - /** Constructor to be privately used by Importer */ - SortByPTypeProcess(); - - /** Destructor, private as well */ - ~SortByPTypeProcess(); - -public: - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - -private: - - int configRemoveMeshes; -}; - - -} // end of namespace Assimp - -#endif // !!AI_SORTBYPTYPEPROCESS_H_INC diff --git a/3rdparty/assimp/code/SpatialSort.cpp b/3rdparty/assimp/code/SpatialSort.cpp deleted file mode 100644 index 343f9091..00000000 --- a/3rdparty/assimp/code/SpatialSort.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 helper class to quickly find vertices close to a given position */ - -#include "AssimpPCH.h" -#include "SpatialSort.h" - -using namespace Assimp; - -// CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8. -#ifndef CHAR_BIT -# define CHAR_BIT 8 -#endif - -// ------------------------------------------------------------------------------------------------ -// Constructs a spatially sorted representation from the given position array. -SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions, - unsigned int pElementOffset) - - // define the reference plane. We choose some arbitrary vector away from all basic axises - // in the hope that no model spreads all its vertices along this plane. - : mPlaneNormal(0.8523f, 0.34321f, 0.5736f) -{ - mPlaneNormal.Normalize(); - Fill(pPositions,pNumPositions,pElementOffset); -} - -// ------------------------------------------------------------------------------------------------ -SpatialSort :: SpatialSort() -: mPlaneNormal(0.8523f, 0.34321f, 0.5736f) -{ - mPlaneNormal.Normalize(); -} - -// ------------------------------------------------------------------------------------------------ -// Destructor -SpatialSort::~SpatialSort() -{ - // nothing to do here, everything destructs automatically -} - -// ------------------------------------------------------------------------------------------------ -void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions, - unsigned int pElementOffset, - bool pFinalize /*= true */) -{ - mPositions.clear(); - Append(pPositions,pNumPositions,pElementOffset,pFinalize); -} - -// ------------------------------------------------------------------------------------------------ -void SpatialSort :: Finalize() -{ - std::sort( mPositions.begin(), mPositions.end()); -} - -// ------------------------------------------------------------------------------------------------ -void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions, - unsigned int pElementOffset, - bool pFinalize /*= true */) -{ - // store references to all given positions along with their distance to the reference plane - const size_t initial = mPositions.size(); - mPositions.reserve(initial + (pFinalize?pNumPositions:pNumPositions*2)); - for( unsigned int a = 0; a < pNumPositions; a++) - { - const char* tempPointer = reinterpret_cast<const char*> (pPositions); - const aiVector3D* vec = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset); - - // store position by index and distance - float distance = *vec * mPlaneNormal; - - // UGLY HACK !!! - // TODO: fix it - volatile int KillOptimisation = *((int*)&distance); - - mPositions.push_back( Entry( a+initial, *vec, distance)); - } - - if (pFinalize) { - // now sort the array ascending by distance. - Finalize(); - } -} - -// ------------------------------------------------------------------------------------------------ -// Returns an iterator for all positions close to the given position. -void SpatialSort::FindPositions( const aiVector3D& pPosition, - float pRadius, std::vector<unsigned int>& poResults) const -{ - const float dist = pPosition * mPlaneNormal; - const float minDist = dist - pRadius, maxDist = dist + pRadius; - - // clear the array in this strange fashion because a simple clear() would also deallocate - // the array which we want to avoid - poResults.erase( poResults.begin(), poResults.end()); - - // quick check for positions outside the range - if( mPositions.size() == 0) - return; - if( maxDist < mPositions.front().mDistance) - return; - if( minDist > mPositions.back().mDistance) - return; - - // do a binary search for the minimal distance to start the iteration there - unsigned int index = (unsigned int)mPositions.size() / 2; - unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4; - while( binaryStepSize > 1) - { - if( mPositions[index].mDistance < minDist) - index += binaryStepSize; - else - index -= binaryStepSize; - - binaryStepSize /= 2; - } - - // depending on the direction of the last step we need to single step a bit back or forth - // to find the actual beginning element of the range - while( index > 0 && mPositions[index].mDistance > minDist) - index--; - while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist) - index++; - - // Mow start iterating from there until the first position lays outside of the distance range. - // Add all positions inside the distance range within the given radius to the result aray - std::vector<Entry>::const_iterator it = mPositions.begin() + index; - const float pSquared = pRadius*pRadius; - while( it->mDistance < maxDist) - { - if( (it->mPosition - pPosition).SquareLength() < pSquared) - poResults.push_back( it->mIndex); - ++it; - if( it == mPositions.end()) - break; - } - - // that's it -} - -namespace { - - // Binary, signed-integer representation of a single-precision floating-point value. - // IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are - // ordered the same way when their bits are reinterpreted as sign-magnitude integers." - // This allows us to convert all floating-point numbers to signed integers of arbitrary size - // and then use them to work with ULPs (Units in the Last Place, for high-precision - // computations) or to compare them (integer comparisons are faster than floating-point - // comparisons on many platforms). - typedef signed int BinFloat; - - // -------------------------------------------------------------------------------------------- - // Converts the bit pattern of a floating-point number to its signed integer representation. - BinFloat ToBinary( const float & pValue) { - - // If this assertion fails, signed int is not big enough to store a float on your platform. - // Please correct the declaration of BinFloat a few lines above - but do it in a portable, - // #ifdef'd manner! - BOOST_STATIC_ASSERT( sizeof(BinFloat) >= sizeof(float)); - - #if defined( _MSC_VER) - // If this assertion fails, Visual C++ has finally moved to ILP64. This means that this - // code has just become legacy code! Find out the current value of _MSC_VER and modify - // the #if above so it evaluates false on the current and all upcoming VC versions (or - // on the current platform, if LP64 or LLP64 are still used on other platforms). - BOOST_STATIC_ASSERT( sizeof(BinFloat) == sizeof(float)); - - // This works best on Visual C++, but other compilers have their problems with it. - const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue); - #else - // On many compilers, reinterpreting a float address as an integer causes aliasing - // problems. This is an ugly but more or less safe way of doing it. - union { - float asFloat; - BinFloat asBin; - } conversion; - conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float) - conversion.asFloat = pValue; - const BinFloat binValue = conversion.asBin; - #endif - - // floating-point numbers are of sign-magnitude format, so find out what signed number - // representation we must convert negative values to. - // See http://en.wikipedia.org/wiki/Signed_number_representations. - - // Two's complement? - if( (-42 == (~42 + 1)) && (binValue & 0x80000000)) - return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue; - // One's complement? - else if( (-42 == ~42) && (binValue & 0x80000000)) - return BinFloat(-0) - binValue; - // Sign-magnitude? - else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary - return binValue; - else - return binValue; - } - -} // namespace - -// ------------------------------------------------------------------------------------------------ -// Fills an array with indices of all positions indentical to the given position. In opposite to -// FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units. -void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition, - std::vector<unsigned int>& poResults) const -{ - // Epsilons have a huge disadvantage: they are of constant precision, while floating-point - // values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but - // if you apply it to 0.001, it is enormous. - - // The best way to overcome this is the unit in the last place (ULP). A precision of 2 ULPs - // tells us that a float does not differ more than 2 bits from the "real" value. ULPs are of - // logarithmic precision - around 1, they are 1÷(2^24) and around 10000, they are 0.00125. - - // For standard C math, we can assume a precision of 0.5 ULPs according to IEEE 754. The - // incoming vertex positions might have already been transformed, probably using rather - // inaccurate SSE instructions, so we assume a tolerance of 4 ULPs to safely identify - // identical vertex positions. - static const int toleranceInULPs = 4; - // An interesting point is that the inaccuracy grows linear with the number of operations: - // multiplying to numbers, each inaccurate to four ULPs, results in an inaccuracy of four ULPs - // plus 0.5 ULPs for the multiplication. - // To compute the distance to the plane, a dot product is needed - that is a multiplication and - // an addition on each number. - static const int distanceToleranceInULPs = toleranceInULPs + 1; - // The squared distance between two 3D vectors is computed the same way, but with an additional - // subtraction. - static const int distance3DToleranceInULPs = distanceToleranceInULPs + 1; - - // Convert the plane distance to its signed integer representation so the ULPs tolerance can be - // applied. For some reason, VC won't optimize two calls of the bit pattern conversion. - const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs; - const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs; - - // clear the array in this strange fashion because a simple clear() would also deallocate - // the array which we want to avoid - poResults.erase( poResults.begin(), poResults.end()); - - // do a binary search for the minimal distance to start the iteration there - unsigned int index = (unsigned int)mPositions.size() / 2; - unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4; - while( binaryStepSize > 1) - { - // Ugly, but conditional jumps are faster with integers than with floats - if( minDistBinary > ToBinary(mPositions[index].mDistance)) - index += binaryStepSize; - else - index -= binaryStepSize; - - binaryStepSize /= 2; - } - - // depending on the direction of the last step we need to single step a bit back or forth - // to find the actual beginning element of the range - while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) ) - index--; - while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance)) - index++; - - // Now start iterating from there until the first position lays outside of the distance range. - // Add all positions inside the distance range within the tolerance to the result aray - std::vector<Entry>::const_iterator it = mPositions.begin() + index; - while( ToBinary(it->mDistance) < maxDistBinary) - { - if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength())) - poResults.push_back(it->mIndex); - ++it; - if( it == mPositions.end()) - break; - } - - // that's it -} - -// ------------------------------------------------------------------------------------------------ -unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,float pRadius) const -{ - fill.resize(mPositions.size(),0xffffffff); - float dist, maxDist; - - unsigned int t=0; - const float pSquared = pRadius*pRadius; - for (size_t i = 0; i < mPositions.size();) { - dist = mPositions[i].mPosition * mPlaneNormal; - maxDist = dist + pRadius; - - fill[mPositions[i].mIndex] = t; - const aiVector3D& oldpos = mPositions[i].mPosition; - for (++i; i < fill.size() && mPositions[i].mDistance < maxDist - && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i) - { - fill[mPositions[i].mIndex] = t; - } - ++t; - } - -#ifdef _DEBUG - - // debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1 - for (size_t i = 0; i < fill.size(); ++i) { - ai_assert(fill[i]<mPositions.size()); - } - -#endif - return t; -} - diff --git a/3rdparty/assimp/code/SpatialSort.h b/3rdparty/assimp/code/SpatialSort.h deleted file mode 100644 index 3205c05f..00000000 --- a/3rdparty/assimp/code/SpatialSort.h +++ /dev/null @@ -1,170 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -/** Small helper classes to optimise finding vertizes close to a given location */ -#ifndef AI_SPATIALSORT_H_INC -#define AI_SPATIALSORT_H_INC - -#include <vector> -#include "../include/aiTypes.h" - -namespace Assimp -{ - -// ------------------------------------------------------------------------------------------------ -/** A little helper class to quickly find all vertices in the epsilon environment of a given - * position. Construct an instance with an array of positions. The class stores the given positions - * by their indices and sorts them by their distance to an arbitrary chosen plane. - * You can then query the instance for all vertices close to a given position in an average O(log n) - * time, with O(n) worst case complexity when all vertices lay on the plane. The plane is chosen - * so that it avoids common planes in usual data sets. */ -// ------------------------------------------------------------------------------------------------ -class ASSIMP_API SpatialSort -{ -public: - - SpatialSort(); - - // ------------------------------------------------------------------------------------ - /** Constructs a spatially sorted representation from the given position array. - * Supply the positions in its layout in memory, the class will only refer to them - * by index. - * @param pPositions Pointer to the first position vector of the array. - * @param pNumPositions Number of vectors to expect in that array. - * @param pElementOffset Offset in bytes from the beginning of one vector in memory - * to the beginning of the next vector. */ - SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions, - unsigned int pElementOffset); - - /** Destructor */ - ~SpatialSort(); - -public: - - // ------------------------------------------------------------------------------------ - /** Sets the input data for the SpatialSort. This replaces existing data, if any. - * The new data receives new indices in ascending order. - * - * @param pPositions Pointer to the first position vector of the array. - * @param pNumPositions Number of vectors to expect in that array. - * @param pElementOffset Offset in bytes from the beginning of one vector in memory - * to the beginning of the next vector. - * @param pFinalize Specifies whether the SpatialSort's internal representation - * is finalized after the new data has been added. Finalization is - * required in order to use #FindPosition() or #GenerateMappingTable(). - * If you don't finalize yet, you can use #Append() to add data from - * other sources.*/ - void Fill( const aiVector3D* pPositions, unsigned int pNumPositions, - unsigned int pElementOffset, - bool pFinalize = true); - - - // ------------------------------------------------------------------------------------ - /** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */ - void Append( const aiVector3D* pPositions, unsigned int pNumPositions, - unsigned int pElementOffset, - bool pFinalize = true); - - - // ------------------------------------------------------------------------------------ - /** Finalize the spatial hash data structure. This can be useful after - * multiple calls to #Append() with the pFinalize parameter set to false. - * This is finally required before one of #FindPositions() and #GenerateMappingTable() - * can be called to query the spatial sort.*/ - void Finalize(); - - // ------------------------------------------------------------------------------------ - /** Returns an iterator for all positions close to the given position. - * @param pPosition The position to look for vertices. - * @param pRadius Maximal distance from the position a vertex may have to be counted in. - * @param poResults The container to store the indices of the found positions. - * Will be emptied by the call so it may contain anything. - * @return An iterator to iterate over all vertices in the given area.*/ - void FindPositions( const aiVector3D& pPosition, float pRadius, - std::vector<unsigned int>& poResults) const; - - // ------------------------------------------------------------------------------------ - /** Fills an array with indices of all positions indentical to the given position. In - * opposite to FindPositions(), not an epsilon is used but a (very low) tolerance of - * four floating-point units. - * @param pPosition The position to look for vertices. - * @param poResults The container to store the indices of the found positions. - * Will be emptied by the call so it may contain anything.*/ - void FindIdenticalPositions( const aiVector3D& pPosition, - std::vector<unsigned int>& poResults) const; - - // ------------------------------------------------------------------------------------ - /** Compute a table that maps each vertex ID referring to a spatially close - * enough position to the same output ID. Output IDs are assigned in ascending order - * from 0...n. - * @param fill Will be filled with numPositions entries. - * @param pRadius Maximal distance from the position a vertex may have to - * be counted in. - * @return Number of unique vertices (n). */ - unsigned int GenerateMappingTable(std::vector<unsigned int>& fill, - float pRadius) const; - -protected: - /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */ - aiVector3D mPlaneNormal; - - /** An entry in a spatially sorted position array. Consists of a vertex index, - * its position and its precalculated distance from the reference plane */ - struct Entry - { - unsigned int mIndex; ///< The vertex referred by this entry - aiVector3D mPosition; ///< Position - float mDistance; ///< Distance of this vertex to the sorting plane - - Entry() { /** intentionally not initialized.*/ } - Entry( unsigned int pIndex, const aiVector3D& pPosition, float pDistance) - : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance) - { } - - bool operator < (const Entry& e) const { return mDistance < e.mDistance; } - }; - - // all positions, sorted by distance to the sorting plane - std::vector<Entry> mPositions; -}; - -} // end of namespace Assimp - -#endif // AI_SPATIALSORT_H_INC diff --git a/3rdparty/assimp/code/SplitLargeMeshes.cpp b/3rdparty/assimp/code/SplitLargeMeshes.cpp deleted file mode 100644 index f4950461..00000000 --- a/3rdparty/assimp/code/SplitLargeMeshes.cpp +++ /dev/null @@ -1,677 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 SplitLargeMeshes postprocessing step -*/ - -#include "AssimpPCH.h" - -// internal headers of the post-processing framework -#include "SplitLargeMeshes.h" -#include "ProcessHelper.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -SplitLargeMeshesProcess_Triangle::SplitLargeMeshesProcess_Triangle() -{ - LIMIT = AI_SLM_DEFAULT_MAX_TRIANGLES; -} - -// ------------------------------------------------------------------------------------------------ -SplitLargeMeshesProcess_Triangle::~SplitLargeMeshesProcess_Triangle() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool SplitLargeMeshesProcess_Triangle::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_SplitLargeMeshes) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void SplitLargeMeshesProcess_Triangle::Execute( aiScene* pScene) -{ - if (0xffffffff == this->LIMIT)return; - - DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle begin"); - std::vector<std::pair<aiMesh*, unsigned int> > avList; - - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - this->SplitMesh(a, pScene->mMeshes[a],avList); - - if (avList.size() != pScene->mNumMeshes) - { - // it seems something has been splitted. rebuild the mesh list - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)avList.size(); - pScene->mMeshes = new aiMesh*[avList.size()]; - - for (unsigned int i = 0; i < avList.size();++i) - pScene->mMeshes[i] = avList[i].first; - - // now we need to update all nodes - this->UpdateNode(pScene->mRootNode,avList); - DefaultLogger::get()->info("SplitLargeMeshesProcess_Triangle finished. Meshes have been splitted"); - } - else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Triangle finished. There was nothing to do"); - return; -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties -void SplitLargeMeshesProcess_Triangle::SetupProperties( const Importer* pImp) -{ - // get the current value of the split property - this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_TRIANGLE_LIMIT,AI_SLM_DEFAULT_MAX_TRIANGLES); -} - -// ------------------------------------------------------------------------------------------------ -// Update a node after some meshes have been split -void SplitLargeMeshesProcess_Triangle::UpdateNode(aiNode* pcNode, - const std::vector<std::pair<aiMesh*, unsigned int> >& avList) -{ - // for every index in out list build a new entry - std::vector<unsigned int> aiEntries; - aiEntries.reserve(pcNode->mNumMeshes + 1); - for (unsigned int i = 0; i < pcNode->mNumMeshes;++i) - { - for (unsigned int a = 0; a < avList.size();++a) - { - if (avList[a].second == pcNode->mMeshes[i]) - { - aiEntries.push_back(a); - } - } - } - - // now build the new list - delete pcNode->mMeshes; - pcNode->mNumMeshes = (unsigned int)aiEntries.size(); - pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes]; - - for (unsigned int b = 0; b < pcNode->mNumMeshes;++b) - pcNode->mMeshes[b] = aiEntries[b]; - - // recusively update all other nodes - for (unsigned int i = 0; i < pcNode->mNumChildren;++i) - { - UpdateNode ( pcNode->mChildren[i], avList ); - } - return; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void SplitLargeMeshesProcess_Triangle::SplitMesh( - unsigned int a, - aiMesh* pMesh, - std::vector<std::pair<aiMesh*, unsigned int> >& avList) -{ - if (pMesh->mNumFaces > SplitLargeMeshesProcess_Triangle::LIMIT) - { - DefaultLogger::get()->info("Mesh exceeds the triangle limit. It will be split ..."); - - // we need to split this mesh into sub meshes - // determine the size of a submesh - const unsigned int iSubMeshes = (pMesh->mNumFaces / LIMIT) + 1; - - const unsigned int iOutFaceNum = pMesh->mNumFaces / iSubMeshes; - const unsigned int iOutVertexNum = iOutFaceNum * 3; - - // now generate all submeshes - for (unsigned int i = 0; i < iSubMeshes;++i) - { - aiMesh* pcMesh = new aiMesh; - pcMesh->mNumFaces = iOutFaceNum; - pcMesh->mMaterialIndex = pMesh->mMaterialIndex; - - // the name carries the adjacency information between the meshes - pcMesh->mName = pMesh->mName; - - if (i == iSubMeshes-1) - { - pcMesh->mNumFaces = iOutFaceNum + ( - pMesh->mNumFaces - iOutFaceNum * iSubMeshes); - } - // copy the list of faces - pcMesh->mFaces = new aiFace[pcMesh->mNumFaces]; - - const unsigned int iBase = iOutFaceNum * i; - - // get the total number of indices - unsigned int iCnt = 0; - for (unsigned int p = iBase; p < pcMesh->mNumFaces + iBase;++p) - { - iCnt += pMesh->mFaces[p].mNumIndices; - } - pcMesh->mNumVertices = iCnt; - - // allocate storage - if (pMesh->mVertices != NULL) - pcMesh->mVertices = new aiVector3D[iCnt]; - - if (pMesh->HasNormals()) - pcMesh->mNormals = new aiVector3D[iCnt]; - - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents = new aiVector3D[iCnt]; - pcMesh->mBitangents = new aiVector3D[iCnt]; - } - - // texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - { - pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; - if (pMesh->HasTextureCoords( c)) - { - pcMesh->mTextureCoords[c] = new aiVector3D[iCnt]; - } - } - - // vertex colors - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) - { - if (pMesh->HasVertexColors( c)) - { - pcMesh->mColors[c] = new aiColor4D[iCnt]; - } - } - - if (pMesh->HasBones()) - { - // assume the number of bones won't change in most cases - pcMesh->mBones = new aiBone*[pMesh->mNumBones]; - - // iterate through all bones of the mesh and find those which - // need to be copied to the splitted mesh - std::vector<aiVertexWeight> avTempWeights; - for (unsigned int p = 0; p < pcMesh->mNumBones;++p) - { - aiBone* const bone = pcMesh->mBones[p]; - avTempWeights.clear(); - avTempWeights.reserve(bone->mNumWeights / iSubMeshes); - - for (unsigned int q = 0; q < bone->mNumWeights;++q) - { - aiVertexWeight& weight = bone->mWeights[q]; - if (weight.mVertexId >= iBase && weight.mVertexId < iBase + iOutVertexNum) - { - avTempWeights.push_back(weight); - weight = avTempWeights.back(); - weight.mVertexId -= iBase; - } - } - - if (!avTempWeights.empty()) - { - // we'll need this bone. Copy it ... - aiBone* pc = new aiBone(); - pcMesh->mBones[pcMesh->mNumBones++] = pc; - pc->mName = aiString(bone->mName); - pc->mNumWeights = (unsigned int)avTempWeights.size(); - pc->mOffsetMatrix = bone->mOffsetMatrix; - - // no need to reallocate the array for the last submesh. - // Here we can reuse the (large) source array, although - // we'll waste some memory - if (iSubMeshes-1 == i) - { - pc->mWeights = bone->mWeights; - bone->mWeights = NULL; - } - else pc->mWeights = new aiVertexWeight[pc->mNumWeights]; - - // copy the weights - ::memcpy(pc->mWeights,&avTempWeights[0],sizeof(aiVertexWeight)*pc->mNumWeights); - } - } - } - - // (we will also need to copy the array of indices) - unsigned int iCurrent = 0; - for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) - { - pcMesh->mFaces[p].mNumIndices = 3; - // allocate a new array - const unsigned int iTemp = p + iBase; - const unsigned int iNumIndices = pMesh->mFaces[iTemp].mNumIndices; - - // setup face type and number of indices - pcMesh->mFaces[p].mNumIndices = iNumIndices; - unsigned int* pi = pMesh->mFaces[iTemp].mIndices; - unsigned int* piOut = pcMesh->mFaces[p].mIndices = new unsigned int[iNumIndices]; - - // need to update the output primitive types - switch (iNumIndices) - { - case 1: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - } - - // and copy the contents of the old array, offset by current base - for (unsigned int v = 0; v < iNumIndices;++v) - { - unsigned int iIndex = pi[v]; - unsigned int iIndexOut = iCurrent++; - piOut[v] = iIndexOut; - - // copy positions - if (pMesh->mVertices != NULL) - pcMesh->mVertices[iIndexOut] = pMesh->mVertices[iIndex]; - - // copy normals - if (pMesh->HasNormals()) - pcMesh->mNormals[iIndexOut] = pMesh->mNormals[iIndex]; - - // copy tangents/bitangents - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents[iIndexOut] = pMesh->mTangents[iIndex]; - pcMesh->mBitangents[iIndexOut] = pMesh->mBitangents[iIndex]; - } - - // texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - { - if (pMesh->HasTextureCoords( c)) - pcMesh->mTextureCoords[c][iIndexOut] = pMesh->mTextureCoords[c][iIndex]; - } - // vertex colors - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) - { - if (pMesh->HasVertexColors( c)) - pcMesh->mColors[c][iIndexOut] = pMesh->mColors[c][iIndex]; - } - } - } - - // add the newly created mesh to the list - avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); - } - - // now delete the old mesh data - delete pMesh; - } - else avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); - return; -} - -// ------------------------------------------------------------------------------------------------ -SplitLargeMeshesProcess_Vertex::SplitLargeMeshesProcess_Vertex() -{ - LIMIT = AI_SLM_DEFAULT_MAX_VERTICES; -} - -// ------------------------------------------------------------------------------------------------ -SplitLargeMeshesProcess_Vertex::~SplitLargeMeshesProcess_Vertex() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool SplitLargeMeshesProcess_Vertex::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_SplitLargeMeshes) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void SplitLargeMeshesProcess_Vertex::Execute( aiScene* pScene) -{ - std::vector<std::pair<aiMesh*, unsigned int> > avList; - - if (0xffffffff == this->LIMIT)return; - - DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex begin"); - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - this->SplitMesh(a, pScene->mMeshes[a],avList); - - if (avList.size() != pScene->mNumMeshes) - { - // it seems something has been splitted. rebuild the mesh list - delete[] pScene->mMeshes; - pScene->mNumMeshes = (unsigned int)avList.size(); - pScene->mMeshes = new aiMesh*[avList.size()]; - - for (unsigned int i = 0; i < avList.size();++i) - pScene->mMeshes[i] = avList[i].first; - - // now we need to update all nodes - SplitLargeMeshesProcess_Triangle::UpdateNode(pScene->mRootNode,avList); - DefaultLogger::get()->info("SplitLargeMeshesProcess_Vertex finished. Meshes have been splitted"); - } - else DefaultLogger::get()->debug("SplitLargeMeshesProcess_Vertex finished. There was nothing to do"); - return; -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties -void SplitLargeMeshesProcess_Vertex::SetupProperties( const Importer* pImp) -{ - this->LIMIT = pImp->GetPropertyInteger(AI_CONFIG_PP_SLM_VERTEX_LIMIT,AI_SLM_DEFAULT_MAX_VERTICES); -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void SplitLargeMeshesProcess_Vertex::SplitMesh( - unsigned int a, - aiMesh* pMesh, - std::vector<std::pair<aiMesh*, unsigned int> >& avList) -{ - if (pMesh->mNumVertices > SplitLargeMeshesProcess_Vertex::LIMIT) - { - typedef std::vector< std::pair<unsigned int,float> > VertexWeightTable; - - // build a per-vertex weight list if necessary - VertexWeightTable* avPerVertexWeights = ComputeVertexBoneWeightTable(pMesh); - - // we need to split this mesh into sub meshes - // determine the estimated size of a submesh - // (this could be too large. Max waste is a single digit percentage) - const unsigned int iSubMeshes = (pMesh->mNumVertices / SplitLargeMeshesProcess_Vertex::LIMIT) + 1; - //const unsigned int iOutVertexNum2 = pMesh->mNumVertices /iSubMeshes; - - // create a std::vector<unsigned int> to indicate which vertices - // have already been copied - std::vector<unsigned int> avWasCopied; - avWasCopied.resize(pMesh->mNumVertices,0xFFFFFFFF); - - // try to find a good estimate for the number of output faces - // per mesh. Add 12.5% as buffer - unsigned int iEstimatedSize = pMesh->mNumFaces / iSubMeshes; - iEstimatedSize += iEstimatedSize >> 3; - - // now generate all submeshes - unsigned int iBase = 0; - while (true) - { - const unsigned int iOutVertexNum = SplitLargeMeshesProcess_Vertex::LIMIT; - - aiMesh* pcMesh = new aiMesh; - pcMesh->mNumVertices = 0; - pcMesh->mMaterialIndex = pMesh->mMaterialIndex; - - // the name carries the adjacency information between the meshes - pcMesh->mName = pMesh->mName; - - typedef std::vector<aiVertexWeight> BoneWeightList; - if (pMesh->HasBones()) - { - pcMesh->mBones = new aiBone*[pMesh->mNumBones]; - ::memset(pcMesh->mBones,0,sizeof(void*)*pMesh->mNumBones); - } - - // clear the temporary helper array - if (iBase) - { - // we can't use memset here we unsigned int needn' be 32 bits - for (std::vector<unsigned int>::iterator - iter = avWasCopied.begin(),end = avWasCopied.end(); - iter != end;++iter) - { - (*iter) = 0xffffffff; - } - } - - // output vectors - std::vector<aiFace> vFaces; - - // reserve enough storage for most cases - if (pMesh->HasPositions()) - { - pcMesh->mVertices = new aiVector3D[iOutVertexNum]; - } - if (pMesh->HasNormals()) - { - pcMesh->mNormals = new aiVector3D[iOutVertexNum]; - } - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents = new aiVector3D[iOutVertexNum]; - pcMesh->mBitangents = new aiVector3D[iOutVertexNum]; - } - for (unsigned int c = 0; pMesh->HasVertexColors(c);++c) - { - pcMesh->mColors[c] = new aiColor4D[iOutVertexNum]; - } - for (unsigned int c = 0; pMesh->HasTextureCoords(c);++c) - { - pcMesh->mNumUVComponents[c] = pMesh->mNumUVComponents[c]; - pcMesh->mTextureCoords[c] = new aiVector3D[iOutVertexNum]; - } - vFaces.reserve(iEstimatedSize); - - // (we will also need to copy the array of indices) - while (iBase < pMesh->mNumFaces) - { - // allocate a new array - const unsigned int iNumIndices = pMesh->mFaces[iBase].mNumIndices; - - // doesn't catch degenerates but is quite fast - unsigned int iNeed = 0; - for (unsigned int v = 0; v < iNumIndices;++v) - { - unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; - - // check whether we do already have this vertex - if (0xFFFFFFFF == avWasCopied[iIndex]) - { - iNeed++; - } - } - if (pcMesh->mNumVertices + iNeed > iOutVertexNum) - { - // don't use this face - break; - } - - vFaces.push_back(aiFace()); - aiFace& rFace = vFaces.back(); - - // setup face type and number of indices - rFace.mNumIndices = iNumIndices; - rFace.mIndices = new unsigned int[iNumIndices]; - - // need to update the output primitive types - switch (rFace.mNumIndices) - { - case 1: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; - case 2: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; - case 3: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; - default: - pcMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; - } - - // and copy the contents of the old array, offset by current base - for (unsigned int v = 0; v < iNumIndices;++v) - { - unsigned int iIndex = pMesh->mFaces[iBase].mIndices[v]; - - // check whether we do already have this vertex - if (0xFFFFFFFF != avWasCopied[iIndex]) - { - rFace.mIndices[v] = avWasCopied[iIndex]; - continue; - } - - // copy positions - pcMesh->mVertices[pcMesh->mNumVertices] = (pMesh->mVertices[iIndex]); - - // copy normals - if (pMesh->HasNormals()) - { - pcMesh->mNormals[pcMesh->mNumVertices] = (pMesh->mNormals[iIndex]); - } - - // copy tangents/bitangents - if (pMesh->HasTangentsAndBitangents()) - { - pcMesh->mTangents[pcMesh->mNumVertices] = (pMesh->mTangents[iIndex]); - pcMesh->mBitangents[pcMesh->mNumVertices] = (pMesh->mBitangents[iIndex]); - } - - // texture coordinates - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) - { - if (pMesh->HasTextureCoords( c)) - { - pcMesh->mTextureCoords[c][pcMesh->mNumVertices] = pMesh->mTextureCoords[c][iIndex]; - } - } - // vertex colors - for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) - { - if (pMesh->HasVertexColors( c)) - { - pcMesh->mColors[c][pcMesh->mNumVertices] = pMesh->mColors[c][iIndex]; - } - } - // check whether we have bone weights assigned to this vertex - rFace.mIndices[v] = pcMesh->mNumVertices; - if (avPerVertexWeights) - { - VertexWeightTable& table = avPerVertexWeights[ pcMesh->mNumVertices ]; - if ( !table.empty() ) - { - for (VertexWeightTable::const_iterator - iter = table.begin(); - iter != table.end();++iter) - { - // allocate the bone weight array if necessary - BoneWeightList* pcWeightList = (BoneWeightList*)pcMesh->mBones[(*iter).first]; - if (!pcWeightList) - { - pcMesh->mBones[(*iter).first] = (aiBone*)(pcWeightList = new BoneWeightList()); - } - pcWeightList->push_back(aiVertexWeight(pcMesh->mNumVertices,(*iter).second)); - } - } - } - - avWasCopied[iIndex] = pcMesh->mNumVertices; - pcMesh->mNumVertices++; - } - iBase++; - if (pcMesh->mNumVertices == iOutVertexNum) - { - // break here. The face is only added if it was complete - break; - } - } - - // check which bones we'll need to create for this submesh - if (pMesh->HasBones()) - { - aiBone** ppCurrent = pcMesh->mBones; - for (unsigned int k = 0; k < pMesh->mNumBones;++k) - { - // check whether the bone is existing - BoneWeightList* pcWeightList; - if ((pcWeightList = (BoneWeightList*)pcMesh->mBones[k])) - { - aiBone* pcOldBone = pMesh->mBones[k]; - aiBone* pcOut; - *ppCurrent++ = pcOut = new aiBone(); - pcOut->mName = aiString(pcOldBone->mName); - pcOut->mOffsetMatrix = pcOldBone->mOffsetMatrix; - pcOut->mNumWeights = (unsigned int)pcWeightList->size(); - pcOut->mWeights = new aiVertexWeight[pcOut->mNumWeights]; - - // copy the vertex weights - ::memcpy(pcOut->mWeights,&pcWeightList->operator[](0), - pcOut->mNumWeights * sizeof(aiVertexWeight)); - - // delete the temporary bone weight list - delete pcWeightList; - pcMesh->mNumBones++; - } - } - } - - // copy the face list to the mesh - pcMesh->mFaces = new aiFace[vFaces.size()]; - pcMesh->mNumFaces = (unsigned int)vFaces.size(); - - for (unsigned int p = 0; p < pcMesh->mNumFaces;++p) - pcMesh->mFaces[p] = vFaces[p]; - - // add the newly created mesh to the list - avList.push_back(std::pair<aiMesh*, unsigned int>(pcMesh,a)); - - if (iBase == pMesh->mNumFaces) - { - // have all faces ... finish the outer loop, too - break; - } - } - - // delete the per-vertex weight list again - delete[] avPerVertexWeights; - - // now delete the old mesh data - delete pMesh; - return; - } - avList.push_back(std::pair<aiMesh*, unsigned int>(pMesh,a)); - return; -} diff --git a/3rdparty/assimp/code/SplitLargeMeshes.h b/3rdparty/assimp/code/SplitLargeMeshes.h deleted file mode 100644 index e3c08ddb..00000000 --- a/3rdparty/assimp/code/SplitLargeMeshes.h +++ /dev/null @@ -1,216 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to split large meshes into submeshes - */ -#ifndef AI_SPLITLARGEMESHES_H_INC -#define AI_SPLITLARGEMESHES_H_INC - -#include <vector> -#include "BaseProcess.h" - -#include "../include/aiMesh.h" -#include "../include/aiScene.h" - -class SplitLargeMeshesTest; -namespace Assimp -{ - -class SplitLargeMeshesProcess_Triangle; -class SplitLargeMeshesProcess_Vertex; - -// NOTE: If you change these limits, don't forget to change the -// corresponding values in all Assimp ports - -// ********************************************************** -// Java: ConfigProperty.java, -// ConfigProperty.DEFAULT_VERTEX_SPLIT_LIMIT -// ConfigProperty.DEFAULT_TRIANGLE_SPLIT_LIMIT -// ********************************************************** - -// default limit for vertices -#if (!defined AI_SLM_DEFAULT_MAX_VERTICES) -# define AI_SLM_DEFAULT_MAX_VERTICES 1000000 -#endif - -// default limit for triangles -#if (!defined AI_SLM_DEFAULT_MAX_TRIANGLES) -# define AI_SLM_DEFAULT_MAX_TRIANGLES 1000000 -#endif - -// --------------------------------------------------------------------------- -/** Postprocessing filter to split large meshes into submeshes - * - * Applied BEFORE the JoinVertices-Step occurs. - * Returns NON-UNIQUE vertices, splits by triangle number. -*/ -class ASSIMP_API SplitLargeMeshesProcess_Triangle : public BaseProcess -{ - friend class Importer; - friend class SplitLargeMeshesProcess_Vertex; - friend class ::SplitLargeMeshesTest; - -protected: - /** Constructor to be privately used by Importer */ - SplitLargeMeshesProcess_Triangle(); - - /** Destructor, private as well */ - ~SplitLargeMeshesProcess_Triangle(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag. - * @param pFlags The processing flags the importer was called with. A - * bitwise combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, - * false if not. - */ - bool IsActive( unsigned int pFlags) const; - - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - virtual void SetupProperties(const Importer* pImp); - - - //! Set the split limit - needed for unit testing - inline void SetLimit(unsigned int l) - {LIMIT = l;} - - //! Get the split limit - inline unsigned int GetLimit() const - {return LIMIT;} - -protected: - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - //! Apply the algorithm to a given mesh - void SplitMesh (unsigned int a, aiMesh* pcMesh, - std::vector<std::pair<aiMesh*, unsigned int> >& avList); - - // ------------------------------------------------------------------- - //! Update a node in the asset after a few of its meshes - //! have been split - static void UpdateNode(aiNode* pcNode, - const std::vector<std::pair<aiMesh*, unsigned int> >& avList); - -public: - //! Triangle limit - unsigned int LIMIT; -}; - - -// --------------------------------------------------------------------------- -/** Postprocessing filter to split large meshes into submeshes - * - * Applied AFTER the JoinVertices-Step occurs. - * Returns UNIQUE vertices, splits by vertex number. -*/ -class ASSIMP_API SplitLargeMeshesProcess_Vertex : public BaseProcess -{ - friend class Importer; - friend class ::SplitLargeMeshesTest; - -protected: - /** Constructor to be privately used by Importer */ - SplitLargeMeshesProcess_Vertex(); - - /** Destructor, private as well */ - ~SplitLargeMeshesProcess_Vertex(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Called prior to ExecuteOnScene(). - * The function is a request to the process to update its configuration - * basing on the Importer's configuration property list. - */ - virtual void SetupProperties(const Importer* pImp); - - - //! Set the split limit - needed for unit testing - inline void SetLimit(unsigned int l) - {LIMIT = l;} - - //! Get the split limit - inline unsigned int GetLimit() const - {return LIMIT;} - -protected: - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - //! Apply the algorithm to a given mesh - void SplitMesh (unsigned int a, aiMesh* pcMesh, - std::vector<std::pair<aiMesh*, unsigned int> >& avList); - - // NOTE: Reuse SplitLargeMeshesProcess_Triangle::UpdateNode() - -public: - //! Triangle limit - unsigned int LIMIT; -}; - -} // end of namespace Assimp - -#endif // !!AI_SPLITLARGEMESHES_H_INC diff --git a/3rdparty/assimp/code/StandardShapes.cpp b/3rdparty/assimp/code/StandardShapes.cpp deleted file mode 100644 index e752918b..00000000 --- a/3rdparty/assimp/code/StandardShapes.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 StandardShapes.cpp - * @brief Implementation of the StandardShapes class - * - * The primitive geometry data comes from - * http://geometrictools.com/Documentation/PlatonicSolids.pdf. - */ - -#include "AssimpPCH.h" -#include "StandardShapes.h" - -namespace Assimp { - - -# define ADD_TRIANGLE(n0,n1,n2) \ - positions.push_back(n0); \ - positions.push_back(n1); \ - positions.push_back(n2); - -# define ADD_PENTAGON(n0,n1,n2,n3,n4) \ - if (polygons) \ - { \ - positions.push_back(n0); \ - positions.push_back(n1); \ - positions.push_back(n2); \ - positions.push_back(n3); \ - positions.push_back(n4); \ - } \ - else \ - { \ - ADD_TRIANGLE(n0, n1, n2) \ - ADD_TRIANGLE(n0, n2, n3) \ - ADD_TRIANGLE(n0, n3, n4) \ - } - -# define ADD_QUAD(n0,n1,n2,n3) \ - if (polygons) \ - { \ - positions.push_back(n0); \ - positions.push_back(n1); \ - positions.push_back(n2); \ - positions.push_back(n3); \ - } \ - else \ - { \ - ADD_TRIANGLE(n0, n1, n2) \ - ADD_TRIANGLE(n0, n2, n3) \ - } - - -// ------------------------------------------------------------------------------------------------ -// Fast subdivision for a mesh whose verts have a magnitude of 1 -void Subdivide(std::vector<aiVector3D>& positions) -{ - // assume this to be constant - (fixme: must be 1.0? I think so) - const float fl1 = positions[0].Length(); - - unsigned int origSize = (unsigned int)positions.size(); - for (unsigned int i = 0 ; i < origSize ; i+=3) - { - aiVector3D& tv0 = positions[i]; - aiVector3D& tv1 = positions[i+1]; - aiVector3D& tv2 = positions[i+2]; - - aiVector3D a = tv0, b = tv1, c = tv2; - aiVector3D v1 = aiVector3D(a.x+b.x, a.y+b.y, a.z+b.z).Normalize()*fl1; - aiVector3D v2 = aiVector3D(a.x+c.x, a.y+c.y, a.z+c.z).Normalize()*fl1; - aiVector3D v3 = aiVector3D(b.x+c.x, b.y+c.y, b.z+c.z).Normalize()*fl1; - - tv0 = v1; tv1 = v3; tv2 = v2; // overwrite the original - ADD_TRIANGLE(v1, v2, a); - ADD_TRIANGLE(v2, v3, c); - ADD_TRIANGLE(v3, v1, b); - } -} - -// ------------------------------------------------------------------------------------------------ -// Construct a mesh from given vertex positions -aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions, - unsigned int numIndices) -{ - if (positions.size() & numIndices || positions.empty() || !numIndices) - return NULL; - - // Determine which kinds of primitives the mesh consists of - aiMesh* out = new aiMesh(); - switch (numIndices) - { - case 1: - out->mPrimitiveTypes = aiPrimitiveType_POINT; - break; - case 2: - out->mPrimitiveTypes = aiPrimitiveType_LINE; - break; - case 3: - out->mPrimitiveTypes = aiPrimitiveType_TRIANGLE; - break; - default: - out->mPrimitiveTypes = aiPrimitiveType_POLYGON; - break; - }; - - out->mNumFaces = (unsigned int)positions.size() / numIndices; - out->mFaces = new aiFace[out->mNumFaces]; - for (unsigned int i = 0, a = 0; i < out->mNumFaces;++i) - { - aiFace& f = out->mFaces[i]; - f.mNumIndices = numIndices; - f.mIndices = new unsigned int[numIndices]; - for (unsigned int i = 0; i < numIndices;++i,++a) - f.mIndices[i] = a; - } - out->mNumVertices = (unsigned int)positions.size(); - out->mVertices = new aiVector3D[out->mNumVertices]; - ::memcpy(out->mVertices,&positions[0],out->mNumVertices*sizeof(aiVector3D)); - return out; -} - -// ------------------------------------------------------------------------------------------------ -// Construct a mesh with a specific shape (callback) -aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( - std::vector<aiVector3D>&)) -{ - std::vector<aiVector3D> temp; - unsigned num = (*GenerateFunc)(temp); - return MakeMesh(temp,num); -} - -// ------------------------------------------------------------------------------------------------ -// Construct a mesh with a specific shape (callback) -aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)( - std::vector<aiVector3D>&, bool)) -{ - std::vector<aiVector3D> temp; - unsigned num = (*GenerateFunc)(temp,true); - return MakeMesh(temp,num); -} - -// ------------------------------------------------------------------------------------------------ -// Construct a mesh with a specific shape (callback) -aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)( - unsigned int,std::vector<aiVector3D>&)) -{ - std::vector<aiVector3D> temp; - (*GenerateFunc)(num,temp); - return MakeMesh(temp,3); -} - -// ------------------------------------------------------------------------------------------------ -// Build an incosahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions) -{ - positions.reserve(positions.size()+60); - - const float t = (1.f + 2.236067977f)/2.f; - const float s = sqrt(1.f + t*t); - - const aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s; - const aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s; - const aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s; - const aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s; - const aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s; - const aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s; - const aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s; - const aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s; - const aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s; - const aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s; - const aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s; - const aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/s; - - ADD_TRIANGLE(v0,v8,v4); - ADD_TRIANGLE(v0,v5,v10); - ADD_TRIANGLE(v2,v4,v9); - ADD_TRIANGLE(v2,v11,v5); - - ADD_TRIANGLE(v1,v6,v8); - ADD_TRIANGLE(v1,v10,v7); - ADD_TRIANGLE(v3,v9,v6); - ADD_TRIANGLE(v3,v7,v11); - - ADD_TRIANGLE(v0,v10,v8); - ADD_TRIANGLE(v1,v8,v10); - ADD_TRIANGLE(v2,v9,v11); - ADD_TRIANGLE(v3,v11,v9); - - ADD_TRIANGLE(v4,v2,v0); - ADD_TRIANGLE(v5,v0,v2); - ADD_TRIANGLE(v6,v1,v3); - ADD_TRIANGLE(v7,v3,v1); - - ADD_TRIANGLE(v8,v6,v4); - ADD_TRIANGLE(v9,v4,v6); - ADD_TRIANGLE(v10,v5,v7); - ADD_TRIANGLE(v11,v7,v5); - return 3; -} - -// ------------------------------------------------------------------------------------------------ -// Build a dodecahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions, - bool polygons /*= false*/) -{ - positions.reserve(positions.size()+108); - - const float a = 1.f / 1.7320508f; - const float b = sqrt((3.f-2.23606797f)/6.f); - const float c = sqrt((3.f+2.23606797f)/6.f); - - const aiVector3D v0 = aiVector3D(a,a,a); - const aiVector3D v1 = aiVector3D(a,a,-a); - const aiVector3D v2 = aiVector3D(a,-a,a); - const aiVector3D v3 = aiVector3D(a,-a,-a); - const aiVector3D v4 = aiVector3D(-a,a,a); - const aiVector3D v5 = aiVector3D(-a,a,-a); - const aiVector3D v6 = aiVector3D(-a,-a,a); - const aiVector3D v7 = aiVector3D(-a,-a,-a); - const aiVector3D v8 = aiVector3D(b,c,0.f); - const aiVector3D v9 = aiVector3D(-b,c,0.f); - const aiVector3D v10 = aiVector3D(b,-c,0.f); - const aiVector3D v11 = aiVector3D(-b,-c,0.f); - const aiVector3D v12 = aiVector3D(c, 0.f, b); - const aiVector3D v13 = aiVector3D(c, 0.f, -b); - const aiVector3D v14 = aiVector3D(-c, 0.f, b); - const aiVector3D v15 = aiVector3D(-c, 0.f, -b); - const aiVector3D v16 = aiVector3D(0.f, b, c); - const aiVector3D v17 = aiVector3D(0.f, -b, c); - const aiVector3D v18 = aiVector3D(0.f, b, -c); - const aiVector3D v19 = aiVector3D(0.f, -b, -c); - - ADD_PENTAGON(v0, v8, v9, v4, v16); - ADD_PENTAGON(v0, v12, v13, v1, v8); - ADD_PENTAGON(v0, v16, v17, v2, v12); - ADD_PENTAGON(v8, v1, v18, v5, v9); - ADD_PENTAGON(v12, v2, v10, v3, v13); - ADD_PENTAGON(v16, v4, v14, v6, v17); - ADD_PENTAGON(v9, v5, v15, v14, v4); - - ADD_PENTAGON(v6, v11, v10, v2, v17); - ADD_PENTAGON(v3, v19, v18, v1, v13); - ADD_PENTAGON(v7, v15, v5, v18, v19); - ADD_PENTAGON(v7, v11, v6, v14, v15); - ADD_PENTAGON(v7, v19, v3, v10, v11); - return (polygons ? 5 : 3); -} - -// ------------------------------------------------------------------------------------------------ -// Build an octahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions) -{ - positions.reserve(positions.size()+24); - - const aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ; - const aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f); - const aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f); - const aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f); - const aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f); - const aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f); - - ADD_TRIANGLE(v4,v0,v2); - ADD_TRIANGLE(v4,v2,v1); - ADD_TRIANGLE(v4,v1,v3); - ADD_TRIANGLE(v4,v3,v0); - - ADD_TRIANGLE(v5,v2,v0); - ADD_TRIANGLE(v5,v1,v2); - ADD_TRIANGLE(v5,v3,v1); - ADD_TRIANGLE(v5,v0,v3); - return 3; -} - -// ------------------------------------------------------------------------------------------------ -// Build a tetrahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions) -{ - positions.reserve(positions.size()+9); - - const float a = 1.41421f/3.f; - const float b = 2.4494f/3.f; - - const aiVector3D v0 = aiVector3D(0.f,0.f,1.f); - const aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f); - const aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f); - const aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f); - - ADD_TRIANGLE(v0,v1,v2); - ADD_TRIANGLE(v0,v2,v3); - ADD_TRIANGLE(v0,v3,v1); - ADD_TRIANGLE(v1,v3,v2); - return 3; -} - -// ------------------------------------------------------------------------------------------------ -// Build a hexahedron with points.magnitude == 1 -unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions, - bool polygons /*= false*/) -{ - positions.reserve(positions.size()+36); - const float length = 1.f/1.73205080f; - - const aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length; - const aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length; - const aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length; - const aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length; - const aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length; - const aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length; - const aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length; - const aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*length; - - ADD_QUAD(v0,v3,v2,v1); - ADD_QUAD(v0,v1,v5,v4); - ADD_QUAD(v0,v4,v7,v3); - ADD_QUAD(v6,v5,v1,v2); - ADD_QUAD(v6,v2,v3,v7); - ADD_QUAD(v6,v7,v4,v5); - return (polygons ? 4 : 3); -} - -// Cleanup ... -#undef ADD_TRIANGLE -#undef ADD_QUAD -#undef ADD_PENTAGON - -// ------------------------------------------------------------------------------------------------ -// Create a subdivision sphere -void StandardShapes::MakeSphere(unsigned int tess, - std::vector<aiVector3D>& positions) -{ - // Reserve enough storage. Every subdivision - // splits each triangle in 4, the icosahedron consists of 60 verts - positions.reserve(positions.size()+60 * integer_pow(4, tess)); - - // Construct an icosahedron to start with - MakeIcosahedron(positions); - - // ... and subdivide it until the requested output - // tesselation is reached - for (unsigned int i = 0; i<tess;++i) - Subdivide(positions); -} - -// ------------------------------------------------------------------------------------------------ -// Build a cone -void StandardShapes::MakeCone(float height,float radius1, - float radius2,unsigned int tess, - std::vector<aiVector3D>& positions,bool bOpen /*= false */) -{ - // Sorry, a cone with less than 3 segments makes ABSOLUTELY NO SENSE - if (tess < 3 || !height) - return; - - size_t old = positions.size(); - - // No negative radii - radius1 = ::fabs(radius1); - radius2 = ::fabs(radius2); - - float halfHeight = height / 2; - - // radius1 is always the smaller one - if (radius2 > radius1) - { - std::swap(radius2,radius1); - halfHeight = -halfHeight; - } - else old = 0xffffffff; - - // Use a large epsilon to check whether the cone is pointy - if (radius1 < (radius2-radius1)*10e-3f)radius1 = 0.f; - - // We will need 3*2 verts per segment + 3*2 verts per segment - // if the cone is closed - const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0); - positions.reserve(positions.size () + mem); - - // Now construct all segments - const float angle_delta = (float)AI_MATH_TWO_PI / tess; - const float angle_max = (float)AI_MATH_TWO_PI; - - float s = 1.f; // cos(angle == 0); - float t = 0.f; // sin(angle == 0); - - for (float angle = 0.f; angle < angle_max; ) - { - const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 ); - const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 ); - - const float next = angle + angle_delta; - float s2 = ::cos(next); - float t2 = ::sin(next); - - const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 ); - const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 ); - - positions.push_back(v1); - positions.push_back(v2); - positions.push_back(v3); - positions.push_back(v4); - positions.push_back(v1); - positions.push_back(v3); - - if (!bOpen) - { - // generate the end 'cap' - positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 )); - positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 )); - positions.push_back(aiVector3D(0.f, halfHeight, 0.f)); - - - if (radius1) - { - // generate the other end 'cap' - positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 )); - positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 )); - positions.push_back(aiVector3D(0.f, -halfHeight, 0.f)); - - } - } - s = s2; - t = t2; - angle = next; - } - - // Need to flip face order? - if (0xffffffff != old ) - { - for (size_t s = old; s < positions.size();s += 3) - std::swap(positions[s],positions[s+1]); - } -} - -// ------------------------------------------------------------------------------------------------ -// Build a circle -void StandardShapes::MakeCircle(float radius, unsigned int tess, - std::vector<aiVector3D>& positions) -{ - // Sorry, a circle with less than 3 segments makes ABSOLUTELY NO SENSE - if (tess < 3 || !radius) - return; - - radius = ::fabs(radius); - - // We will need 3 vertices per segment - positions.reserve(positions.size()+tess*3); - - const float angle_delta = (float)AI_MATH_TWO_PI / tess; - const float angle_max = (float)AI_MATH_TWO_PI; - - float s = 1.f; // cos(angle == 0); - float t = 0.f; // sin(angle == 0); - - for (float angle = 0.f; angle < angle_max; ) - { - positions.push_back(aiVector3D(s * radius,0.f,t * radius)); - angle += angle_delta; - s = ::cos(angle); - t = ::sin(angle); - positions.push_back(aiVector3D(s * radius,0.f,t * radius)); - - positions.push_back(aiVector3D(0.f,0.f,0.f)); - } -} - -} // ! Assimp diff --git a/3rdparty/assimp/code/StandardShapes.h b/3rdparty/assimp/code/StandardShapes.h deleted file mode 100644 index ae59eb9d..00000000 --- a/3rdparty/assimp/code/StandardShapes.h +++ /dev/null @@ -1,196 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Declares a helper class, "StandardShapes" which generates - * vertices for standard shapes, such as cylnders, cones, spheres .. - */ -#ifndef AI_STANDARD_SHAPES_H_INC -#define AI_STANDARD_SHAPES_H_INC - -#include <vector> - - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** \brief Helper class to generate vertex buffers for standard geometric - * shapes, such as cylinders, cones, boxes, spheres, elipsoids ... . - */ -class ASSIMP_API StandardShapes -{ - // class cannot be instanced - StandardShapes() {} - -public: - - - // ---------------------------------------------------------------- - /** Generates a mesh from an array of vertex positions. - * - * @param positions List of vertex positions - * @param numIndices Number of indices per primitive - * @return Output mesh - */ - static aiMesh* MakeMesh(const std::vector<aiVector3D>& positions, - unsigned int numIndices); - - - static aiMesh* MakeMesh ( unsigned int (*GenerateFunc) - (std::vector<aiVector3D>&)); - - static aiMesh* MakeMesh ( unsigned int (*GenerateFunc) - (std::vector<aiVector3D>&, bool)); - - static aiMesh* MakeMesh ( unsigned int n, void (*GenerateFunc) - (unsigned int,std::vector<aiVector3D>&)); - - // ---------------------------------------------------------------- - /** @brief Generates a hexahedron (cube) - * - * Hexahedrons can be scaled on all axes. - * @param positions Receives output triangles. - * @param polygons If you pass true here quads will be returned - * @return Number of vertices per face - */ - static unsigned int MakeHexahedron( - std::vector<aiVector3D>& positions, - bool polygons = false); - - // ---------------------------------------------------------------- - /** @brief Generates an icosahedron - * - * @param positions Receives output triangles. - * @return Number of vertices per face - */ - static unsigned int MakeIcosahedron( - std::vector<aiVector3D>& positions); - - - // ---------------------------------------------------------------- - /** @brief Generates a dodecahedron - * - * @param positions Receives output triangles - * @param polygons If you pass true here pentagons will be returned - * @return Number of vertices per face - */ - static unsigned int MakeDodecahedron( - std::vector<aiVector3D>& positions, - bool polygons = false); - - - // ---------------------------------------------------------------- - /** @brief Generates an octahedron - * - * @param positions Receives output triangles. - * @return Number of vertices per face - */ - static unsigned int MakeOctahedron( - std::vector<aiVector3D>& positions); - - - // ---------------------------------------------------------------- - /** @brief Generates a tetrahedron - * - * @param positions Receives output triangles. - * @return Number of vertices per face - */ - static unsigned int MakeTetrahedron( - std::vector<aiVector3D>& positions); - - - - // ---------------------------------------------------------------- - /** @brief Generates a sphere - * - * @param tess Number of subdivions - 0 generates a octahedron - * @param positions Receives output triangles. - */ - static void MakeSphere(unsigned int tess, - std::vector<aiVector3D>& positions); - - - // ---------------------------------------------------------------- - /** @brief Generates a cone or a cylinder, either open or closed. - * - * @code - * - * |-----| <- radius 1 - * - * __x__ <- ] ^ - * / \ | height | - * / \ | Y - * / \ | - * / \ | - * /______x______\ <- ] <- end cap - * - * |-------------| <- radius 2 - * - * @endcode - * - * @param height Height of the cone - * @param radius1 First radius - * @param radius2 Second radius - * @param tess Number of triangles. - * @param bOpened true for an open cone/cylinder. An open shape has - * no 'end caps' - * @param positions Receives output triangles - */ - static void MakeCone(float height,float radius1, - float radius2,unsigned int tess, - std::vector<aiVector3D>& positions,bool bOpen= false); - - - // ---------------------------------------------------------------- - /** @brief Generates a flat circle - * - * The circle is constructed in the planed formed by the x,z - * axes of the cartesian coordinate system. - * - * @param radius Radius of the circle - * @param tess Number of segments. - * @param positions Receives output triangles. - */ - static void MakeCircle(float radius, unsigned int tess, - std::vector<aiVector3D>& positions); - -}; -} // ! Assimp - -#endif // !! AI_STANDARD_SHAPES_H_INC diff --git a/3rdparty/assimp/code/StdOStreamLogStream.h b/3rdparty/assimp/code/StdOStreamLogStream.h deleted file mode 100644 index 653dbf42..00000000 --- a/3rdparty/assimp/code/StdOStreamLogStream.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef AI_STROSTREAMLOGSTREAM_H_INC -#define AI_STROSTREAMLOGSTREAM_H_INC - -#include "../include/LogStream.h" -#include <ostream> - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** @class StdOStreamLogStream - * @brief Logs into a std::ostream - */ -class StdOStreamLogStream : public LogStream -{ -public: - /** @brief Construction from an existing std::ostream - * @param _ostream Output stream to be used - */ - StdOStreamLogStream(std::ostream& _ostream); - - /** @brief Destructor */ - ~StdOStreamLogStream(); - - /** @brief Writer */ - void write(const char* message); -private: - std::ostream& ostream; -}; - -// --------------------------------------------------------------------------- -// Default constructor -inline StdOStreamLogStream::StdOStreamLogStream(std::ostream& _ostream) - : ostream (_ostream) -{} - -// --------------------------------------------------------------------------- -// Default constructor -inline StdOStreamLogStream::~StdOStreamLogStream() -{} - -// --------------------------------------------------------------------------- -// Write method -inline void StdOStreamLogStream::write(const char* message) -{ - ostream << message; - ostream.flush(); -} - -// --------------------------------------------------------------------------- -} // Namespace Assimp - -#endif // guard diff --git a/3rdparty/assimp/code/StreamReader.h b/3rdparty/assimp/code/StreamReader.h deleted file mode 100644 index 2f42d5e9..00000000 --- a/3rdparty/assimp/code/StreamReader.h +++ /dev/null @@ -1,384 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the StreamReader class which reads data from - * a binary stream with a well-defined endianess. */ - -#ifndef AI_STREAMREADER_H_INCLUDED -#define AI_STREAMREADER_H_INCLUDED - -#include "ByteSwap.h" -namespace Assimp { - namespace Intern { - -// -------------------------------------------------------------------------------------------- -template <typename T, bool doit> -struct ByteSwapper { - void operator() (T* inout) { - ByteSwap::Swap(inout); - } -}; - -template <typename T> -struct ByteSwapper<T,false> { - void operator() (T*) { - } -}; - -// -------------------------------------------------------------------------------------------- -template <bool SwapEndianess, typename T, bool RuntimeSwitch> -struct Getter { - void operator() (T* inout, bool le) { -#ifdef AI_BUILD_BIG_ENDIAN - le = le; -#else - le = !le; -#endif - if (le) { - ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout); - } - else ByteSwapper<T,false> () (inout); - } -}; - -template <bool SwapEndianess, typename T> -struct Getter<SwapEndianess,T,false> { - void operator() (T* inout, bool le) { - - // static branch - ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout); - } -}; -} // end Intern - -// -------------------------------------------------------------------------------------------- -/** Wrapper class around IOStream to allow for consistent reading of binary data in both - * little and big endian format. Don't attempt to instance the template directly. Use - * StreamReaderLE to read from a little-endian stream and StreamReaderBE to read from a - * BE stream. The class expects that the endianess of any input data is known at - * compile-time, which should usually be true (#BaseImporter::ConvertToUTF8 implements - * runtime endianess conversions for text files). - * - * XXX switch from unsigned int for size types to size_t? or ptrdiff_t?*/ -// -------------------------------------------------------------------------------------------- -template <bool SwapEndianess = false, bool RuntimeSwitch = false> -class StreamReader -{ - -public: - - // FIXME: use these data types throughout the whole library, - // then change them to 64 bit values :-) - - typedef int diff; - typedef unsigned int pos; - -public: - - - // --------------------------------------------------------------------- - /** Construction from a given stream with a well-defined endianess. - * - * The StreamReader holds a permanent strong reference to the - * stream, which is released upon destruction. - * @param stream Input stream. The stream is not restarted if - * its file pointer is not at 0. Instead, the stream reader - * reads from the current position to the end of the stream. - * @param le If @c RuntimeSwitch is true: specifies whether the - * stream is in little endian byte order. Otherwise the - * endianess information is contained in the @c SwapEndianess - * template parameter and this parameter is meaningless. */ - StreamReader(boost::shared_ptr<IOStream> stream, bool le = false) - : stream(stream) - , le(le) - { - _Begin(); - } - - // --------------------------------------------------------------------- - StreamReader(IOStream* stream, bool le = false) - : stream(boost::shared_ptr<IOStream>(stream)) - , le(le) - { - _Begin(); - } - - // --------------------------------------------------------------------- - ~StreamReader() { - delete[] buffer; - } - -public: - - // deprecated, use overloaded operator>> instead - - // --------------------------------------------------------------------- - /** Read a float from the stream */ - float GetF4() - { - return Get<float>(); - } - - // --------------------------------------------------------------------- - /** Read a double from the stream */ - double GetF8() { - return Get<double>(); - } - - // --------------------------------------------------------------------- - /** Read a signed 16 bit integer from the stream */ - int16_t GetI2() { - return Get<int16_t>(); - } - - // --------------------------------------------------------------------- - /** Read a signed 8 bit integer from the stream */ - int8_t GetI1() { - return Get<int8_t>(); - } - - // --------------------------------------------------------------------- - /** Read an signed 32 bit integer from the stream */ - int32_t GetI4() { - return Get<int32_t>(); - } - - // --------------------------------------------------------------------- - /** Read a signed 64 bit integer from the stream */ - int64_t GetI8() { - return Get<int64_t>(); - } - - // --------------------------------------------------------------------- - /** Read a unsigned 16 bit integer from the stream */ - uint16_t GetU2() { - return Get<uint16_t>(); - } - - // --------------------------------------------------------------------- - /** Read a unsigned 8 bit integer from the stream */ - uint8_t GetU1() { - return Get<uint8_t>(); - } - - // --------------------------------------------------------------------- - /** Read an unsigned 32 bit integer from the stream */ - uint32_t GetU4() { - return Get<uint32_t>(); - } - - // --------------------------------------------------------------------- - /** Read a unsigned 64 bit integer from the stream */ - uint64_t GetU8() { - return Get<uint64_t>(); - } - -public: - - // --------------------------------------------------------------------- - /** Get the remaining stream size (to the end of the srream) */ - unsigned int GetRemainingSize() const { - return (unsigned int)(end - current); - } - - - // --------------------------------------------------------------------- - /** Get the remaining stream size (to the current read limit). The - * return value is the remaining size of the stream if no custom - * read limit has been set. */ - unsigned int GetRemainingSizeToLimit() const { - return (unsigned int)(limit - current); - } - - - // --------------------------------------------------------------------- - /** Increase the file pointer (relative seeking) */ - void IncPtr(int plus) { - current += plus; - if (current > limit) { - throw DeadlyImportError("End of file or read limit was reached"); - } - } - - // --------------------------------------------------------------------- - /** Get the current file pointer */ - int8_t* GetPtr() const { - return current; - } - - - // --------------------------------------------------------------------- - /** Set current file pointer (Get it from #GetPtr). This is if you - * prefer to do pointer arithmetics on your own or want to copy - * large chunks of data at once. - * @param p The new pointer, which is validated against the size - * limit and buffer boundaries. */ - void SetPtr(int8_t* p) { - - current = p; - if (current > limit || current < buffer) { - throw DeadlyImportError("End of file or read limit was reached"); - } - } - - // --------------------------------------------------------------------- - /** Copy n bytes to an external buffer - * @param out Destination for copying - * @param bytes Number of bytes to copy */ - void CopyAndAdvance(void* out, size_t bytes) { - - int8_t* ur = GetPtr(); - SetPtr(ur+bytes); // fire exception if eof - - memcpy(out,ur,bytes); - } - - - // --------------------------------------------------------------------- - /** Get the current offset from the beginning of the file */ - int GetCurrentPos() const { - return (unsigned int)(current - buffer); - } - - void SetCurrentPos(size_t pos) { - SetPtr(buffer + pos); - } - - // --------------------------------------------------------------------- - /** Setup a temporary read limit - * - * @param limit Maximum number of bytes to be read from - * the beginning of the file. Passing 0xffffffff - * resets the limit to the original end of the stream. */ - void SetReadLimit(unsigned int _limit) { - - if (0xffffffff == _limit) { - limit = end; - return; - } - - limit = buffer + _limit; - if (limit > end) { - throw DeadlyImportError("StreamReader: Invalid read limit"); - } - } - - // --------------------------------------------------------------------- - /** Get the current read limit in bytes. Reading over this limit - * accidentially raises an exception. */ - int GetReadLimit() const { - return (unsigned int)(limit - buffer); - } - - // --------------------------------------------------------------------- - /** Skip to the read limit in bytes. Reading over this limit - * accidentially raises an exception. */ - void SkipToReadLimit() { - current = limit; - } - - // --------------------------------------------------------------------- - /** overload operator>> and allow chaining of >> ops. */ - template <typename T> - StreamReader& operator >> (T& f) { - f = Get<T>(); - return *this; - } - -private: - - // --------------------------------------------------------------------- - /** Generic read method. ByteSwap::Swap(T*) *must* be defined */ - template <typename T> - T Get() { - if (current + sizeof(T) > limit) { - throw DeadlyImportError("End of file or stream limit was reached"); - } - - T f = *((const T*)current); - Intern :: Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le); - - current += sizeof(T); - return f; - } - - // --------------------------------------------------------------------- - void _Begin() { - if (!stream) { - throw DeadlyImportError("StreamReader: Unable to open file"); - } - - const size_t s = stream->FileSize() - stream->Tell(); - if (!s) { - throw DeadlyImportError("StreamReader: File is empty or EOF is already reached"); - } - - current = buffer = new int8_t[s]; - stream->Read(current,s,1); - end = limit = &buffer[s]; - } - -private: - - - boost::shared_ptr<IOStream> stream; - int8_t *buffer, *current, *end, *limit; - bool le; -}; - - -// -------------------------------------------------------------------------------------------- -// `static` StreamReaders. Their byte order is fixed and they might be a little bit faster. -#ifdef AI_BUILD_BIG_ENDIAN - typedef StreamReader<true> StreamReaderLE; - typedef StreamReader<false> StreamReaderBE; -#else - typedef StreamReader<true> StreamReaderBE; - typedef StreamReader<false> StreamReaderLE; -#endif - -// `dynamic` StreamReader. The byte order of the input data is specified in the -// c'tor. This involves runtime branching and might be a little bit slower. -typedef StreamReader<true,true> StreamReaderAny; - -} // end namespace Assimp - -#endif // !! AI_STREAMREADER_H_INCLUDED diff --git a/3rdparty/assimp/code/StringComparison.h b/3rdparty/assimp/code/StringComparison.h deleted file mode 100644 index ed79874c..00000000 --- a/3rdparty/assimp/code/StringComparison.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Definition of platform independent string workers: - - ASSIMP_itoa10 - ASSIMP_stricmp - ASSIMP_strincmp - - These functions are not consistently available on all platforms, - or the provided implementations behave too differently. -*/ -#ifndef INCLUDED_AI_STRING_WORKERS_H -#define INCLUDED_AI_STRING_WORKERS_H - -namespace Assimp { - -// ------------------------------------------------------------------------------- -/** @brief itoa with a fixed base 10 - * 'itoa' is not consistently available on all platforms so it is quite useful - * to have a small replacement function here. No need to use a full sprintf() - * if we just want to print a number ... - * @param out Output buffer - * @param max Maximum number of characters to be written, including '\0'. - * This parameter may not be 0. - * @param number Number to be written - * @return Length of the output string, excluding the '\0' - */ -inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) -{ - ai_assert(NULL != out); - - // write the unary minus to indicate we have a negative number - unsigned int written = 1u; - if (number < 0 && written < max) { - *out++ = '-'; - ++written; - number = -number; - } - - // We begin with the largest number that is not zero. - int32_t cur = 1000000000; // 2147483648 - bool mustPrint = false; - while (written < max) { - - const unsigned int digit = number / cur; - if (mustPrint || digit > 0 || 1 == cur) { - // print all future zeroes from now - mustPrint = true; - - *out++ = '0'+digit; - - ++written; - number -= digit*cur; - if (1 == cur) { - break; - } - } - cur /= 10; - } - - // append a terminal zero - *out++ = '\0'; - return written-1; -} - -// ------------------------------------------------------------------------------- -/** @brief itoa with a fixed base 10 (Secure template overload) - * The compiler should choose this function if he or she is able to determine the - * size of the array automatically. - */ -template <size_t length> -inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) -{ - return ASSIMP_itoa10(out,length,number); -} - -// ------------------------------------------------------------------------------- -/** @brief Helper function to do platform independent string comparison. - * - * This is required since stricmp() is not consistently available on - * all platforms. Some platforms use the '_' prefix, others don't even - * have such a function. - * - * @param s1 First input string - * @param s2 Second input string - * @return 0 if the given strings are identical - */ -inline int ASSIMP_stricmp(const char *s1, const char *s2) -{ - ai_assert(NULL != s1 && NULL != s2); - -#if (defined _MSC_VER) - - return ::_stricmp(s1,s2); -#elif defined( __GNUC__ ) - - return ::strcasecmp(s1,s2); -#else - - register char c1, c2; - do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } - while ( c1 && (c1 == c2) ); - return c1 - c2; -#endif -} - -// ------------------------------------------------------------------------------- -/** @brief Case independent comparison of two std::strings - * - * @param a First string - * @param b Second string - * @return 0 if a == b - */ -inline int ASSIMP_stricmp(const std::string& a, const std::string& b) -{ - register int i = (int)b.length()-(int)a.length(); - return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str())); -} - -// ------------------------------------------------------------------------------- -/** @brief Helper function to do platform independent string comparison. - * - * This is required since strincmp() is not consistently available on - * all platforms. Some platforms use the '_' prefix, others don't even - * have such a function. - * - * @param s1 First input string - * @param s2 Second input string - * @param n Macimum number of characters to compare - * @return 0 if the given strings are identical - */ -inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) -{ - ai_assert(NULL != s1 && NULL != s2); - if (!n)return 0; - -#if (defined _MSC_VER) - - return ::_strnicmp(s1,s2,n); - -#elif defined( __GNUC__ ) - - return ::strncasecmp(s1,s2, n); - -#else - register char c1, c2; - unsigned int p = 0; - do - { - if (p++ >= n)return 0; - c1 = tolower(*s1++); - c2 = tolower(*s2++); - } - while ( c1 && (c1 == c2) ); - - return c1 - c2; -#endif -} - - -// ------------------------------------------------------------------------------- -/** @brief Evaluates an integer power - * - * todo: move somewhere where it fits better in than here - */ -inline unsigned int integer_pow (unsigned int base, unsigned int power) -{ - unsigned int res = 1; - for (unsigned int i = 0; i < power;++i) - res *= base; - - return res; -} -} // end of namespace - -#endif // ! AI_STRINGCOMPARISON_H_INC diff --git a/3rdparty/assimp/code/Subdivision.cpp b/3rdparty/assimp/code/Subdivision.cpp deleted file mode 100644 index 2ed204c6..00000000 --- a/3rdparty/assimp/code/Subdivision.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" - -#include "Subdivision.h" -#include "SceneCombiner.h" -#include "SpatialSort.h" -#include "ProcessHelper.h" -#include "Vertex.h" - -using namespace Assimp; -void mydummy() {} - -// ------------------------------------------------------------------------------------------------ -/** Subdivider stub class to implement the Catmull-Clarke subdivision algorithm. The - * implementation is basing on recursive refinement. Directly evaluating the result is also - * possibel and much quicker, but it depends on lengthy matrix lookup tables. */ -// ------------------------------------------------------------------------------------------------ -class CatmullClarkSubdivider : public Subdivider -{ - -public: - - void Subdivide (const aiMesh* mesh, aiMesh*& out, unsigned int num, bool discard_input); - void Subdivide (const aiMesh* const * smesh, size_t nmesh, - aiMesh** out, unsigned int num, bool discard_input); - - // --------------------------------------------------------------------------- - /** Intermediate description of an edge between two corners of a polygon*/ - // --------------------------------------------------------------------------- - struct Edge - { - Edge() - : ref(0) - {} - Vertex edge_point, midpoint; - unsigned int ref; - }; - - - - typedef std::vector<unsigned int> UIntVector; - typedef std::map<uint64_t,Edge> EdgeMap; - - // --------------------------------------------------------------------------- - // Hashing function to derive an index into an #EdgeMap from two given - // 'unsigned int' vertex coordinates (!!distinct coordinates - same - // vertex position == same index!!). - // NOTE - this leads to rare hash collisions if a) sizeof(unsigned int)>4 - // and (id[0]>2^32-1 or id[0]>2^32-1). - // MAKE_EDGE_HASH() uses temporaries, so INIT_EDGE_HASH() needs to be put - // at the head of every function which is about to use MAKE_EDGE_HASH(). - // Reason is that the hash is that hash construction needs to hold the - // invariant id0<id1 to identify an edge - else two hashes would refer - // to the same edge. - // --------------------------------------------------------------------------- -#define MAKE_EDGE_HASH(id0,id1) (eh_tmp0__=id0,eh_tmp1__=id1,\ - (eh_tmp0__<eh_tmp1__?std::swap(eh_tmp0__,eh_tmp1__):mydummy()),(uint64_t)eh_tmp0__^((uint64_t)eh_tmp1__<<32u)) - - -#define INIT_EDGE_HASH_TEMPORARIES()\ - unsigned int eh_tmp0__, eh_tmp1__; - -private: - - void InternSubdivide (const aiMesh* const * smesh, - size_t nmesh,aiMesh** out, unsigned int num); -}; - - -// ------------------------------------------------------------------------------------------------ -// Construct a subdivider of a specific type -Subdivider* Subdivider::Create (Algorithm algo) -{ - switch (algo) - { - case CATMULL_CLARKE: - return new CatmullClarkSubdivider(); - }; - - ai_assert(false); - return NULL; // shouldn't happen -} - -// ------------------------------------------------------------------------------------------------ -// Call the Catmull Clark subdivision algorithm for one mesh -void CatmullClarkSubdivider::Subdivide ( - const aiMesh* mesh, - aiMesh*& out, - unsigned int num, - bool discard_input - ) -{ - assert(mesh != out); - Subdivide(&mesh,1,&out,num,discard_input); -} - -// ------------------------------------------------------------------------------------------------ -// Call the Catmull Clark subdivision algorithm for multiple meshes -void CatmullClarkSubdivider::Subdivide ( - const aiMesh* const * smesh, - size_t nmesh, - aiMesh** out, - unsigned int num, - bool discard_input - ) -{ - ai_assert(NULL != smesh && NULL != out); - - // course, both regions may not overlap - assert(smesh<out || smesh+nmesh>out+nmesh); - if (!num) { - - // No subdivision at all. Need to copy all the meshes .. argh. - if (discard_input) { - for (size_t s = 0; s < nmesh; ++s) { - out[s] = const_cast<aiMesh*>( smesh[s] ); - const_cast<aiMesh*&>( smesh[s] ) = NULL; - } - } - else { - for (size_t s = 0; s < nmesh; ++s) { - SceneCombiner::Copy(out+s,smesh[s]); - } - } - return; - } - - std::vector<const aiMesh*> inmeshes; - std::vector<aiMesh*> outmeshes; - std::vector<unsigned int> maptbl; - - inmeshes.reserve(nmesh); - outmeshes.reserve(nmesh); - maptbl.reserve(nmesh); - - // Remove pure line and point meshes from the working set to reduce the - // number of edge cases the subdivider is forced to deal with. Line and - // point meshes are simply passed through. - for (size_t s = 0; s < nmesh; ++s) { - const aiMesh* i = smesh[s]; - // FIX - mPrimitiveTypes might not yet be initialized - if (i->mPrimitiveTypes && (i->mPrimitiveTypes & (aiPrimitiveType_LINE|aiPrimitiveType_POINT))==i->mPrimitiveTypes) { - DefaultLogger::get()->debug("Catmull-Clark Subdivider: Skipping pure line/point mesh"); - - if (discard_input) { - out[s] = const_cast<aiMesh*>( i ); - const_cast<aiMesh*&>( smesh[s] ) = NULL; - } - else { - SceneCombiner::Copy(out+s,i); - } - continue; - } - - outmeshes.push_back(NULL);inmeshes.push_back(i); - maptbl.push_back(s); - } - - // Do the actual subdivision on the preallocated storage. InternSubdivide - // *always* assumes that enough storage is available, it does not bother - // checking any ranges. - ai_assert(inmeshes.size()==outmeshes.size()&&inmeshes.size()==maptbl.size()); - if (inmeshes.empty()) { - DefaultLogger::get()->warn("Catmull-Clark Subdivider: Pure point/line scene, I can't do anything"); - return; - } - InternSubdivide(&inmeshes.front(),inmeshes.size(),&outmeshes.front(),num); - for (unsigned int i = 0; i < maptbl.size(); ++i) { - ai_assert(outmeshes[i]); - out[maptbl[i]] = outmeshes[i]; - } - - if (discard_input) { - for (size_t s = 0; s < nmesh; ++s) { - delete smesh[s]; - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Note - this is an implementation of the standard (recursive) Cm-Cl algorithm without further -// optimizations (except we're using some nice LUTs). A description of the algorithm can be found -// here: http://en.wikipedia.org/wiki/Catmull-Clark_subdivision_surface -// -// The code is mostly O(n), however parts are O(nlogn) which is therefore the algorithm's -// expected total runtime complexity. The implementation is able to work in-place on the same -// mesh arrays. Calling #InternSubdivide() directly is not encouraged. The code can operate -// in-place unless 'smesh' and 'out' are equal (no strange overlaps or reorderings). -// Previous data is replaced/deleted then. -// ------------------------------------------------------------------------------------------------ -void CatmullClarkSubdivider::InternSubdivide ( - const aiMesh* const * smesh, - size_t nmesh, - aiMesh** out, - unsigned int num - ) -{ - ai_assert(NULL != smesh && NULL != out); - INIT_EDGE_HASH_TEMPORARIES(); - - // no subdivision requested or end of recursive refinement - if (!num) { - return; - } - - UIntVector maptbl; - SpatialSort spatial; - - // --------------------------------------------------------------------- - // 0. Offset table to index all meshes continously , generate a spatially - // sorted representation of all vertices in all meshes. - // --------------------------------------------------------------------- - typedef std::pair<unsigned int,unsigned int> IntPair; - std::vector<IntPair> moffsets(nmesh); - unsigned int totfaces = 0, totvert = 0; - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* mesh = smesh[t]; - - spatial.Append(mesh->mVertices,mesh->mNumVertices,sizeof(aiVector3D),false); - moffsets[t] = IntPair(totfaces,totvert); - - totfaces += mesh->mNumFaces; - totvert += mesh->mNumVertices; - } - - spatial.Finalize(); - const unsigned int num_unique = spatial.GenerateMappingTable(maptbl,ComputePositionEpsilon(smesh,nmesh)); - - -#define FLATTEN_VERTEX_IDX(mesh_idx, vert_idx) (moffsets[mesh_idx].second+vert_idx) -#define FLATTEN_FACE_IDX(mesh_idx, face_idx) (moffsets[mesh_idx].first+face_idx) - - // --------------------------------------------------------------------- - // 1. Compute the centroid point for all faces - // --------------------------------------------------------------------- - std::vector<Vertex> centroids(totfaces); - unsigned int nfacesout = 0; - for (size_t t = 0, n = 0; t < nmesh; ++t) { - const aiMesh* mesh = smesh[t]; - for (unsigned int i = 0; i < mesh->mNumFaces;++i,++n) - { - const aiFace& face = mesh->mFaces[i]; - Vertex& c = centroids[n]; - - for (unsigned int a = 0; a < face.mNumIndices;++a) { - c += Vertex(mesh,face.mIndices[a]); - } - - c /= static_cast<float>(face.mNumIndices); - nfacesout += face.mNumIndices; - } - } - - EdgeMap edges; - - // --------------------------------------------------------------------- - // 2. Set each edge point to be the average of all neighbouring - // face points and original points. Every edge exists twice - // if there is a neighboring face. - // --------------------------------------------------------------------- - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* mesh = smesh[t]; - - for (unsigned int i = 0; i < mesh->mNumFaces;++i) { - const aiFace& face = mesh->mFaces[i]; - - for (unsigned int p =0; p< face.mNumIndices; ++p) { - const unsigned int id[] = { - face.mIndices[p], - face.mIndices[p==face.mNumIndices-1?0:p+1] - }; - const unsigned int mp[] = { - maptbl[FLATTEN_VERTEX_IDX(t,id[0])], - maptbl[FLATTEN_VERTEX_IDX(t,id[1])] - }; - - Edge& e = edges[MAKE_EDGE_HASH(mp[0],mp[1])]; - e.ref++; - if (e.ref<=2) { - if (e.ref==1) { // original points (end points) - add only once - e.edge_point = e.midpoint = Vertex(mesh,id[0])+Vertex(mesh,id[1]); - e.midpoint *= 0.5f; - } - e.edge_point += centroids[FLATTEN_FACE_IDX(t,i)]; - } - } - } - } - - // --------------------------------------------------------------------- - // 3. Normalize edge points - // --------------------------------------------------------------------- - {unsigned int bad_cnt = 0; - for (EdgeMap::iterator it = edges.begin(); it != edges.end(); ++it) { - if ((*it).second.ref < 2) { - ai_assert((*it).second.ref); - ++bad_cnt; - } - (*it).second.edge_point *= 1.f/((*it).second.ref+2.f); - } - - if (bad_cnt) { - // Report the number of bad edges. bad edges are referenced by less than two - // faces in the mesh. They occur at outer model boundaries in non-closed - // shapes. - char tmp[512]; - sprintf(tmp,"Catmull-Clark Subdivider: got %u bad edges touching only one face (totally %u edges). ", - bad_cnt,static_cast<unsigned int>(edges.size())); - - DefaultLogger::get()->debug(tmp); - }} - - // --------------------------------------------------------------------- - // 4. Compute a vertex-face adjacency table. We can't reuse the code - // from VertexTriangleAdjacency because we need the table for multiple - // meshes and out vertex indices need to be mapped to distinct values - // first. - // --------------------------------------------------------------------- - UIntVector faceadjac(nfacesout), cntadjfac(maptbl.size(),0), ofsadjvec(maptbl.size()+1,0); { - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* const minp = smesh[t]; - for (unsigned int i = 0; i < minp->mNumFaces; ++i) { - - const aiFace& f = minp->mFaces[i]; - for (unsigned int n = 0; n < f.mNumIndices; ++n) { - ++cntadjfac[maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]; - } - } - } - unsigned int cur = 0; - for (size_t i = 0; i < cntadjfac.size(); ++i) { - ofsadjvec[i+1] = cur; - cur += cntadjfac[i]; - } - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* const minp = smesh[t]; - for (unsigned int i = 0; i < minp->mNumFaces; ++i) { - - const aiFace& f = minp->mFaces[i]; - for (unsigned int n = 0; n < f.mNumIndices; ++n) { - faceadjac[ofsadjvec[1+maptbl[FLATTEN_VERTEX_IDX(t,f.mIndices[n])]]++] = FLATTEN_FACE_IDX(t,i); - } - } - } - - // check the other way round for consistency -#ifdef _DEBUG - - for (size_t t = 0; t < ofsadjvec.size()-1; ++t) { - for (unsigned int m = 0; m < cntadjfac[t]; ++m) { - const unsigned int fidx = faceadjac[ofsadjvec[t]+m]; - ai_assert(fidx < totfaces); - for (size_t n = 1; n < nmesh; ++n) { - - if (moffsets[n].first > fidx) { - const aiMesh* msh = smesh[--n]; - const aiFace& f = msh->mFaces[fidx-moffsets[n].first]; - - bool haveit = false; - for (unsigned int i = 0; i < f.mNumIndices; ++i) { - if (maptbl[FLATTEN_VERTEX_IDX(n,f.mIndices[i])]==(unsigned int)t) { - haveit = true; break; - } - } - ai_assert(haveit); - break; - } - } - } - } - -#endif - } - -#define GET_ADJACENT_FACES_AND_CNT(vidx,fstartout,numout) \ - fstartout = &faceadjac[ofsadjvec[vidx]], numout = cntadjfac[vidx] - - typedef std::pair<bool,Vertex> TouchedOVertex; - std::vector<TouchedOVertex > new_points(num_unique,TouchedOVertex(false,Vertex())); - // --------------------------------------------------------------------- - // 5. Spawn a quad from each face point to the corresponding edge points - // the original points being the fourth quad points. - // --------------------------------------------------------------------- - for (size_t t = 0; t < nmesh; ++t) { - const aiMesh* const minp = smesh[t]; - aiMesh* const mout = out[t] = new aiMesh(); - - for (unsigned int a = 0; a < minp->mNumFaces; ++a) { - mout->mNumFaces += minp->mFaces[a].mNumIndices; - } - - // We need random access to the old face buffer, so reuse is not possible. - mout->mFaces = new aiFace[mout->mNumFaces]; - - mout->mNumVertices = mout->mNumFaces*4; - mout->mVertices = new aiVector3D[mout->mNumVertices]; - - // quads only, keep material index - mout->mPrimitiveTypes = aiPrimitiveType_POLYGON; - mout->mMaterialIndex = minp->mMaterialIndex; - - if (minp->HasNormals()) { - mout->mNormals = new aiVector3D[mout->mNumVertices]; - } - - if (minp->HasTangentsAndBitangents()) { - mout->mTangents = new aiVector3D[mout->mNumVertices]; - mout->mBitangents = new aiVector3D[mout->mNumVertices]; - } - - for (unsigned int i = 0; minp->HasTextureCoords(i); ++i) { - mout->mTextureCoords[i] = new aiVector3D[mout->mNumVertices]; - mout->mNumUVComponents[i] = minp->mNumUVComponents[i]; - } - - for (unsigned int i = 0; minp->HasVertexColors(i); ++i) { - mout->mColors[i] = new aiColor4D[mout->mNumVertices]; - } - - mout->mNumVertices = mout->mNumFaces<<2u; - for (unsigned int i = 0, v = 0, n = 0; i < minp->mNumFaces;++i) { - - const aiFace& face = minp->mFaces[i]; - for (unsigned int a = 0; a < face.mNumIndices;++a) { - - // Get a clean new face. - aiFace& faceOut = mout->mFaces[n++]; - faceOut.mIndices = new unsigned int [faceOut.mNumIndices = 4]; - - // Spawn a new quadrilateral (ccw winding) for this original point between: - // a) face centroid - centroids[FLATTEN_FACE_IDX(t,i)].SortBack(mout,faceOut.mIndices[0]=v++); - - // b) adjacent edge on the left, seen from the centroid - const Edge& e0 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])], - maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a==face.mNumIndices-1?0:a+1]) - ])]; // fixme: replace with mod face.mNumIndices? - - // c) adjacent edge on the right, seen from the centroid - const Edge& e1 = edges[MAKE_EDGE_HASH(maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])], - maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[!a?face.mNumIndices-1:a-1]) - ])]; // fixme: replace with mod face.mNumIndices? - - e0.edge_point.SortBack(mout,faceOut.mIndices[3]=v++); - e1.edge_point.SortBack(mout,faceOut.mIndices[1]=v++); - - // d= original point P with distinct index i - // F := 0 - // R := 0 - // n := 0 - // for each face f containing i - // F := F+ centroid of f - // R := R+ midpoint of edge of f from i to i+1 - // n := n+1 - // - // (F+2R+(n-3)P)/n - const unsigned int org = maptbl[FLATTEN_VERTEX_IDX(t,face.mIndices[a])]; - TouchedOVertex& ov = new_points[org]; - - if (!ov.first) { - ov.first = true; - - const unsigned int* adj; unsigned int cnt; - GET_ADJACENT_FACES_AND_CNT(org,adj,cnt); - - if (cnt < 3) { - ov.second = Vertex(minp,face.mIndices[a]); - } - else { - - Vertex F,R; - for (unsigned int o = 0; o < cnt; ++o) { - ai_assert(adj[o] < totfaces); - F += centroids[adj[o]]; - - // adj[0] is a global face index - search the face in the mesh list - const aiMesh* mp = NULL; - size_t nidx; - - if (adj[o] < moffsets[0].first) { - mp = smesh[nidx=0]; - } - else { - for (nidx = 1; nidx<= nmesh; ++nidx) { - if (nidx == nmesh ||moffsets[nidx].first > adj[o]) { - mp = smesh[--nidx]; - break; - } - } - } - - ai_assert(adj[o]-moffsets[nidx].first < mp->mNumFaces); - const aiFace& f = mp->mFaces[adj[o]-moffsets[nidx].first]; -# ifdef _DEBUG - bool haveit = false; -# endif - - // find our original point in the face - for (unsigned int m = 0; m < f.mNumIndices; ++m) { - if (maptbl[FLATTEN_VERTEX_IDX(nidx,f.mIndices[m])] == org) { - - // add *both* edges. this way, we can be sure that we add - // *all* adjacent edges to R. In a closed shape, every - // edge is added twice - so we simply leave out the - // factor 2.f in the amove formula and get the right - // result. - - const Edge& c0 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX( - nidx,f.mIndices[!m?f.mNumIndices-1:m-1])])]; - // fixme: replace with mod face.mNumIndices? - - const Edge& c1 = edges[MAKE_EDGE_HASH(org,maptbl[FLATTEN_VERTEX_IDX( - nidx,f.mIndices[m==f.mNumIndices-1?0:m+1])])]; - // fixme: replace with mod face.mNumIndices? - R += c0.midpoint+c1.midpoint; - -# ifdef _DEBUG - haveit = true; -# endif - break; - } - } - - // this invariant *must* hold if the vertex-to-face adjacency table is valid - ai_assert(haveit); - } - - const float div = static_cast<float>(cnt), divsq = 1.f/(div*div); - ov.second = Vertex(minp,face.mIndices[a])*((div-3.f) / div) + R*divsq + F*divsq; - } - } - ov.second.SortBack(mout,faceOut.mIndices[2]=v++); - } - } - } - - // --------------------------------------------------------------------- - // 7. Apply the next subdivision step. - // --------------------------------------------------------------------- - if (num != 1) { - std::vector<aiMesh*> tmp(nmesh); - InternSubdivide (out,nmesh,&tmp.front(),num-1); - for (size_t i = 0; i < nmesh; ++i) { - delete out[i]; - out[i] = tmp[i]; - } - } -} diff --git a/3rdparty/assimp/code/Subdivision.h b/3rdparty/assimp/code/Subdivision.h deleted file mode 100644 index 31a7a258..00000000 --- a/3rdparty/assimp/code/Subdivision.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a helper class to evaluate subdivision surfaces.*/ -#ifndef AI_SUBDISIVION_H_INC -#define AI_SUBDISIVION_H_INC -namespace Assimp { - -// ------------------------------------------------------------------------------ -/** Helper class to evaluate subdivision surfaces. Different algorithms - * are provided for choice. */ -// ------------------------------------------------------------------------------ -class ASSIMP_API Subdivider -{ -public: - - /** Enumerates all supported subvidision algorithms */ - enum Algorithm { - CATMULL_CLARKE = 0x1 - }; - -public: - - virtual ~Subdivider() { - } - -public: - - // --------------------------------------------------------------- - /** Create a subdivider of a specific type - * - * @param algo Algorithm to be used for subdivision - * @return Subdivider instance. */ - static Subdivider* Create (Algorithm algo); - - // --------------------------------------------------------------- - /** Subdivide a mesh using the selected algorithm - * - * @param mesh First mesh to be subdivided. Must be in verbose - * format. - * @param out Receives the output mesh, allocated by me. - * @param num Number of subdivisions to perform. - * @param discard_input If true is passed, the input mesh is - * deleted after the subdivision is complete. This can - * improve performance because it allows the optimization - * to reuse the existing mesh for intermediate results. - * @pre out!=mesh*/ - virtual void Subdivide (const aiMesh* mesh, - aiMesh*& out, unsigned int num, - bool discard_input = false) = 0; - - // --------------------------------------------------------------- - /** Subdivide multiple meshes using the selected algorithm. This - * avoids erroneous smoothing on objects consisting of multiple - * per-material meshes. Usually, most 3d modellers smooth on a - * per-object base, regardless the materials assigned to the - * meshes. - * - * @param smesh Array of meshes to be subdivided. Must be in - * verbose format. - * @param nmesh Number of meshes in smesh. - * @param out Receives the output meshes. The array must be - * sufficiently large (at least @c nmesh elements) and may not - * overlap the input array. Output meshes map one-to-one to - * their corresponding input meshes. The meshes are allocated - * by the function. - * @param discard_input If true is passed, input meshes are - * deleted after the subdivision is complete. This can - * improve performance because it allows the optimization - * of reusing existing meshes for intermediate results. - * @param num Number of subdivisions to perform. - * @pre nmesh != 0, smesh and out may not overlap*/ - virtual void Subdivide ( - const aiMesh* const * smesh, - size_t nmesh, - aiMesh** out, - unsigned int num, - bool discard_input = false) = 0; - -private: -}; - -} // end namespace Assimp - - -#endif // !! AI_SUBDISIVION_H_INC - diff --git a/3rdparty/assimp/code/TargetAnimation.cpp b/3rdparty/assimp/code/TargetAnimation.cpp deleted file mode 100644 index 76fe5e3d..00000000 --- a/3rdparty/assimp/code/TargetAnimation.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#include "AssimpPCH.h" -#include "TargetAnimation.h" -#include <algorithm> - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -KeyIterator::KeyIterator(const std::vector<aiVectorKey>* _objPos, - const std::vector<aiVectorKey>* _targetObjPos, - const aiVector3D* defaultObjectPos /*= NULL*/, - const aiVector3D* defaultTargetPos /*= NULL*/) - - : reachedEnd (false) - , curTime (-1.) - , objPos (_objPos) - , targetObjPos (_targetObjPos) - , nextObjPos (0) - , nextTargetObjPos(0) -{ - // Generate default transformation tracks if necessary - if (!objPos || objPos->empty()) - { - defaultObjPos.resize(1); - defaultObjPos.front().mTime = 10e10; - - if (defaultObjectPos) - defaultObjPos.front().mValue = *defaultObjectPos; - - objPos = & defaultObjPos; - } - if (!targetObjPos || targetObjPos->empty()) - { - defaultTargetObjPos.resize(1); - defaultTargetObjPos.front().mTime = 10e10; - - if (defaultTargetPos) - defaultTargetObjPos.front().mValue = *defaultTargetPos; - - targetObjPos = & defaultTargetObjPos; - } -} - -// ------------------------------------------------------------------------------------------------ -template <class T> -inline T Interpolate(const T& one, const T& two, float val) -{ - return one + (two-one)*val; -} - -// ------------------------------------------------------------------------------------------------ -void KeyIterator::operator ++() -{ - // If we are already at the end of all keyframes, return - if (reachedEnd) { - return; - } - - // Now search in all arrays for the time value closest - // to our current position on the time line - double d0,d1; - - d0 = objPos->at ( std::min<unsigned int> ( nextObjPos, objPos->size()-1) ).mTime; - d1 = targetObjPos->at( std::min<unsigned int> ( nextTargetObjPos, targetObjPos->size()-1) ).mTime; - - // Easiest case - all are identical. In this - // case we don't need to interpolate so we can - // return earlier - if ( d0 == d1 ) - { - curTime = d0; - curPosition = objPos->at(nextObjPos).mValue; - curTargetPosition = targetObjPos->at(nextTargetObjPos).mValue; - - // increment counters - if (objPos->size() != nextObjPos-1) - ++nextObjPos; - - if (targetObjPos->size() != nextTargetObjPos-1) - ++nextTargetObjPos; - } - - // An object position key is closest to us - else if (d0 < d1) - { - curTime = d0; - - // interpolate the other - if (1 == targetObjPos->size() || !nextTargetObjPos) { - curTargetPosition = targetObjPos->at(0).mValue; - } - else - { - const aiVectorKey& last = targetObjPos->at(nextTargetObjPos); - const aiVectorKey& first = targetObjPos->at(nextTargetObjPos-1); - - curTargetPosition = Interpolate(first.mValue, last.mValue, (float) ( - (curTime-first.mTime) / (last.mTime-first.mTime) )); - } - - if (objPos->size() != nextObjPos-1) - ++nextObjPos; - } - // A target position key is closest to us - else - { - curTime = d1; - - // interpolate the other - if (1 == objPos->size() || !nextObjPos) { - curPosition = objPos->at(0).mValue; - } - else - { - const aiVectorKey& last = objPos->at(nextObjPos); - const aiVectorKey& first = objPos->at(nextObjPos-1); - - curPosition = Interpolate(first.mValue, last.mValue, (float) ( - (curTime-first.mTime) / (last.mTime-first.mTime))); - } - - if (targetObjPos->size() != nextTargetObjPos-1) - ++nextTargetObjPos; - } - - if (nextObjPos >= objPos->size()-1 && - nextTargetObjPos >= targetObjPos->size()-1) - { - // We reached the very last keyframe - reachedEnd = true; - } -} - -// ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::SetTargetAnimationChannel ( - const std::vector<aiVectorKey>* _targetPositions) -{ - ai_assert(NULL != _targetPositions); - targetPositions = _targetPositions; -} - -// ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::SetMainAnimationChannel ( - const std::vector<aiVectorKey>* _objectPositions) -{ - ai_assert(NULL != _objectPositions); - objectPositions = _objectPositions; -} - -// ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::SetFixedMainAnimationChannel( - const aiVector3D& fixed) -{ - objectPositions = NULL; // just to avoid confusion - fixedMain = fixed; -} - -// ------------------------------------------------------------------------------------------------ -void TargetAnimationHelper::Process(std::vector<aiVectorKey>* distanceTrack) -{ - ai_assert(NULL != targetPositions && NULL != distanceTrack); - - // TODO: in most cases we won't need the extra array - std::vector<aiVectorKey> real; - - std::vector<aiVectorKey>* fill = (distanceTrack == objectPositions ? &real : distanceTrack); - fill->reserve(std::max( objectPositions->size(), targetPositions->size() )); - - // Iterate through all object keys and interpolate their values if necessary. - // Then get the corresponding target position, compute the difference - // vector between object and target position. Then compute a rotation matrix - // that rotates the base vector of the object coordinate system at that time - // to match the diff vector. - - KeyIterator iter(objectPositions,targetPositions,&fixedMain); - for (;!iter.Finished();++iter) - { - const aiVector3D& position = iter.GetCurPosition(); - const aiVector3D& tposition = iter.GetCurTargetPosition(); - - // diff vector - aiVector3D diff = tposition - position; - float f = diff.Length(); - - // output distance vector - if (f) - { - fill->push_back(aiVectorKey()); - aiVectorKey& v = fill->back(); - v.mTime = iter.GetCurTime(); - v.mValue = diff; - - diff /= f; - } - else - { - // FIXME: handle this - } - - // diff is now the vector in which our camera is pointing - } - - if (real.size()) { - *distanceTrack = real; - } -} diff --git a/3rdparty/assimp/code/TargetAnimation.h b/3rdparty/assimp/code/TargetAnimation.h deleted file mode 100644 index 9c675302..00000000 --- a/3rdparty/assimp/code/TargetAnimation.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a helper class for the ASE and 3DS loaders to - help them compute camera and spot light animation channels */ -#ifndef AI_TARGET_ANIMATION_H_INC -#define AI_TARGET_ANIMATION_H_INC - - -namespace Assimp { - - - -// --------------------------------------------------------------------------- -/** Helper class to iterate through all keys in an animation channel. - * - * Missing tracks are interpolated. This is a helper class for - * TargetAnimationHelper, but it can be freely used for other purposes. -*/ -class ASSIMP_API KeyIterator -{ -public: - - - // ------------------------------------------------------------------ - /** Constructs a new key iterator - * - * @param _objPos Object position track. May be NULL. - * @param _targetObjPos Target object position track. May be NULL. - * @param defaultObjectPos Default object position to be used if - * no animated track is available. May be NULL. - * @param defaultTargetPos Default target position to be used if - * no animated track is available. May be NULL. - */ - KeyIterator(const std::vector<aiVectorKey>* _objPos, - const std::vector<aiVectorKey>* _targetObjPos, - const aiVector3D* defaultObjectPos = NULL, - const aiVector3D* defaultTargetPos = NULL); - - // ------------------------------------------------------------------ - /** Returns true if all keys have been processed - */ - bool Finished() const - {return reachedEnd;} - - // ------------------------------------------------------------------ - /** Increment the iterator - */ - void operator++(); - inline void operator++(int) - {return ++(*this);} - - - - // ------------------------------------------------------------------ - /** Getters to retrieve the current state of the iterator - */ - inline const aiVector3D& GetCurPosition() const - {return curPosition;} - - inline const aiVector3D& GetCurTargetPosition() const - {return curTargetPosition;} - - inline double GetCurTime() const - {return curTime;} - -private: - - //! Did we reach the end? - bool reachedEnd; - - //! Represents the current position of the iterator - aiVector3D curPosition, curTargetPosition; - - double curTime; - - //! Input tracks and the next key to process - const std::vector<aiVectorKey>* objPos,*targetObjPos; - - unsigned int nextObjPos, nextTargetObjPos; - std::vector<aiVectorKey> defaultObjPos,defaultTargetObjPos; -}; - -// --------------------------------------------------------------------------- -/** Helper class for the 3DS and ASE loaders to compute camera and spot light - * animations. - * - * 3DS and ASE store the differently to Assimp - there is an animation - * channel for the camera/spot light itself and a separate position - * animation channels specifying the position of the camera/spot light - * look-at target */ -class ASSIMP_API TargetAnimationHelper -{ -public: - - TargetAnimationHelper() - : targetPositions (NULL) - , objectPositions (NULL) - {} - - - // ------------------------------------------------------------------ - /** Sets the target animation channel - * - * This channel specifies the position of the camera/spot light - * target at a specific position. - * - * @param targetPositions Translation channel*/ - void SetTargetAnimationChannel (const - std::vector<aiVectorKey>* targetPositions); - - - // ------------------------------------------------------------------ - /** Sets the main animation channel - * - * @param objectPositions Translation channel */ - void SetMainAnimationChannel ( const - std::vector<aiVectorKey>* objectPositions); - - // ------------------------------------------------------------------ - /** Sets the main animation channel to a fixed value - * - * @param fixed Fixed value for the main animation channel*/ - void SetFixedMainAnimationChannel(const aiVector3D& fixed); - - - // ------------------------------------------------------------------ - /** Computes final animation channels - * @param distanceTrack Receive camera translation keys ... != NULL. */ - void Process( std::vector<aiVectorKey>* distanceTrack ); - - -private: - - const std::vector<aiVectorKey>* targetPositions,*objectPositions; - aiVector3D fixedMain; -}; - - -} // ! end namespace Assimp - -#endif // include guard diff --git a/3rdparty/assimp/code/TerragenLoader.cpp b/3rdparty/assimp/code/TerragenLoader.cpp deleted file mode 100644 index 3a19d17e..00000000 --- a/3rdparty/assimp/code/TerragenLoader.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Terragen importer class */ - -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER -#include "TerragenLoader.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -TerragenImporter::TerragenImporter() -: configComputeUVs (false) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -TerragenImporter::~TerragenImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool TerragenImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - // check file extension - std::string extension = GetExtension(pFile); - - if ( extension == "ter") - return true; - - if ( !extension.length() || checkSig) { - /* If CanRead() is called in order to check whether we - * support a specific file extension in general pIOHandler - * might be NULL and it's our duty to return true here. - */ - if (!pIOHandler)return true; - const char* tokens[] = {"terragen"}; - return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -// Build a string of all file extensions supported -void TerragenImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("ter"); -} - -// ------------------------------------------------------------------------------------------------ -// Setup import properties -void TerragenImporter::SetupProperties(const Importer* pImp) -{ - // AI_CONFIG_IMPORT_TER_MAKE_UVS - configComputeUVs = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS,0) ); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void TerragenImporter::InternReadFile( const std::string& pFile, - aiScene* pScene, IOSystem* pIOHandler) -{ - IOStream* file = pIOHandler->Open( pFile, "rb"); - - // Check whether we can read from the file - if ( file == NULL) - throw DeadlyImportError( "Failed to open TERRAGEN TERRAIN file " + pFile + "."); - - // Construct a stream reader to read all data in the correct endianess - StreamReaderLE reader(file); - if (reader.GetRemainingSize() < 16) - throw DeadlyImportError( "TER: file is too small" ); - - // Check for the existence of the two magic strings 'TERRAGEN' and 'TERRAIN ' - if (::strncmp((const char*)reader.GetPtr(),AI_TERR_BASE_STRING,8)) - throw DeadlyImportError( "TER: Magic string \'TERRAGEN\' not found" ); - - if (::strncmp((const char*)reader.GetPtr()+8,AI_TERR_TERRAIN_STRING,8)) - throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" ); - - unsigned int x = 0,y = 0,mode = 0; - float rad = 6370.f; - - - aiNode* root = pScene->mRootNode = new aiNode(); - root->mName.Set("<TERRAGEN.TERRAIN>"); - - // Default scaling is 30 - root->mTransformation.a1 = root->mTransformation.b2 = root->mTransformation.c3 = 30.f; - - // Now read all chunks until we're finished or an EOF marker is encountered - reader.IncPtr(16); - while (reader.GetRemainingSize() >= 4) - { - const char* head = (const char*)reader.GetPtr(); - reader.IncPtr(4); - - // EOF, break in every case - if (!::strncmp(head,AI_TERR_EOF_STRING,4)) - break; - - // Number of x-data points - if (!::strncmp(head,AI_TERR_CHUNK_XPTS,4)) - { - x = (uint16_t)reader.GetI2(); - } - // Number of y-data points - else if (!::strncmp(head,AI_TERR_CHUNK_YPTS,4)) - { - y = (uint16_t)reader.GetI2(); - } - // Squared terrains width-1. - else if (!::strncmp(head,AI_TERR_CHUNK_SIZE,4)) - { - x = y = (uint16_t)reader.GetI2()+1; - } - // terrain scaling - else if (!::strncmp(head,AI_TERR_CHUNK_SCAL,4)) - { - root->mTransformation.a1 = reader.GetF4(); - root->mTransformation.b2 = reader.GetF4(); - root->mTransformation.c3 = reader.GetF4(); - } - // mapping == 1: earth radius - else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4)) - { - rad = reader.GetF4(); - } - // mapping mode - else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4)) - { - mode = reader.GetI1(); - if (0 != mode) - DefaultLogger::get()->error("TER: Unsupported mapping mode, a flat terrain is returned"); - } - // actual terrain data - else if (!::strncmp(head,AI_TERR_CHUNK_ALTW,4)) - { - float hscale = (float)reader.GetI2() / 65536; - float bheight = (float)reader.GetI2(); - - if (!hscale)hscale = 1; - - // Ensure we have enough data - if (reader.GetRemainingSize() < x*y*2) - throw DeadlyImportError("TER: ALTW chunk is too small"); - - if (x <= 1 || y <= 1) - throw DeadlyImportError("TER: Invalid terrain size"); - - // Allocate the output mesh - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = 1]; - aiMesh* m = pScene->mMeshes[0] = new aiMesh(); - - // We return quads - aiFace* f = m->mFaces = new aiFace[m->mNumFaces = (x-1)*(y-1)]; - aiVector3D* pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces*4]; - - aiVector3D *uv( NULL ); - float step_y( 0.0f ), step_x( 0.0f ); - if (configComputeUVs) { - uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices]; - step_y = 1.f/y; - step_x = 1.f/x; - } - const int16_t* data = (const int16_t*)reader.GetPtr(); - - for (unsigned int yy = 0, t = 0; yy < y-1;++yy) { - for (unsigned int xx = 0; xx < x-1;++xx,++f) { - - // make verts - const float fy = (float)yy, fx = (float)xx; - register unsigned tmp,tmp2; - *pv++ = aiVector3D(fx,fy, (float)data[(tmp2=x*yy) + xx] * hscale + bheight); - *pv++ = aiVector3D(fx,fy+1, (float)data[(tmp=x*(yy+1)) + xx] * hscale + bheight); - *pv++ = aiVector3D(fx+1,fy+1,(float)data[tmp + xx+1] * hscale + bheight); - *pv++ = aiVector3D(fx+1,fy, (float)data[tmp2 + xx+1] * hscale + bheight); - - // also make texture coordinates, if necessary - if (configComputeUVs) { - *uv++ = aiVector3D( step_x*xx, step_y*yy, 0.f ); - *uv++ = aiVector3D( step_x*xx, step_y*(yy+1), 0.f ); - *uv++ = aiVector3D( step_x*(xx+1), step_y*(yy+1), 0.f ); - *uv++ = aiVector3D( step_x*(xx+1), step_y*yy, 0.f ); - } - - // make indices - f->mIndices = new unsigned int[f->mNumIndices = 4]; - for (unsigned int i = 0; i < 4;++i) - f->mIndices[i] = t++; - } - } - - // Add the mesh to the root node - root->mMeshes = new unsigned int[root->mNumMeshes = 1]; - root->mMeshes[0] = 0; - } - - // Get to the next chunk (4 byte aligned) - unsigned dtt; - if ((dtt = reader.GetCurrentPos() & 0x3)) - reader.IncPtr(4-dtt); - } - - // Check whether we have a mesh now - if (pScene->mNumMeshes != 1) - throw DeadlyImportError("TER: Unable to load terrain"); - - // Set the AI_SCENE_FLAGS_TERRAIN bit - pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN; -} - -#endif // !! ASSIMP_BUILD_NO_TERRAGEN_IMPORTER diff --git a/3rdparty/assimp/code/TerragenLoader.h b/3rdparty/assimp/code/TerragenLoader.h deleted file mode 100644 index 48e97d1a..00000000 --- a/3rdparty/assimp/code/TerragenLoader.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 TerragenLoader.h - * @brief Declaration of the .ter importer class. - */ -#ifndef INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H -#define INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H - -#include "BaseImporter.h" -namespace Assimp { - -// Magic strings -#define AI_TERR_BASE_STRING "TERRAGEN" -#define AI_TERR_TERRAIN_STRING "TERRAIN " -#define AI_TERR_EOF_STRING "EOF " - -// Chunka -#define AI_TERR_CHUNK_XPTS "XPTS" -#define AI_TERR_CHUNK_YPTS "YPTS" -#define AI_TERR_CHUNK_SIZE "SIZE" -#define AI_TERR_CHUNK_SCAL "SCAL" -#define AI_TERR_CHUNK_CRAD "CRAD" -#define AI_TERR_CHUNK_CRVM "CRVM" -#define AI_TERR_CHUNK_ALTW "ALTW" - -// --------------------------------------------------------------------------- -/** @brief Importer class to load Terragen (0.9) terrain files. - * - * The loader is basing on the information found here: - * http://www.planetside.co.uk/terragen/dev/tgterrain.html#chunks -*/ -class TerragenImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - TerragenImporter(); - - /** Destructor, private as well */ - ~TerragenImporter(); - -public: - - // ------------------------------------------------------------------- - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - -private: - - bool configComputeUVs; - -}; //! class TerragenImporter - -} // end of namespace Assimp - -#endif // AI_AC3DIMPORTER_H_INC diff --git a/3rdparty/assimp/code/TextureTransform.cpp b/3rdparty/assimp/code/TextureTransform.cpp deleted file mode 100644 index dd6b1bf9..00000000 --- a/3rdparty/assimp/code/TextureTransform.cpp +++ /dev/null @@ -1,563 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 A helper class that processes texture transformations */ - - -#include "AssimpPCH.h" -#include "TextureTransform.h" - -using namespace Assimp; - - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -TextureTransformStep::TextureTransformStep() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -TextureTransformStep::~TextureTransformStep() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool TextureTransformStep::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_TransformUVCoords) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Setup properties -void TextureTransformStep::SetupProperties(const Importer* pImp) -{ - configFlags = pImp->GetPropertyInteger(AI_CONFIG_PP_TUV_EVALUATE,AI_UVTRAFO_ALL); -} - -// ------------------------------------------------------------------------------------------------ -void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) -{ - /* This function tries to simplify the input UV transformation. - * That's very important as it allows us to reduce the number - * of output UV channels. The oder in which the transformations - * are applied is - as always - scaling, rotation, translation. - */ - - char szTemp[512]; - int rounded = 0; - - - /* Optimize the rotation angle. That's slightly difficult as - * we have an inprecise floating-point number (when comparing - * UV transformations we'll take that into account by using - * an epsilon of 5 degrees). If there is a rotation value, we can't - * perform any further optimizations. - */ - if (info.mRotation) - { - float out = info.mRotation; - if ((rounded = (int)(info.mRotation / (float)AI_MATH_TWO_PI))) - { - out -= rounded*(float)AI_MATH_PI; - - sprintf(szTemp,"Texture coordinate rotation %f can be simplified to %f",info.mRotation,out); - DefaultLogger::get()->info(szTemp); - } - - // Next step - convert negative rotation angles to positives - if (out < 0.f) - out = (float)AI_MATH_TWO_PI * 2 + out; - - info.mRotation = out; - return; - } - - - /* Optimize UV translation in the U direction. To determine whether - * or not we can optimize we need to look at the requested mapping - * type (e.g. if mirroring is active there IS a difference between - * offset 2 and 3) - */ - if ((rounded = (int)info.mTranslation.x)) { - float out; - szTemp[0] = 0; - if (aiTextureMapMode_Wrap == info.mapU) { - // Wrap - simple take the fraction of the field - out = info.mTranslation.x-(float)rounded; - sprintf(szTemp,"[w] UV U offset %f can be simplified to %f",info.mTranslation.x,out); - } - else if (aiTextureMapMode_Mirror == info.mapU && 1 != rounded) { - // Mirror - if (rounded % 2) - rounded--; - out = info.mTranslation.x-(float)rounded; - - sprintf(szTemp,"[m/d] UV U offset %f can be simplified to %f",info.mTranslation.x,out); - } - else if (aiTextureMapMode_Clamp == info.mapU || aiTextureMapMode_Decal == info.mapU) { - // Clamp - translations beyond 1,1 are senseless - sprintf(szTemp,"[c] UV U offset %f can be clamped to 1.0f",info.mTranslation.x); - - out = 1.f; - } - if (szTemp[0]) { - DefaultLogger::get()->info(szTemp); - info.mTranslation.x = out; - } - } - - /* Optimize UV translation in the V direction. To determine whether - * or not we can optimize we need to look at the requested mapping - * type (e.g. if mirroring is active there IS a difference between - * offset 2 and 3) - */ - if ((rounded = (int)info.mTranslation.y)) { - float out; - szTemp[0] = 0; - if (aiTextureMapMode_Wrap == info.mapV) { - // Wrap - simple take the fraction of the field - out = info.mTranslation.y-(float)rounded; - sprintf(szTemp,"[w] UV V offset %f can be simplified to %f",info.mTranslation.y,out); - } - else if (aiTextureMapMode_Mirror == info.mapV && 1 != rounded) { - // Mirror - if (rounded % 2) - rounded--; - out = info.mTranslation.x-(float)rounded; - - sprintf(szTemp,"[m/d] UV V offset %f can be simplified to %f",info.mTranslation.y,out); - } - else if (aiTextureMapMode_Clamp == info.mapV || aiTextureMapMode_Decal == info.mapV) { - // Clamp - translations beyond 1,1 are senseless - sprintf(szTemp,"[c] UV V offset %f canbe clamped to 1.0f",info.mTranslation.y); - - out = 1.f; - } - if (szTemp[0]) { - DefaultLogger::get()->info(szTemp); - info.mTranslation.y = out; - } - } - return; -} - -// ------------------------------------------------------------------------------------------------ -void UpdateUVIndex(const std::list<TTUpdateInfo>& l, unsigned int n) -{ - // Don't set if == 0 && wasn't set before - for (std::list<TTUpdateInfo>::const_iterator it = l.begin();it != l.end(); ++it) { - const TTUpdateInfo& info = *it; - - if (info.directShortcut) - *info.directShortcut = n; - else if (!n) - { - info.mat->AddProperty<int>((int*)&n,1,AI_MATKEY_UVWSRC(info.semantic,info.index)); - } - } -} - -// ------------------------------------------------------------------------------------------------ -inline const char* MappingModeToChar(aiTextureMapMode map) -{ - if (aiTextureMapMode_Wrap == map) - return "-w"; - - if (aiTextureMapMode_Mirror == map) - return "-m"; - - return "-c"; -} - -// ------------------------------------------------------------------------------------------------ -void TextureTransformStep::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("TransformUVCoordsProcess begin"); - - - /* We build a per-mesh list of texture transformations we'll need - * to apply. To achieve this, we iterate through all materials, - * find all textures and get their transformations and UV indices. - * Then we search for all meshes using this material. - */ - typedef std::list<STransformVecInfo> MeshTrafoList; - std::vector<MeshTrafoList> meshLists(pScene->mNumMeshes); - - for (unsigned int i = 0; i < pScene->mNumMaterials;++i) { - - aiMaterial* mat = pScene->mMaterials[i]; - for (unsigned int a = 0; a < mat->mNumProperties;++a) { - - aiMaterialProperty* prop = mat->mProperties[a]; - if (!::strcmp( prop->mKey.data, "$tex.file")) { - STransformVecInfo info; - - // Setup a shortcut structure to allow for a fast updating - // of the UV index later - TTUpdateInfo update; - update.mat = (MaterialHelper*) mat; - update.semantic = prop->mSemantic; - update.index = prop->mIndex; - - // Get textured properties and transform - for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2) - { - aiMaterialProperty* prop2 = mat->mProperties[a2]; - if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex) - continue; - - if ( !::strcmp( prop2->mKey.data, "$tex.uvwsrc")) - { - info.uvIndex = *((int*)prop2->mData); - - // Store a direct pointer for later use - update.directShortcut = (unsigned int*) prop2->mData; - } - - else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodeu")) - info.mapU = *((aiTextureMapMode*)prop2->mData); - - else if ( !::strcmp( prop2->mKey.data, "$tex.mapmodev")) - info.mapV = *((aiTextureMapMode*)prop2->mData); - - else if ( !::strcmp( prop2->mKey.data, "$tex.uvtrafo")) - { - // ValidateDS should check this - ai_assert(prop2->mDataLength >= 20); - ::memcpy(&info.mTranslation.x,prop2->mData,sizeof(float)*5); - delete[] prop2->mData; - - // Directly remove this property from the list - mat->mNumProperties--; - for (unsigned int a3 = a2; a3 < mat->mNumProperties;++a3) - mat->mProperties[a3] = mat->mProperties[a3+1]; - - // Warn: could be an underflow, but nevertheless it should work - --a2; - } - } - - // Find out which transformations are to be evaluated - if (!(configFlags & AI_UVTRAFO_ROTATION)) - info.mRotation = 0.f; - - if (!(configFlags & AI_UVTRAFO_SCALING)) - info.mScaling = aiVector2D(1.f,1.f); - - if (!(configFlags & AI_UVTRAFO_TRANSLATION)) - info.mTranslation = aiVector2D(0.f,0.f); - - // Do some preprocessing - PreProcessUVTransform(info); - info.uvIndex = std::min(info.uvIndex,AI_MAX_NUMBER_OF_TEXTURECOORDS -1u); - - // Find out whether this material is used by more than - // one mesh. This will make our task much, much more difficult! - unsigned int cnt = 0; - for (unsigned int n = 0; n < pScene->mNumMeshes;++n) { - if (pScene->mMeshes[n]->mMaterialIndex == i) - ++cnt; - } - - if (!cnt) - continue; - else if (1 != cnt) { - // This material is referenced by more than one mesh! - // So we need to make sure the UV index for the texture - // is identical for each of it ... - info.lockedPos = AI_TT_UV_IDX_LOCK_TBD; - } - - // Get all coresponding meshes - for (unsigned int n = 0; n < pScene->mNumMeshes;++n) { - aiMesh* mesh = pScene->mMeshes[n]; - if (mesh->mMaterialIndex != i || !mesh->mTextureCoords[0]) - continue; - - unsigned int uv = info.uvIndex; - if (!mesh->mTextureCoords[uv]) { - // If the requested UV index is not available, take the first one instead. - uv = 0; - } - - if (mesh->mNumUVComponents[info.uvIndex] >= 3){ - DefaultLogger::get()->warn("UV transformations on 3D mapping channels are not supported"); - continue; - } - - MeshTrafoList::iterator it; - - // Check whether we have this transform setup already - for (it = meshLists[n].begin();it != meshLists[n].end(); ++it) { - - if ((*it) == info && (*it).uvIndex == uv) { - (*it).updateList.push_back(update); - break; - } - } - - if (it == meshLists[n].end()) { - meshLists[n].push_back(info); - meshLists[n].back().uvIndex = uv; - meshLists[n].back().updateList.push_back(update); - } - } - } - } - } - - char buffer[1024]; // should be sufficiently large - unsigned int outChannels = 0, inChannels = 0, transformedChannels = 0; - - // Now process all meshes. Important: we don't remove unreferenced UV channels. - // This is a job for the RemoveUnreferencedData-Step. - for (unsigned int q = 0; q < pScene->mNumMeshes;++q) { - - aiMesh* mesh = pScene->mMeshes[q]; - MeshTrafoList& trafo = meshLists[q]; - - inChannels += mesh->GetNumUVChannels(); - - if (!mesh->mTextureCoords[0] || trafo.empty() || (trafo.size() == 1 && trafo.begin()->IsUntransformed())) { - outChannels += mesh->GetNumUVChannels(); - continue; - } - - // Move untransformed UV channels to the first position in the list .... - // except if we need a new locked index which should be as small as possible - bool veto = false, need = false; - unsigned int cnt = 0; - unsigned int untransformed = 0; - - MeshTrafoList::iterator it,it2; - for (it = trafo.begin();it != trafo.end(); ++it,++cnt) { - - if (!(*it).IsUntransformed()) { - need = true; - } - - if ((*it).lockedPos == AI_TT_UV_IDX_LOCK_TBD) { - // Lock this index and make sure it won't be changed - (*it).lockedPos = cnt; - veto = true; - continue; - } - - if (!veto && it != trafo.begin() && (*it).IsUntransformed()) { - for (it2 = trafo.begin();it2 != it; ++it2) { - if (!(*it2).IsUntransformed()) - break; - } - trafo.insert(it2,*it); - trafo.erase(it); - break; - } - } - if (!need) - continue; - - // Find all that are not at their 'locked' position and move them to it. - // Conflicts are possible but quite unlikely. - cnt = 0; - for (it = trafo.begin();it != trafo.end(); ++it,++cnt) { - if ((*it).lockedPos != AI_TT_UV_IDX_LOCK_NONE && (*it).lockedPos != cnt) { - it2 = trafo.begin();unsigned int t = 0; - while (t != (*it).lockedPos) - ++it2; - - if ((*it2).lockedPos != AI_TT_UV_IDX_LOCK_NONE) { - DefaultLogger::get()->error("Channel mismatch, can't compute all transformations properly [design bug]"); - continue; - } - - std::swap(*it2,*it); - if ((*it).lockedPos == untransformed) - untransformed = cnt; - } - } - - // ... and add dummies for all unreferenced channels - // at the end of the list - bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) - ref[n] = (!mesh->mTextureCoords[n] ? true : false); - - for (it = trafo.begin();it != trafo.end(); ++it) - ref[(*it).uvIndex] = true; - - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) { - if (ref[n]) - continue; - trafo.push_back(STransformVecInfo()); - trafo.back().uvIndex = n; - } - - // Then check whether this list breaks the channel limit. - // The unimportant ones are at the end of the list, so - // it shouldn't be too worse if we remove them. - unsigned int size = (unsigned int)trafo.size(); - if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) { - - if (!DefaultLogger::isNullLogger()) { - ::sprintf(buffer,"%u UV channels required but just %u available", - static_cast<unsigned int>(trafo.size()),AI_MAX_NUMBER_OF_TEXTURECOORDS); - - DefaultLogger::get()->error(buffer); - } - size = AI_MAX_NUMBER_OF_TEXTURECOORDS; - } - - - aiVector3D* old[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) - old[n] = mesh->mTextureCoords[n]; - - // Now continue and generate the output channels. Channels - // that we're not going to need later can be overridden. - it = trafo.begin(); - for (unsigned int n = 0; n < trafo.size();++n,++it) { - - if (n >= size) { - // Try to use an untransformed channel for all channels we threw over board - UpdateUVIndex((*it).updateList,untransformed); - continue; - } - - outChannels++; - - // Write to the log - if (!DefaultLogger::isNullLogger()) { - sprintf(buffer,"Mesh %u, channel %u: t(%.3f,%.3f), s(%.3f,%.3f), r(%.3f), %s%s", - q,n, - (*it).mTranslation.x, - (*it).mTranslation.y, - (*it).mScaling.x, - (*it).mScaling.y, - AI_RAD_TO_DEG( (*it).mRotation), - MappingModeToChar ((*it).mapU), - MappingModeToChar ((*it).mapV)); - - DefaultLogger::get()->info(buffer); - } - - // Check whether we need a new buffer here - if (mesh->mTextureCoords[n]) { - - it2 = it;++it2; - for (unsigned int m = n+1; m < size;++m, ++it2) { - - if ((*it2).uvIndex == n){ - it2 = trafo.begin(); - break; - } - } - if (it2 == trafo.begin()){ - mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices]; - } - } - else mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices]; - - aiVector3D* src = old[(*it).uvIndex]; - aiVector3D* dest, *end; - dest = mesh->mTextureCoords[n]; - - ai_assert(NULL != src); - - // Copy the data to the destination array - if (dest != src) - ::memcpy(dest,src,sizeof(aiVector3D)*mesh->mNumVertices); - - end = dest + mesh->mNumVertices; - - // Build a transformation matrix and transform all UV coords with it - if (!(*it).IsUntransformed()) { - const aiVector2D& trl = (*it).mTranslation; - const aiVector2D& scl = (*it).mScaling; - - // fixme: simplify .. - ++transformedChannels; - aiMatrix3x3 matrix; - - aiMatrix3x3 m2,m3,m4,m5; - - m4.a1 = scl.x; - m4.b2 = scl.y; - - m2.a3 = m2.b3 = 0.5f; - m3.a3 = m3.b3 = -0.5f; - - if ((*it).mRotation > AI_TT_ROTATION_EPSILON ) - aiMatrix3x3::RotationZ((*it).mRotation,matrix); - - m5.a3 += trl.x; m5.b3 += trl.y; - matrix = m2 * m4 * matrix * m3 * m5; - - for (src = dest; src != end; ++src) { /* manual homogenious divide */ - src->z = 1.f; - *src = matrix * *src; - src->x /= src->z; - src->y /= src->z; - src->z = 0.f; - } - } - - // Update all UV indices - UpdateUVIndex((*it).updateList,n); - } - } - - // Print some detailled statistics into the log - if (!DefaultLogger::isNullLogger()) { - - if (transformedChannels) { - ::sprintf(buffer,"TransformUVCoordsProcess end: %u output channels (in: %u, modified: %u)", - outChannels,inChannels,transformedChannels); - - DefaultLogger::get()->info(buffer); - } - else DefaultLogger::get()->debug("TransformUVCoordsProcess finished"); - } -} - - diff --git a/3rdparty/assimp/code/TextureTransform.h b/3rdparty/assimp/code/TextureTransform.h deleted file mode 100644 index dd57e2a5..00000000 --- a/3rdparty/assimp/code/TextureTransform.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Definition of a helper step that processes texture transformations */ -#ifndef AI_TEXTURE_TRANSFORM_H_INCLUDED -#define AI_TEXTURE_TRANSFORM_H_INCLUDED - -#include "BaseImporter.h" -#include "BaseProcess.h" - -struct aiNode; - -namespace Assimp { - -#define AI_TT_UV_IDX_LOCK_TBD 0xffffffff -#define AI_TT_UV_IDX_LOCK_NONE 0xeeeeeeee - - -#define AI_TT_ROTATION_EPSILON ((float)AI_DEG_TO_RAD(0.5)) - -// --------------------------------------------------------------------------- -/** Small helper structure representing a shortcut into the material list - * to be able to update some values quickly. -*/ -struct TTUpdateInfo -{ - TTUpdateInfo() : - directShortcut (NULL) - , mat (NULL) - , semantic (0) - , index (0) - {} - - //! Direct shortcut, if available - unsigned int* directShortcut; - - //! Material - MaterialHelper *mat; - - //! Texture type and index - unsigned int semantic, index; -}; - - -// --------------------------------------------------------------------------- -/** Helper class representing texture coordinate transformations -*/ -struct STransformVecInfo : public aiUVTransform -{ - - STransformVecInfo() - : uvIndex (0) - , mapU (aiTextureMapMode_Wrap) - , mapV (aiTextureMapMode_Wrap) - , lockedPos (AI_TT_UV_IDX_LOCK_NONE) - {} - - //! Source texture coordinate index - unsigned int uvIndex; - - //! Texture mapping mode in the u, v direction - aiTextureMapMode mapU,mapV; - - //! Locked destination UV index - //! AI_TT_UV_IDX_LOCK_TBD - to be determined - //! AI_TT_UV_IDX_LOCK_NONE - none (default) - unsigned int lockedPos; - - //! Update info - shortcuts into all materials - //! that are referencing this transform setup - std::list<TTUpdateInfo> updateList; - - - // ------------------------------------------------------------------- - /** Compare two transform setups - */ - inline bool operator== (const STransformVecInfo& other) const - { - // We use a small epsilon here - const static float epsilon = 0.05f; - - if (fabs( mTranslation.x - other.mTranslation.x ) > epsilon || - fabs( mTranslation.y - other.mTranslation.y ) > epsilon) - { - return false; - } - - if (fabs( mScaling.x - other.mScaling.x ) > epsilon || - fabs( mScaling.y - other.mScaling.y ) > epsilon) - { - return false; - } - - if (fabs( mRotation - other.mRotation) > epsilon) - { - return false; - } - return true; - } - - inline bool operator!= (const STransformVecInfo& other) const - { - return !(*this == other); - } - - - // ------------------------------------------------------------------- - /** Returns whether this is an untransformed texture coordinate set - */ - inline bool IsUntransformed() const - { - return (1.0f == mScaling.x && 1.f == mScaling.y && - !mTranslation.x && !mTranslation.y && - mRotation < AI_TT_ROTATION_EPSILON); - } - - // ------------------------------------------------------------------- - /** Build a 3x3 matrix from the transformations - */ - inline void GetMatrix(aiMatrix3x3& mOut) - { - mOut = aiMatrix3x3(); - - if (1.0f != mScaling.x || 1.0f != mScaling.y) - { - aiMatrix3x3 mScale; - mScale.a1 = mScaling.x; - mScale.b2 = mScaling.y; - mOut = mScale; - } - if (mRotation) - { - aiMatrix3x3 mRot; - mRot.a1 = mRot.b2 = cos(mRotation); - mRot.a2 = mRot.b1 = sin(mRotation); - mRot.a2 = -mRot.a2; - mOut *= mRot; - } - if (mTranslation.x || mTranslation.y) - { - aiMatrix3x3 mTrans; - mTrans.a3 = mTranslation.x; - mTrans.b3 = mTranslation.y; - mOut *= mTrans; - } - } -}; - - -// --------------------------------------------------------------------------- -/** Helper step to compute final UV coordinate sets if there are scalings - * or rotations in the original data read from the file. -*/ -class ASSIMP_API TextureTransformStep : public BaseProcess -{ -public: - - TextureTransformStep(); - ~TextureTransformStep(); - - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - - // ------------------------------------------------------------------- - void SetupProperties(const Importer* pImp); - - -protected: - - - // ------------------------------------------------------------------- - /** Preprocess a specific UV transformation setup - * - * @param info Transformation setup to be preprocessed. - */ - void PreProcessUVTransform(STransformVecInfo& info); - -private: - - unsigned int configFlags; -}; - -} - -#endif //! AI_TEXTURE_TRANSFORM_H_INCLUDED diff --git a/3rdparty/assimp/code/TinyFormatter.h b/3rdparty/assimp/code/TinyFormatter.h deleted file mode 100644 index c8478e12..00000000 --- a/3rdparty/assimp/code/TinyFormatter.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 TinyFormatter.h - * @brief Utility to format log messages more easily. Introduced - * to get rid of the boost::format dependency. Much slinker, - * basically just extends stringstream. - */ -#ifndef INCLUDED_TINY_FORMATTER_H -#define INCLUDED_TINY_FORMATTER_H - -#include <sstream> - -namespace Assimp { - namespace Formatter { - -// ------------------------------------------------------------------------------------------------ -/** stringstream utility. Usage: - * @code - * void writelog(const std::string&s); - * void writelog(const std::wstring&s); - * ... - * writelog(format()<< "hi! this is a number: " << 4); - * writelog(wformat()<< L"hi! this is a number: " << 4); - * - * @endcode */ -template < typename T, - typename CharTraits = std::char_traits<T>, - typename Allocator = std::allocator<T> -> -class basic_formatter -{ - -public: - - typedef class std::basic_string< - T,CharTraits,Allocator - > string; - - typedef class std::basic_ostringstream< - T,CharTraits,Allocator - > stringstream; - -public: - - basic_formatter() {} - - /* Allow basic_formatter<T>'s to be used almost interchangeably - * with std::(w)string or const (w)char* arguments because the - * conversion c'tor is called implicitly. */ - template <typename TT> - basic_formatter(const TT& sin) { - underlying << sin; - } - -public: - - operator string () const { - return underlying.str(); - } - - - /* note - this is declared const because binding temporaries does only - * work for const references, so many function prototypes will - * include const basic_formatter<T>& s but might still want to - * modify the formatted string without the need for a full copy.*/ - template <typename TToken> - const basic_formatter& operator << (const TToken& s) const { - underlying << s; - return *this; - } - - template <typename TToken> - basic_formatter& operator << (const TToken& s) { - underlying << s; - return *this; - } - - - // comma operator overloaded as well, choose your preferred way. - template <typename TToken> - const basic_formatter& operator, (const TToken& s) const { - underlying << s; - return *this; - } - - template <typename TToken> - basic_formatter& operator, (const TToken& s) { - underlying << s; - return *this; - } - -private: - mutable stringstream underlying; -}; - - -typedef basic_formatter< char > format; -typedef basic_formatter< wchar_t > wformat; - -} // ! namespace Formatter - -} // ! namespace Assimp -#endif diff --git a/3rdparty/assimp/code/TriangulateProcess.cpp b/3rdparty/assimp/code/TriangulateProcess.cpp deleted file mode 100644 index c63e43c4..00000000 --- a/3rdparty/assimp/code/TriangulateProcess.cpp +++ /dev/null @@ -1,401 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2009, ASSIMP Development 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 Development 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 TriangulateProcess.cpp - * @brief Implementation of the post processing step to split up - * all faces with more than three indices into triangles. - * - * - * The triangulation algorithm will handle concave or convex polygons. - * Self-intersecting or non-planar polygons are not rejected, but - * they're probably not triangulated correctly. - * - * AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING - * - generates vertex colors to represent the face winding order. - * the first vertex of a polygon becomes red, the last blue. - */ - -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_TRIANGULATE_PROCESS -#include "TriangulateProcess.h" -#include "ProcessHelper.h" - -//#define AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -TriangulateProcess::TriangulateProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -TriangulateProcess::~TriangulateProcess() -{ - // nothing to do here -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool TriangulateProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_Triangulate) != 0; -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void TriangulateProcess::Execute( aiScene* pScene) -{ - DefaultLogger::get()->debug("TriangulateProcess begin"); - - bool bHas = false; - for ( unsigned int a = 0; a < pScene->mNumMeshes; a++) - { - if ( TriangulateMesh( pScene->mMeshes[a])) - bHas = true; - } - if (bHas)DefaultLogger::get()->info ("TriangulateProcess finished. All polygons have been triangulated."); - else DefaultLogger::get()->debug("TriangulateProcess finished. There was nothing to be done."); -} - -// ------------------------------------------------------------------------------------------------ -// Test whether a point p2 is on the left side of the line formed by p0-p1 -inline bool OnLeftSideOfLine(const aiVector2D& p0, const aiVector2D& p1,const aiVector2D& p2) -{ - return ( (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y) ) > 0; -} - -// ------------------------------------------------------------------------------------------------ -// Test whether a point is inside a given triangle in R2 -inline bool PointInTriangle2D(const aiVector2D& p0, const aiVector2D& p1,const aiVector2D& p2, const aiVector2D& pp) -{ - // Point in triangle test using baryzentric coordinates - const aiVector2D v0 = p1 - p0; - const aiVector2D v1 = p2 - p0; - const aiVector2D v2 = pp - p0; - - float dot00 = v0 * v0; - float dot01 = v0 * v1; - float dot02 = v0 * v2; - float dot11 = v1 * v1; - float dot12 = v1 * v2; - - const float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); - dot11 = (dot11 * dot02 - dot01 * dot12) * invDenom; - dot00 = (dot00 * dot12 - dot01 * dot02) * invDenom; - - return (dot11 > 0) && (dot00 > 0) && (dot11 + dot00 < 1); -} - -// ------------------------------------------------------------------------------------------------ -// Triangulates the given mesh. -bool TriangulateProcess::TriangulateMesh( aiMesh* pMesh) -{ - // Now we have aiMesh::mPrimitiveTypes, so this is only here for test cases - if (!pMesh->mPrimitiveTypes) { - bool bNeed = false; - - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) { - const aiFace& face = pMesh->mFaces[a]; - - if ( face.mNumIndices != 3) { - bNeed = true; - } - } - if (!bNeed) - return false; - } - else if (!(pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) { - return false; - } - - // the output mesh will contain triangles, but no polys anymore - pMesh->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - pMesh->mPrimitiveTypes &= ~aiPrimitiveType_POLYGON; - - // Find out how many output faces we'll get - unsigned int numOut = 0, max_out = 0; - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) { - aiFace& face = pMesh->mFaces[a]; - if ( face.mNumIndices <= 3) - numOut++; - - else { - numOut += face.mNumIndices-2; - max_out = std::max(max_out,face.mNumIndices); - } - } - - // Just another check whether aiMesh::mPrimitiveTypes is correct - assert(numOut != pMesh->mNumFaces); - - aiVector3D* nor_out = NULL; - if (!pMesh->mNormals && pMesh->mPrimitiveTypes == aiPrimitiveType_POLYGON) { - nor_out = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; - } - - aiFace* out = new aiFace[numOut], *curOut = out; - std::vector<aiVector3D> temp_verts(max_out+2); /* temporary storage for vertices */ - - // Apply vertex colors to represent the face winding? -#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING - if (!pMesh->mColors[0]) - pMesh->mColors[0] = new aiColor4D[pMesh->mNumVertices]; - else - new(pMesh->mColors[0]) aiColor4D[pMesh->mNumVertices]; - - aiColor4D* clr = pMesh->mColors[0]; -#endif - - // use boost::scoped_array to avoid slow std::vector<bool> specialiations - boost::scoped_array<bool> done(new bool[max_out]); - for ( unsigned int a = 0; a < pMesh->mNumFaces; a++) { - aiFace& face = pMesh->mFaces[a]; - - unsigned int* idx = face.mIndices; - int num = (int)face.mNumIndices, ear = 0, tmp, prev = num-1, next = 0, max = num; - - // Apply vertex colors to represent the face winding? -#ifdef AI_BUILD_TRIANGULATE_COLOR_FACE_WINDING - for (unsigned int i = 0; i < face.mNumIndices; ++i) { - aiColor4D& c = clr[idx[i]]; - c.r = (i+1) / (float)max; - c.b = 1.f - c.r; - } -#endif - - // if it's a simple point,line or triangle: just copy it - if ( face.mNumIndices <= 3) - { - aiFace& nface = *curOut++; - nface.mNumIndices = face.mNumIndices; - nface.mIndices = face.mIndices; - } - // quadrilaterals can't have ears. trifanning will always work - else if ( face.mNumIndices == 4) { - aiFace& nface = *curOut++; - nface.mNumIndices = 3; - nface.mIndices = face.mIndices; - - aiFace& sface = *curOut++; - sface.mNumIndices = 3; - sface.mIndices = new unsigned int[3]; - - sface.mIndices[0] = face.mIndices[0]; - sface.mIndices[1] = face.mIndices[2]; - sface.mIndices[2] = face.mIndices[3]; - } - else - { - // A polygon with more than 3 vertices can be either concave or convex. - // Usually everything we're getting is convex and we could easily - // triangulate by trifanning. However, LightWave is probably the only - // modeller to make extensive use of highly concave monster polygons ... - // so we need to apply the full 'ear cutting' algorithm. - - // RERQUIREMENT: polygon is expected to be simple and *nearly* planar. - // We project it onto a plane to get 2d data. Working in R3 would - // also be possible but it's more difficult to implement. - - // Collect all vertices of of the polygon. - aiVector3D* verts = pMesh->mVertices; - for (tmp = 0; tmp < max; ++tmp) { - temp_verts[tmp] = verts[idx[tmp]]; - } - - // Get newell normal of the polygon. Store it for future use if it's a polygon-only mesh - aiVector3D n; - NewellNormal<3,3,3>(n,max,&temp_verts.front().x,&temp_verts.front().y,&temp_verts.front().z); - if (nor_out) { - for (tmp = 0; tmp < max; ++tmp) - nor_out[idx[tmp]] = n; - } - - // Select largest normal coordinate to ignore for projection - const float ax = (n.x>0 ? n.x : -n.x); - const float ay = (n.y>0 ? n.y : -n.y); - const float az = (n.z>0 ? n.z : -n.z); - - unsigned int ac = 0, bc = 1; /* no z coord. projection to xy */ - float inv = n.z; - if (ax > ay) { - if (ax > az) { /* no x coord. projection to yz */ - ac = 1; bc = 2; - inv = n.x; - } - } - else if (ay > az) { /* no y coord. projection to zy */ - ac = 2; bc = 0; - inv = n.y; - } - - // Swap projection axes to take the negated projection vector into account - if (inv < 0.f) { - std::swap(ac,bc); - } - - for (tmp =0; tmp < max; ++tmp) { - temp_verts[tmp].x = verts[idx[tmp]][ac]; - temp_verts[tmp].y = verts[idx[tmp]][bc]; - done[tmp] = false; - } - - // - // FIXME: currently this is the slow O(kn) variant with a worst case - // complexity of O(n^2) (I think). Can be done in O(n). - while (num > 3) { - - // Find the next ear of the polygon - int num_found = 0; - for (ear = next;;prev = ear,ear = next) { - - // break after we looped two times without a positive match - for (next=ear+1;done[(next>max-1?next=0:next)];++next); - if (next < ear) { - if (++num_found == 2) { - break; - } - } - const aiVector2D* pnt1 = (const aiVector2D*)&temp_verts[ear], - *pnt0 = (const aiVector2D*)&temp_verts[prev], - *pnt2 = (const aiVector2D*)&temp_verts[next]; - - // Must be a convex point. Assuming ccw winding, it must be on the right of the line between p-1 and p+1. - if (OnLeftSideOfLine (*pnt0,*pnt2,*pnt1)) { - continue; - } - - // and no other point may be contained in this triangle - for ( tmp = 0; tmp < max; ++tmp) { - - // We need to compare the actual values because it's possible that multiple indexes in - // the polygon are refering to the same position. concave_polygon.obj is a sample - // - // FIXME: Use 'epsiloned' comparisons instead? Due to numeric inaccuracies in - // PointInTriangle() I'm guessing that it's actually possible to construct - // input data that would cause us to end up with no ears. The problem is, - // which epsilon? If we chose a too large value, we'd get wrong results - const aiVector2D& vtmp = * ((aiVector2D*) &temp_verts[tmp] ); - if ( vtmp != *pnt1 && vtmp != *pnt2 && vtmp != *pnt0 && PointInTriangle2D(*pnt0,*pnt1,*pnt2,vtmp)) - break; - - } - if (tmp != max) { - continue; - } - - // this vertex is an ear - break; - } - if (num_found == 2) { - - // Due to the 'two ear theorem', every simple polygon with more than three points must - // have 2 'ears'. Here's definitely someting wrong ... but we don't give up yet. - // - - // Instead we're continuting with the standard trifanning algorithm which we'd - // use if we had only convex polygons. That's life. - DefaultLogger::get()->error("Failed to triangulate polygon (no ear found). Probably not a simple polygon?"); - - curOut -= (max-num); /* undo all previous work */ - for (tmp = 0; tmp < max-2; ++tmp) { - aiFace& nface = *curOut++; - - nface.mNumIndices = 3; - if (!nface.mIndices) - nface.mIndices = new unsigned int[3]; - - nface.mIndices[0] = idx[0]; - nface.mIndices[1] = idx[tmp+1]; - nface.mIndices[2] = idx[tmp+2]; - } - num = 0; - break; - } - - aiFace& nface = *curOut++; - nface.mNumIndices = 3; - - if (!nface.mIndices) { - nface.mIndices = new unsigned int[3]; - } - - // setup indices for the new triangle ... - nface.mIndices[0] = idx[prev]; - nface.mIndices[1] = idx[ear]; - nface.mIndices[2] = idx[next]; - - // exclude the ear from most further processing - done[ear] = true; - --num; - } - if (num > 0) { - // We have three indices forming the last 'ear' remaining. Collect them. - aiFace& nface = *curOut++; - nface.mNumIndices = 3; - nface.mIndices = face.mIndices; - - for (tmp = 0; done[tmp]; ++tmp); - idx[0] = idx[tmp]; - - for (++tmp; done[tmp]; ++tmp); - idx[1] = idx[tmp]; - - for (++tmp; done[tmp]; ++tmp); - idx[2] = idx[tmp]; - } - } - face.mIndices = NULL; /* prevent unintended deletion of our awesome results. would be a pity */ - } - - // kill the old faces - delete [] pMesh->mFaces; - - // ... and store the new ones - pMesh->mFaces = out; - pMesh->mNumFaces = (unsigned int)(curOut-out); /* not necessarily equal to numOut */ - return true; -} - -#endif // !! ASSIMP_BUILD_NO_TRIANGULATE_PROCESS diff --git a/3rdparty/assimp/code/TriangulateProcess.h b/3rdparty/assimp/code/TriangulateProcess.h deleted file mode 100644 index 7a680e5a..00000000 --- a/3rdparty/assimp/code/TriangulateProcess.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a post processing step to triangulate all faces - with more than three vertices. - */ -#ifndef AI_TRIANGULATEPROCESS_H_INC -#define AI_TRIANGULATEPROCESS_H_INC - -#include "BaseProcess.h" - -struct aiMesh; - -class TriangulateProcessTest; -namespace Assimp -{ - -// --------------------------------------------------------------------------- -/** The TriangulateProcess splits up all faces with more than three indices - * into triangles. You usually want this to happen because the graphics cards - * need their data as triangles. - */ -class ASSIMP_API TriangulateProcess : public BaseProcess -{ - friend class Importer; - friend class ::TriangulateProcessTest; // grant the unit test full access to us - -protected: - /** Constructor to be privately used by Importer */ - TriangulateProcess(); - - /** Destructor, private as well */ - ~TriangulateProcess(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the processing step is present in the given flag field. - * @param pFlags The processing flags the importer was called with. A bitwise - * combination of #aiPostProcessSteps. - * @return true if the process is present in this flag fields, false if not. - */ - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - /** Executes the post processing step on the given imported data. - * At the moment a process is not supposed to fail. - * @param pScene The imported data to work at. - */ - void Execute( aiScene* pScene); - -protected: - // ------------------------------------------------------------------- - /** Triangulates the given mesh. - * @param pMesh The mesh to triangulate. - */ - bool TriangulateMesh( aiMesh* pMesh); -}; - -} // end of namespace Assimp - -#endif // AI_TRIANGULATEPROCESS_H_INC diff --git a/3rdparty/assimp/code/UnrealLoader.cpp b/3rdparty/assimp/code/UnrealLoader.cpp deleted file mode 100644 index cae51224..00000000 --- a/3rdparty/assimp/code/UnrealLoader.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 UnrealLoader.cpp - * @brief Implementation of the UNREAL (*.3D) importer class - * - * Sources: - * http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/ - */ - -#include "AssimpPCH.h" - -#ifndef ASSIMP_BUILD_NO_3D_IMPORTER - -#include "UnrealLoader.h" -#include "StreamReader.h" -#include "ParsingUtils.h" -#include "fast_atof.h" -#include "ConvertToLHProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -UnrealImporter::UnrealImporter() -: configFrameID (0) -, configHandleFlags (true) -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -UnrealImporter::~UnrealImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// 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"); -} - -// ------------------------------------------------------------------------------------------------ -// Build a string of all file extensions supported -void UnrealImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("3d"); - extensions.insert("uc"); -} - -// ------------------------------------------------------------------------------------------------ -// 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,0xffffffff); - if (0xffffffff == 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) -{ - // 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 = strtol10(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_atof_move(data+2,(float&)nd->mTransformation.a1); - } - else if (data[0] == 'Y' && data[1] == '=') { - data = fast_atof_move(data+2,(float&)nd->mTransformation.b2); - } - else if (data[0] == 'Z' && data[1] == '=') { - data = fast_atof_move(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 - MaterialHelper* mat = new MaterialHelper(); - 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); -} - -#endif // !! ASSIMP_BUILD_NO_3D_IMPORTER diff --git a/3rdparty/assimp/code/UnrealLoader.h b/3rdparty/assimp/code/UnrealLoader.h deleted file mode 100644 index 64724602..00000000 --- a/3rdparty/assimp/code/UnrealLoader.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 UnrealLoader.h - * @brief Declaration of the .3d (UNREAL) importer class. - */ -#ifndef INCLUDED_AI_3D_LOADER_H -#define INCLUDED_AI_3D_LOADER_H - -#include "BaseImporter.h" -namespace Assimp { -namespace Unreal { - - /* - 0 = Normal one-sided - 1 = Normal two-sided - 2 = Translucent two-sided - 3 = Masked two-sided - 4 = Modulation blended two-sided - 8 = Placeholder triangle for weapon positioning (invisible) - */ -enum MeshFlags { - MF_NORMAL_OS = 0, - MF_NORMAL_TS = 1, - MF_NORMAL_TRANS_TS = 2, - MF_NORMAL_MASKED_TS = 3, - MF_NORMAL_MOD_TS = 4, - MF_WEAPON_PLACEHOLDER = 8 -}; - - // a single triangle -struct Triangle { - uint16_t mVertex[3]; // Vertex indices - char mType; // James' Mesh Type - char mColor; // Color for flat and Gourand Shaded - unsigned char mTex[3][2]; // Texture UV coordinates - unsigned char mTextureNum; // Source texture offset - char mFlags; // Unreal Mesh Flags (unused) - - unsigned int matIndex; -}; - -// temporary representation for a material -struct TempMat { - TempMat() - : numFaces (0) - {} - - TempMat(const Triangle& in) - : type ((Unreal::MeshFlags)in.mType) - , tex (in.mTextureNum) - , numFaces (0) - {} - - // type of mesh - Unreal::MeshFlags type; - - // index of texture - unsigned int tex; - - // number of faces using us - unsigned int numFaces; - - // for std::find - bool operator == (const TempMat& o ) { - return (tex == o.tex && type == o.type); - } -}; - -struct Vertex -{ - int32_t X : 11; - int32_t Y : 11; - int32_t Z : 10; -}; - - // UNREAL vertex compression -inline void CompressVertex(const aiVector3D& v, uint32_t& out) -{ - union { - Vertex n; - int32_t t; - }; - n.X = (int32_t)v.x; - n.Y = (int32_t)v.y; - n.Z = (int32_t)v.z; - out = t; -} - - // UNREAL vertex decompression -inline void DecompressVertex(aiVector3D& v, int32_t in) -{ - union { - Vertex n; - int32_t i; - }; - i = in; - - v.x = (float)n.X; - v.y = (float)n.Y; - v.z = (float)n.Z; -} - -} // end namespace Unreal - -// --------------------------------------------------------------------------- -/** @brief Importer class to load UNREAL files (*.3d) -*/ -class UnrealImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - UnrealImporter(); - - /** Destructor, private as well */ - ~UnrealImporter(); - -public: - - // ------------------------------------------------------------------- - /** @brief Returns whether we can handle the format of the given file - * - * See BaseImporter::CanRead() for details. - **/ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; - -protected: - - // ------------------------------------------------------------------- - /** @brief Called by Importer::GetExtensionList() - * - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - - // ------------------------------------------------------------------- - /** @brief Setup properties for the importer - * - * See BaseImporter::SetupProperties() for details - */ - void SetupProperties(const Importer* pImp); - - - // ------------------------------------------------------------------- - /** @brief Imports the given file into the given scene structure. - * - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - -private: - - //! frame to be loaded - uint32_t configFrameID; - - //! process surface flags - bool configHandleFlags; - -}; // !class UnrealImporter - -} // end of namespace Assimp -#endif // AI_UNREALIMPORTER_H_INC diff --git a/3rdparty/assimp/code/ValidateDataStructure.cpp b/3rdparty/assimp/code/ValidateDataStructure.cpp deleted file mode 100644 index 6c506ac2..00000000 --- a/3rdparty/assimp/code/ValidateDataStructure.cpp +++ /dev/null @@ -1,968 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 ValidateDataStructure.cpp - * @brief Implementation of the post processing step to validate - * the data structure returned by Assimp. - */ - -#include "AssimpPCH.h" - -// internal headers -#include "ValidateDataStructure.h" -#include "BaseImporter.h" -#include "fast_atof.h" -#include "ProcessHelper.h" - -// CRT headers -#include <stdarg.h> - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -ValidateDSProcess::ValidateDSProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -ValidateDSProcess::~ValidateDSProcess() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the processing step is present in the given flag field. -bool ValidateDSProcess::IsActive( unsigned int pFlags) const -{ - return (pFlags & aiProcess_ValidateDataStructure) != 0; -} -// ------------------------------------------------------------------------------------------------ -AI_WONT_RETURN void ValidateDSProcess::ReportError(const char* msg,...) -{ - ai_assert(NULL != msg); - - va_list args; - va_start(args,msg); - - char szBuffer[3000]; - const int iLen = vsprintf(szBuffer,msg,args); - ai_assert(iLen > 0); - - va_end(args); -#ifdef _DEBUG - aiAssert( szBuffer,__LINE__,__FILE__ ); -#endif - throw DeadlyImportError("Validation failed: " + std::string(szBuffer,iLen)); -} -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::ReportWarning(const char* msg,...) -{ - ai_assert(NULL != msg); - - va_list args; - va_start(args,msg); - - char szBuffer[3000]; - const int iLen = vsprintf(szBuffer,msg,args); - ai_assert(iLen > 0); - - va_end(args); - DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen)); -} - -// ------------------------------------------------------------------------------------------------ -inline int HasNameMatch(const aiString& in, aiNode* node) -{ - int result = (node->mName == in ? 1 : 0 ); - for (unsigned int i = 0; i < node->mNumChildren;++i) { - result += HasNameMatch(in,node->mChildren[i]); - } - return result; -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -inline void ValidateDSProcess::DoValidation(T** parray, unsigned int size, - const char* firstName, const char* secondName) -{ - // validate all entries - if (size) - { - if (!parray) - { - ReportError("aiScene::%s is NULL (aiScene::%s is %i)", - firstName, secondName, size); - } - for (unsigned int i = 0; i < size;++i) - { - if (!parray[i]) - { - ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)", - firstName,i,secondName,size); - } - Validate(parray[i]); - } - } -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -inline void ValidateDSProcess::DoValidationEx(T** parray, unsigned int size, - const char* firstName, const char* secondName) -{ - // validate all entries - if (size) - { - if (!parray) { - ReportError("aiScene::%s is NULL (aiScene::%s is %i)", - firstName, secondName, size); - } - for (unsigned int i = 0; i < size;++i) - { - if (!parray[i]) - { - ReportError("aiScene::%s[%i] is NULL (aiScene::%s is %i)", - firstName,i,secondName,size); - } - Validate(parray[i]); - - // check whether there are duplicate names - for (unsigned int a = i+1; a < size;++a) - { - if (parray[i]->mName == parray[a]->mName) - { - this->ReportError("aiScene::%s[%i] has the same name as " - "aiScene::%s[%i]",firstName, i,secondName, a); - } - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -template <typename T> -inline void ValidateDSProcess::DoValidationWithNameCheck(T** array, - unsigned int size, const char* firstName, - const char* secondName) -{ - // validate all entries - DoValidationEx(array,size,firstName,secondName); - - for (unsigned int i = 0; i < size;++i) - { - int res = HasNameMatch(array[i]->mName,mScene->mRootNode); - if (!res) { - ReportError("aiScene::%s[%i] has no corresponding node in the scene graph (%s)", - firstName,i,array[i]->mName.data); - } - else if (1 != res) { - ReportError("aiScene::%s[%i]: there are more than one nodes with %s as name", - firstName,i,array[i]->mName.data); - } - } -} - -// ------------------------------------------------------------------------------------------------ -// Executes the post processing step on the given imported data. -void ValidateDSProcess::Execute( aiScene* pScene) -{ - this->mScene = pScene; - DefaultLogger::get()->debug("ValidateDataStructureProcess begin"); - - // validate the node graph of the scene - Validate(pScene->mRootNode); - - // validate all meshes - if (pScene->mNumMeshes) { - DoValidation(pScene->mMeshes,pScene->mNumMeshes,"mMeshes","mNumMeshes"); - } - else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - ReportError("aiScene::mNumMeshes is 0. At least one mesh must be there"); - } - else if (pScene->mMeshes) { - ReportError("aiScene::mMeshes is non-null although there are no meshes"); - } - - // validate all animations - if (pScene->mNumAnimations) { - DoValidation(pScene->mAnimations,pScene->mNumAnimations, - "mAnimations","mNumAnimations"); - } - else if (pScene->mAnimations) { - ReportError("aiScene::mAnimations is non-null although there are no animations"); - } - - // validate all cameras - if (pScene->mNumCameras) { - DoValidationWithNameCheck(pScene->mCameras,pScene->mNumCameras, - "mCameras","mNumCameras"); - } - else if (pScene->mCameras) { - ReportError("aiScene::mCameras is non-null although there are no cameras"); - } - - // validate all lights - if (pScene->mNumLights) { - DoValidationWithNameCheck(pScene->mLights,pScene->mNumLights, - "mLights","mNumLights"); - } - else if (pScene->mLights) { - ReportError("aiScene::mLights is non-null although there are no lights"); - } - - // validate all textures - if (pScene->mNumTextures) { - DoValidation(pScene->mTextures,pScene->mNumTextures, - "mTextures","mNumTextures"); - } - else if (pScene->mTextures) { - ReportError("aiScene::mTextures is non-null although there are no textures"); - } - - // validate all materials - if (pScene->mNumMaterials) { - DoValidation(pScene->mMaterials,pScene->mNumMaterials,"mMaterials","mNumMaterials"); - } -#if 0 - // NOTE: ScenePreprocessor generates a default material if none is there - else if (!(mScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)) { - ReportError("aiScene::mNumMaterials is 0. At least one material must be there"); - } -#endif - else if (pScene->mMaterials) { - ReportError("aiScene::mMaterials is non-null although there are no materials"); - } - -// if (!has)ReportError("The aiScene data structure is empty"); - DefaultLogger::get()->debug("ValidateDataStructureProcess end"); -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiLight* pLight) -{ - if (pLight->mType == aiLightSource_UNDEFINED) - ReportWarning("aiLight::mType is aiLightSource_UNDEFINED"); - - if (!pLight->mAttenuationConstant && - !pLight->mAttenuationLinear && - !pLight->mAttenuationQuadratic) { - ReportWarning("aiLight::mAttenuationXXX - all are zero"); - } - - if (pLight->mAngleInnerCone > pLight->mAngleOuterCone) - ReportError("aiLight::mAngleInnerCone is larger than aiLight::mAngleOuterCone"); - - if (pLight->mColorDiffuse.IsBlack() && pLight->mColorAmbient.IsBlack() - && pLight->mColorSpecular.IsBlack()) - { - ReportWarning("aiLight::mColorXXX - all are black and won't have any influence"); - } -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiCamera* pCamera) -{ - if (pCamera->mClipPlaneFar <= pCamera->mClipPlaneNear) - ReportError("aiCamera::mClipPlaneFar must be >= aiCamera::mClipPlaneNear"); - - // FIX: there are many 3ds files with invalid FOVs. No reason to - // reject them at all ... a warning is appropriate. - if (!pCamera->mHorizontalFOV || pCamera->mHorizontalFOV >= (float)AI_MATH_PI) - ReportWarning("%f is not a valid value for aiCamera::mHorizontalFOV",pCamera->mHorizontalFOV); -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMesh* pMesh) -{ - // validate the material index of the mesh - if (mScene->mNumMaterials && pMesh->mMaterialIndex >= mScene->mNumMaterials) - { - ReportError("aiMesh::mMaterialIndex is invalid (value: %i maximum: %i)", - pMesh->mMaterialIndex,mScene->mNumMaterials-1); - } - - Validate(&pMesh->mName); - - for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) - { - aiFace& face = pMesh->mFaces[i]; - - if (pMesh->mPrimitiveTypes) - { - switch (face.mNumIndices) - { - case 0: - ReportError("aiMesh::mFaces[%i].mNumIndices is 0",i); - case 1: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POINT)) - { - ReportError("aiMesh::mFaces[%i] is a POINT but aiMesh::mPrimtiveTypes " - "does not report the POINT flag",i); - } - break; - case 2: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_LINE)) - { - ReportError("aiMesh::mFaces[%i] is a LINE but aiMesh::mPrimtiveTypes " - "does not report the LINE flag",i); - } - break; - case 3: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE)) - { - ReportError("aiMesh::mFaces[%i] is a TRIANGLE but aiMesh::mPrimtiveTypes " - "does not report the TRIANGLE flag",i); - } - break; - default: - if (0 == (pMesh->mPrimitiveTypes & aiPrimitiveType_POLYGON)) - { - this->ReportError("aiMesh::mFaces[%i] is a POLYGON but aiMesh::mPrimtiveTypes " - "does not report the POLYGON flag",i); - } - break; - }; - } - - if (!face.mIndices) - ReportError("aiMesh::mFaces[%i].mIndices is NULL",i); - } - - // positions must always be there ... - if (!pMesh->mNumVertices || (!pMesh->mVertices && !mScene->mFlags)) { - ReportError("The mesh contains no vertices"); - } - - if (pMesh->mNumVertices > AI_MAX_VERTICES) { - ReportError("Mesh has too many vertices: %u, but the limit is %u",pMesh->mNumVertices,AI_MAX_VERTICES); - } - if (pMesh->mNumFaces > AI_MAX_FACES) { - ReportError("Mesh has too many faces: %u, but the limit is %u",pMesh->mNumFaces,AI_MAX_FACES); - } - - // if tangents are there there must also be bitangent vectors ... - if ((pMesh->mTangents != NULL) != (pMesh->mBitangents != NULL)) { - ReportError("If there are tangents, bitangent vectors must be present as well"); - } - - // faces, too - if (!pMesh->mNumFaces || (!pMesh->mFaces && !mScene->mFlags)) { - ReportError("Mesh contains no faces"); - } - - // now check whether the face indexing layout is correct: - // unique vertices, pseudo-indexed. - std::vector<bool> abRefList; - abRefList.resize(pMesh->mNumVertices,false); - for (unsigned int i = 0; i < pMesh->mNumFaces;++i) - { - aiFace& face = pMesh->mFaces[i]; - if (face.mNumIndices > AI_MAX_FACE_INDICES) { - ReportError("Face %u has too many faces: %u, but the limit is %u",i,face.mNumIndices,AI_MAX_FACE_INDICES); - } - - for (unsigned int a = 0; a < face.mNumIndices;++a) - { - if (face.mIndices[a] >= pMesh->mNumVertices) { - ReportError("aiMesh::mFaces[%i]::mIndices[%i] is out of range",i,a); - } - // the MSB flag is temporarily used by the extra verbose - // mode to tell us that the JoinVerticesProcess might have - // been executed already. - if ( !(this->mScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT ) && abRefList[face.mIndices[a]]) - { - ReportError("aiMesh::mVertices[%i] is referenced twice - second " - "time by aiMesh::mFaces[%i]::mIndices[%i]",face.mIndices[a],i,a); - } - abRefList[face.mIndices[a]] = true; - } - } - - // check whether there are vertices that aren't referenced by a face - bool b = false; - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) { - if (!abRefList[i])b = true; - } - abRefList.clear(); - if (b)ReportWarning("There are unreferenced vertices"); - - // texture channel 2 may not be set if channel 1 is zero ... - { - unsigned int i = 0; - for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - { - if (!pMesh->HasTextureCoords(i))break; - } - for (;i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i) - if (pMesh->HasTextureCoords(i)) - { - ReportError("Texture coordinate channel %i exists " - "although the previous channel was NULL.",i); - } - } - // the same for the vertex colors - { - unsigned int i = 0; - for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i) - { - if (!pMesh->HasVertexColors(i))break; - } - for (;i < AI_MAX_NUMBER_OF_COLOR_SETS;++i) - if (pMesh->HasVertexColors(i)) - { - ReportError("Vertex color channel %i is exists " - "although the previous channel was NULL.",i); - } - } - - - // now validate all bones - if (pMesh->mNumBones) - { - if (!pMesh->mBones) - { - ReportError("aiMesh::mBones is NULL (aiMesh::mNumBones is %i)", - pMesh->mNumBones); - } - boost::scoped_array<float> afSum(NULL); - if (pMesh->mNumVertices) - { - afSum.reset(new float[pMesh->mNumVertices]); - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) - afSum[i] = 0.0f; - } - - // check whether there are duplicate bone names - for (unsigned int i = 0; i < pMesh->mNumBones;++i) - { - const aiBone* bone = pMesh->mBones[i]; - if (bone->mNumWeights > AI_MAX_BONE_WEIGHTS) { - ReportError("Bone %u has too many weights: %u, but the limit is %u",i,bone->mNumWeights,AI_MAX_BONE_WEIGHTS); - } - - if (!pMesh->mBones[i]) - { - ReportError("aiMesh::mBones[%i] is NULL (aiMesh::mNumBones is %i)", - i,pMesh->mNumBones); - } - Validate(pMesh,pMesh->mBones[i],afSum.get()); - - for (unsigned int a = i+1; a < pMesh->mNumBones;++a) - { - if (pMesh->mBones[i]->mName == pMesh->mBones[a]->mName) - { - ReportError("aiMesh::mBones[%i] has the same name as " - "aiMesh::mBones[%i]",i,a); - } - } - } - // check whether all bone weights for a vertex sum to 1.0 ... - for (unsigned int i = 0; i < pMesh->mNumVertices;++i) - { - if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05)) { - ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]); - } - } - } - else if (pMesh->mBones) - { - ReportError("aiMesh::mBones is non-null although there are no bones"); - } -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMesh* pMesh, - const aiBone* pBone,float* afSum) -{ - this->Validate(&pBone->mName); - - if (!pBone->mNumWeights) { - ReportError("aiBone::mNumWeights is zero"); - } - - // check whether all vertices affected by this bone are valid - for (unsigned int i = 0; i < pBone->mNumWeights;++i) - { - if (pBone->mWeights[i].mVertexId >= pMesh->mNumVertices) { - ReportError("aiBone::mWeights[%i].mVertexId is out of range",i); - } - else if (!pBone->mWeights[i].mWeight || pBone->mWeights[i].mWeight > 1.0f) { - ReportWarning("aiBone::mWeights[%i].mWeight has an invalid value",i); - } - afSum[pBone->mWeights[i].mVertexId] += pBone->mWeights[i].mWeight; - } -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiAnimation* pAnimation) -{ - Validate(&pAnimation->mName); - - // validate all materials - if (pAnimation->mNumChannels) - { - if (!pAnimation->mChannels) { - ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)", - pAnimation->mNumChannels); - } - for (unsigned int i = 0; i < pAnimation->mNumChannels;++i) - { - if (!pAnimation->mChannels[i]) - { - ReportError("aiAnimation::mChannels[%i] is NULL (aiAnimation::mNumChannels is %i)", - i, pAnimation->mNumChannels); - } - Validate(pAnimation, pAnimation->mChannels[i]); - } - } - else ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there."); - - // Animation duration is allowed to be zero in cases where the anim contains only a single key frame. - // if (!pAnimation->mDuration)this->ReportError("aiAnimation::mDuration is zero"); -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::SearchForInvalidTextures(const aiMaterial* pMaterial, - aiTextureType type) -{ - const char* szType = TextureTypeToString(type); - - // **************************************************************************** - // Search all keys of the material ... - // textures must be specified with ascending indices - // (e.g. diffuse #2 may not be specified if diffuse #1 is not there ...) - // **************************************************************************** - - int iNumIndices = 0; - int iIndex = -1; - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) - { - aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (!::strcmp(prop->mKey.data,"$tex.file") && prop->mSemantic == type) { - iIndex = std::max(iIndex, (int) prop->mIndex); - ++iNumIndices; - - if (aiPTI_String != prop->mType) - ReportError("Material property %s is expected to be a string",prop->mKey.data); - } - } - if (iIndex +1 != iNumIndices) { - ReportError("%s #%i is set, but there are only %i %s textures", - szType,iIndex,iNumIndices,szType); - } - if (!iNumIndices)return; - std::vector<aiTextureMapping> mappings(iNumIndices); - - // Now check whether all UV indices are valid ... - bool bNoSpecified = true; - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) - { - aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (prop->mSemantic != type)continue; - - if ((int)prop->mIndex >= iNumIndices) - { - ReportError("Found texture property with index %i, although there " - "are only %i textures of type %s", - prop->mIndex, iNumIndices, szType); - } - - if (!::strcmp(prop->mKey.data,"$tex.mapping")) { - if (aiPTI_Integer != prop->mType || prop->mDataLength < sizeof(aiTextureMapping)) - { - ReportError("Material property %s%i is expected to be an integer (size is %i)", - prop->mKey.data,prop->mIndex,prop->mDataLength); - } - mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData); - } - else if (!::strcmp(prop->mKey.data,"$tex.uvtrafo")) { - if (aiPTI_Float != prop->mType || prop->mDataLength < sizeof(aiUVTransform)) - { - ReportError("Material property %s%i is expected to be 5 floats large (size is %i)", - prop->mKey.data,prop->mIndex, prop->mDataLength); - } - mappings[prop->mIndex] = *((aiTextureMapping*)prop->mData); - } - else if (!::strcmp(prop->mKey.data,"$tex.uvwsrc")) { - if (aiPTI_Integer != prop->mType || sizeof(int) > prop->mDataLength) - { - ReportError("Material property %s%i is expected to be an integer (size is %i)", - prop->mKey.data,prop->mIndex,prop->mDataLength); - } - bNoSpecified = false; - - // Ignore UV indices for texture channels that are not there ... - - // Get the value - iIndex = *((unsigned int*)prop->mData); - - // Check whether there is a mesh using this material - // which has not enough UV channels ... - for (unsigned int a = 0; a < mScene->mNumMeshes;++a) - { - aiMesh* mesh = this->mScene->mMeshes[a]; - if (mesh->mMaterialIndex == (unsigned int)i) - { - int iChannels = 0; - while (mesh->HasTextureCoords(iChannels))++iChannels; - if (iIndex >= iChannels) - { - ReportWarning("Invalid UV index: %i (key %s). Mesh %i has only %i UV channels", - iIndex,prop->mKey.data,a,iChannels); - } - } - } - } - } - if (bNoSpecified) - { - // Assume that all textures are using the first UV channel - for (unsigned int a = 0; a < mScene->mNumMeshes;++a) - { - aiMesh* mesh = mScene->mMeshes[a]; - if (mesh->mMaterialIndex == (unsigned int)iIndex && mappings[0] == aiTextureMapping_UV) - { - if (!mesh->mTextureCoords[0]) - { - // This is a special case ... it could be that the - // original mesh format intended the use of a special - // mapping here. - ReportWarning("UV-mapped texture, but there are no UV coords"); - } - } - } - } -} -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiMaterial* pMaterial) -{ - // check whether there are material keys that are obviously not legal - for (unsigned int i = 0; i < pMaterial->mNumProperties;++i) - { - const aiMaterialProperty* prop = pMaterial->mProperties[i]; - if (!prop) { - ReportError("aiMaterial::mProperties[%i] is NULL (aiMaterial::mNumProperties is %i)", - i,pMaterial->mNumProperties); - } - if (!prop->mDataLength || !prop->mData) { - ReportError("aiMaterial::mProperties[%i].mDataLength or " - "aiMaterial::mProperties[%i].mData is 0",i,i); - } - // check all predefined types - if (aiPTI_String == prop->mType) { - // FIX: strings are now stored in a less expensive way, but we can't use the - // validation routine for 'normal' aiStrings - uint32_t len; - if (prop->mDataLength < 5 || prop->mDataLength < 4 + (len=*reinterpret_cast<uint32_t*>(prop->mData)) + 1) { - ReportError("aiMaterial::mProperties[%i].mDataLength is " - "too small to contain a string (%i, needed: %i)", - i,prop->mDataLength,sizeof(aiString)); - } - if (prop->mData[prop->mDataLength-1]) { - ReportError("Missing null-terminator in string material property"); - } - // Validate((const aiString*)prop->mData); - } - else if (aiPTI_Float == prop->mType) { - if (prop->mDataLength < sizeof(float)) { - ReportError("aiMaterial::mProperties[%i].mDataLength is " - "too small to contain a float (%i, needed: %i)", - i,prop->mDataLength,sizeof(float)); - } - } - else if (aiPTI_Integer == prop->mType) { - if (prop->mDataLength < sizeof(int)) { - ReportError("aiMaterial::mProperties[%i].mDataLength is " - "too small to contain an integer (%i, needed: %i)", - i,prop->mDataLength,sizeof(int)); - } - } - // TODO: check whether there is a key with an unknown name ... - } - - // make some more specific tests - float fTemp; - int iShading; - if (AI_SUCCESS == aiGetMaterialInteger( pMaterial,AI_MATKEY_SHADING_MODEL,&iShading)) { - switch ((aiShadingMode)iShading) - { - case aiShadingMode_Blinn: - case aiShadingMode_CookTorrance: - case aiShadingMode_Phong: - - if (AI_SUCCESS != aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS,&fTemp)) { - ReportWarning("A specular shading model is specified but there is no " - "AI_MATKEY_SHININESS key"); - } - if (AI_SUCCESS == aiGetMaterialFloat(pMaterial,AI_MATKEY_SHININESS_STRENGTH,&fTemp) && !fTemp) { - ReportWarning("A specular shading model is specified but the value of the " - "AI_MATKEY_SHININESS_STRENGTH key is 0.0"); - } - break; - default: ; - }; - } - - if (AI_SUCCESS == aiGetMaterialFloat( pMaterial,AI_MATKEY_OPACITY,&fTemp) && (!fTemp || fTemp > 1.01f)) { - ReportWarning("Invalid opacity value (must be 0 < opacity < 1.0)"); - } - - // Check whether there are invalid texture keys - // TODO: that's a relict of the past, where texture type and index were baked - // into the material string ... we could do that in one single pass. - SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE); - SearchForInvalidTextures(pMaterial,aiTextureType_SPECULAR); - SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT); - SearchForInvalidTextures(pMaterial,aiTextureType_EMISSIVE); - SearchForInvalidTextures(pMaterial,aiTextureType_OPACITY); - SearchForInvalidTextures(pMaterial,aiTextureType_SHININESS); - SearchForInvalidTextures(pMaterial,aiTextureType_HEIGHT); - SearchForInvalidTextures(pMaterial,aiTextureType_NORMALS); - SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT); - SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP); - SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION); -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiTexture* pTexture) -{ - // the data section may NEVER be NULL - if (!pTexture->pcData) { - ReportError("aiTexture::pcData is NULL"); - } - if (pTexture->mHeight) - { - if (!pTexture->mWidth)ReportError("aiTexture::mWidth is zero " - "(aiTexture::mHeight is %i, uncompressed texture)",pTexture->mHeight); - } - else - { - if (!pTexture->mWidth) { - ReportError("aiTexture::mWidth is zero (compressed texture)"); - } - if ('\0' != pTexture->achFormatHint[3]) { - ReportWarning("aiTexture::achFormatHint must be zero-terminated"); - } - else if ('.' == pTexture->achFormatHint[0]) { - ReportWarning("aiTexture::achFormatHint should contain a file extension " - "without a leading dot (format hint: %s).",pTexture->achFormatHint); - } - } - - const char* sz = pTexture->achFormatHint; - if ((sz[0] >= 'A' && sz[0] <= 'Z') || - (sz[1] >= 'A' && sz[1] <= 'Z') || - (sz[2] >= 'A' && sz[2] <= 'Z') || - (sz[3] >= 'A' && sz[3] <= 'Z')) { - ReportError("aiTexture::achFormatHint contains non-lowercase letters"); - } -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiAnimation* pAnimation, - const aiNodeAnim* pNodeAnim) -{ - Validate(&pNodeAnim->mNodeName); - - if (!pNodeAnim->mNumPositionKeys && !pNodeAnim->mScalingKeys && !pNodeAnim->mNumRotationKeys) - ReportError("Empty node animation channel"); - - // otherwise check whether one of the keys exceeds the total duration of the animation - if (pNodeAnim->mNumPositionKeys) - { - if (!pNodeAnim->mPositionKeys) - { - this->ReportError("aiNodeAnim::mPositionKeys is NULL (aiNodeAnim::mNumPositionKeys is %i)", - pNodeAnim->mNumPositionKeys); - } - double dLast = -10e10; - for (unsigned int i = 0; i < pNodeAnim->mNumPositionKeys;++i) - { - // ScenePreprocessor will compute the duration if still the default value - // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration, - // seems to be due the compilers register usage/width. - if (pAnimation->mDuration > 0. && pNodeAnim->mPositionKeys[i].mTime > pAnimation->mDuration+0.001) - { - ReportError("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pNodeAnim->mPositionKeys[i].mTime, - (float)pAnimation->mDuration); - } - if (i && pNodeAnim->mPositionKeys[i].mTime <= dLast) - { - ReportWarning("aiNodeAnim::mPositionKeys[%i].mTime (%.5f) is smaller " - "than aiAnimation::mPositionKeys[%i] (which is %.5f)",i, - (float)pNodeAnim->mPositionKeys[i].mTime, - i-1, (float)dLast); - } - dLast = pNodeAnim->mPositionKeys[i].mTime; - } - } - // rotation keys - if (pNodeAnim->mNumRotationKeys) - { - if (!pNodeAnim->mRotationKeys) - { - this->ReportError("aiNodeAnim::mRotationKeys is NULL (aiNodeAnim::mNumRotationKeys is %i)", - pNodeAnim->mNumRotationKeys); - } - double dLast = -10e10; - for (unsigned int i = 0; i < pNodeAnim->mNumRotationKeys;++i) - { - if (pAnimation->mDuration > 0. && pNodeAnim->mRotationKeys[i].mTime > pAnimation->mDuration+0.001) - { - ReportError("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pNodeAnim->mRotationKeys[i].mTime, - (float)pAnimation->mDuration); - } - if (i && pNodeAnim->mRotationKeys[i].mTime <= dLast) - { - ReportWarning("aiNodeAnim::mRotationKeys[%i].mTime (%.5f) is smaller " - "than aiAnimation::mRotationKeys[%i] (which is %.5f)",i, - (float)pNodeAnim->mRotationKeys[i].mTime, - i-1, (float)dLast); - } - dLast = pNodeAnim->mRotationKeys[i].mTime; - } - } - // scaling keys - if (pNodeAnim->mNumScalingKeys) - { - if (!pNodeAnim->mScalingKeys) { - ReportError("aiNodeAnim::mScalingKeys is NULL (aiNodeAnim::mNumScalingKeys is %i)", - pNodeAnim->mNumScalingKeys); - } - double dLast = -10e10; - for (unsigned int i = 0; i < pNodeAnim->mNumScalingKeys;++i) - { - if (pAnimation->mDuration > 0. && pNodeAnim->mScalingKeys[i].mTime > pAnimation->mDuration+0.001) - { - ReportError("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is larger " - "than aiAnimation::mDuration (which is %.5f)",i, - (float)pNodeAnim->mScalingKeys[i].mTime, - (float)pAnimation->mDuration); - } - if (i && pNodeAnim->mScalingKeys[i].mTime <= dLast) - { - ReportWarning("aiNodeAnim::mScalingKeys[%i].mTime (%.5f) is smaller " - "than aiAnimation::mScalingKeys[%i] (which is %.5f)",i, - (float)pNodeAnim->mScalingKeys[i].mTime, - i-1, (float)dLast); - } - dLast = pNodeAnim->mScalingKeys[i].mTime; - } - } - - if (!pNodeAnim->mNumScalingKeys && !pNodeAnim->mNumRotationKeys && - !pNodeAnim->mNumPositionKeys) - { - ReportError("A node animation channel must have at least one subtrack"); - } -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiNode* pNode) -{ - if (!pNode)ReportError("A node of the scenegraph is NULL"); - if (pNode != mScene->mRootNode && !pNode->mParent) - this->ReportError("A node has no valid parent (aiNode::mParent is NULL)"); - - this->Validate(&pNode->mName); - - // validate all meshes - if (pNode->mNumMeshes) - { - if (!pNode->mMeshes) - { - ReportError("aiNode::mMeshes is NULL (aiNode::mNumMeshes is %i)", - pNode->mNumMeshes); - } - std::vector<bool> abHadMesh; - abHadMesh.resize(mScene->mNumMeshes,false); - for (unsigned int i = 0; i < pNode->mNumMeshes;++i) - { - if (pNode->mMeshes[i] >= mScene->mNumMeshes) - { - ReportError("aiNode::mMeshes[%i] is out of range (maximum is %i)", - pNode->mMeshes[i],mScene->mNumMeshes-1); - } - if (abHadMesh[pNode->mMeshes[i]]) - { - ReportError("aiNode::mMeshes[%i] is already referenced by this node (value: %i)", - i,pNode->mMeshes[i]); - } - abHadMesh[pNode->mMeshes[i]] = true; - } - } - if (pNode->mNumChildren) - { - if (!pNode->mChildren) { - ReportError("aiNode::mChildren is NULL (aiNode::mNumChildren is %i)", - pNode->mNumChildren); - } - for (unsigned int i = 0; i < pNode->mNumChildren;++i) { - Validate(pNode->mChildren[i]); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void ValidateDSProcess::Validate( const aiString* pString) -{ - if (pString->length > MAXLEN) - { - this->ReportError("aiString::length is too large (%i, maximum is %i)", - pString->length,MAXLEN); - } - const char* sz = pString->data; - while (true) - { - if ('\0' == *sz) - { - if (pString->length != (unsigned int)(sz-pString->data)) - ReportError("aiString::data is invalid: the terminal zero is at a wrong offset"); - break; - } - else if (sz >= &pString->data[MAXLEN]) - ReportError("aiString::data is invalid. There is no terminal character"); - ++sz; - } -} diff --git a/3rdparty/assimp/code/ValidateDataStructure.h b/3rdparty/assimp/code/ValidateDataStructure.h deleted file mode 100644 index e9aa12fb..00000000 --- a/3rdparty/assimp/code/ValidateDataStructure.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a (dummy) post processing step to validate the loader's - * output data structure (for debugging) - */ -#ifndef AI_VALIDATEPROCESS_H_INC -#define AI_VALIDATEPROCESS_H_INC - -#include "../include/aiTypes.h" -#include "BaseProcess.h" - -struct aiBone; -struct aiMesh; -struct aiAnimation; -struct aiNodeAnim; -struct aiTexture; -struct aiMaterial; -struct aiNode; -struct aiString; - -namespace Assimp { - -// -------------------------------------------------------------------------------------- -/** Validates the whole ASSIMP scene data structure for correctness. - * ImportErrorException is thrown of the scene is corrupt.*/ -// -------------------------------------------------------------------------------------- -class ASSIMP_API ValidateDSProcess : public BaseProcess -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - ValidateDSProcess(); - - /** Destructor, private as well */ - ~ValidateDSProcess(); - -public: - // ------------------------------------------------------------------- - bool IsActive( unsigned int pFlags) const; - - // ------------------------------------------------------------------- - void Execute( aiScene* pScene); - -protected: - - // ------------------------------------------------------------------- - /** Report a validation error. This will throw an exception, - * control won't return. - * @param msg Format string for sprintf().*/ - AI_WONT_RETURN void ReportError(const char* msg,...); - - - // ------------------------------------------------------------------- - /** Report a validation warning. This won't throw an exception, - * control will return to the callera. - * @param msg Format string for sprintf().*/ - void ReportWarning(const char* msg,...); - - - // ------------------------------------------------------------------- - /** Validates a mesh - * @param pMesh Input mesh*/ - void Validate( const aiMesh* pMesh); - - // ------------------------------------------------------------------- - /** Validates a bone - * @param pMesh Input mesh - * @param pBone Input bone*/ - void Validate( const aiMesh* pMesh,const aiBone* pBone,float* afSum); - - // ------------------------------------------------------------------- - /** Validates an animation - * @param pAnimation Input animation*/ - void Validate( const aiAnimation* pAnimation); - - // ------------------------------------------------------------------- - /** Validates a material - * @param pMaterial Input material*/ - void Validate( const aiMaterial* pMaterial); - - // ------------------------------------------------------------------- - /** Search the material data structure for invalid or corrupt - * texture keys. - * @param pMaterial Input material - * @param type Type of the texture*/ - void SearchForInvalidTextures(const aiMaterial* pMaterial, - aiTextureType type); - - // ------------------------------------------------------------------- - /** Validates a texture - * @param pTexture Input texture*/ - void Validate( const aiTexture* pTexture); - - // ------------------------------------------------------------------- - /** Validates a light source - * @param pLight Input light - */ - void Validate( const aiLight* pLight); - - // ------------------------------------------------------------------- - /** Validates a camera - * @param pCamera Input camera*/ - void Validate( const aiCamera* pCamera); - - // ------------------------------------------------------------------- - /** Validates a bone animation channel - * @param pAnimation Animation channel. - * @param pBoneAnim Input bone animation */ - void Validate( const aiAnimation* pAnimation, - const aiNodeAnim* pBoneAnim); - - // ------------------------------------------------------------------- - /** Validates a node and all of its subnodes - * @param Node Input node*/ - void Validate( const aiNode* pNode); - - // ------------------------------------------------------------------- - /** Validates a string - * @param pString Input string*/ - void Validate( const aiString* pString); - -private: - - // template to validate one of the aiScene::mXXX arrays - template <typename T> - inline void DoValidation(T** array, unsigned int size, - const char* firstName, const char* secondName); - - // extended version: checks whethr T::mName occurs twice - template <typename T> - inline void DoValidationEx(T** array, unsigned int size, - const char* firstName, const char* secondName); - - // extension to the first template which does also search - // the nodegraph for an item with the same name - template <typename T> - inline void DoValidationWithNameCheck(T** array, unsigned int size, - const char* firstName, const char* secondName); - - aiScene* mScene; -}; - - - - -} // end of namespace Assimp - -#endif // AI_VALIDATEPROCESS_H_INC diff --git a/3rdparty/assimp/code/Vertex.h b/3rdparty/assimp/code/Vertex.h deleted file mode 100644 index 51e5c84d..00000000 --- a/3rdparty/assimp/code/Vertex.h +++ /dev/null @@ -1,301 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a helper class to represent an interleaved vertex */ -#ifndef AI_VERTEX_H_INC -#define AI_VERTEX_H_INC -namespace Assimp { - - /////////////////////////////////////////////////////////////////////////// - // std::plus-family operates on operands with identical types - we need to - // support all the (vectype op float) combinations in vector maths. - // Providing T(float) would open the way to endless implicit conversions. - /////////////////////////////////////////////////////////////////////////// - namespace Intern { - template <typename T0, typename T1, typename TRES = T0> struct plus { - TRES operator() (const T0& t0, const T1& t1) const { - return t0+t1; - } - }; - template <typename T0, typename T1, typename TRES = T0> struct minus { - TRES operator() (const T0& t0, const T1& t1) const { - return t0-t1; - } - }; - template <typename T0, typename T1, typename TRES = T0> struct multiplies { - TRES operator() (const T0& t0, const T1& t1) const { - return t0*t1; - } - }; - template <typename T0, typename T1, typename TRES = T0> struct divides { - TRES operator() (const T0& t0, const T1& t1) const { - return t0/t1; - } - }; - } - -// ------------------------------------------------------------------------------------------------ -/** Intermediate description a vertex with all possible components. Defines a full set of - * operators, so you may use such a 'Vertex' in basic arithmetics. All operators are applied - * to *all* vertex components equally. This is useful for stuff like interpolation - * or subdivision, but won't work if special handling is required for some vertex components. */ -// ------------------------------------------------------------------------------------------------ -class Vertex -{ - friend Vertex operator + (const Vertex&,const Vertex&); - friend Vertex operator - (const Vertex&,const Vertex&); - - friend Vertex operator + (const Vertex&,float); - friend Vertex operator - (const Vertex&,float); - friend Vertex operator * (const Vertex&,float); - friend Vertex operator / (const Vertex&,float); - - friend Vertex operator + (float, const Vertex&); - friend Vertex operator - (float, const Vertex&); - friend Vertex operator * (float, const Vertex&); - friend Vertex operator / (float, const Vertex&); - -public: - - Vertex() {} - - // ---------------------------------------------------------------------------- - /** Extract a particular vertex from a mesh and interleave all components */ - explicit Vertex(const aiMesh* msh, unsigned int idx) { - ai_assert(idx < msh->mNumVertices); - position = msh->mVertices[idx]; - - if (msh->HasNormals()) { - normal = msh->mNormals[idx]; - } - - if (msh->HasTangentsAndBitangents()) { - tangent = msh->mTangents[idx]; - bitangent = msh->mBitangents[idx]; - } - - for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) { - texcoords[i] = msh->mTextureCoords[i][idx]; - } - - for (unsigned int i = 0; msh->HasVertexColors(i); ++i) { - colors[i] = msh->mColors[i][idx]; - } - } - -public: - - Vertex& operator += (const Vertex& v) { - *this = *this+v; - return *this; - } - - Vertex& operator -= (const Vertex& v) { - *this = *this-v; - return *this; - } - - - - Vertex& operator += (float v) { - *this = *this+v; - return *this; - } - - Vertex& operator -= (float v) { - *this = *this-v; - return *this; - } - - Vertex& operator *= (float v) { - *this = *this*v; - return *this; - } - - Vertex& operator /= (float v) { - *this = *this/v; - return *this; - } - -public: - - // ---------------------------------------------------------------------------- - /** Convert back to non-interleaved storage */ - void SortBack(aiMesh* out, unsigned int idx) const { - - ai_assert(idx<out->mNumVertices); - out->mVertices[idx] = position; - - if (out->HasNormals()) { - out->mNormals[idx] = normal; - } - - if (out->HasTangentsAndBitangents()) { - out->mTangents[idx] = tangent; - out->mBitangents[idx] = bitangent; - } - - for (unsigned int i = 0; out->HasTextureCoords(i); ++i) { - out->mTextureCoords[i][idx] = texcoords[i]; - } - - for (unsigned int i = 0; out->HasVertexColors(i); ++i) { - out->mColors[i][idx] = colors[i]; - } - } - -private: - - // ---------------------------------------------------------------------------- - /** Construct from two operands and a binary operation to combine them */ - template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) { - // this is a heavy task for the compiler to optimize ... *pray* - - Vertex res; - res.position = op<aiVector3D>()(v0.position,v1.position); - res.normal = op<aiVector3D>()(v0.normal,v1.normal); - res.tangent = op<aiVector3D>()(v0.tangent,v1.tangent); - res.bitangent = op<aiVector3D>()(v0.bitangent,v1.bitangent); - - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - res.texcoords[i] = op<aiVector3D>()(v0.texcoords[i],v1.texcoords[i]); - } - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { - res.colors[i] = op<aiColor4D>()(v0.colors[i],v1.colors[i]); - } - return res; - } - - // ---------------------------------------------------------------------------- - /** This time binary arithmetics of v0 with a floating-point number */ - template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, float f) { - // this is a heavy task for the compiler to optimize ... *pray* - - Vertex res; - res.position = op<aiVector3D,float,aiVector3D>()(v0.position,f); - res.normal = op<aiVector3D,float,aiVector3D>()(v0.normal,f); - res.tangent = op<aiVector3D,float,aiVector3D>()(v0.tangent,f); - res.bitangent = op<aiVector3D,float,aiVector3D>()(v0.bitangent,f); - - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - res.texcoords[i] = op<aiVector3D,float,aiVector3D>()(v0.texcoords[i],f); - } - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { - res.colors[i] = op<aiColor4D,float,aiColor4D>()(v0.colors[i],f); - } - return res; - } - - // ---------------------------------------------------------------------------- - /** This time binary arithmetics of v0 with a floating-point number */ - template <template <typename, typename, typename> class op> static Vertex BinaryOp(float f, const Vertex& v0) { - // this is a heavy task for the compiler to optimize ... *pray* - - Vertex res; - res.position = op<float,aiVector3D,aiVector3D>()(f,v0.position); - res.normal = op<float,aiVector3D,aiVector3D>()(f,v0.normal); - res.tangent = op<float,aiVector3D,aiVector3D>()(f,v0.tangent); - res.bitangent = op<float,aiVector3D,aiVector3D>()(f,v0.bitangent); - - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { - res.texcoords[i] = op<float,aiVector3D,aiVector3D>()(f,v0.texcoords[i]); - } - for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) { - res.colors[i] = op<float,aiColor4D,aiColor4D>()(f,v0.colors[i]); - } - return res; - } - -public: - - aiVector3D position; - aiVector3D normal; - aiVector3D tangent, bitangent; - - aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS]; -}; - - - -// ------------------------------------------------------------------------------------------------ -AI_FORCE_INLINE Vertex operator + (const Vertex& v0,const Vertex& v1) { - return Vertex::BinaryOp<std::plus>(v0,v1); -} - -AI_FORCE_INLINE Vertex operator - (const Vertex& v0,const Vertex& v1) { - return Vertex::BinaryOp<std::minus>(v0,v1); -} - -// ------------------------------------------------------------------------------------------------ -AI_FORCE_INLINE Vertex operator + (const Vertex& v0,float f) { - return Vertex::BinaryOp<Intern::plus>(v0,f); -} - -AI_FORCE_INLINE Vertex operator - (const Vertex& v0,float f) { - return Vertex::BinaryOp<Intern::minus>(v0,f); -} - -AI_FORCE_INLINE Vertex operator * (const Vertex& v0,float f) { - return Vertex::BinaryOp<Intern::multiplies>(v0,f); -} - -AI_FORCE_INLINE Vertex operator / (const Vertex& v0,float f) { - return Vertex::BinaryOp<Intern::divides>(v0,f); -} - -// ------------------------------------------------------------------------------------------------ -AI_FORCE_INLINE Vertex operator + (float f,const Vertex& v0) { - return Vertex::BinaryOp<Intern::plus>(f,v0); -} - -AI_FORCE_INLINE Vertex operator - (float f,const Vertex& v0) { - return Vertex::BinaryOp<Intern::minus>(f,v0); -} - -AI_FORCE_INLINE Vertex operator * (float f,const Vertex& v0) { - return Vertex::BinaryOp<Intern::multiplies>(f,v0); -} - -AI_FORCE_INLINE Vertex operator / (float f,const Vertex& v0) { - return Vertex::BinaryOp<Intern::divides>(f,v0); -} - -} -#endif diff --git a/3rdparty/assimp/code/VertexTriangleAdjacency.cpp b/3rdparty/assimp/code/VertexTriangleAdjacency.cpp deleted file mode 100644 index 07ab5090..00000000 --- a/3rdparty/assimp/code/VertexTriangleAdjacency.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 VertexTriangleAdjacency helper class - */ - -#include "AssimpPCH.h" - -// internal headers -#include "VertexTriangleAdjacency.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -VertexTriangleAdjacency::VertexTriangleAdjacency(aiFace *pcFaces, - unsigned int iNumFaces, - unsigned int iNumVertices /*= 0*/, - bool bComputeNumTriangles /*= false*/) -{ - // compute the number of referenced vertices if it wasn't specified by the caller - const aiFace* const pcFaceEnd = pcFaces + iNumFaces; - if (!iNumVertices) { - - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) { - ai_assert(3 == pcFace->mNumIndices); - iNumVertices = std::max(iNumVertices,pcFace->mIndices[0]); - iNumVertices = std::max(iNumVertices,pcFace->mIndices[1]); - iNumVertices = std::max(iNumVertices,pcFace->mIndices[2]); - } - } - unsigned int* pi; - - // allocate storage - if (bComputeNumTriangles) { - pi = mLiveTriangles = new unsigned int[iNumVertices+1]; - memset(mLiveTriangles,0,sizeof(unsigned int)*(iNumVertices+1)); - mOffsetTable = new unsigned int[iNumVertices+2]+1; - } - else { - pi = mOffsetTable = new unsigned int[iNumVertices+2]+1; - memset(mOffsetTable,0,sizeof(unsigned int)*(iNumVertices+1)); - mLiveTriangles = NULL; // important, otherwise the d'tor would crash - } - - // get a pointer to the end of the buffer - unsigned int* piEnd = pi+iNumVertices; - *piEnd++ = 0u; - - // first pass: compute the number of faces referencing each vertex - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace) - { - pi[pcFace->mIndices[0]]++; - pi[pcFace->mIndices[1]]++; - pi[pcFace->mIndices[2]]++; - } - - // second pass: compute the final offset table - unsigned int iSum = 0; - unsigned int* piCurOut = this->mOffsetTable; - for (unsigned int* piCur = pi; piCur != piEnd;++piCur,++piCurOut) { - - unsigned int iLastSum = iSum; - iSum += *piCur; - *piCurOut = iLastSum; - } - pi = this->mOffsetTable; - - // third pass: compute the final table - this->mAdjacencyTable = new unsigned int[iSum]; - iSum = 0; - for (aiFace* pcFace = pcFaces; pcFace != pcFaceEnd; ++pcFace,++iSum) { - - unsigned int idx = pcFace->mIndices[0]; - mAdjacencyTable[pi[idx]++] = iSum; - - idx = pcFace->mIndices[1]; - mAdjacencyTable[pi[idx]++] = iSum; - - idx = pcFace->mIndices[2]; - mAdjacencyTable[pi[idx]++] = iSum; - } - // fourth pass: undo the offset computations made during the third pass - // We could do this in a separate buffer, but this would be TIMES slower. - --mOffsetTable; - *mOffsetTable = 0u; -} -// ------------------------------------------------------------------------------------------------ -VertexTriangleAdjacency::~VertexTriangleAdjacency() -{ - // delete allocated storage - delete[] mOffsetTable; - delete[] mAdjacencyTable; - delete[] mLiveTriangles; -} diff --git a/3rdparty/assimp/code/VertexTriangleAdjacency.h b/3rdparty/assimp/code/VertexTriangleAdjacency.h deleted file mode 100644 index f5d2f7b2..00000000 --- a/3rdparty/assimp/code/VertexTriangleAdjacency.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines a helper class to compute a vertex-triangle adjacency map */ -#ifndef AI_VTADJACENCY_H_INC -#define AI_VTADJACENCY_H_INC - -#include "BaseProcess.h" -#include "../include/aiTypes.h" -#include "../include/aiAssert.h" - -struct aiMesh; -namespace Assimp { - -// -------------------------------------------------------------------------------------------- -/** @brief The VertexTriangleAdjacency class computes a vertex-triangle - * adjacency map from a given index buffer. - * - * @note Although it is called #VertexTriangleAdjacency, the current version does also - * support arbitrary polygons. */ -// -------------------------------------------------------------------------------------------- -class ASSIMP_API VertexTriangleAdjacency -{ -public: - - // ---------------------------------------------------------------------------- - /** @brief Construction from an existing index buffer - * @param pcFaces Index buffer - * @param iNumFaces Number of faces in the buffer - * @param iNumVertices Number of referenced vertices. This value - * is computed automatically if 0 is specified. - * @param bComputeNumTriangles If you want the class to compute - * a list containing the number of referenced triangles per vertex - * per vertex - pass true. */ - VertexTriangleAdjacency(aiFace* pcFaces,unsigned int iNumFaces, - unsigned int iNumVertices = 0, - bool bComputeNumTriangles = true); - - - // ---------------------------------------------------------------------------- - /** @brief Destructor */ - ~VertexTriangleAdjacency(); - - -public: - - // ---------------------------------------------------------------------------- - /** @brief Get all triangles adjacent to a vertex - * @param iVertIndex Index of the vertex - * @return A pointer to the adjacency list. */ - unsigned int* GetAdjacentTriangles(unsigned int iVertIndex) const - { - ai_assert(iVertIndex < iNumVertices); - return &mAdjacencyTable[ mOffsetTable[iVertIndex]]; - } - - - // ---------------------------------------------------------------------------- - /** @brief Get the number of triangles that are referenced by - * a vertex. This function returns a reference that can be modified - * @param iVertIndex Index of the vertex - * @return Number of referenced triangles */ - unsigned int& GetNumTrianglesPtr(unsigned int iVertIndex) - { - ai_assert(iVertIndex < iNumVertices && NULL != mLiveTriangles); - return mLiveTriangles[iVertIndex]; - } - - -public: - - //! Offset table - unsigned int* mOffsetTable; - - //! Adjacency table - unsigned int* mAdjacencyTable; - - //! Table containing the number of referenced triangles per vertex - unsigned int* mLiveTriangles; - - //! Debug: Number of referenced vertices - unsigned int iNumVertices; - -}; -} - -#endif // !! AI_VTADJACENCY_H_INC diff --git a/3rdparty/assimp/code/Win32DebugLogStream.h b/3rdparty/assimp/code/Win32DebugLogStream.h deleted file mode 100644 index a17b5f05..00000000 --- a/3rdparty/assimp/code/Win32DebugLogStream.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef AI_WIN32DEBUGLOGSTREAM_H_INC -#define AI_WIN32DEBUGLOGSTREAM_H_INC - -#ifdef WIN32 - -#include "../include/LogStream.h" -#include "Windows.h" - -namespace Assimp { - -// --------------------------------------------------------------------------- -/** @class Win32DebugLogStream - * @brief Logs into the debug stream from win32. - */ -class Win32DebugLogStream : - public LogStream -{ -public: - /** @brief Default constructor */ - Win32DebugLogStream(); - - /** @brief Destructor */ - ~Win32DebugLogStream(); - - /** @brief Writer */ - void write(const char* messgae); -}; - -// --------------------------------------------------------------------------- -// Default constructor -inline Win32DebugLogStream::Win32DebugLogStream() -{} - -// --------------------------------------------------------------------------- -// Default constructor -inline Win32DebugLogStream::~Win32DebugLogStream() -{} - -// --------------------------------------------------------------------------- -// Write method -inline void Win32DebugLogStream::write(const char* message) -{ - OutputDebugStringA( message); -} - -// --------------------------------------------------------------------------- -} // Namespace Assimp - -#endif // ! WIN32 -#endif // guard diff --git a/3rdparty/assimp/code/XFileHelper.h b/3rdparty/assimp/code/XFileHelper.h deleted file mode 100644 index 23b8f77c..00000000 --- a/3rdparty/assimp/code/XFileHelper.h +++ /dev/null @@ -1,200 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Defines the helper data structures for importing XFiles */ -#ifndef AI_XFILEHELPER_H_INC -#define AI_XFILEHELPER_H_INC - -#include <string> -#include <vector> - -#include "../include/aiTypes.h" -#include "../include/aiQuaternion.h" -#include "../include/aiMesh.h" -#include "../include/aiAnim.h" - -namespace Assimp -{ -namespace XFile -{ - -/** Helper structure representing a XFile mesh face */ -struct Face -{ - std::vector<unsigned int> mIndices; -}; - -/** Helper structure representing a texture filename inside a material and its potential source */ -struct TexEntry -{ - std::string mName; - bool mIsNormalMap; // true if the texname was specified in a NormalmapFilename tag - - TexEntry() { mIsNormalMap = false; } - TexEntry( const std::string& pName, bool pIsNormalMap = false) - : mName( pName), mIsNormalMap( pIsNormalMap) - { /* done */ } -}; - -/** Helper structure representing a XFile material */ -struct Material -{ - std::string mName; - bool mIsReference; // if true, mName holds a name by which the actual material can be found in the material list - aiColor4D mDiffuse; - float mSpecularExponent; - aiColor3D mSpecular; - aiColor3D mEmissive; - std::vector<TexEntry> mTextures; - - Material() { mIsReference = false; } -}; - -/** Helper structure to represent a bone weight */ -struct BoneWeight -{ - unsigned int mVertex; - float mWeight; -}; - -/** Helper structure to represent a bone in a mesh */ -struct Bone -{ - std::string mName; - std::vector<BoneWeight> mWeights; - aiMatrix4x4 mOffsetMatrix; -}; - -/** Helper structure to represent an XFile mesh */ -struct Mesh -{ - std::vector<aiVector3D> mPositions; - std::vector<Face> mPosFaces; - std::vector<aiVector3D> mNormals; - std::vector<Face> mNormFaces; - unsigned int mNumTextures; - std::vector<aiVector2D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; - unsigned int mNumColorSets; - std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS]; - - std::vector<unsigned int> mFaceMaterials; - std::vector<Material> mMaterials; - - std::vector<Bone> mBones; - - Mesh() { mNumTextures = 0; mNumColorSets = 0; } -}; - -/** Helper structure to represent a XFile frame */ -struct Node -{ - std::string mName; - aiMatrix4x4 mTrafoMatrix; - Node* mParent; - std::vector<Node*> mChildren; - std::vector<Mesh*> mMeshes; - - Node() { mParent = NULL; } - Node( Node* pParent) { mParent = pParent; } - ~Node() - { - for ( unsigned int a = 0; a < mChildren.size(); a++) - delete mChildren[a]; - for ( unsigned int a = 0; a < mMeshes.size(); a++) - delete mMeshes[a]; - } -}; - -struct MatrixKey -{ - double mTime; - aiMatrix4x4 mMatrix; -}; - -/** Helper structure representing a single animated bone in a XFile */ -struct AnimBone -{ - std::string mBoneName; - std::vector<aiVectorKey> mPosKeys; // either three separate key sequences for position, rotation, scaling - std::vector<aiQuatKey> mRotKeys; - std::vector<aiVectorKey> mScaleKeys; - std::vector<MatrixKey> mTrafoKeys; // or a combined key sequence of transformation matrices. -}; - -/** Helper structure to represent an animation set in a XFile */ -struct Animation -{ - std::string mName; - std::vector<AnimBone*> mAnims; - - ~Animation() - { - for ( unsigned int a = 0; a < mAnims.size(); a++) - delete mAnims[a]; - } -}; - -/** Helper structure analogue to aiScene */ -struct Scene -{ - Node* mRootNode; - - std::vector<Mesh*> mGlobalMeshes; // global meshes found outside of any frames - std::vector<Material> mGlobalMaterials; // global materials found outside of any meshes. - - std::vector<Animation*> mAnims; - unsigned int mAnimTicksPerSecond; - - Scene() { mRootNode = NULL; mAnimTicksPerSecond = 0; } - ~Scene() - { - delete mRootNode; - for ( unsigned int a = 0; a < mGlobalMeshes.size(); a++) - delete mGlobalMeshes[a]; - for ( unsigned int a = 0; a < mAnims.size(); a++) - delete mAnims[a]; - } -}; - -} // end of namespace XFile -} // end of namespace Assimp - -#endif // AI_XFILEHELPER_H_INC diff --git a/3rdparty/assimp/code/XFileImporter.cpp b/3rdparty/assimp/code/XFileImporter.cpp deleted file mode 100644 index 1abfb1f2..00000000 --- a/3rdparty/assimp/code/XFileImporter.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 XFileImporter.cpp - * @brief Implementation of the XFile importer class - */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_X_IMPORTER - -#include "XFileImporter.h" -#include "XFileParser.h" -#include "ConvertToLHProcess.h" - -using namespace Assimp; - -// ------------------------------------------------------------------------------------------------ -// Constructor to be privately used by Importer -XFileImporter::XFileImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -XFileImporter::~XFileImporter() -{} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const -{ - std::string extension = GetExtension(pFile); - if (extension == "x") { - return true; - } - if (!extension.length() || checkSig) { - uint32_t token[1]; - token[0] = AI_MAKE_MAGIC("xof "); - return CheckMagicToken(pIOHandler,pFile,token,1,0); - } - return false; -} - -// ------------------------------------------------------------------------------------------------ -void XFileImporter::GetExtensionList(std::set<std::string>& extensions) -{ - extensions.insert("x"); -} - -// ------------------------------------------------------------------------------------------------ -// Imports the given file into the given scene structure. -void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) -{ - // read file into memory - boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - if ( file.get() == NULL) - throw DeadlyImportError( "Failed to open file " + pFile + "."); - - size_t fileSize = file->FileSize(); - if ( fileSize < 16) - throw DeadlyImportError( "XFile is too small."); - - // need to clear members - this method might be called multiple - // times on a single XFileImporter instance. - mImportedMats.clear(); - - // in the hope that binary files will never start with a BOM ... - mBuffer.resize( fileSize); - file->Read( &mBuffer.front(), 1, fileSize); - ConvertToUTF8(mBuffer); - - // parse the file into a temporary representation - XFileParser parser( mBuffer); - - // and create the proper return structures out of it - CreateDataRepresentationFromImport( pScene, parser.GetImportedData()); - - // if nothing came from it, report it as error - if ( !pScene->mRootNode) - throw DeadlyImportError( "XFile is ill-formatted - no content imported."); -} - -// ------------------------------------------------------------------------------------------------ -// Constructs the return data structure out of the imported data. -void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, const XFile::Scene* pData) -{ - // Read the global materials first so that meshes referring to them can find them later - ConvertMaterials( pScene, pData->mGlobalMaterials); - - // copy nodes, extracting meshes and materials on the way - pScene->mRootNode = CreateNodes( pScene, NULL, pData->mRootNode); - - // extract animations - CreateAnimations( pScene, pData); - - // read the global meshes that were stored outside of any node - if ( pData->mGlobalMeshes.size() > 0) - { - // create a root node to hold them if there isn't any, yet - if ( pScene->mRootNode == NULL) - { - pScene->mRootNode = new aiNode; - pScene->mRootNode->mName.Set( "$dummy_node"); - } - - // convert all global meshes and store them in the root node. - // If there was one before, the global meshes now suddenly have its transformation matrix... - // Don't know what to do there, I don't want to insert another node under the present root node - // just to avoid this. - CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes); - } - - // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly - MakeLeftHandedProcess convertProcess; - convertProcess.Execute( pScene); - - FlipWindingOrderProcess flipper; - flipper.Execute(pScene); - - // finally: create a dummy material if not material was imported - if ( pScene->mNumMaterials == 0) - { - pScene->mNumMaterials = 1; - // create the Material - Assimp::MaterialHelper* mat = new Assimp::MaterialHelper; - int shadeMode = (int) aiShadingMode_Gouraud; - mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); - // material colours - int specExp = 1; - - aiColor3D clr = aiColor3D( 0, 0, 0); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR); - - clr = aiColor3D( 0.5f, 0.5f, 0.5f); - mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS); - - pScene->mMaterials = new aiMaterial*[1]; - pScene->mMaterials[0] = mat; - } -} - -// ------------------------------------------------------------------------------------------------ -// Recursively creates scene nodes from the imported hierarchy. -aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode) -{ - if ( !pNode) - return NULL; - - // create node - aiNode* node = new aiNode; - node->mName.length = pNode->mName.length(); - node->mParent = pParent; - memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length()); - node->mName.data[node->mName.length] = 0; - node->mTransformation = pNode->mTrafoMatrix; - - // convert meshes from the source node - CreateMeshes( pScene, node, pNode->mMeshes); - - // handle childs - if ( pNode->mChildren.size() > 0) - { - node->mNumChildren = (unsigned int)pNode->mChildren.size(); - node->mChildren = new aiNode* [node->mNumChildren]; - - for ( unsigned int a = 0; a < pNode->mChildren.size(); a++) - node->mChildren[a] = CreateNodes( pScene, node, pNode->mChildren[a]); - } - - return node; -} - -// ------------------------------------------------------------------------------------------------ -// Creates the meshes for the given node. -void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes) -{ - if ( pMeshes.size() == 0) - return; - - // create a mesh for each mesh-material combination in the source node - std::vector<aiMesh*> meshes; - for ( unsigned int a = 0; a < pMeshes.size(); a++) - { - const XFile::Mesh* sourceMesh = pMeshes[a]; - // first convert its materials so that we can find them when searching by name afterwards - ConvertMaterials( pScene, sourceMesh->mMaterials); - - unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u); - for ( unsigned int b = 0; b < numMaterials; b++) - { - // collect the faces belonging to this material - std::vector<unsigned int> faces; - unsigned int numVertices = 0; - if ( sourceMesh->mFaceMaterials.size() > 0) - { - // if there is a per-face material defined, select the faces with the corresponding material - for ( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); c++) - { - if ( sourceMesh->mFaceMaterials[c] == b) - { - faces.push_back( c); - numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); - } - } - } else - { - // if there is no per-face material, place everything into one mesh - for ( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); c++) - { - faces.push_back( c); - numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); - } - } - - // no faces/vertices using this material? strange... - if ( numVertices == 0) - continue; - - // create a submesh using this material - aiMesh* mesh = new aiMesh; - meshes.push_back( mesh); - - // find the material by name in the scene's material list. Either own material - // or referenced material, it should already be found there - if ( sourceMesh->mFaceMaterials.size() > 0) - { - std::map<std::string, unsigned int>::const_iterator matIt = mImportedMats.find( sourceMesh->mMaterials[b].mName); - if ( matIt == mImportedMats.end()) - mesh->mMaterialIndex = 0; - else - mesh->mMaterialIndex = matIt->second; - } else - { - mesh->mMaterialIndex = 0; - } - - // Create properly sized data arrays in the mesh. We store unique vertices per face, - // as specified - mesh->mNumVertices = numVertices; - mesh->mVertices = new aiVector3D[numVertices]; - mesh->mNumFaces = (unsigned int)faces.size(); - mesh->mFaces = new aiFace[mesh->mNumFaces]; - - // normals? - if ( sourceMesh->mNormals.size() > 0) - mesh->mNormals = new aiVector3D[numVertices]; - // texture coords - for ( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; c++) - { - if ( sourceMesh->mTexCoords[c].size() > 0) - mesh->mTextureCoords[c] = new aiVector3D[numVertices]; - } - // vertex colors - for ( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; c++) - { - if ( sourceMesh->mColors[c].size() > 0) - mesh->mColors[c] = new aiColor4D[numVertices]; - } - - // now collect the vertex data of all data streams present in the imported mesh - unsigned int newIndex = 0; - std::vector<unsigned int> orgPoints; // from which original point each new vertex stems - orgPoints.resize( numVertices, 0); - - for ( unsigned int c = 0; c < faces.size(); c++) - { - unsigned int f = faces[c]; // index of the source face - const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face - - // create face. either triangle or triangle fan depending on the index count - aiFace& df = mesh->mFaces[c]; // destination face - df.mNumIndices = (unsigned int)pf.mIndices.size(); - df.mIndices = new unsigned int[ df.mNumIndices]; - - // collect vertex data for indices of this face - for ( unsigned int d = 0; d < df.mNumIndices; d++) - { - df.mIndices[d] = newIndex; - orgPoints[newIndex] = pf.mIndices[d]; - - // Position - mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]]; - // Normal, if present - if ( mesh->HasNormals()) - mesh->mNormals[newIndex] = sourceMesh->mNormals[sourceMesh->mNormFaces[f].mIndices[d]]; - - // texture coord sets - for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; e++) - { - if ( mesh->HasTextureCoords( e)) - { - aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]]; - mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f); - } - } - // vertex color sets - for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; e++) - if ( mesh->HasVertexColors( e)) - mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]]; - - newIndex++; - } - } - - // there should be as much new vertices as we calculated before - assert( newIndex == numVertices); - - // convert all bones of the source mesh which influence vertices in this newly created mesh - const std::vector<XFile::Bone>& bones = sourceMesh->mBones; - std::vector<aiBone*> newBones; - for ( unsigned int c = 0; c < bones.size(); c++) - { - const XFile::Bone& obone = bones[c]; - // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex - std::vector<float> oldWeights( sourceMesh->mPositions.size(), 0.0f); - for ( unsigned int d = 0; d < obone.mWeights.size(); d++) - oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight; - - // collect all vertex weights that influence a vertex in the new mesh - std::vector<aiVertexWeight> newWeights; - newWeights.reserve( numVertices); - for ( unsigned int d = 0; d < orgPoints.size(); d++) - { - // does the new vertex stem from an old vertex which was influenced by this bone? - float w = oldWeights[orgPoints[d]]; - if ( w > 0.0f) - newWeights.push_back( aiVertexWeight( d, w)); - } - - // if the bone has no weights in the newly created mesh, ignore it - if ( newWeights.size() == 0) - continue; - - // create - aiBone* nbone = new aiBone; - newBones.push_back( nbone); - // copy name and matrix - nbone->mName.Set( obone.mName); - nbone->mOffsetMatrix = obone.mOffsetMatrix; - nbone->mNumWeights = (unsigned int)newWeights.size(); - nbone->mWeights = new aiVertexWeight[nbone->mNumWeights]; - for ( unsigned int d = 0; d < newWeights.size(); d++) - nbone->mWeights[d] = newWeights[d]; - } - - // store the bones in the mesh - mesh->mNumBones = (unsigned int)newBones.size(); - if ( newBones.size() > 0) - { - mesh->mBones = new aiBone*[mesh->mNumBones]; - std::copy( newBones.begin(), newBones.end(), mesh->mBones); - } - } - } - - // reallocate scene mesh array to be large enough - aiMesh** prevArray = pScene->mMeshes; - pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()]; - if ( prevArray) - { - memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*)); - delete [] prevArray; - } - - // allocate mesh index array in the node - pNode->mNumMeshes = (unsigned int)meshes.size(); - pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; - - // store all meshes in the mesh library of the scene and store their indices in the node - for ( unsigned int a = 0; a < meshes.size(); a++) - { - pScene->mMeshes[pScene->mNumMeshes] = meshes[a]; - pNode->mMeshes[a] = pScene->mNumMeshes; - pScene->mNumMeshes++; - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts the animations from the given imported data and creates them in the scene. -void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData) -{ - std::vector<aiAnimation*> newAnims; - - for ( unsigned int a = 0; a < pData->mAnims.size(); a++) - { - const XFile::Animation* anim = pData->mAnims[a]; - // some exporters mock me with empty animation tags. - if ( anim->mAnims.size() == 0) - continue; - - // create a new animation to hold the data - aiAnimation* nanim = new aiAnimation; - newAnims.push_back( nanim); - nanim->mName.Set( anim->mName); - // duration will be determined by the maximum length - nanim->mDuration = 0; - nanim->mTicksPerSecond = pData->mAnimTicksPerSecond; - nanim->mNumChannels = (unsigned int)anim->mAnims.size(); - nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels]; - - for ( unsigned int b = 0; b < anim->mAnims.size(); b++) - { - const XFile::AnimBone* bone = anim->mAnims[b]; - aiNodeAnim* nbone = new aiNodeAnim; - nbone->mNodeName.Set( bone->mBoneName); - nanim->mChannels[b] = nbone; - - // keyframes are given as combined transformation matrix keys - if ( bone->mTrafoKeys.size() > 0) - { - nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size(); - nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; - nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size(); - nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; - nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size(); - nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - - for ( unsigned int c = 0; c < bone->mTrafoKeys.size(); c++) - { - // deconstruct each matrix into separate position, rotation and scaling - double time = bone->mTrafoKeys[c].mTime; - aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix; - - // extract position - aiVector3D pos( trafo.a4, trafo.b4, trafo.c4); - - nbone->mPositionKeys[c].mTime = time; - nbone->mPositionKeys[c].mValue = pos; - - // extract scaling - aiVector3D scale; - scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length(); - scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length(); - scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length(); - nbone->mScalingKeys[c].mTime = time; - nbone->mScalingKeys[c].mValue = scale; - - // reconstruct rotation matrix without scaling - aiMatrix3x3 rotmat( - trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, - trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, - trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); - - // and convert it into a quaternion - nbone->mRotationKeys[c].mTime = time; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); - } - - // longest lasting key sequence determines duration - nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime); - } else - { - // separate key sequences for position, rotation, scaling - nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size(); - nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; - for ( unsigned int c = 0; c < nbone->mNumPositionKeys; c++) - { - aiVector3D pos = bone->mPosKeys[c].mValue; - - nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime; - nbone->mPositionKeys[c].mValue = pos; - } - - // rotation - nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size(); - nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; - for ( unsigned int c = 0; c < nbone->mNumRotationKeys; c++) - { - aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix(); - - nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime; - nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); - nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion - } - - // scaling - nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size(); - nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; - for ( unsigned int c = 0; c < nbone->mNumScalingKeys; c++) - nbone->mScalingKeys[c] = bone->mScaleKeys[c]; - - // longest lasting key sequence determines duration - if ( bone->mPosKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime); - if ( bone->mRotKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime); - if ( bone->mScaleKeys.size() > 0) - nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime); - } - } - } - - // store all converted animations in the scene - if ( newAnims.size() > 0) - { - pScene->mNumAnimations = (unsigned int)newAnims.size(); - pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations]; - for ( unsigned int a = 0; a < newAnims.size(); a++) - pScene->mAnimations[a] = newAnims[a]; - } -} - -// ------------------------------------------------------------------------------------------------ -// Converts all materials in the given array and stores them in the scene's material list. -void XFileImporter::ConvertMaterials( aiScene* pScene, const std::vector<XFile::Material>& pMaterials) -{ - // count the non-referrer materials in the array - unsigned int numMaterials = 0; - for ( unsigned int a = 0; a < pMaterials.size(); a++) - if ( !pMaterials[a].mIsReference) - numMaterials++; - - if ( numMaterials == 0) - return; - - // resize the scene's material list to offer enough space for the new materials - aiMaterial** prevMats = pScene->mMaterials; - pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numMaterials]; - if ( prevMats) - { - memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*)); - delete [] prevMats; - } - - // convert all the materials given in the array - for ( unsigned int a = 0; a < pMaterials.size(); a++) - { - const XFile::Material& oldMat = pMaterials[a]; - if ( oldMat.mIsReference) - continue; - - Assimp::MaterialHelper* mat = new Assimp::MaterialHelper; - aiString name; - name.Set( oldMat.mName); - mat->AddProperty( &name, AI_MATKEY_NAME); - - // Shading model: hardcoded to PHONG, there is no such information in an XFile - // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix - // for some models in the SDK (e.g. good old tiny.x) - int shadeMode = (int)oldMat.mSpecularExponent == 0.0f - ? aiShadingMode_Gouraud : aiShadingMode_Phong; - - mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); - // material colours - // FIX: Setup this as ambient not as emissive color - mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_AMBIENT); - mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); - mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); - mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); - - - // texture, if there is one - if (1 == oldMat.mTextures.size()) - { - const XFile::TexEntry& otex = oldMat.mTextures.back(); - if (otex.mName.length()) - { - // if there is only one texture assume it contains the diffuse color - aiString tex( otex.mName); - if ( otex.mIsNormalMap) - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(0)); - else - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(0)); - } - } - else - { - // Otherwise ... try to search for typical strings in the - // texture's file name like 'bump' or 'diffuse' - unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0; - for ( unsigned int b = 0; b < oldMat.mTextures.size(); b++) - { - const XFile::TexEntry& otex = oldMat.mTextures[b]; - std::string sz = otex.mName; - if (!sz.length())continue; - - - // find the file name - //const size_t iLen = sz.length(); - std::string::size_type s = sz.find_last_of("\\/"); - if (std::string::npos == s) - s = 0; - - // cut off the file extension - std::string::size_type sExt = sz.find_last_of('.'); - if (std::string::npos != sExt){ - sz[sExt] = '\0'; - } - - // convert to lower case for easier comparision - for ( unsigned int c = 0; c < sz.length(); c++) - if ( isalpha( sz[c])) - sz[c] = tolower( sz[c]); - - - // Place texture filename property under the corresponding name - aiString tex( oldMat.mTextures[b].mName); - - // bump map - if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) - { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); - } else - if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) - { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); - } else - if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) - { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); - } else - if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) - { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); - } else - if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) - { - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); - } else - { - // Assume it is a diffuse texture - mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); - } - } - } - - pScene->mMaterials[pScene->mNumMaterials] = mat; - mImportedMats[oldMat.mName] = pScene->mNumMaterials; - pScene->mNumMaterials++; - } -} - -#endif // !! ASSIMP_BUILD_NO_X_IMPORTER - diff --git a/3rdparty/assimp/code/XFileImporter.h b/3rdparty/assimp/code/XFileImporter.h deleted file mode 100644 index 4dbce4b0..00000000 --- a/3rdparty/assimp/code/XFileImporter.h +++ /dev/null @@ -1,159 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 XFileImporter.h - * @brief Definition of the XFile importer class. - */ -#ifndef AI_XFILEIMPORTER_H_INC -#define AI_XFILEIMPORTER_H_INC - -#include <map> - -#include "XFileHelper.h" -#include "BaseImporter.h" - -#include "../include/aiTypes.h" - -struct aiNode; - -namespace Assimp { - -namespace XFile { -struct Scene; -struct Node; -} - -// --------------------------------------------------------------------------- -/** The XFileImporter is a worker class capable of importing a scene from a - * DirectX file .x - */ -class XFileImporter : public BaseImporter -{ - friend class Importer; - -protected: - /** Constructor to be privately used by Importer */ - XFileImporter(); - - /** Destructor, private as well */ - ~XFileImporter(); - -public: - // ------------------------------------------------------------------- - /** Returns whether the class can handle the format of the given file. - * See BaseImporter::CanRead() for details. */ - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool CheckSig) const; - -protected: - - // ------------------------------------------------------------------- - /** Called by Importer::GetExtensionList() for each loaded importer. - * See BaseImporter::GetExtensionList() for details - */ - void GetExtensionList(std::set<std::string>& extensions); - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); - - // ------------------------------------------------------------------- - /** Constructs the return data structure out of the imported data. - * @param pScene The scene to construct the return data in. - * @param pData The imported data in the internal temporary - * representation. - */ - void CreateDataRepresentationFromImport( aiScene* pScene, - const XFile::Scene* pData); - - // ------------------------------------------------------------------- - /** Recursively creates scene nodes from the imported hierarchy. - * The meshes and materials of the nodes will be extracted on the way. - * @param pScene The scene to construct the return data in. - * @param pParent The parent node where to create new child nodes - * @param pNode The temporary node to copy. - * @return The created node - */ - aiNode* CreateNodes( aiScene* pScene, aiNode* pParent, - const XFile::Node* pNode); - - // ------------------------------------------------------------------- - /** Converts all meshes in the given mesh array. Each mesh is splitted - * up per material, the indices of the generated meshes are stored in - * the node structure. - * @param pScene The scene to construct the return data in. - * @param pNode The target node structure that references the - * constructed meshes. - * @param pMeshes The array of meshes to convert - */ - void CreateMeshes( aiScene* pScene, aiNode* pNode, - const std::vector<XFile::Mesh*>& pMeshes); - - // ------------------------------------------------------------------- - /** Converts the animations from the given imported data and creates - * them in the scene. - * @param pScene The scene to hold to converted animations - * @param pData The data to read the animations from - */ - void CreateAnimations( aiScene* pScene, const XFile::Scene* pData); - - // ------------------------------------------------------------------- - /** Converts all materials in the given array and stores them in the - * scene's material list. - * @param pScene The scene to hold the converted materials. - * @param pMaterials The material array to convert. - */ - void ConvertMaterials( aiScene* pScene, - const std::vector<XFile::Material>& pMaterials); - -protected: - /** Buffer to hold the loaded file */ - std::vector<char> mBuffer; - - /** Imported materials: index in the scene's material list by name */ - std::map<std::string, unsigned int> mImportedMats; -}; - -} // end of namespace Assimp - -#endif // AI_BASEIMPORTER_H_INC diff --git a/3rdparty/assimp/code/XFileParser.cpp b/3rdparty/assimp/code/XFileParser.cpp deleted file mode 100644 index 229366ff..00000000 --- a/3rdparty/assimp/code/XFileParser.cpp +++ /dev/null @@ -1,1434 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 XFile parser helper class */ - -#include "AssimpPCH.h" -#ifndef ASSIMP_BUILD_NO_X_IMPORTER - -#include "XFileParser.h" -#include "XFileHelper.h" -#include "fast_atof.h" - -using namespace Assimp; -using namespace Assimp::XFile; - -#ifndef ASSIMP_BUILD_NO_COMPRESSED_X - -# ifdef ASSIMP_BUILD_NO_OWN_ZLIB -# include <zlib.h> -# else -# include "../contrib/zlib/zlib.h" -# endif - -// Magic identifier for MSZIP compressed data -#define MSZIP_MAGIC 0x4B43 -#define MSZIP_BLOCK 32786 - -// ------------------------------------------------------------------------------------------------ -// Dummy memory wrappers for use with zlib -static void* dummy_alloc (void* /*opaque*/, unsigned int items, unsigned int size) { - return ::operator new(items*size); -} - -static void dummy_free (void* /*opaque*/, void* address) { - return ::operator delete(address); -} - -#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X - -// ------------------------------------------------------------------------------------------------ -// Constructor. Creates a data structure out of the XFile given in the memory block. -XFileParser::XFileParser( const std::vector<char>& pBuffer) -{ - mMajorVersion = mMinorVersion = 0; - mIsBinaryFormat = false; - mBinaryNumCount = 0; - P = End = NULL; - mLineNumber = 0; - mScene = NULL; - - // vector to store uncompressed file for INFLATE'd X files - std::vector<char> uncompressed; - - // set up memory pointers - P = &pBuffer.front(); - End = P + pBuffer.size(); - - // check header - if ( strncmp( P, "xof ", 4) != 0) - throw DeadlyImportError( "Header mismatch, file is not an XFile."); - - // read version. It comes in a four byte format such as "0302" - mMajorVersion = (unsigned int)(P[4] - 48) * 10 + (unsigned int)(P[5] - 48); - mMinorVersion = (unsigned int)(P[6] - 48) * 10 + (unsigned int)(P[7] - 48); - - bool compressed = false; - - // txt - pure ASCII text format - if ( strncmp( P + 8, "txt ", 4) == 0) - mIsBinaryFormat = false; - - // bin - Binary format - else if ( strncmp( P + 8, "bin ", 4) == 0) - mIsBinaryFormat = true; - - // tzip - Inflate compressed text format - else if ( strncmp( P + 8, "tzip", 4) == 0) - { - mIsBinaryFormat = false; - compressed = true; - } - // bzip - Inflate compressed binary format - else if ( strncmp( P + 8, "bzip", 4) == 0) - { - mIsBinaryFormat = true; - compressed = true; - } - else ThrowException( boost::str(boost::format("Unsupported xfile format '%c%c%c%c'") - % P[8] % P[9] % P[10] % P[11])); - - // float size - mBinaryFloatSize = (unsigned int)(P[12] - 48) * 1000 - + (unsigned int)(P[13] - 48) * 100 - + (unsigned int)(P[14] - 48) * 10 - + (unsigned int)(P[15] - 48); - - if ( mBinaryFloatSize != 32 && mBinaryFloatSize != 64) - ThrowException( boost::str( boost::format( "Unknown float size %1% specified in xfile header.") - % mBinaryFloatSize)); - - P += 16; - - // If this is a compressed X file, apply the inflate algorithm to it - if (compressed) - { -#ifdef ASSIMP_BUILD_NO_COMPRESSED_X - throw DeadlyImportError("Assimp was built without compressed X support"); -#else - /* /////////////////////////////////////////////////////////////////////// - * COMPRESSED X FILE FORMAT - * /////////////////////////////////////////////////////////////////////// - * [xhead] - * 2 major - * 2 minor - * 4 type // bzip,tzip - * [mszip_master_head] - * 4 unkn // checksum? - * 2 unkn // flags? (seems to be constant) - * [mszip_head] - * 2 ofs // offset to next section - * 2 magic // 'CK' - * ... ofs bytes of data - * ... next mszip_head - * - * http://www.kdedevelopers.org/node/3181 has been very helpful. - * /////////////////////////////////////////////////////////////////////// - */ - - // build a zlib stream - z_stream stream; - stream.opaque = NULL; - stream.zalloc = &dummy_alloc; - stream.zfree = &dummy_free; - stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII); - - // initialize the inflation algorithm - ::inflateInit2(&stream, -MAX_WBITS); - - // skip unknown data (checksum, flags?) - P += 6; - - // First find out how much storage we'll need. Count sections. - const char* P1 = P; - unsigned int est_out = 0; - while (P1 < End) - { - // read next offset - uint16_t ofs = *((uint16_t*)P1); - AI_SWAP2(ofs); P1 += 2; - - if (ofs >= MSZIP_BLOCK) - throw DeadlyImportError("X: Invalid offset to next MSZIP compressed block"); - - // check magic word - uint16_t magic = *((uint16_t*)P1); - AI_SWAP2(magic); P1 += 2; - - if (magic != MSZIP_MAGIC) - throw DeadlyImportError("X: Unsupported compressed format, expected MSZIP header"); - - // and advance to the next offset - P1 += ofs; - est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size - } - - // Allocate storage and do the actual uncompressing - uncompressed.resize(est_out); - char* out = &uncompressed.front(); - while (P < End) - { - uint16_t ofs = *((uint16_t*)P); - AI_SWAP2(ofs); - P += 4; - - // push data to the stream - stream.next_in = (Bytef*)P; - stream.avail_in = ofs; - stream.next_out = (Bytef*)out; - stream.avail_out = MSZIP_BLOCK; - - // and decompress the data .... - int ret = ::inflate( &stream, Z_SYNC_FLUSH ); - if (ret != Z_OK && ret != Z_STREAM_END) - throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data"); - - ::inflateReset( &stream ); - ::inflateSetDictionary( &stream, (const Bytef*)out , MSZIP_BLOCK - stream.avail_out ); - - // and advance to the next offset - out += MSZIP_BLOCK - stream.avail_out; - P += ofs; - } - - // terminate zlib - ::inflateEnd(&stream); - - // ok, update pointers to point to the uncompressed file data - P = &uncompressed[0]; - End = out; - - // FIXME: we don't need the compressed data anymore, could release - // it already for better memory usage. Consider breaking const-co. - DefaultLogger::get()->info("Successfully decompressed MSZIP-compressed file"); -#endif // !! ASSIMP_BUILD_NO_COMPRESSED_X - } - else - { - // start reading here - ReadUntilEndOfLine(); - } - - mScene = new Scene; - ParseFile(); - - // filter the imported hierarchy for some degenerated cases - if ( mScene->mRootNode) { - FilterHierarchy( mScene->mRootNode); - } -} - -// ------------------------------------------------------------------------------------------------ -// Destructor. Destroys all imported data along with it -XFileParser::~XFileParser() -{ - // kill everything we created - delete mScene; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseFile() -{ - bool running = true; - while ( running ) - { - // read name of next object - std::string objectName = GetNextToken(); - if (objectName.length() == 0) - break; - - // parse specific object - if ( objectName == "template") - ParseDataObjectTemplate(); - else - if ( objectName == "Frame") - ParseDataObjectFrame( NULL); - else - if ( objectName == "Mesh") - { - // some meshes have no frames at all - Mesh* mesh = new Mesh; - ParseDataObjectMesh( mesh); - mScene->mGlobalMeshes.push_back( mesh); - } else - if ( objectName == "AnimTicksPerSecond") - ParseDataObjectAnimTicksPerSecond(); - else - if ( objectName == "AnimationSet") - ParseDataObjectAnimationSet(); - else - if ( objectName == "Material") - { - // Material outside of a mesh or node - Material material; - ParseDataObjectMaterial( &material); - mScene->mGlobalMaterials.push_back( material); - } else - if ( objectName == "}") - { - // whatever? - DefaultLogger::get()->warn("} found in dataObject"); - } else - { - // unknown format - DefaultLogger::get()->warn("Unknown data object in animation of .x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTemplate() -{ - // parse a template data object. Currently not stored. - std::string name; - readHeadOfDataObject( &name); - - // read GUID - std::string guid = GetNextToken(); - - // read and ignore data members - bool running = true; - while ( running ) - { - std::string s = GetNextToken(); - - if ( s == "}") - break; - - if ( s.length() == 0) - ThrowException( "Unexpected end of file reached while parsing template definition"); - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectFrame( Node* pParent) -{ - // A coordinate frame, or "frame of reference." The Frame template - // is open and can contain any object. The Direct3D extensions (D3DX) - // mesh-loading functions recognize Mesh, FrameTransformMatrix, and - // Frame template instances as child objects when loading a Frame - // instance. - std::string name; - readHeadOfDataObject(&name); - - // create a named node and place it at its parent, if given - Node* node = new Node( pParent); - node->mName = name; - if ( pParent) - { - pParent->mChildren.push_back( node); - } else - { - // there might be multiple root nodes - if ( mScene->mRootNode != NULL) - { - // place a dummy root if not there - if ( mScene->mRootNode->mName != "$dummy_root") - { - Node* exroot = mScene->mRootNode; - mScene->mRootNode = new Node( NULL); - mScene->mRootNode->mName = "$dummy_root"; - mScene->mRootNode->mChildren.push_back( exroot); - exroot->mParent = mScene->mRootNode; - } - // put the new node as its child instead - mScene->mRootNode->mChildren.push_back( node); - node->mParent = mScene->mRootNode; - } else - { - // it's the first node imported. place it as root - mScene->mRootNode = node; - } - } - - // Now inside a frame. - // read tokens until closing brace is reached. - bool running = true; - while ( running ) - { - std::string objectName = GetNextToken(); - if (objectName.size() == 0) - ThrowException( "Unexpected end of file reached while parsing frame"); - - if ( objectName == "}") - break; // frame finished - else - if ( objectName == "Frame") - ParseDataObjectFrame( node); // child frame - else - if ( objectName == "FrameTransformMatrix") - ParseDataObjectTransformationMatrix( node->mTrafoMatrix); - else - if ( objectName == "Mesh") - { - Mesh* mesh = new Mesh; - node->mMeshes.push_back( mesh); - ParseDataObjectMesh( mesh); - } else - { - DefaultLogger::get()->warn("Unknown data object in frame in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix) -{ - // read header, we're not interested if it has a name - readHeadOfDataObject(); - - // read its components - pMatrix.a1 = ReadFloat(); pMatrix.b1 = ReadFloat(); - pMatrix.c1 = ReadFloat(); pMatrix.d1 = ReadFloat(); - pMatrix.a2 = ReadFloat(); pMatrix.b2 = ReadFloat(); - pMatrix.c2 = ReadFloat(); pMatrix.d2 = ReadFloat(); - pMatrix.a3 = ReadFloat(); pMatrix.b3 = ReadFloat(); - pMatrix.c3 = ReadFloat(); pMatrix.d3 = ReadFloat(); - pMatrix.a4 = ReadFloat(); pMatrix.b4 = ReadFloat(); - pMatrix.c4 = ReadFloat(); pMatrix.d4 = ReadFloat(); - - // trailing symbols - CheckForSemicolon(); - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMesh( Mesh* pMesh) -{ - std::string name; - readHeadOfDataObject( &name); - - // read vertex count - unsigned int numVertices = ReadInt(); - pMesh->mPositions.resize( numVertices); - - // read vertices - for ( unsigned int a = 0; a < numVertices; a++) - pMesh->mPositions[a] = ReadVector3(); - - // read position faces - unsigned int numPosFaces = ReadInt(); - pMesh->mPosFaces.resize( numPosFaces); - for ( unsigned int a = 0; a < numPosFaces; a++) - { - unsigned int numIndices = ReadInt(); - if ( numIndices < 3) - ThrowException( boost::str( boost::format( "Invalid index count %1% for face %2%.") % numIndices % a)); - - // read indices - Face& face = pMesh->mPosFaces[a]; - for ( unsigned int b = 0; b < numIndices; b++) - face.mIndices.push_back( ReadInt()); - CheckForSeparator(); - } - - // here, other data objects may follow - bool running = true; - while ( running ) - { - std::string objectName = GetNextToken(); - - if ( objectName.size() == 0) - ThrowException( "Unexpected end of file while parsing mesh structure"); - else - if ( objectName == "}") - break; // mesh finished - else - if ( objectName == "MeshNormals") - ParseDataObjectMeshNormals( pMesh); - else - if ( objectName == "MeshTextureCoords") - ParseDataObjectMeshTextureCoords( pMesh); - else - if ( objectName == "MeshVertexColors") - ParseDataObjectMeshVertexColors( pMesh); - else - if ( objectName == "MeshMaterialList") - ParseDataObjectMeshMaterialList( pMesh); - else - if ( objectName == "VertexDuplicationIndices") - ParseUnknownDataObject(); // we'll ignore vertex duplication indices - else - if ( objectName == "XSkinMeshHeader") - ParseDataObjectSkinMeshHeader( pMesh); - else - if ( objectName == "SkinWeights") - ParseDataObjectSkinWeights( pMesh); - else - { - DefaultLogger::get()->warn("Unknown data object in mesh in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectSkinWeights( Mesh *pMesh) -{ - readHeadOfDataObject(); - - std::string transformNodeName; - GetNextTokenAsString( transformNodeName); - - pMesh->mBones.push_back( Bone()); - Bone& bone = pMesh->mBones.back(); - bone.mName = transformNodeName; - - // read vertex weights - unsigned int numWeights = ReadInt(); - bone.mWeights.reserve( numWeights); - - for ( unsigned int a = 0; a < numWeights; a++) - { - BoneWeight weight; - weight.mVertex = ReadInt(); - bone.mWeights.push_back( weight); - } - - // read vertex weights - for ( unsigned int a = 0; a < numWeights; a++) - bone.mWeights[a].mWeight = ReadFloat(); - - // read matrix offset - bone.mOffsetMatrix.a1 = ReadFloat(); bone.mOffsetMatrix.b1 = ReadFloat(); - bone.mOffsetMatrix.c1 = ReadFloat(); bone.mOffsetMatrix.d1 = ReadFloat(); - bone.mOffsetMatrix.a2 = ReadFloat(); bone.mOffsetMatrix.b2 = ReadFloat(); - bone.mOffsetMatrix.c2 = ReadFloat(); bone.mOffsetMatrix.d2 = ReadFloat(); - bone.mOffsetMatrix.a3 = ReadFloat(); bone.mOffsetMatrix.b3 = ReadFloat(); - bone.mOffsetMatrix.c3 = ReadFloat(); bone.mOffsetMatrix.d3 = ReadFloat(); - bone.mOffsetMatrix.a4 = ReadFloat(); bone.mOffsetMatrix.b4 = ReadFloat(); - bone.mOffsetMatrix.c4 = ReadFloat(); bone.mOffsetMatrix.d4 = ReadFloat(); - - CheckForSemicolon(); - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectSkinMeshHeader( Mesh* /*pMesh*/ ) -{ - readHeadOfDataObject(); - - /*unsigned int maxSkinWeightsPerVertex =*/ ReadInt(); - /*unsigned int maxSkinWeightsPerFace =*/ ReadInt(); - /*unsigned int numBonesInMesh = */ReadInt(); - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh) -{ - readHeadOfDataObject(); - - // read count - unsigned int numNormals = ReadInt(); - pMesh->mNormals.resize( numNormals); - - // read normal vectors - for ( unsigned int a = 0; a < numNormals; a++) - pMesh->mNormals[a] = ReadVector3(); - - // read normal indices - unsigned int numFaces = ReadInt(); - if ( numFaces != pMesh->mPosFaces.size()) - ThrowException( "Normal face count does not match vertex face count."); - - for ( unsigned int a = 0; a < numFaces; a++) - { - unsigned int numIndices = ReadInt(); - pMesh->mNormFaces.push_back( Face()); - Face& face = pMesh->mNormFaces.back(); - - for ( unsigned int b = 0; b < numIndices; b++) - face.mIndices.push_back( ReadInt()); - - CheckForSeparator(); - } - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshTextureCoords( Mesh* pMesh) -{ - readHeadOfDataObject(); - std::vector<aiVector2D>& coords = pMesh->mTexCoords[pMesh->mNumTextures++]; - - unsigned int numCoords = ReadInt(); - if ( numCoords != pMesh->mPositions.size()) - ThrowException( "Texture coord count does not match vertex count"); - - coords.resize( numCoords); - for ( unsigned int a = 0; a < numCoords; a++) - coords[a] = ReadVector2(); - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshVertexColors( Mesh* pMesh) -{ - readHeadOfDataObject(); - std::vector<aiColor4D>& colors = pMesh->mColors[pMesh->mNumColorSets++]; - - unsigned int numColors = ReadInt(); - if ( numColors != pMesh->mPositions.size()) - ThrowException( "Vertex color count does not match vertex count"); - - colors.resize( numColors, aiColor4D( 0, 0, 0, 1)); - for ( unsigned int a = 0; a < numColors; a++) - { - unsigned int index = ReadInt(); - if ( index >= pMesh->mPositions.size()) - ThrowException( "Vertex color index out of bounds"); - - colors[index] = ReadRGBA(); - // HACK: (thom) Maxon Cinema XPort plugin puts a third separator here, kwxPort puts a comma. - // Ignore gracefully. - if ( !mIsBinaryFormat) - { - FindNextNoneWhiteSpace(); - if ( *P == ';' || *P == ',') - P++; - } - } - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMeshMaterialList( Mesh* pMesh) -{ - readHeadOfDataObject(); - - // read material count - /*unsigned int numMaterials =*/ ReadInt(); - // read non triangulated face material index count - unsigned int numMatIndices = ReadInt(); - - // some models have a material index count of 1... to be able to read them we - // replicate this single material index on every face - if ( numMatIndices != pMesh->mPosFaces.size() && numMatIndices != 1) - ThrowException( "Per-Face material index count does not match face count."); - - // read per-face material indices - for ( unsigned int a = 0; a < numMatIndices; a++) - pMesh->mFaceMaterials.push_back( ReadInt()); - - // in version 03.02, the face indices end with two semicolons. - // commented out version check, as version 03.03 exported from blender also has 2 semicolons - if ( !mIsBinaryFormat) // && MajorVersion == 3 && MinorVersion <= 2) - { - if ( *P == ';') - ++P; - } - - // if there was only a single material index, replicate it on all faces - while ( pMesh->mFaceMaterials.size() < pMesh->mPosFaces.size()) - pMesh->mFaceMaterials.push_back( pMesh->mFaceMaterials.front()); - - // read following data objects - bool running = true; - while ( running ) - { - std::string objectName = GetNextToken(); - if ( objectName.size() == 0) - ThrowException( "Unexpected end of file while parsing mesh material list."); - else - if ( objectName == "}") - break; // material list finished - else - if ( objectName == "{") - { - // template materials - std::string matName = GetNextToken(); - Material material; - material.mIsReference = true; - material.mName = matName; - pMesh->mMaterials.push_back( material); - - CheckForClosingBrace(); // skip } - } else - if ( objectName == "Material") - { - pMesh->mMaterials.push_back( Material()); - ParseDataObjectMaterial( &pMesh->mMaterials.back()); - } else - if ( objectName == ";") - { - // ignore - } else - { - DefaultLogger::get()->warn("Unknown data object in material list in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectMaterial( Material* pMaterial) -{ - std::string matName; - readHeadOfDataObject( &matName); - if ( matName.empty()) - matName = std::string( "material") + boost::lexical_cast<std::string>( mLineNumber); - pMaterial->mName = matName; - pMaterial->mIsReference = false; - - // read material values - pMaterial->mDiffuse = ReadRGBA(); - pMaterial->mSpecularExponent = ReadFloat(); - pMaterial->mSpecular = ReadRGB(); - pMaterial->mEmissive = ReadRGB(); - - // read other data objects - bool running = true; - while ( running ) - { - std::string objectName = GetNextToken(); - if ( objectName.size() == 0) - ThrowException( "Unexpected end of file while parsing mesh material"); - else - if ( objectName == "}") - break; // material finished - else - if ( objectName == "TextureFilename" || objectName == "TextureFileName") - { - // some exporters write "TextureFileName" instead. - std::string texname; - ParseDataObjectTextureFilename( texname); - pMaterial->mTextures.push_back( TexEntry( texname)); - } else - if ( objectName == "NormalmapFilename" || objectName == "NormalmapFileName") - { - // one exporter writes out the normal map in a separate filename tag - std::string texname; - ParseDataObjectTextureFilename( texname); - pMaterial->mTextures.push_back( TexEntry( texname, true)); - } else - { - DefaultLogger::get()->warn("Unknown data object in material in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimTicksPerSecond() -{ - readHeadOfDataObject(); - mScene->mAnimTicksPerSecond = ReadInt(); - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimationSet() -{ - std::string animName; - readHeadOfDataObject( &animName); - - Animation* anim = new Animation; - mScene->mAnims.push_back( anim); - anim->mName = animName; - - bool running = true; - while ( running ) - { - std::string objectName = GetNextToken(); - if ( objectName.length() == 0) - ThrowException( "Unexpected end of file while parsing animation set."); - else - if ( objectName == "}") - break; // animation set finished - else - if ( objectName == "Animation") - ParseDataObjectAnimation( anim); - else - { - DefaultLogger::get()->warn("Unknown data object in animation set in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimation( Animation* pAnim) -{ - readHeadOfDataObject(); - AnimBone* banim = new AnimBone; - pAnim->mAnims.push_back( banim); - - bool running = true; - while ( running ) - { - std::string objectName = GetNextToken(); - - if ( objectName.length() == 0) - ThrowException( "Unexpected end of file while parsing animation."); - else - if ( objectName == "}") - break; // animation finished - else - if ( objectName == "AnimationKey") - ParseDataObjectAnimationKey( banim); - else - if ( objectName == "AnimationOptions") - ParseUnknownDataObject(); // not interested - else - if ( objectName == "{") - { - // read frame name - banim->mBoneName = GetNextToken(); - CheckForClosingBrace(); - } else - { - DefaultLogger::get()->warn("Unknown data object in animation in x file"); - ParseUnknownDataObject(); - } - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectAnimationKey( AnimBone* pAnimBone) -{ - readHeadOfDataObject(); - - // read key type - unsigned int keyType = ReadInt(); - - // read number of keys - unsigned int numKeys = ReadInt(); - - for ( unsigned int a = 0; a < numKeys; a++) - { - // read time - unsigned int time = ReadInt(); - - // read keys - switch( keyType) - { - case 0: // rotation quaternion - { - // read count - if ( ReadInt() != 4) - ThrowException( "Invalid number of arguments for quaternion key in animation"); - - aiQuatKey key; - key.mTime = double( time); - key.mValue.w = ReadFloat(); - key.mValue.x = ReadFloat(); - key.mValue.y = ReadFloat(); - key.mValue.z = ReadFloat(); - pAnimBone->mRotKeys.push_back( key); - - CheckForSemicolon(); - break; - } - - case 1: // scale vector - case 2: // position vector - { - // read count - if ( ReadInt() != 3) - ThrowException( "Invalid number of arguments for vector key in animation"); - - aiVectorKey key; - key.mTime = double( time); - key.mValue = ReadVector3(); - - if ( keyType == 2) - pAnimBone->mPosKeys.push_back( key); - else - pAnimBone->mScaleKeys.push_back( key); - - break; - } - - case 3: // combined transformation matrix - case 4: // denoted both as 3 or as 4 - { - // read count - if ( ReadInt() != 16) - ThrowException( "Invalid number of arguments for matrix key in animation"); - - // read matrix - MatrixKey key; - key.mTime = double( time); - key.mMatrix.a1 = ReadFloat(); key.mMatrix.b1 = ReadFloat(); - key.mMatrix.c1 = ReadFloat(); key.mMatrix.d1 = ReadFloat(); - key.mMatrix.a2 = ReadFloat(); key.mMatrix.b2 = ReadFloat(); - key.mMatrix.c2 = ReadFloat(); key.mMatrix.d2 = ReadFloat(); - key.mMatrix.a3 = ReadFloat(); key.mMatrix.b3 = ReadFloat(); - key.mMatrix.c3 = ReadFloat(); key.mMatrix.d3 = ReadFloat(); - key.mMatrix.a4 = ReadFloat(); key.mMatrix.b4 = ReadFloat(); - key.mMatrix.c4 = ReadFloat(); key.mMatrix.d4 = ReadFloat(); - pAnimBone->mTrafoKeys.push_back( key); - - CheckForSemicolon(); - break; - } - - default: - ThrowException( boost::str( boost::format( "Unknown key type %1% in animation.") % keyType)); - break; - } // end switch - - // key separator - CheckForSeparator(); - } - - CheckForClosingBrace(); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseDataObjectTextureFilename( std::string& pName) -{ - readHeadOfDataObject(); - GetNextTokenAsString( pName); - CheckForClosingBrace(); - - // FIX: some files (e.g. AnimationTest.x) have "" as texture file name - if (!pName.length()) - { - DefaultLogger::get()->warn("Length of texture file name is zero. Skipping this texture."); - } - - // some exporters write double backslash paths out. We simply replace them if we find them - while ( pName.find( "\\\\") != std::string::npos) - pName.replace( pName.find( "\\\\"), 2, "\\"); -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ParseUnknownDataObject() -{ - // find opening delimiter - bool running = true; - while ( running ) - { - std::string t = GetNextToken(); - if ( t.length() == 0) - ThrowException( "Unexpected end of file while parsing unknown segment."); - - if ( t == "{") - break; - } - - unsigned int counter = 1; - - // parse until closing delimiter - while ( counter > 0) - { - std::string t = GetNextToken(); - - if ( t.length() == 0) - ThrowException( "Unexpected end of file while parsing unknown segment."); - - if ( t == "{") - ++counter; - else - if ( t == "}") - --counter; - } -} - -// ------------------------------------------------------------------------------------------------ -//! checks for closing curly brace -void XFileParser::CheckForClosingBrace() -{ - if ( GetNextToken() != "}") - ThrowException( "Closing brace expected."); -} - -// ------------------------------------------------------------------------------------------------ -//! checks for one following semicolon -void XFileParser::CheckForSemicolon() -{ - if ( mIsBinaryFormat) - return; - - if ( GetNextToken() != ";") - ThrowException( "Semicolon expected."); -} - -// ------------------------------------------------------------------------------------------------ -//! checks for a separator char, either a ',' or a ';' -void XFileParser::CheckForSeparator() -{ - if ( mIsBinaryFormat) - return; - - std::string token = GetNextToken(); - if ( token != "," && token != ";") - ThrowException( "Separator character (';' or ',') expected."); -} - -// ------------------------------------------------------------------------------------------------ -// tests and possibly consumes a separator char, but does nothing if there was no separator -void XFileParser::TestForSeparator() -{ - if ( mIsBinaryFormat) - return; - - FindNextNoneWhiteSpace(); - if ( P >= End) - return; - - // test and skip - if ( *P == ';' || *P == ',') - P++; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::readHeadOfDataObject( std::string* poName) -{ - std::string nameOrBrace = GetNextToken(); - if ( nameOrBrace != "{") - { - if ( poName) - *poName = nameOrBrace; - - if ( GetNextToken() != "{") - ThrowException( "Opening brace expected."); - } -} - -// ------------------------------------------------------------------------------------------------ -std::string XFileParser::GetNextToken() -{ - std::string s; - - // process binary-formatted file - if ( mIsBinaryFormat) - { - // in binary mode it will only return NAME and STRING token - // and (correctly) skip over other tokens. - - unsigned int tok = ReadBinWord(); - unsigned int len; - - // standalone tokens - switch( tok) - { - case 1: - // name token - len = ReadBinDWord(); - s = std::string(P, len); - P += len; - return s; - case 2: - // string token - len = ReadBinDWord(); - s = std::string(P, len); - P += (len + 2); - return s; - case 3: - // integer token - P += 4; - return "<integer>"; - case 5: - // GUID token - P += 16; - return "<guid>"; - case 6: - len = ReadBinDWord(); - P += (len * 4); - return "<int_list>"; - case 7: - len = ReadBinDWord(); - P += (len * mBinaryFloatSize); - return "<flt_list>"; - case 0x0a: - return "{"; - case 0x0b: - return "}"; - case 0x0c: - return "("; - case 0x0d: - return ")"; - case 0x0e: - return "["; - case 0x0f: - return "]"; - case 0x10: - return "<"; - case 0x11: - return ">"; - case 0x12: - return "."; - case 0x13: - return ","; - case 0x14: - return ";"; - case 0x1f: - return "template"; - case 0x28: - return "WORD"; - case 0x29: - return "DWORD"; - case 0x2a: - return "FLOAT"; - case 0x2b: - return "DOUBLE"; - case 0x2c: - return "CHAR"; - case 0x2d: - return "UCHAR"; - case 0x2e: - return "SWORD"; - case 0x2f: - return "SDWORD"; - case 0x30: - return "void"; - case 0x31: - return "string"; - case 0x32: - return "unicode"; - case 0x33: - return "cstring"; - case 0x34: - return "array"; - } - } - // process text-formatted file - else - { - FindNextNoneWhiteSpace(); - if ( P >= End) - return s; - - while ( (P < End) && !isspace( (unsigned char) *P)) - { - // either keep token delimiters when already holding a token, or return if first valid char - if ( *P == ';' || *P == '}' || *P == '{' || *P == ',') - { - if ( !s.size()) - s.append( P++, 1); - break; // stop for delimiter - } - s.append( P++, 1); - } - } - return s; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::FindNextNoneWhiteSpace() -{ - if ( mIsBinaryFormat) - return; - - bool running = true; - while ( running ) - { - while ( P < End && isspace( (unsigned char) *P)) - { - if ( *P == '\n') - mLineNumber++; - ++P; - } - - if ( P >= End) - return; - - // check if this is a comment - if ( (P[0] == '/' && P[1] == '/') || P[0] == '#') - ReadUntilEndOfLine(); - else - break; - } -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::GetNextTokenAsString( std::string& poString) -{ - if ( mIsBinaryFormat) - { - poString = GetNextToken(); - return; - } - - FindNextNoneWhiteSpace(); - if ( P >= End) - ThrowException( "Unexpected end of file while parsing string"); - - if ( *P != '"') - ThrowException( "Expected quotation mark."); - ++P; - - while ( P < End && *P != '"') - poString.append( P++, 1); - - if ( P >= End-1) - ThrowException( "Unexpected end of file while parsing string"); - - if ( P[1] != ';' || P[0] != '"') - ThrowException( "Expected quotation mark and semicolon at the end of a string."); - P+=2; -} - -// ------------------------------------------------------------------------------------------------ -void XFileParser::ReadUntilEndOfLine() -{ - if ( mIsBinaryFormat) - return; - - while ( P < End) - { - if ( *P == '\n' || *P == '\r') - { - ++P; mLineNumber++; - return; - } - - ++P; - } -} - -// ------------------------------------------------------------------------------------------------ -unsigned short XFileParser::ReadBinWord() -{ - const unsigned char* q = (const unsigned char*) P; - unsigned short tmp = q[0] | (q[1] << 8); - P += 2; - return tmp; -} - -// ------------------------------------------------------------------------------------------------ -unsigned int XFileParser::ReadBinDWord() -{ - const unsigned char* q = (const unsigned char*) P; - unsigned int tmp = q[0] | (q[1] << 8) | (q[2] << 16) | (q[3] << 24); - P += 4; - return tmp; -} - -// ------------------------------------------------------------------------------------------------ -unsigned int XFileParser::ReadInt() -{ - if ( mIsBinaryFormat) - { - if ( mBinaryNumCount == 0) - { - unsigned short tmp = ReadBinWord(); // 0x06 or 0x03 - if ( tmp == 0x06) // array of ints follows - mBinaryNumCount = ReadBinDWord(); - else // single int follows - mBinaryNumCount = 1; - } - - --mBinaryNumCount; - return ReadBinDWord(); - } else - { - FindNextNoneWhiteSpace(); - - // TODO: consider using strtol10s instead??? - - // check preceeding minus sign - bool isNegative = false; - if ( *P == '-') - { - isNegative = true; - P++; - } - - // at least one digit expected - if ( !isdigit( *P)) - ThrowException( "Number expected."); - - // read digits - unsigned int number = 0; - while ( P < End) - { - if ( !isdigit( *P)) - break; - number = number * 10 + (*P - 48); - P++; - } - - CheckForSeparator(); - return isNegative ? ((unsigned int) -int( number)) : number; - } -} - -// ------------------------------------------------------------------------------------------------ -float XFileParser::ReadFloat() -{ - if ( mIsBinaryFormat) - { - if ( mBinaryNumCount == 0) - { - unsigned short tmp = ReadBinWord(); // 0x07 or 0x42 - if ( tmp == 0x07) // array of floats following - mBinaryNumCount = ReadBinDWord(); - else // single float following - mBinaryNumCount = 1; - } - - --mBinaryNumCount; - if ( mBinaryFloatSize == 8) - { - float result = (float) (*(double*) P); - P += 8; - return result; - } else - { - float result = *(float*) P; - P += 4; - return result; - } - } - - // text version - FindNextNoneWhiteSpace(); - // check for various special strings to allow reading files from faulty exporters - // I mean you, Blender! - if ( strncmp( P, "-1.#IND00", 9) == 0 || strncmp( P, "1.#IND00", 8) == 0) - { - P += 9; - CheckForSeparator(); - return 0.0f; - } else - if ( strncmp( P, "1.#QNAN0", 8) == 0) - { - P += 8; - CheckForSeparator(); - return 0.0f; - } - - float result = 0.0f; - P = fast_atof_move( P, result); - - CheckForSeparator(); - - return result; -} - -// ------------------------------------------------------------------------------------------------ -aiVector2D XFileParser::ReadVector2() -{ - aiVector2D vector; - vector.x = ReadFloat(); - vector.y = ReadFloat(); - TestForSeparator(); - - return vector; -} - -// ------------------------------------------------------------------------------------------------ -aiVector3D XFileParser::ReadVector3() -{ - aiVector3D vector; - vector.x = ReadFloat(); - vector.y = ReadFloat(); - vector.z = ReadFloat(); - TestForSeparator(); - - return vector; -} - -// ------------------------------------------------------------------------------------------------ -aiColor4D XFileParser::ReadRGBA() -{ - aiColor4D color; - color.r = ReadFloat(); - color.g = ReadFloat(); - color.b = ReadFloat(); - color.a = ReadFloat(); - TestForSeparator(); - - return color; -} - -// ------------------------------------------------------------------------------------------------ -aiColor3D XFileParser::ReadRGB() -{ - aiColor3D color; - color.r = ReadFloat(); - color.g = ReadFloat(); - color.b = ReadFloat(); - TestForSeparator(); - - return color; -} - -// ------------------------------------------------------------------------------------------------ -// Throws an exception with a line number and the given text. -void XFileParser::ThrowException( const std::string& pText) -{ - if ( mIsBinaryFormat) - throw DeadlyImportError( pText); - else - throw DeadlyImportError( boost::str( boost::format( "Line %d: %s") % mLineNumber % pText)); -} - - -// ------------------------------------------------------------------------------------------------ -// Filters the imported hierarchy for some degenerated cases that some exporters produce. -void XFileParser::FilterHierarchy( XFile::Node* pNode) -{ - // if the node has just a single unnamed child containing a mesh, remove - // the anonymous node inbetween. The 3DSMax kwXport plugin seems to produce this - // mess in some cases - if ( pNode->mChildren.size() == 1) - { - XFile::Node* child = pNode->mChildren.front(); - if ( child->mName.length() == 0 && child->mMeshes.size() > 0) - { - // transfer its meshes to us - for ( unsigned int a = 0; a < child->mMeshes.size(); a++) - pNode->mMeshes.push_back( child->mMeshes[a]); - child->mMeshes.clear(); - - // then kill it - delete child; - pNode->mChildren.clear(); - } - } - - // recurse - for ( unsigned int a = 0; a < pNode->mChildren.size(); a++) - FilterHierarchy( pNode->mChildren[a]); -} - -#endif // !! ASSIMP_BUILD_NO_X_IMPORTER diff --git a/3rdparty/assimp/code/XFileParser.h b/3rdparty/assimp/code/XFileParser.h deleted file mode 100644 index 8000c133..00000000 --- a/3rdparty/assimp/code/XFileParser.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 Helper class to parse a XFile into a temporary structure */ -#ifndef AI_XFILEPARSER_H_INC -#define AI_XFILEPARSER_H_INC - -#include <string> -#include <vector> - -#include "../include/aiTypes.h" - -namespace Assimp -{ - namespace XFile - { - struct Node; - struct Mesh; - struct Scene; - struct Material; - struct Animation; - struct AnimBone; - } - -/** The XFileParser reads a XFile either in text or binary form and builds a temporary - * data structure out of it. - */ -class XFileParser -{ -public: - /** Constructor. Creates a data structure out of the XFile given in the memory block. - * @param pBuffer Memory buffer containing the XFile - */ - XFileParser( const std::vector<char>& pBuffer); - - /** Destructor. Destroys all imported data along with it */ - ~XFileParser(); - - /** Returns the temporary representation of the imported data */ - const XFile::Scene* GetImportedData() const { return mScene; } - -protected: - void ParseFile(); - void ParseDataObjectTemplate(); - void ParseDataObjectFrame( XFile::Node *pParent); - void ParseDataObjectTransformationMatrix( aiMatrix4x4& pMatrix); - void ParseDataObjectMesh( XFile::Mesh* pMesh); - void ParseDataObjectSkinWeights( XFile::Mesh* pMesh); - void ParseDataObjectSkinMeshHeader( XFile::Mesh* pMesh); - void ParseDataObjectMeshNormals( XFile::Mesh* pMesh); - void ParseDataObjectMeshTextureCoords( XFile::Mesh* pMesh); - void ParseDataObjectMeshVertexColors( XFile::Mesh* pMesh); - void ParseDataObjectMeshMaterialList( XFile::Mesh* pMesh); - void ParseDataObjectMaterial( XFile::Material* pMaterial); - void ParseDataObjectAnimTicksPerSecond(); - void ParseDataObjectAnimationSet(); - void ParseDataObjectAnimation( XFile::Animation* pAnim); - void ParseDataObjectAnimationKey( XFile::AnimBone *pAnimBone); - void ParseDataObjectTextureFilename( std::string& pName); - void ParseUnknownDataObject(); - - //! places pointer to next begin of a token, and ignores comments - void FindNextNoneWhiteSpace(); - - //! returns next parseable token. Returns empty string if no token there - std::string GetNextToken(); - - //! reads header of dataobject including the opening brace. - //! returns false if error happened, and writes name of object - //! if there is one - void readHeadOfDataObject( std::string* poName = NULL); - - //! checks for closing curly brace, throws exception if not there - void CheckForClosingBrace(); - - //! checks for one following semicolon, throws exception if not there - void CheckForSemicolon(); - - //! checks for a separator char, either a ',' or a ';' - void CheckForSeparator(); - - /// tests and possibly consumes a separator char, but does nothing if there was no separator - void TestForSeparator(); - - //! reads a x file style string - void GetNextTokenAsString( std::string& poString); - - void ReadUntilEndOfLine(); - - unsigned short ReadBinWord(); - unsigned int ReadBinDWord(); - unsigned int ReadInt(); - float ReadFloat(); - aiVector2D ReadVector2(); - aiVector3D ReadVector3(); - aiColor3D ReadRGB(); - aiColor4D ReadRGBA(); - - /** Throws an exception with a line number and the given text. */ - void ThrowException( const std::string& pText); - - /** Filters the imported hierarchy for some degenerated cases that some exporters produce. - * @param pData The sub-hierarchy to filter - */ - void FilterHierarchy( XFile::Node* pNode); - -protected: - unsigned int mMajorVersion, mMinorVersion; ///< version numbers - bool mIsBinaryFormat; ///< true if the file is in binary, false if it's in text form - unsigned int mBinaryFloatSize; ///< float size, either 32 or 64 bits - // counter for number arrays in binary format - unsigned int mBinaryNumCount; - - const char* P; - const char* End; - - /// Line number when reading in text format - unsigned int mLineNumber; - - /// Imported data - XFile::Scene* mScene; -}; - -} -#endif // AI_XFILEPARSER_H_INC diff --git a/3rdparty/assimp/code/aiAssert.cpp b/3rdparty/assimp/code/aiAssert.cpp deleted file mode 100644 index 552014f7..00000000 --- a/3rdparty/assimp/code/aiAssert.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2008, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ -#include "AssimpPCH.h" -#include "../include/aiAssert.h" -#ifdef _WIN32 -#ifndef __GNUC__ -# include "crtdbg.h" -#endif // ndef gcc -#endif // _WIN32 - -// Set a breakpoint using win32, else line, file and message will be returned and progam ends with -// errrocode = 1 -AI_WONT_RETURN void Assimp::aiAssert (const std::string &message, unsigned int uiLine, const std::string &file) -{ - // moved expression testing out of the function and into the macro to avoid constructing - // two std::string on every single ai_assert test -// if (!expression) - { - // FIX (Aramis): changed std::cerr to std::cout that the message appears in VS' output window ... - std::cout << "File :" << file << ", line " << uiLine << " : " << message << std::endl; - -#ifdef _WIN32 -#ifndef __GNUC__ - // Set breakpoint - __debugbreak(); -#endif //ndef gcc -#else - exit (1); -#endif - } -} diff --git a/3rdparty/assimp/code/assbin_chunks.h b/3rdparty/assimp/code/assbin_chunks.h deleted file mode 100644 index 342b7879..00000000 --- a/3rdparty/assimp/code/assbin_chunks.h +++ /dev/null @@ -1,196 +0,0 @@ - -#ifndef INCLUDED_ASSBIN_CHUNKS_H -#define INCLUDED_ASSBIN_CHUNKS_H - -#define ASSBIN_VERSION_MAJOR 1 -#define ASSBIN_VERSION_MINOR 0 - -/** -@page assfile .ASS File formats - -@section over Overview -Assimp provides its own interchange format, which is intended to applications which need -to serialize 3D-models and to reload them quickly. Assimp's file formats are designed to -be read by Assimp itself. They encode additional information needed by Assimp to optimize -its postprocessing pipeline. If you once apply specific steps to a scene, then save it -and reread it from an ASS format using the same post processing settings, they won't -be executed again. - -The format comes in two flavours: XML and binary - both of them hold a complete dump of -the 'aiScene' data structure returned by the APIs. The focus for the binary format -(<tt>.assbin</tt>) is fast loading. Optional deflate compression helps reduce file size. The XML -flavour, <tt>.assxml</tt> or simply .xml, is just a plain-to-xml conversion of aiScene. - -ASSBIN is Assimp's binary interchange format. assimp_cmd (<tt><root>/tools/assimp_cmd</tt>) is able to -write it and the core library provides a loader for it. - -@section assxml XML File format - -The format is pretty much self-explanatory due to its similarity to the in-memory aiScene structure. -With few exceptions, C structures are wrapped in XML elements. - -The DTD for ASSXML can be found in <tt><root>/doc/AssXML_Scheme.xml</tt>. Or have look -at the output files generated by assimp_cmd. - -@section assbin Binary file format - -The ASSBIN file format is composed of chunks to represent the hierarchical aiScene data structure. -This makes the format extensible and allows backward-compatibility with future data structure -versions. The <tt><root>/code/assbin_chunks.h</tt> header contains some magic constants -for use by stand-alone ASSBIN loaders. Also, Assimp's own file writer can be found -in <tt><root>/tools/assimp_cmd/WriteDumb.cpp</tt> (yes, the 'b' is no typo ...). - -@verbatim - -------------------------------------------------------------------------------- -1. File structure: -------------------------------------------------------------------------------- - ----------------------- -| Header (500 bytes) | ----------------------- -| Variable chunks | ----------------------- - -------------------------------------------------------------------------------- -2. Definitions: -------------------------------------------------------------------------------- - -integer is four bytes wide, stored in little-endian byte order. -short is two bytes wide, stored in little-endian byte order. -byte is a single byte. -string is an integer n followed by n UTF-8 characters, not terminated by zero -float is an IEEE 754 single-precision floating-point value -double is an IEEE 754 double-precision floating-point value -t[n] is an array of n elements of type t - -------------------------------------------------------------------------------- -2. Header: -------------------------------------------------------------------------------- - -byte[44] Magic identification string for ASSBIN files. - 'ASSIMP.binary' - -integer Major version of the Assimp library which wrote the file -integer Minor version of the Assimp library which wrote the file - match these against ASSBIN_VERSION_MAJOR and ASSBIN_VERSION_MINOR - -integer SVN revision of the Assimp library (intended for our internal - debugging - if you write Ass files from your own APPs, set this value to 0. -integer Assimp compile flags - -short 0 for normal files, 1 for shortened dumps for regression tests - these should have the file extension assbin.regress - -short 1 if the data after the header is compressed with the DEFLATE algorithm, - 0 for uncompressed files. - For compressed files, the first integer after the header is - always the uncompressed data size - -byte[256] Zero-terminated source file name, UTF-8 -byte[128] Zero-terminated command line parameters passed to assimp_cmd, UTF-8 - -byte[64] Reserved for future use ----> Total length: 512 bytes - -------------------------------------------------------------------------------- -3. Chunks: -------------------------------------------------------------------------------- - -integer Magic chunk ID (ASSBIN_CHUNK_XXX) -integer Chunk data length, in bytes - (unknown chunks are possible, a good reader skips over them) - -byte[n] length-of-chunk bytes of data, depending on the chunk type - -Chunks can contain nested chunks. Nested chunks are ALWAYS at the end of the chunk, -their size is included in length-of-chunk. - -The chunk layout for all ASSIMP data structures is derived from their C declarations. -The general 'rule' to get from Assimp headers to the serialized layout is: - - 1. POD members (i.e. aiMesh::mPrimitiveTypes, aiMesh::mNumVertices), - in order of declaration. - - 2. Array-members (aiMesh::mFaces, aiMesh::mVertices, aiBone::mWeights), - in order of declaration. - - 2. Object array members (i.e aiMesh::mBones, aiScene::mMeshes) are stored in - subchunks directly following the data written in 1.) and 2.) - - - Of course, there are some exceptions to this general order: - -[[aiScene]] - - - The root node holding the scene structure is naturally stored in - a ASSBIN_CHUNK_AINODE subchunk following 1.) and 2.) (which is - empty for aiScene). - -[[aiMesh]] - - - mTextureCoords and mNumUVComponents are serialized as follows: - - [number of used uv channels times] - integer mNumUVComponents[n] - float mTextureCoords[n][mNumUVComponents[n]] - - -> more than AI_MAX_TEXCOORD_CHANNELS can be stored. This allows Assimp - builds with different settings for AI_MAX_TEXCOORD_CHANNELS to exchange - data. Unlike the in-memory format, only the used components of the - UV coordinates are written to disk. If mNumUVComponents[0] is 1, the - corresponding mTextureCoords array consists of mNumTextureCoords*1 - single floats. - - - The array member block of aiMesh is prefixed with an integer that specifies - the kinds of vertex components actually present in the mesh. This is a - bitwise combination of the ASSBIN_MESH_HAS_xxx constants. - -[[aiFace]] - - - mNumIndices is stored as short - - mIndices are written as short, if aiMesh::mNumVertices<65536 - -[[aiNode]] - - - mParent is ommitted - -[[aiLight]] - - - mAttenuationXXX not written if aiLight::mType == aiLightSource_DIRECTIONAL - - mAngleXXX not written if aiLight::mType != aiLightSource_SPOT - -[[aiMaterial]] - - - mNumAllocated is ommitted, for obvious reasons :-) - - - @endverbatim*/ - - -#define ASSBIN_HEADER_LENGTH 512 - -// these are the magic chunk identifiers for the binary ASS file format -#define ASSBIN_CHUNK_AICAMERA 0x1234 -#define ASSBIN_CHUNK_AILIGHT 0x1235 -#define ASSBIN_CHUNK_AITEXTURE 0x1236 -#define ASSBIN_CHUNK_AIMESH 0x1237 -#define ASSBIN_CHUNK_AINODEANIM 0x1238 -#define ASSBIN_CHUNK_AISCENE 0x1239 -#define ASSBIN_CHUNK_AIBONE 0x123a -#define ASSBIN_CHUNK_AIANIMATION 0x123b -#define ASSBIN_CHUNK_AINODE 0x123c -#define ASSBIN_CHUNK_AIMATERIAL 0x123d -#define ASSBIN_CHUNK_AIMATERIALPROPERTY 0x123e - -#define ASSBIN_MESH_HAS_POSITIONS 0x1 -#define ASSBIN_MESH_HAS_NORMALS 0x2 -#define ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS 0x4 -#define ASSBIN_MESH_HAS_TEXCOORD_BASE 0x100 -#define ASSBIN_MESH_HAS_COLOR_BASE 0x10000 - -#define ASSBIN_MESH_HAS_TEXCOORD(n) (ASSBIN_MESH_HAS_TEXCOORD_BASE << n) -#define ASSBIN_MESH_HAS_COLOR(n) (ASSBIN_MESH_HAS_COLOR_BASE << n) - - -#endif // INCLUDED_ASSBIN_CHUNKS_H diff --git a/3rdparty/assimp/code/fast_atof.h b/3rdparty/assimp/code/fast_atof.h deleted file mode 100644 index a584efb7..00000000 --- a/3rdparty/assimp/code/fast_atof.h +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (C) 2002-2007 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine" and the "irrXML" project. -// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h - -// ------------------------------------------------------------------------------------ -// Original description: (Schrompf) -// Adapted to the ASSIMP library because the builtin atof indeed takes AGES to parse a -// float inside a large string. Before parsing, it does a strlen on the given point. -// Changes: -// 22nd October 08 (Aramis_acg): Added temporary cast to double, added strtol10_64 -// to ensure long numbers are handled correctly -// ------------------------------------------------------------------------------------ - - -#ifndef __FAST_A_TO_F_H_INCLUDED__ -#define __FAST_A_TO_F_H_INCLUDED__ - -#include <math.h> - -namespace Assimp -{ - -const float fast_atof_table[16] = { // we write [16] here instead of [] to work around a swig bug - 0.f, - 0.1f, - 0.01f, - 0.001f, - 0.0001f, - 0.00001f, - 0.000001f, - 0.0000001f, - 0.00000001f, - 0.000000001f, - 0.0000000001f, - 0.00000000001f, - 0.000000000001f, - 0.0000000000001f, - 0.00000000000001f, - 0.000000000000001f -}; - - -// ------------------------------------------------------------------------------------ -// Convert a string in decimal format to a number -// ------------------------------------------------------------------------------------ -inline unsigned int strtol10( const char* in, const char** out=0) -{ - unsigned int value = 0; - - bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '9' ) - break; - - value = ( value * 10 ) + ( *in - '0' ); - ++in; - } - if (out)*out = in; - return value; -} - -// ------------------------------------------------------------------------------------ -// Convert a string in octal format to a number -// ------------------------------------------------------------------------------------ -inline unsigned int strtol8( const char* in, const char** out=0) -{ - unsigned int value = 0; - - bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '7' ) - break; - - value = ( value << 3 ) + ( *in - '0' ); - ++in; - } - if (out)*out = in; - return value; -} - -// ------------------------------------------------------------------------------------ -// Convert a string in hex format to a number -// ------------------------------------------------------------------------------------ -inline unsigned int strtol16( const char* in, const char** out=0) -{ - unsigned int value = 0; - - bool running = true; - while ( running ) - { - if ( *in >= '0' && *in <= '9' ) - { - value = ( value << 4u ) + ( *in - '0' ); - } - else if (*in >= 'A' && *in <= 'F') - { - value = ( value << 4u ) + ( *in - 'A' ) + 10; - } - else if (*in >= 'a' && *in <= 'f') - { - value = ( value << 4u ) + ( *in - 'a' ) + 10; - } - else break; - ++in; - } - if (out)*out = in; - return value; -} - -// ------------------------------------------------------------------------------------ -// Convert just one hex digit -// Return value is 0xffffffff if the input is not hex -// ------------------------------------------------------------------------------------ -inline unsigned int HexDigitToDecimal(char in) -{ - unsigned int out = 0xffffffff; - if (in >= '0' && in <= '9') - out = in - '0'; - - else if (in >= 'a' && in <= 'f') - out = 10u + in - 'a'; - - else if (in >= 'A' && in <= 'F') - out = 10u + in - 'A'; - - // return value is 0xffffffff if the input is not a hex digit - return out; -} - -// ------------------------------------------------------------------------------------ -// Convert a hex-encoded octet (2 characters processed) -// Return value is 0xffffffff if the input is not hex -// ------------------------------------------------------------------------------------ -inline uint8_t HexOctetToDecimal(const char* in) -{ - return ((uint8_t)HexDigitToDecimal(in[0])<<4)+(uint8_t)HexDigitToDecimal(in[1]); -} - - -// ------------------------------------------------------------------------------------ -// signed variant of strtol10 -// ------------------------------------------------------------------------------------ -inline int strtol10s( const char* in, const char** out=0) -{ - bool inv = (*in=='-'); - if (inv || *in=='+') - ++in; - - int value = strtol10(in,out); - if (inv) { - value = -value; - } - return value; -} - -// ------------------------------------------------------------------------------------ -// Parse a C++-like integer literal - hex and oct prefixes. -// 0xNNNN - hex -// 0NNN - oct -// NNN - dec -// ------------------------------------------------------------------------------------ -inline unsigned int strtol_cppstyle( const char* in, const char** out=0) -{ - if ('0' == in[0]) - { - return 'x' == in[1] ? strtol16(in+2,out) : strtol8(in+1,out); - } - return strtol10(in, out); -} - -// ------------------------------------------------------------------------------------ -// Special version of the function, providing higher accuracy and safety -// It is mainly used by fast_atof to prevent ugly and unwanted integer overflows. -// ------------------------------------------------------------------------------------ -inline uint64_t strtol10_64( const char* in, const char** out=0, unsigned int* max_inout=0) -{ - unsigned int cur = 0; - uint64_t value = 0; - - bool running = true; - while ( running ) - { - if ( *in < '0' || *in > '9' ) - break; - - const uint64_t new_value = ( value * 10 ) + ( *in - '0' ); - - if (new_value < value) /* numeric overflow, we rely on you */ - return value; - - value = new_value; - - ++in; - ++cur; - - if (max_inout && *max_inout == cur) { - - if (out) { /* skip to end */ - while (*in >= '0' && *in <= '9') - ++in; - *out = in; - } - - return value; - } - } - if (out) - *out = in; - - if (max_inout) - *max_inout = cur; - - return value; -} - -// Number of relevant decimals for floating-point parsing. -#define AI_FAST_ATOF_RELAVANT_DECIMALS 6 - -// ------------------------------------------------------------------------------------ -//! Provides a fast function for converting a string into a float, -//! about 6 times faster than atof in win32. -// If you find any bugs, please send them to me, niko (at) irrlicht3d.org. -// ------------------------------------------------------------------------------------ -inline const char* fast_atof_move( const char* c, float& out) -{ - float f; - - bool inv = (*c=='-'); - if (inv || *c=='+') - ++c; - - f = (float) strtol10_64 ( c, &c); - if (*c == '.' || (c[0] == ',' && (c[1] >= '0' || c[1] <= '9'))) // allow for commas, too - { - ++c; - - // NOTE: The original implementation is highly unaccurate here. The precision of a single - // IEEE 754 float is not high enough, everything behind the 6th digit tends to be more - // inaccurate than it would need to be. Casting to double seems to solve the problem. - // strtol_64 is used to prevent integer overflow. - - // Another fix: this tends to become 0 for long numbers if we don't limit the maximum - // number of digits to be read. AI_FAST_ATOF_RELAVANT_DECIMALS can be a value between - // 1 and 15. - unsigned int diff = AI_FAST_ATOF_RELAVANT_DECIMALS; - double pl = (double) strtol10_64 ( c, &c, &diff ); - - pl *= fast_atof_table[diff]; - f += (float)pl; - } - - // A major 'E' must be allowed. Necessary for proper reading of some DXF files. - // Thanks to Zhao Lei to point out that this if () must be outside the if (*c == '.' ..) - if (*c == 'e' || *c == 'E') - { - ++c; - bool einv = (*c=='-'); - if (einv || *c=='+') - ++c; - - float exp = (float)strtol10_64(c, &c); - if (einv) - exp *= -1.0f; - - f *= pow(10.0f, exp); - } - - if (inv) - f *= -1.0f; - - out = f; - return c; -} - -// ------------------------------------------------------------------------------------ -// The same but more human. -inline float fast_atof(const char* c) -{ - float ret; - fast_atof_move(c, ret); - return ret; -} - - -inline float fast_atof( const char* c, const char** cout) -{ - float ret; - *cout = fast_atof_move(c, ret); - - return ret; -} - -inline float fast_atof( const char** inout) -{ - float ret; - *inout = fast_atof_move(*inout, ret); - - return ret; -} - -} // end of namespace Assimp - -#endif - diff --git a/3rdparty/assimp/code/irrXMLWrapper.h b/3rdparty/assimp/code/irrXMLWrapper.h deleted file mode 100644 index af751668..00000000 --- a/3rdparty/assimp/code/irrXMLWrapper.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -Open Asset Import Library (ASSIMP) ----------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. - ----------------------------------------------------------------------- -*/ - -#ifndef INCLUDED_AI_IRRXML_WRAPPER -#define INCLUDED_AI_IRRXML_WRAPPER - -// some long includes .... -#include "./../contrib/irrXML/irrXML.h" -#include "./../include/IOStream.h" -namespace Assimp { - -// --------------------------------------------------------------------------------- -/** @brief Utility class to make IrrXML work together with our custom IO system - * See the IrrXML docs for more details. - * - * Construct IrrXML-Reader in BaseImporter::InternReadFile(): - * @code - * // open the file - * boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile)); - * if ( file.get() == NULL) { - * throw DeadlyImportError( "Failed to open file " + pFile + "."); - * } - * - * // generate a XML reader for it - * boost::scoped_ptr<CIrrXML_IOStreamReader> mIOWrapper( new CIrrXML_IOStreamReader( file.get())); - * mReader = irr::io::createIrrXMLReader( mIOWrapper.get()); - * if ( !mReader) { - * ThrowException( "xxxx: Unable to open file."); - * } - * @endcode - **/ -class CIrrXML_IOStreamReader - : public irr::io::IFileReadCallBack -{ -public: - - // ---------------------------------------------------------------------------------- - //! Construction from an existing IOStream - CIrrXML_IOStreamReader(IOStream* _stream) - : stream (_stream) - , t (0) - { - - // Map the buffer into memory and convert it to UTF8. IrrXML provides its - // own conversion, which is merely a cast from uintNN_t to uint8_t. Thus, - // it is not suitable for our purposes and we have to do it BEFORE IrrXML - // gets the buffer. Sadly, this forces as to map the whole file into - // memory. - - data.resize(stream->FileSize()); - stream->Read(&data[0],data.size(),1); - - BaseImporter::ConvertToUTF8(data); - } - - // ---------------------------------------------------------------------------------- - //! Virtual destructor - virtual ~CIrrXML_IOStreamReader() {}; - - // ---------------------------------------------------------------------------------- - //! Reads an amount of bytes from the file. - /** @param buffer: Pointer to output buffer. - * @param sizeToRead: Amount of bytes to read - * @return Returns how much bytes were read. */ - virtual int read(void* buffer, int sizeToRead) { - if (sizeToRead<0) { - return 0; - } - if (t+sizeToRead>data.size()) { - sizeToRead = data.size()-t; - } - - memcpy(buffer,&data.front()+t,sizeToRead); - - t += sizeToRead; - return sizeToRead; - } - - // ---------------------------------------------------------------------------------- - //! Returns size of file in bytes - virtual int getSize() { - return (int)data.size(); - } - -private: - IOStream* stream; - std::vector<char> data; - size_t t; - -}; // ! class CIrrXML_IOStreamReader - -} // ! Assimp - -#endif // !! INCLUDED_AI_IRRXML_WRAPPER diff --git a/3rdparty/assimp/code/pstdint.h b/3rdparty/assimp/code/pstdint.h deleted file mode 100644 index 0c1cec84..00000000 --- a/3rdparty/assimp/code/pstdint.h +++ /dev/null @@ -1,729 +0,0 @@ -/* A portable stdint.h - **************************************************************************** - * BSD License: - **************************************************************************** - * - * Copyright (c) 2005-2007 Paul Hsieh - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - **************************************************************************** - * - * Version 0.1.10 - * - * The ANSI C standard committee, for the C99 standard, specified the - * inclusion of a new standard include file called stdint.h. This is - * a very useful and long desired include file which contains several - * very precise definitions for integer scalar types that is - * critically important for making portable several classes of - * applications including cryptography, hashing, variable length - * integer libraries and so on. But for most developers its likely - * useful just for programming sanity. - * - * The problem is that most compiler vendors have decided not to - * implement the C99 standard, and the next C++ language standard - * (which has a lot more mindshare these days) will be a long time in - * coming and its unknown whether or not it will include stdint.h or - * how much adoption it will have. Either way, it will be a long time - * before all compilers come with a stdint.h and it also does nothing - * for the extremely large number of compilers available today which - * do not include this file, or anything comparable to it. - * - * So that's what this file is all about. Its an attempt to build a - * single universal include file that works on as many platforms as - * possible to deliver what stdint.h is supposed to. A few things - * that should be noted about this file: - * - * 1) It is not guaranteed to be portable and/or present an identical - * interface on all platforms. The extreme variability of the - * ANSI C standard makes this an impossibility right from the - * very get go. Its really only meant to be useful for the vast - * majority of platforms that possess the capability of - * implementing usefully and precisely defined, standard sized - * integer scalars. Systems which are not intrinsically 2s - * complement may produce invalid constants. - * - * 2) There is an unavoidable use of non-reserved symbols. - * - * 3) Other standard include files are invoked. - * - * 4) This file may come in conflict with future platforms that do - * include stdint.h. The hope is that one or the other can be - * used with no real difference. - * - * 5) In the current verison, if your platform can't represent - * int32_t, int16_t and int8_t, it just dumps out with a compiler - * error. - * - * 6) 64 bit integers may or may not be defined. Test for their - * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. - * Note that this is different from the C99 specification which - * requires the existence of 64 bit support in the compiler. If - * this is not defined for your platform, yet it is capable of - * dealing with 64 bits then it is because this file has not yet - * been extended to cover all of your system's capabilities. - * - * 7) (u)intptr_t may or may not be defined. Test for its presence - * with the test: #ifdef PTRDIFF_MAX. If this is not defined - * for your platform, then it is because this file has not yet - * been extended to cover all of your system's capabilities, not - * because its optional. - * - * 8) The following might not been defined even if your platform is - * capable of defining it: - * - * WCHAR_MIN - * WCHAR_MAX - * (u)int64_t - * PTRDIFF_MIN - * PTRDIFF_MAX - * (u)intptr_t - * - * 9) The following have not been defined: - * - * WINT_MIN - * WINT_MAX - * - * 10) The criteria for defining (u)int_least(*)_t isn't clear, - * except for systems which don't have a type that precisely - * defined 8, 16, or 32 bit types (which this include file does - * not support anyways). Default definitions have been given. - * - * 11) The criteria for defining (u)int_fast(*)_t isn't something I - * would trust to any particular compiler vendor or the ANSI C - * committee. It is well known that "compatible systems" are - * commonly created that have very different performance - * characteristics from the systems they are compatible with, - * especially those whose vendors make both the compiler and the - * system. Default definitions have been given, but its strongly - * recommended that users never use these definitions for any - * reason (they do *NOT* deliver any serious guarantee of - * improved performance -- not in this file, nor any vendor's - * stdint.h). - * - * 12) The following macros: - * - * PRINTF_INTMAX_MODIFIER - * PRINTF_INT64_MODIFIER - * PRINTF_INT32_MODIFIER - * PRINTF_INT16_MODIFIER - * PRINTF_LEAST64_MODIFIER - * PRINTF_LEAST32_MODIFIER - * PRINTF_LEAST16_MODIFIER - * PRINTF_INTPTR_MODIFIER - * - * are strings which have been defined as the modifiers required - * for the "d", "u" and "x" printf formats to correctly output - * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, - * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. - * PRINTF_INTPTR_MODIFIER is not defined for some systems which - * provide their own stdint.h. PRINTF_INT64_MODIFIER is not - * defined if INT64_MAX is not defined. These are an extension - * beyond what C99 specifies must be in stdint.h. - * - * In addition, the following macros are defined: - * - * PRINTF_INTMAX_HEX_WIDTH - * PRINTF_INT64_HEX_WIDTH - * PRINTF_INT32_HEX_WIDTH - * PRINTF_INT16_HEX_WIDTH - * PRINTF_INT8_HEX_WIDTH - * PRINTF_INTMAX_DEC_WIDTH - * PRINTF_INT64_DEC_WIDTH - * PRINTF_INT32_DEC_WIDTH - * PRINTF_INT16_DEC_WIDTH - * PRINTF_INT8_DEC_WIDTH - * - * Which specifies the maximum number of characters required to - * print the number of that type in either hexadecimal or decimal. - * These are an extension beyond what C99 specifies must be in - * stdint.h. - * - * Compilers tested (all with 0 warnings at their highest respective - * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 - * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio - * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 - * - * This file should be considered a work in progress. Suggestions for - * improvements, especially those which increase coverage are strongly - * encouraged. - * - * Acknowledgements - * - * The following people have made significant contributions to the - * development and testing of this file: - * - * Chris Howie - * John Steele Scott - * Dave Thorup - * - */ - -#include <stddef.h> -#include <limits.h> -#include <signal.h> - -/* - * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and - * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. - */ - -#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED) -#include <stdint.h> -#define _PSTDINT_H_INCLUDED -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -# endif -# ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -# endif -# ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -# endif -# ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -# endif -# ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -# endif -# ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -# endif -# ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -# endif -# ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif - -/* - * Something really weird is going on with Open Watcom. Just pull some of - * these duplicated definitions from Open Watcom's stdint.h file for now. - */ - -# if defined (__WATCOMC__) && __WATCOMC__ >= 1250 -# if !defined (INT64_C) -# define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) -# endif -# if !defined (UINT64_C) -# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) -# endif -# if !defined (INT32_C) -# define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) -# endif -# if !defined (UINT32_C) -# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) -# endif -# if !defined (INT16_C) -# define INT16_C(x) (x) -# endif -# if !defined (UINT16_C) -# define UINT16_C(x) (x) -# endif -# if !defined (INT8_C) -# define INT8_C(x) (x) -# endif -# if !defined (UINT8_C) -# define UINT8_C(x) (x) -# endif -# if !defined (UINT64_MAX) -# define UINT64_MAX 18446744073709551615ULL -# endif -# if !defined (INT64_MAX) -# define INT64_MAX 9223372036854775807LL -# endif -# if !defined (UINT32_MAX) -# define UINT32_MAX 4294967295UL -# endif -# if !defined (INT32_MAX) -# define INT32_MAX 2147483647L -# endif -# if !defined (INTMAX_MAX) -# define INTMAX_MAX INT64_MAX -# endif -# if !defined (INTMAX_MIN) -# define INTMAX_MIN INT64_MIN -# endif -# endif -#endif - -#ifndef _PSTDINT_H_INCLUDED -#define _PSTDINT_H_INCLUDED - -#ifndef SIZE_MAX -# define SIZE_MAX (~(size_t)0) -#endif - -/* - * Deduce the type assignments from limits.h under the assumption that - * integer sizes in bits are powers of 2, and follow the ANSI - * definitions. - */ - -#ifndef UINT8_MAX -# define UINT8_MAX 0xff -#endif -#ifndef uint8_t -# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) - typedef unsigned char uint8_t; -# define UINT8_C(v) ((uint8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef INT8_MAX -# define INT8_MAX 0x7f -#endif -#ifndef INT8_MIN -# define INT8_MIN INT8_C(0x80) -#endif -#ifndef int8_t -# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) - typedef signed char int8_t; -# define INT8_C(v) ((int8_t) v) -# else -# error "Platform not supported" -# endif -#endif - -#ifndef UINT16_MAX -# define UINT16_MAX 0xffff -#endif -#ifndef uint16_t -#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) - typedef unsigned int uint16_t; -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -# define UINT16_C(v) ((uint16_t) (v)) -#elif (USHRT_MAX == UINT16_MAX) - typedef unsigned short uint16_t; -# define UINT16_C(v) ((uint16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT16_MAX -# define INT16_MAX 0x7fff -#endif -#ifndef INT16_MIN -# define INT16_MIN INT16_C(0x8000) -#endif -#ifndef int16_t -#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) - typedef signed int int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "" -# endif -#elif (SHRT_MAX == INT16_MAX) - typedef signed short int16_t; -# define INT16_C(v) ((int16_t) (v)) -# ifndef PRINTF_INT16_MODIFIER -# define PRINTF_INT16_MODIFIER "h" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef UINT32_MAX -# define UINT32_MAX (0xffffffffUL) -#endif -#ifndef uint32_t -#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) - typedef unsigned long uint32_t; -# define UINT32_C(v) v ## UL -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (UINT_MAX == UINT32_MAX) - typedef unsigned int uint32_t; -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -# define UINT32_C(v) v ## U -#elif (USHRT_MAX == UINT32_MAX) - typedef unsigned short uint32_t; -# define UINT32_C(v) ((unsigned short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -#ifndef INT32_MAX -# define INT32_MAX (0x7fffffffL) -#endif -#ifndef INT32_MIN -# define INT32_MIN INT32_C(0x80000000) -#endif -#ifndef int32_t -#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) - typedef signed long int32_t; -# define INT32_C(v) v ## L -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "l" -# endif -#elif (INT_MAX == INT32_MAX) - typedef signed int int32_t; -# define INT32_C(v) v -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#elif (SHRT_MAX == INT32_MAX) - typedef signed short int32_t; -# define INT32_C(v) ((short) (v)) -# ifndef PRINTF_INT32_MODIFIER -# define PRINTF_INT32_MODIFIER "" -# endif -#else -#error "Platform not supported" -#endif -#endif - -/* - * The macro stdint_int64_defined is temporarily used to record - * whether or not 64 integer support is available. It must be - * defined for any 64 integer extensions for new platforms that are - * added. - */ - -#undef stdint_int64_defined -#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) -# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# endif -#endif - -#if !defined (stdint_int64_defined) -# if defined(__GNUC__) -# define stdint_int64_defined - __extension__ typedef long long int64_t; - __extension__ typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) -# define stdint_int64_defined - typedef long long int64_t; - typedef unsigned long long uint64_t; -# define UINT64_C(v) v ## ULL -# define INT64_C(v) v ## LL -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "ll" -# endif -# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) -# define stdint_int64_defined - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; -# define UINT64_C(v) v ## UI64 -# define INT64_C(v) v ## I64 -# ifndef PRINTF_INT64_MODIFIER -# define PRINTF_INT64_MODIFIER "I64" -# endif -# endif -#endif - -#if !defined (LONG_LONG_MAX) && defined (INT64_C) -# define LONG_LONG_MAX INT64_C (9223372036854775807) -#endif -#ifndef ULONG_LONG_MAX -# define ULONG_LONG_MAX UINT64_C (18446744073709551615) -#endif - -#if !defined (INT64_MAX) && defined (INT64_C) -# define INT64_MAX INT64_C (9223372036854775807) -#endif -#if !defined (INT64_MIN) && defined (INT64_C) -# define INT64_MIN INT64_C (-9223372036854775808) -#endif -#if !defined (UINT64_MAX) && defined (INT64_C) -# define UINT64_MAX UINT64_C (18446744073709551615) -#endif - -/* - * Width of hexadecimal for number field. - */ - -#ifndef PRINTF_INT64_HEX_WIDTH -# define PRINTF_INT64_HEX_WIDTH "16" -#endif -#ifndef PRINTF_INT32_HEX_WIDTH -# define PRINTF_INT32_HEX_WIDTH "8" -#endif -#ifndef PRINTF_INT16_HEX_WIDTH -# define PRINTF_INT16_HEX_WIDTH "4" -#endif -#ifndef PRINTF_INT8_HEX_WIDTH -# define PRINTF_INT8_HEX_WIDTH "2" -#endif - -#ifndef PRINTF_INT64_DEC_WIDTH -# define PRINTF_INT64_DEC_WIDTH "20" -#endif -#ifndef PRINTF_INT32_DEC_WIDTH -# define PRINTF_INT32_DEC_WIDTH "10" -#endif -#ifndef PRINTF_INT16_DEC_WIDTH -# define PRINTF_INT16_DEC_WIDTH "5" -#endif -#ifndef PRINTF_INT8_DEC_WIDTH -# define PRINTF_INT8_DEC_WIDTH "3" -#endif - -/* - * Ok, lets not worry about 128 bit integers for now. Moore's law says - * we don't need to worry about that until about 2040 at which point - * we'll have bigger things to worry about. - */ - -#ifdef stdint_int64_defined - typedef int64_t intmax_t; - typedef uint64_t uintmax_t; -# define INTMAX_MAX INT64_MAX -# define INTMAX_MIN INT64_MIN -# define UINTMAX_MAX UINT64_MAX -# define UINTMAX_C(v) UINT64_C(v) -# define INTMAX_C(v) INT64_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH -# endif -#else - typedef int32_t intmax_t; - typedef uint32_t uintmax_t; -# define INTMAX_MAX INT32_MAX -# define UINTMAX_MAX UINT32_MAX -# define UINTMAX_C(v) UINT32_C(v) -# define INTMAX_C(v) INT32_C(v) -# ifndef PRINTF_INTMAX_MODIFIER -# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER -# endif -# ifndef PRINTF_INTMAX_HEX_WIDTH -# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH -# endif -# ifndef PRINTF_INTMAX_DEC_WIDTH -# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH -# endif -#endif - -/* - * Because this file currently only supports platforms which have - * precise powers of 2 as bit sizes for the default integers, the - * least definitions are all trivial. Its possible that a future - * version of this file could have different definitions. - */ - -#ifndef stdint_least_defined - typedef int8_t int_least8_t; - typedef uint8_t uint_least8_t; - typedef int16_t int_least16_t; - typedef uint16_t uint_least16_t; - typedef int32_t int_least32_t; - typedef uint32_t uint_least32_t; -# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER -# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER -# define UINT_LEAST8_MAX UINT8_MAX -# define INT_LEAST8_MAX INT8_MAX -# define UINT_LEAST16_MAX UINT16_MAX -# define INT_LEAST16_MAX INT16_MAX -# define UINT_LEAST32_MAX UINT32_MAX -# define INT_LEAST32_MAX INT32_MAX -# define INT_LEAST8_MIN INT8_MIN -# define INT_LEAST16_MIN INT16_MIN -# define INT_LEAST32_MIN INT32_MIN -# ifdef stdint_int64_defined - typedef int64_t int_least64_t; - typedef uint64_t uint_least64_t; -# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER -# define UINT_LEAST64_MAX UINT64_MAX -# define INT_LEAST64_MAX INT64_MAX -# define INT_LEAST64_MIN INT64_MIN -# endif -#endif -#undef stdint_least_defined - -/* - * The ANSI C committee pretending to know or specify anything about - * performance is the epitome of misguided arrogance. The mandate of - * this file is to *ONLY* ever support that absolute minimum - * definition of the fast integer types, for compatibility purposes. - * No extensions, and no attempt to suggest what may or may not be a - * faster integer type will ever be made in this file. Developers are - * warned to stay away from these types when using this or any other - * stdint.h. - */ - -typedef int_least8_t int_fast8_t; -typedef uint_least8_t uint_fast8_t; -typedef int_least16_t int_fast16_t; -typedef uint_least16_t uint_fast16_t; -typedef int_least32_t int_fast32_t; -typedef uint_least32_t uint_fast32_t; -#define UINT_FAST8_MAX UINT_LEAST8_MAX -#define INT_FAST8_MAX INT_LEAST8_MAX -#define UINT_FAST16_MAX UINT_LEAST16_MAX -#define INT_FAST16_MAX INT_LEAST16_MAX -#define UINT_FAST32_MAX UINT_LEAST32_MAX -#define INT_FAST32_MAX INT_LEAST32_MAX -#define INT_FAST8_MIN INT_LEAST8_MIN -#define INT_FAST16_MIN INT_LEAST16_MIN -#define INT_FAST32_MIN INT_LEAST32_MIN -#ifdef stdint_int64_defined - typedef int_least64_t int_fast64_t; - typedef uint_least64_t uint_fast64_t; -# define UINT_FAST64_MAX UINT_LEAST64_MAX -# define INT_FAST64_MAX INT_LEAST64_MAX -# define INT_FAST64_MIN INT_LEAST64_MIN -#endif - -#undef stdint_int64_defined - -/* - * Whatever piecemeal, per compiler thing we can do about the wchar_t - * type limits. - */ - -#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) -# include <wchar.h> -# ifndef WCHAR_MIN -# define WCHAR_MIN 0 -# endif -# ifndef WCHAR_MAX -# define WCHAR_MAX ((wchar_t)-1) -# endif -#endif - -/* - * Whatever piecemeal, per compiler/platform thing we can do about the - * (u)intptr_t types and limits. - */ - -#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -#ifndef STDINT_H_UINTPTR_T_DEFINED -# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) -# define stdint_intptr_bits 64 -# elif defined (__WATCOMC__) || defined (__TURBOC__) -# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) -# define stdint_intptr_bits 16 -# else -# define stdint_intptr_bits 32 -# endif -# elif defined (__i386__) || defined (_WIN32) || defined (WIN32) -# define stdint_intptr_bits 32 -# elif defined (__INTEL_COMPILER) -/* TODO -- what will Intel do about x86-64? */ -# endif - -# ifdef stdint_intptr_bits -# define stdint_intptr_glue3_i(a,b,c) a##b##c -# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) -# ifndef PRINTF_INTPTR_MODIFIER -# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) -# endif -# ifndef PTRDIFF_MAX -# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef PTRDIFF_MIN -# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef UINTPTR_MAX -# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MAX -# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) -# endif -# ifndef INTPTR_MIN -# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) -# endif -# ifndef INTPTR_C -# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) -# endif -# ifndef UINTPTR_C -# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) -# endif - typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; - typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; -# else -/* TODO -- This following is likely wrong for some platforms, and does - nothing for the definition of uintptr_t. */ - typedef ptrdiff_t intptr_t; -# endif -# define STDINT_H_UINTPTR_T_DEFINED -#endif - -/* - * Assumes sig_atomic_t is signed and we have a 2s complement machine. - */ - -#ifndef SIG_ATOMIC_MAX -# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) -#endif - -#endif - diff --git a/3rdparty/assimp/code/qnan.h b/3rdparty/assimp/code/qnan.h deleted file mode 100644 index c21dc86a..00000000 --- a/3rdparty/assimp/code/qnan.h +++ /dev/null @@ -1,110 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (ASSIMP) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 qnan.h - * @brief Some utilities for our dealings with qnans. - * - * @note Some loaders use qnans to mark invalid values tempoarily, also - * Assimp explicitly enforces undefined normals to be set to qnan. - * qnan utilities are available in standard libraries (C99 for example) - * but last time I checked compiler coverage was so bad that I decided - * to reinvent the wheel. - */ - -#ifndef AI_QNAN_H_INCLUDED -#define AI_QNAN_H_INCLUDED - -// --------------------------------------------------------------------------- -/** Data structure to represent the bit pattern of a 32 Bit - * IEEE 754 floating-point number. */ -union _IEEESingle -{ - float Float; - struct - { - uint32_t Frac : 23; - uint32_t Exp : 8; - uint32_t Sign : 1; - } IEEE; -} ; - -// --------------------------------------------------------------------------- -/** Check whether a given float is qNaN. - * @param in Input value */ -AI_FORCE_INLINE bool is_qnan(float in) -{ - // the straightforward solution does not work: - // return (in != in); - // compiler generates code like this - // load <in> to <register-with-different-width> - // compare <register-with-different-width> against <in> - - // FIXME: Use <float> stuff instead? I think fpclassify needs C99 - return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1 && - reinterpret_cast<_IEEESingle*>(&in)->IEEE.Frac); -} - -// --------------------------------------------------------------------------- -/** Check whether a float is NOT qNaN. - * @param in Input value */ -AI_FORCE_INLINE bool is_not_qnan(float in) -{ - return !is_qnan(in); -} - -// --------------------------------------------------------------------------- -/** @brief check whether a float is either NaN or (+/-) INF. - * - * Denorms return false, they're treated like normal values. - * @param in Input value */ -AI_FORCE_INLINE bool is_special_float(float in) -{ - return (reinterpret_cast<_IEEESingle*>(&in)->IEEE.Exp == (1u << 8)-1); -} - -// --------------------------------------------------------------------------- -/** @brief Get a fresh qnan. */ -AI_FORCE_INLINE float get_qnan() -{ - return std::numeric_limits<float>::quiet_NaN(); -} - -#endif // !! AI_QNAN_H_INCLUDED diff --git a/3rdparty/assimp/code/res/resource.h b/3rdparty/assimp/code/res/resource.h deleted file mode 100644 index a9733ce4..00000000 --- a/3rdparty/assimp/code/res/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by assimp.rc - -// Nächste Standardwerte für neue Objekte -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif |