diff options
Diffstat (limited to 'src/mesh/assimp-master/code/AssetLib/3DS/3DSConverter.cpp')
-rw-r--r-- | src/mesh/assimp-master/code/AssetLib/3DS/3DSConverter.cpp | 807 |
1 files changed, 0 insertions, 807 deletions
diff --git a/src/mesh/assimp-master/code/AssetLib/3DS/3DSConverter.cpp b/src/mesh/assimp-master/code/AssetLib/3DS/3DSConverter.cpp deleted file mode 100644 index 5a01429..0000000 --- a/src/mesh/assimp-master/code/AssetLib/3DS/3DSConverter.cpp +++ /dev/null @@ -1,807 +0,0 @@ -/* ---------------------------------------------------------------------------- -Open Asset Import Library (assimp) ---------------------------------------------------------------------------- - -Copyright (c) 2006-2022, assimp team - -All rights reserved. - -Redistribution and use of this software in source and binary forms, -with or without modification, are permitted provided that the following -conditions are met: - -* Redistributions of source code must retain the above - copyright notice, this list of conditions and the - following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the - following disclaimer in the documentation and/or other - materials provided with the distribution. - -* Neither the name of the assimp team, nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior - written permission of the assimp team. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- -*/ - -/** @file Implementation of the 3ds importer class */ - -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER - -// internal headers -#include "3DSLoader.h" -#include "Common/TargetAnimation.h" -#include <assimp/StringComparison.h> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <cctype> -#include <memory> - -using namespace Assimp; - -static const unsigned int NotSet = 0xcdcdcdcd; - -// ------------------------------------------------------------------------------------------------ -// 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(NotSet); - for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { - std::string s = mScene->mMaterials[i].mName; - for (char & it : s) { - it = static_cast<char>(::tolower(static_cast<unsigned char>(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 (ContainsTextures(i)) { - continue; - } - idx = i; - } - if (NotSet == 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; - ASSIMP_LOG_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("%%%DEFAULT"); - sMat.mDiffuse = aiColor3D(0.3f, 0.3f, 0.3f); - mScene->mMaterials.push_back(sMat); - - ASSIMP_LOG_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()) { - ASSIMP_LOG_WARN("3DS: Vertex index overflow)"); - (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size() - 1; - } - if (!sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size()) { - ASSIMP_LOG_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(aiMaterial &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<ai_real>(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0)); - - // Setup the texture mapping mode - int mapMode = static_cast<int>(texture.mMapMode); - mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0)); - mat.AddProperty<int>(&mapMode, 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.0; - texture.mScaleV *= 2.0; - texture.mOffsetU /= 2.0; - texture.mOffsetV /= 2.0; - } - - // Setup texture UV transformations - mat.AddProperty<ai_real>(&texture.mOffsetU, 5, AI_MATKEY_UVTRANSFORM(type, 0)); -} - -// ------------------------------------------------------------------------------------------------ -// Convert a 3DS material to an aiMaterial -void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat, - aiMaterial &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<ai_real>(&oldMat.mTransparency, 1, AI_MATKEY_OPACITY); - - // Bump height scaling - mat.AddProperty<ai_real>(&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; - } - int eShading_ = static_cast<int>(eShading); - mat.AddProperty<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) { - std::unique_ptr<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(); - meshOut->mName = name; - 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) { - 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(nullptr != 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]; - - if (mesh->mColors[1] == nullptr) { - // 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; - } - ASSIMP_LOG_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; - } - } - - mesh->mColors[1] = (aiColor4D *)1; - } else - mesh->mColors[1] = (aiColor4D *)1; - - // Setup the mesh index - pcOut->mMeshes[i] = iIndex; - } - } - - // Setup the name of the node - // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number - if (pcIn->mInstanceNumber > 1) { - char tmp[12]; - ASSIMP_itoa10(tmp, pcIn->mInstanceNumber); - std::string tempStr = pcIn->mName + "_inst_"; - tempStr += tmp; - pcOut->mName.Set(tempStr); - } else - 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(nullptr != anim); - - if (pcIn->aCameraRollKeys.size() > 1) { - ASSIMP_LOG_VERBOSE_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) - { - ASSIMP_LOG_VERBOSE_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 abs1; - for (unsigned int n = 0; n < nda->mNumRotationKeys; ++n) { - const aiQuatKey &q = pcIn->aRotationKeys[n]; - - abs1 = (n ? abs1 * q.mValue : q.mValue); - nda->mRotationKeys[n].mTime = q.mTime; - nda->mRotationKeys[n].mValue = abs1.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 = static_cast<unsigned int>(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 messed 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 .... - // - ASSIMP_LOG_WARN("No hierarchy information has been found in the file. "); - - pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes + - static_cast<unsigned int>(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 = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", 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 and second vertex color set to store some temporary values so we need to cleanup here - for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a) { - pcOut->mMeshes[a]->mColors[0] = nullptr; - pcOut->mMeshes[a]->mColors[1] = nullptr; - } - - 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) { - aiMaterial *pcNew = new aiMaterial(); - 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 |