diff options
author | sanine <sanine.not@pm.me> | 2023-02-12 23:53:22 -0600 |
---|---|---|
committer | sanine <sanine.not@pm.me> | 2023-02-12 23:53:22 -0600 |
commit | f1fe73d1909a2448a004a88362a1a532d0d4f7c3 (patch) | |
tree | ab37ae3837e2f858de2932bcee9f26e69fab3db1 /libs/assimp/code/AssetLib/3DS | |
parent | f567ea1e2798fd3156a416e61f083ea3e6b95719 (diff) |
switch to tinyobj and nanovg from assimp and cairo
Diffstat (limited to 'libs/assimp/code/AssetLib/3DS')
-rw-r--r-- | libs/assimp/code/AssetLib/3DS/3DSConverter.cpp | 807 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/3DS/3DSExporter.cpp | 584 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/3DS/3DSExporter.h | 98 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/3DS/3DSHelper.h | 702 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/3DS/3DSLoader.cpp | 1336 | ||||
-rw-r--r-- | libs/assimp/code/AssetLib/3DS/3DSLoader.h | 289 |
6 files changed, 0 insertions, 3816 deletions
diff --git a/libs/assimp/code/AssetLib/3DS/3DSConverter.cpp b/libs/assimp/code/AssetLib/3DS/3DSConverter.cpp deleted file mode 100644 index 5a01429..0000000 --- a/libs/assimp/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 diff --git a/libs/assimp/code/AssetLib/3DS/3DSExporter.cpp b/libs/assimp/code/AssetLib/3DS/3DSExporter.cpp deleted file mode 100644 index 71588f9..0000000 --- a/libs/assimp/code/AssetLib/3DS/3DSExporter.cpp +++ /dev/null @@ -1,584 +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. - ----------------------------------------------------------------------- -*/ - -#ifndef ASSIMP_BUILD_NO_EXPORT -#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER - -#include "AssetLib/3DS/3DSExporter.h" -#include "AssetLib/3DS/3DSHelper.h" -#include "AssetLib/3DS/3DSLoader.h" -#include "PostProcessing/SplitLargeMeshes.h" - -#include <assimp/SceneCombiner.h> -#include <assimp/StringComparison.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/Exporter.hpp> -#include <assimp/IOSystem.hpp> - -#include <memory> - -namespace Assimp { - -using namespace D3DS; - -namespace { - -////////////////////////////////////////////////////////////////////////////////////// -// Scope utility to write a 3DS file chunk. -// -// Upon construction, the chunk header is written with the chunk type (flags) -// filled out, but the chunk size left empty. Upon destruction, the correct chunk -// size based on the then-position of the output stream cursor is filled in. -class ChunkWriter { - enum { - CHUNK_SIZE_NOT_SET = 0xdeadbeef, - SIZE_OFFSET = 2 - }; - -public: - ChunkWriter(StreamWriterLE &writer, uint16_t chunk_type) : - writer(writer) { - chunk_start_pos = writer.GetCurrentPos(); - writer.PutU2(chunk_type); - writer.PutU4((uint32_t)CHUNK_SIZE_NOT_SET); - } - - ~ChunkWriter() { - std::size_t head_pos = writer.GetCurrentPos(); - - ai_assert(head_pos > chunk_start_pos); - const std::size_t chunk_size = head_pos - chunk_start_pos; - - writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET); - writer.PutU4(static_cast<uint32_t>(chunk_size)); - writer.SetCurrentPos(head_pos); - } - -private: - StreamWriterLE &writer; - std::size_t chunk_start_pos; -}; - -// Return an unique name for a given |mesh| attached to |node| that -// preserves the mesh's given name if it has one. |index| is the index -// of the mesh in |aiScene::mMeshes|. -std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) { - static const char underscore = '_'; - char postfix[10] = { 0 }; - ASSIMP_itoa10(postfix, index); - - std::string result = node.mName.C_Str(); - if (mesh.mName.length > 0) { - result += underscore; - result += mesh.mName.C_Str(); - } - return result + underscore + postfix; -} - -// Return an unique name for a given |mat| with original position |index| -// in |aiScene::mMaterials|. The name preserves the original material -// name if possible. -std::string GetMaterialName(const aiMaterial &mat, unsigned int index) { - static const std::string underscore = "_"; - char postfix[10] = { 0 }; - ASSIMP_itoa10(postfix, index); - - aiString mat_name; - if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) { - return mat_name.C_Str() + underscore + postfix; - } - - return "Material" + underscore + postfix; -} - -// Collect world transformations for each node -void CollectTrafos(const aiNode *node, std::map<const aiNode *, aiMatrix4x4> &trafos) { - const aiMatrix4x4 &parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4(); - trafos[node] = parent * node->mTransformation; - for (unsigned int i = 0; i < node->mNumChildren; ++i) { - CollectTrafos(node->mChildren[i], trafos); - } -} - -// Generate a flat list of the meshes (by index) assigned to each node -void CollectMeshes(const aiNode *node, std::multimap<const aiNode *, unsigned int> &meshes) { - for (unsigned int i = 0; i < node->mNumMeshes; ++i) { - meshes.insert(std::make_pair(node, node->mMeshes[i])); - } - for (unsigned int i = 0; i < node->mNumChildren; ++i) { - CollectMeshes(node->mChildren[i], meshes); - } -} -} // namespace - -// ------------------------------------------------------------------------------------------------ -// Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp -void ExportScene3DS(const char *pFile, IOSystem *pIOSystem, const aiScene *pScene, const ExportProperties * /*pProperties*/) { - std::shared_ptr<IOStream> outfile(pIOSystem->Open(pFile, "wb")); - if (!outfile) { - throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile)); - } - - // TODO: This extra copy should be avoided and all of this made a preprocess - // requirement of the 3DS exporter. - // - // 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively. - // SplitLargeMeshes can do this, but it requires the correct limit to be set - // which is not possible with the current way of specifying preprocess steps - // in |Exporter::ExportFormatEntry|. - aiScene *scenecopy_tmp; - SceneCombiner::CopyScene(&scenecopy_tmp, pScene); - std::unique_ptr<aiScene> scenecopy(scenecopy_tmp); - - SplitLargeMeshesProcess_Triangle tri_splitter; - tri_splitter.SetLimit(0xffff); - tri_splitter.Execute(scenecopy.get()); - - SplitLargeMeshesProcess_Vertex vert_splitter; - vert_splitter.SetLimit(0xffff); - vert_splitter.Execute(scenecopy.get()); - - // Invoke the actual exporter - Discreet3DSExporter exporter(outfile, scenecopy.get()); -} - -} // end of namespace Assimp - -// ------------------------------------------------------------------------------------------------ -Discreet3DSExporter::Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene *scene) : - scene(scene), writer(outfile) { - CollectTrafos(scene->mRootNode, trafos); - CollectMeshes(scene->mRootNode, meshes); - - ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAIN); - - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_OBJMESH); - WriteMaterials(); - WriteMeshes(); - - { - ChunkWriter curChunk1(writer, Discreet3DS::CHUNK_MASTER_SCALE); - writer.PutF4(1.0f); - } - } - - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_KEYFRAMER); - WriteHierarchy(*scene->mRootNode, -1, -1); - } -} - -// ------------------------------------------------------------------------------------------------ -Discreet3DSExporter::~Discreet3DSExporter() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) { - // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec - { - ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_TRACKINFO); - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); - - // Assimp node names are unique and distinct from all mesh-node - // names we generate; thus we can use them as-is - WriteString(node.mName); - - // Two unknown int16 values - it is even unclear if 0 is a safe value - // but luckily importers do not know better either. - writer.PutI4(0); - - int16_t hierarchy_pos = static_cast<int16_t>(seq); - if (sibling_level != -1) { - hierarchy_pos = (uint16_t)sibling_level; - } - - // Write the hierarchy position - writer.PutI2(hierarchy_pos); - } - } - - // TODO: write transformation chunks - - ++seq; - sibling_level = seq; - - // Write all children - for (unsigned int i = 0; i < node.mNumChildren; ++i) { - seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level); - } - - // Write all meshes as separate nodes to be able to reference the meshes by name - for (unsigned int i = 0; i < node.mNumMeshes; ++i) { - const bool first_child = node.mNumChildren == 0 && i == 0; - - const unsigned int mesh_idx = node.mMeshes[i]; - const aiMesh &mesh = *scene->mMeshes[mesh_idx]; - - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRACKINFO); - { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME); - WriteString(GetMeshName(mesh, mesh_idx, node)); - - writer.PutI4(0); - writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level)); - ++seq; - } - } - return seq; -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteMaterials() { - for (unsigned int i = 0; i < scene->mNumMaterials; ++i) { - ChunkWriter curRootChunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL); - const aiMaterial &mat = *scene->mMaterials[i]; - - { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME); - const std::string &name = GetMaterialName(mat, i); - WriteString(name); - } - - aiColor3D color; - if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE); - WriteColor(color); - } - - if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR); - WriteColor(color); - } - - if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT); - WriteColor(color); - } - - float f; - if (mat.Get(AI_MATKEY_OPACITY, f) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TRANSPARENCY); - WritePercentChunk(1.0f - f); - } - - if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM); - WriteColor(color); - } - - aiShadingMode shading_mode = aiShadingMode_Flat; - if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING); - - Discreet3DS::shadetype3ds shading_mode_out; - switch (shading_mode) { - case aiShadingMode_Flat: - case aiShadingMode_NoShading: - shading_mode_out = Discreet3DS::Flat; - break; - - case aiShadingMode_Gouraud: - case aiShadingMode_Toon: - case aiShadingMode_OrenNayar: - case aiShadingMode_Minnaert: - shading_mode_out = Discreet3DS::Gouraud; - break; - - case aiShadingMode_Phong: - case aiShadingMode_Blinn: - case aiShadingMode_CookTorrance: - case aiShadingMode_Fresnel: - case aiShadingMode_PBR_BRDF: // Possibly should be Discreet3DS::Metal in some cases but this is undocumented - shading_mode_out = Discreet3DS::Phong; - break; - - default: - shading_mode_out = Discreet3DS::Flat; - ai_assert(false); - }; - writer.PutU2(static_cast<uint16_t>(shading_mode_out)); - } - - if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS); - WritePercentChunk(f); - } - - if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT); - WritePercentChunk(f); - } - - int twosided; - if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) { - ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE); - writer.PutI2(1); - } - - // Fallback to BASE_COLOR if no DIFFUSE - if (!WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE)) - WriteTexture(mat, aiTextureType_BASE_COLOR, Discreet3DS::CHUNK_MAT_TEXTURE); - - WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP); - WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP); - WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP); - WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP); - WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP); - WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP); - } -} - -// ------------------------------------------------------------------------------------------------ -// returns true if the texture existed -bool Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) { - aiString path; - aiTextureMapMode map_mode[2] = { - aiTextureMapMode_Wrap, aiTextureMapMode_Wrap - }; - ai_real blend = 1.0; - if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) { - return false; - } - - // TODO: handle embedded textures properly - if (path.data[0] == '*') { - ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str()); - return false; - } - - ChunkWriter chunk(writer, chunk_flags); - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPFILE); - WriteString(path); - } - - WritePercentChunk(blend); - - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING); - uint16_t val = 0; // WRAP - if (map_mode[0] == aiTextureMapMode_Mirror) { - val = 0x2; - } else if (map_mode[0] == aiTextureMapMode_Decal) { - val = 0x10; - } - writer.PutU2(val); - } - // TODO: export texture transformation (i.e. UV offset, scale, rotation) - return true; -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteMeshes() { - // NOTE: 3DS allows for instances. However: - // i) not all importers support reading them - // ii) instances are not as flexible as they are in assimp, in particular, - // nodes can carry (and instance) only one mesh. - // - // This exporter currently deep clones all instanced meshes, i.e. for each mesh - // attached to a node a full TRIMESH chunk is written to the file. - // - // Furthermore, the TRIMESH is transformed into world space so that it will - // appear correctly if importers don't read the scene hierarchy at all. - for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) { - const aiNode &node = *(*it).first; - const unsigned int mesh_idx = (*it).second; - - const aiMesh &mesh = *scene->mMeshes[mesh_idx]; - - // This should not happen if the SLM step is correctly executed - // before the scene is handed to the exporter - ai_assert(mesh.mNumVertices <= 0xffff); - ai_assert(mesh.mNumFaces <= 0xffff); - - const aiMatrix4x4 &trafo = trafos[&node]; - - ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK); - - // Mesh name is tied to the node it is attached to so it can later be referenced - const std::string &name = GetMeshName(mesh, mesh_idx, node); - WriteString(name); - - // TRIMESH chunk - ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH); - - // Vertices in world space - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_VERTLIST); - - const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices); - writer.PutU2(count); - for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &v = mesh.mVertices[i]; - writer.PutF4(v.x); - writer.PutF4(v.y); - writer.PutF4(v.z); - } - } - - // UV coordinates - if (mesh.HasTextureCoords(0)) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAPLIST); - const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices); - writer.PutU2(count); - - for (unsigned int i = 0; i < mesh.mNumVertices; ++i) { - const aiVector3D &v = mesh.mTextureCoords[0][i]; - writer.PutF4(v.x); - writer.PutF4(v.y); - } - } - - // Faces (indices) - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACELIST); - - ai_assert(mesh.mNumFaces <= 0xffff); - - // Count triangles, discard lines and points - uint16_t count = 0; - for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { - const aiFace &f = mesh.mFaces[i]; - if (f.mNumIndices < 3) { - continue; - } - // TRIANGULATE step is a pre-requisite so we should not see polys here - ai_assert(f.mNumIndices == 3); - ++count; - } - - writer.PutU2(count); - for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { - const aiFace &f = mesh.mFaces[i]; - if (f.mNumIndices < 3) { - continue; - } - - for (unsigned int j = 0; j < 3; ++j) { - ai_assert(f.mIndices[j] <= 0xffff); - writer.PutI2(static_cast<uint16_t>(f.mIndices[j])); - } - - // Edge visibility flag - writer.PutI2(0x0); - } - - // TODO: write smoothing groups (CHUNK_SMOOLIST) - - WriteFaceMaterialChunk(mesh); - } - - // Transformation matrix by which the mesh vertices have been pre-transformed with. - { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_TRMATRIX); - // Store rotation 3x3 matrix row wise - for (unsigned int r = 0; r < 3; ++r) { - for (unsigned int c = 0; c < 3; ++c) { - writer.PutF4(trafo[r][c]); - } - } - // Store translation sub vector column wise - for (unsigned int r = 0; r < 3; ++r) { - writer.PutF4(trafo[r][3]); - } - } - } -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh &mesh) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_FACEMAT); - const std::string &name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex); - WriteString(name); - - // Because assimp splits meshes by material, only a single - // FACEMAT chunk needs to be written - ai_assert(mesh.mNumFaces <= 0xffff); - const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces); - writer.PutU2(count); - - for (unsigned int i = 0; i < mesh.mNumFaces; ++i) { - writer.PutU2(static_cast<uint16_t>(i)); - } -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteString(const std::string &s) { - for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) { - writer.PutI1(*it); - } - writer.PutI1('\0'); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteString(const aiString &s) { - for (std::size_t i = 0; i < s.length; ++i) { - writer.PutI1(s.data[i]); - } - writer.PutI1('\0'); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WriteColor(const aiColor3D &color) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_RGBF); - writer.PutF4(color.r); - writer.PutF4(color.g); - writer.PutF4(color.b); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WritePercentChunk(float f) { - ChunkWriter curChunk(writer, Discreet3DS::CHUNK_PERCENTF); - writer.PutF4(f); -} - -// ------------------------------------------------------------------------------------------------ -void Discreet3DSExporter::WritePercentChunk(double f) { - ChunkWriter ccurChunkhunk(writer, Discreet3DS::CHUNK_PERCENTD); - writer.PutF8(f); -} - -#endif // ASSIMP_BUILD_NO_3DS_EXPORTER -#endif // ASSIMP_BUILD_NO_EXPORT diff --git a/libs/assimp/code/AssetLib/3DS/3DSExporter.h b/libs/assimp/code/AssetLib/3DS/3DSExporter.h deleted file mode 100644 index 82ec351..0000000 --- a/libs/assimp/code/AssetLib/3DS/3DSExporter.h +++ /dev/null @@ -1,98 +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 3DSExporter.h - * 3DS Exporter Main Header - */ -#ifndef AI_3DSEXPORTER_H_INC -#define AI_3DSEXPORTER_H_INC - -#include <map> -#include <memory> - -#include <assimp/StreamWriter.h> -#include <assimp/material.h> - -struct aiScene; -struct aiNode; -struct aiMaterial; -struct aiMesh; - -namespace Assimp -{ - -// ------------------------------------------------------------------------------------------------ -/** - * @brief Helper class to export a given scene to a 3DS file. - */ -// ------------------------------------------------------------------------------------------------ -class Discreet3DSExporter { -public: - Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene* pScene); - ~Discreet3DSExporter(); - -private: - void WriteMeshes(); - void WriteMaterials(); - bool WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags); - void WriteFaceMaterialChunk(const aiMesh& mesh); - int WriteHierarchy(const aiNode& node, int level, int sibling_level); - void WriteString(const std::string& s); - void WriteString(const aiString& s); - void WriteColor(const aiColor3D& color); - void WritePercentChunk(float f); - void WritePercentChunk(double f); - -private: - const aiScene* const scene; - StreamWriterLE writer; - - std::map<const aiNode*, aiMatrix4x4> trafos; - - typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap; - MeshesByNodeMap meshes; - -}; - -} // Namespace Assimp - -#endif // AI_3DSEXPORTER_H_INC diff --git a/libs/assimp/code/AssetLib/3DS/3DSHelper.h b/libs/assimp/code/AssetLib/3DS/3DSHelper.h deleted file mode 100644 index dc10980..0000000 --- a/libs/assimp/code/AssetLib/3DS/3DSHelper.h +++ /dev/null @@ -1,702 +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 Defines helper data structures for the import of 3DS files */ - -#ifndef AI_3DSFILEHELPER_H_INC -#define AI_3DSFILEHELPER_H_INC - -#include <assimp/SmoothingGroups.h> -#include <assimp/SpatialSort.h> -#include <assimp/StringUtils.h> -#include <assimp/anim.h> -#include <assimp/camera.h> -#include <assimp/light.h> -#include <assimp/material.h> -#include <assimp/qnan.h> -#include <cstdio> //sprintf - -namespace Assimp { -namespace D3DS { - -#include <assimp/Compiler/pushpack1.h> - -// --------------------------------------------------------------------------- -/** Defines chunks and data structures. -*/ -namespace Discreet3DS { - - //! 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 - CHUNK_PERCENTD = 0x0032, // float8 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 material 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 { -}; - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4315) -#endif // _MSC_VER - -// --------------------------------------------------------------------------- -/** Helper structure representing a texture */ -struct Texture { - //! Default constructor - Texture() AI_NO_EXCEPT - : mTextureBlend(0.0f), - mMapName(), - mOffsetU(0.0), - mOffsetV(0.0), - mScaleU(1.0), - mScaleV(1.0), - mRotation(0.0), - mMapMode(aiTextureMapMode_Wrap), - bPrivate(), - iUVSrc(0) { - mTextureBlend = get_qnan(); - } - - Texture(const Texture &other) : - mTextureBlend(other.mTextureBlend), - mMapName(other.mMapName), - mOffsetU(other.mOffsetU), - mOffsetV(other.mOffsetV), - mScaleU(other.mScaleU), - mScaleV(other.mScaleV), - mRotation(other.mRotation), - mMapMode(other.mMapMode), - bPrivate(other.bPrivate), - iUVSrc(other.iUVSrc) { - // empty - } - - Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend), - mMapName(std::move(other.mMapName)), - mOffsetU(other.mOffsetU), - mOffsetV(other.mOffsetV), - mScaleU(other.mScaleU), - mScaleV(other.mScaleV), - mRotation(other.mRotation), - mMapMode(other.mMapMode), - bPrivate(other.bPrivate), - iUVSrc(other.iUVSrc) { - // empty - } - - Texture &operator=(Texture &&other) AI_NO_EXCEPT { - if (this == &other) { - return *this; - } - - mTextureBlend = other.mTextureBlend; - mMapName = std::move(other.mMapName); - mOffsetU = other.mOffsetU; - mOffsetV = other.mOffsetV; - mScaleU = other.mScaleU; - mScaleV = other.mScaleV; - mRotation = other.mRotation; - mMapMode = other.mMapMode; - bPrivate = other.bPrivate; - iUVSrc = other.iUVSrc; - - return *this; - } - - //! Specifies the blend factor for the texture - ai_real mTextureBlend; - - //! Specifies the filename of the texture - std::string mMapName; - - //! Specifies texture coordinate offsets/scaling/rotations - ai_real mOffsetU; - ai_real mOffsetV; - ai_real mScaleU; - ai_real mScaleV; - ai_real mRotation; - - //! Specifies the mapping mode to be used for the texture - aiTextureMapMode mMapMode; - - //! Used internally - bool bPrivate; - int iUVSrc; -}; - -#include <assimp/Compiler/poppack1.h> - -#ifdef _MSC_VER -#pragma warning(pop) -#endif // _MSC_VER - -// --------------------------------------------------------------------------- -/** Helper structure representing a 3ds material */ -struct Material { - //! Default constructor has been deleted - Material() : - mName(), - mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), - mSpecularExponent(ai_real(0.0)), - mShininessStrength(ai_real(1.0)), - mShading(Discreet3DS::Gouraud), - mTransparency(ai_real(1.0)), - mBumpHeight(ai_real(1.0)), - mTwoSided(false) { - // empty - } - - //! Constructor with explicit name - explicit Material(const std::string &name) : - mName(name), - mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)), - mSpecularExponent(ai_real(0.0)), - mShininessStrength(ai_real(1.0)), - mShading(Discreet3DS::Gouraud), - mTransparency(ai_real(1.0)), - mBumpHeight(ai_real(1.0)), - mTwoSided(false) { - // empty - } - - Material(const Material &other) : - mName(other.mName), - mDiffuse(other.mDiffuse), - mSpecularExponent(other.mSpecularExponent), - mShininessStrength(other.mShininessStrength), - mSpecular(other.mSpecular), - mAmbient(other.mAmbient), - mShading(other.mShading), - mTransparency(other.mTransparency), - sTexDiffuse(other.sTexDiffuse), - sTexOpacity(other.sTexOpacity), - sTexSpecular(other.sTexSpecular), - sTexReflective(other.sTexReflective), - sTexBump(other.sTexBump), - sTexEmissive(other.sTexEmissive), - sTexShininess(other.sTexShininess), - mBumpHeight(other.mBumpHeight), - mEmissive(other.mEmissive), - sTexAmbient(other.sTexAmbient), - mTwoSided(other.mTwoSided) { - // empty - } - - //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it - Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)), - mDiffuse(other.mDiffuse), - mSpecularExponent(other.mSpecularExponent), - mShininessStrength(other.mShininessStrength), - mSpecular(other.mSpecular), - mAmbient(other.mAmbient), - mShading(other.mShading), - mTransparency(other.mTransparency), - sTexDiffuse(std::move(other.sTexDiffuse)), - sTexOpacity(std::move(other.sTexOpacity)), - sTexSpecular(std::move(other.sTexSpecular)), - sTexReflective(std::move(other.sTexReflective)), - sTexBump(std::move(other.sTexBump)), - sTexEmissive(std::move(other.sTexEmissive)), - sTexShininess(std::move(other.sTexShininess)), - mBumpHeight(other.mBumpHeight), - mEmissive(other.mEmissive), - sTexAmbient(std::move(other.sTexAmbient)), - mTwoSided(other.mTwoSided) { - // empty - } - - Material &operator=(Material &&other) AI_NO_EXCEPT { - if (this == &other) { - return *this; - } - - mName = std::move(other.mName); - mDiffuse = other.mDiffuse; - mSpecularExponent = other.mSpecularExponent; - mShininessStrength = other.mShininessStrength, - mSpecular = other.mSpecular; - mAmbient = other.mAmbient; - mShading = other.mShading; - mTransparency = other.mTransparency; - sTexDiffuse = std::move(other.sTexDiffuse); - sTexOpacity = std::move(other.sTexOpacity); - sTexSpecular = std::move(other.sTexSpecular); - sTexReflective = std::move(other.sTexReflective); - sTexBump = std::move(other.sTexBump); - sTexEmissive = std::move(other.sTexEmissive); - sTexShininess = std::move(other.sTexShininess); - mBumpHeight = other.mBumpHeight; - mEmissive = other.mEmissive; - sTexAmbient = std::move(other.sTexAmbient); - mTwoSided = other.mTwoSided; - - return *this; - } - - virtual ~Material() { - // empty - } - - //! Name of the material - std::string mName; - //! Diffuse color of the material - aiColor3D mDiffuse; - //! Specular exponent - ai_real mSpecularExponent; - //! Shininess strength, in percent - ai_real 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 - ai_real 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 - ai_real 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 has been deleted - Mesh() = delete; - - //! Constructor with explicit name - explicit Mesh(const std::string &name) : - mName(name) { - } - - //! 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 - ai_real 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() = delete; - - explicit Node(const std::string &name) : - mParent(nullptr), - mName(name), - mInstanceNumber(0), - mHierarchyPos(0), - mHierarchyIndex(0), - mInstanceCount(1) { - 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; - - //! InstanceNumber of the node - int32_t mInstanceNumber; - - //! 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; - - //instance count, will be kept only for the first node - int32_t mInstanceCount; - - //! 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/libs/assimp/code/AssetLib/3DS/3DSLoader.cpp b/libs/assimp/code/AssetLib/3DS/3DSLoader.cpp deleted file mode 100644 index 0ec8b87..0000000 --- a/libs/assimp/code/AssetLib/3DS/3DSLoader.cpp +++ /dev/null @@ -1,1336 +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 3DSLoader.cpp - * @brief Implementation of the 3ds importer class - * - * http://www.the-labs.com/Blender/3DS-details.html - */ - -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER - -#include "3DSLoader.h" -#include <assimp/StringComparison.h> -#include <assimp/importerdesc.h> -#include <assimp/scene.h> -#include <assimp/DefaultLogger.hpp> -#include <assimp/IOSystem.hpp> - -using namespace Assimp; - -static const aiImporterDesc desc = { - "Discreet 3DS Importer", - "", - "", - "Limited animation support", - aiImporterFlags_SupportBinaryFlavour, - 0, - 0, - 0, - 0, - "3ds prj" -}; - -// ------------------------------------------------------------------------------------------------ -// 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); \ - if (chunkSize <= 0) \ - continue; \ - const unsigned int oldReadLimit = 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() : - stream(), mLastNodeIndex(), mCurrentNode(), mRootNode(), mScene(), mMasterScale(), bHasBG(), bIsPrj() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Destructor, private as well -Discreet3DSImporter::~Discreet3DSImporter() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -// Returns whether the class can handle the format of the given file. -bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { - static const uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ }; - return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]); -} - -// ------------------------------------------------------------------------------------------------ -// Loader registry entry -const aiImporterDesc *Discreet3DSImporter::GetInfo() const { - return &desc; -} - -// ------------------------------------------------------------------------------------------------ -// 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) { - - auto theFile = pIOHandler->Open(pFile, "rb"); - if (!theFile) { - throw DeadlyImportError("3DS: Could not open ", pFile); - } - - StreamReaderLE theStream(theFile); - - // We should have at least one chunk - if (theStream.GetRemainingSize() < 16) { - throw DeadlyImportError("3DS file is either empty or corrupt: ", pFile); - } - this->stream = &theStream; - - // Allocate our temporary 3DS representation - D3DS::Scene _scene; - mScene = &_scene; - - // Initialize members - D3DS::Node _rootNode("UNNAMED"); - mLastNodeIndex = -1; - mCurrentNode = &_rootNode; - mRootNode = mCurrentNode; - mRootNode->mHierarchyPos = -1; - mRootNode->mHierarchyIndex = -1; - mRootNode->mParent = nullptr; - mMasterScale = 1.0f; - mBackgroundImage = std::string(); - bHasBG = false; - bIsPrj = false; - - // Parse the file - ParseMainChunk(); - - // Process all meshes in the file. First check whether all - // face indices have valid values. The generate our - // internal verbose representation. Finally compute normal - // vectors from the smoothing groups we read from the - // file. - for (auto &mesh : mScene->mMeshes) { - if (mesh.mFaces.size() > 0 && mesh.mPositions.size() == 0) { - throw DeadlyImportError("3DS file contains faces but no vertices: ", pFile); - } - CheckIndices(mesh); - MakeUnique(mesh); - ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh); - } - - // Replace all occurrences 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 sub-meshes - GenerateNodeGraph(pScene); - - // Now apply the master scaling factor to the scene - ApplyMasterScale(pScene); - - // Our internal scene representation and the root - // node will be automatically deleted, so the whole hierarchy will follow - - 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 != nullptr); - - 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()) { - ASSIMP_LOG_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; - break; - 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()); - ASSIMP_LOG_INFO("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(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size())))); - 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. - ASSIMP_LOG_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(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; - ai_real len = camera->mLookAt.Length(); - if (len < 1e-5) { - - // There are some files with lookat == position. Don't know why or whether it's ok or not. - ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector"); - camera->mLookAt = aiVector3D(0.0, 1.0, 0.0); - - } else - camera->mLookAt /= len; - - // And finally - the camera rotation angle, in counter clockwise direction - const ai_real angle = AI_DEG_TO_RAD(stream->GetF4()); - aiQuaternion quat(camera->mLookAt, angle); - camera->mUp = quat.GetMatrix() * aiVector3D(0.0, 1.0, 0.0); - - // Read the lense angle - camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4()); - if (camera->mHorizontalFOV < 0.001f) { - camera->mHorizontalFOV = float(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 = FindNode(*it, name); - if (nullptr != nd) { - return nd; - } - } - - return nullptr; -} - -// ------------------------------------------------------------------------------------------------ -// 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 is not really suitable for complex animations, - // so full support is not required. - ASSIMP_LOG_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); - int instanceNumber = 1; - - if (pcNode) { - // if the source is not a CHUNK_TRACKINFO block it won't be an object instance - if (parent != Discreet3DS::CHUNK_TRACKINFO) { - mCurrentNode = pcNode; - break; - } - pcNode->mInstanceCount++; - instanceNumber = pcNode->mInstanceCount; - } - pcNode = new D3DS::Node(name); - pcNode->mInstanceNumber = instanceNumber; - - // 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") { - mCurrentNode->mName = std::string(sz); - break; - } - } - break; - - case Discreet3DS::CHUNK_TRACKPIVOT: - - if (Discreet3DS::CHUNK_TRACKINFO != parent) { - ASSIMP_LOG_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) { - ASSIMP_LOG_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: { - ASSIMP_LOG_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; - if (num > mMesh.mFaces.size()) { - throw DeadlyImportError("3DS: More smoothing groups than faces"); - } - 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) { - ASSIMP_LOG_ERROR("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()) { - ASSIMP_LOG_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 = (int)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 - ASSIMP_LOG_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 - ASSIMP_LOG_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 - ASSIMP_LOG_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 - ASSIMP_LOG_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 - ASSIMP_LOG_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 - ai_real *pcf = &mScene->mMaterials.back().mTransparency; - *pcf = ParsePercentageChunk(); - - // NOTE: transparency, not opacity - if (is_qnan(*pcf)) - *pcf = ai_real(1.0); - else - *pcf = ai_real(1.0) - *pcf * (ai_real)0xFFFF / ai_real(100.0); - } 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 - ai_real *pcf = &mScene->mMaterials.back().mSpecularExponent; - *pcf = ParsePercentageChunk(); - if (is_qnan(*pcf)) - *pcf = 0.0; - else - *pcf *= (ai_real)0xFFFF; - } break; - - case Discreet3DS::CHUNK_MAT_SHININESS_PERCENT: { // This is the shininess strength of the material - ai_real *pcf = &mScene->mMaterials.back().mShininessStrength; - *pcf = ParsePercentageChunk(); - if (is_qnan(*pcf)) - *pcf = ai_real(0.0); - else - *pcf *= (ai_real)0xffff / ai_real(100.0); - } break; - - case Discreet3DS::CHUNK_MAT_SELF_ILPCT: { // This is the self illumination strength of the material - ai_real f = ParsePercentageChunk(); - if (is_qnan(f)) - f = ai_real(0.0); - else - f *= (ai_real)0xFFFF / ai_real(100.0); - 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_PERCENTD: - // Manually parse the blend factor - pcOut->mTextureBlend = ai_real(stream->GetF8()); - 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 = (ai_real)((uint16_t)stream->GetI2()) / ai_real(100.0); - break; - - case Discreet3DS::CHUNK_MAT_MAP_USCALE: - // Texture coordinate scaling in the U direction - pcOut->mScaleU = stream->GetF4(); - if (0.0f == pcOut->mScaleU) { - ASSIMP_LOG_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) { - ASSIMP_LOG_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 -ai_real Discreet3DSImporter::ParsePercentageChunk() { - Discreet3DS::Chunk chunk; - ReadChunk(&chunk); - - if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag) { - return stream->GetF4() * ai_real(100) / ai_real(0xFFFF); - } else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag) { - return (ai_real)((uint16_t)stream->GetI2()) / (ai_real)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 != nullptr); - - // error return value - const ai_real 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; - } - const ai_real invVal = ai_real(1.0) / ai_real(255.0); - out->r = (ai_real)(uint8_t)stream->GetI1() * invVal; - out->g = (ai_real)(uint8_t)stream->GetI1() * invVal; - out->b = (ai_real)(uint8_t)stream->GetI1() * invVal; - } 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 = (ai_real)(uint8_t)stream->GetI1() / ai_real(255.0); - break; - } - *out = clrError; - return; - - default: - stream->IncPtr(diff); - // Skip unknown chunks, hope this won't cause any problems. - return ParseColorChunk(out, acceptPercent); - }; - (void)bGamma; -} - -#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER diff --git a/libs/assimp/code/AssetLib/3DS/3DSLoader.h b/libs/assimp/code/AssetLib/3DS/3DSLoader.h deleted file mode 100644 index f47fcfe..0000000 --- a/libs/assimp/code/AssetLib/3DS/3DSLoader.h +++ /dev/null @@ -1,289 +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 3DSLoader.h - * @brief 3DS File format loader - */ -#ifndef AI_3DSIMPORTER_H_INC -#define AI_3DSIMPORTER_H_INC -#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER - -#include <assimp/BaseImporter.h> -#include <assimp/types.h> - - -#include "3DSHelper.h" -#include <assimp/StreamReader.h> - -struct aiNode; - -namespace Assimp { - - -using namespace D3DS; - -// --------------------------------------------------------------------------------- -/** Importer class for 3D Studio r3 and r4 3DS files - */ -class Discreet3DSImporter : public BaseImporter { -public: - Discreet3DSImporter(); - ~Discreet3DSImporter(); - - // ------------------------------------------------------------------- - /** 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 override; - - // ------------------------------------------------------------------- - /** 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) override; - -protected: - - // ------------------------------------------------------------------- - /** Return importer meta information. - * See #BaseImporter::GetInfo for the details - */ - const aiImporterDesc* GetInfo () const override; - - // ------------------------------------------------------------------- - /** Imports the given file into the given scene structure. - * See BaseImporter::InternReadFile() for details - */ - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler) override; - - // ------------------------------------------------------------------- - /** Converts a temporary material to the outer representation - */ - void ConvertMaterial(D3DS::Material& p_cMat, - aiMaterial& 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. - */ - ai_real 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(); - - bool ContainsTextures(unsigned int i) const { - return !mScene->mMaterials[i].sTexDiffuse.mMapName.empty() || - !mScene->mMaterials[i].sTexBump.mMapName.empty() || - !mScene->mMaterials[i].sTexOpacity.mMapName.empty() || - !mScene->mMaterials[i].sTexEmissive.mMapName.empty() || - !mScene->mMaterials[i].sTexSpecular.mMapName.empty() || - !mScene->mMaterials[i].sTexShininess.mMapName.empty() ; - } - - // ------------------------------------------------------------------- - /** 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 */ - ai_real 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 // !! ASSIMP_BUILD_NO_3DS_IMPORTER - -#endif // AI_3DSIMPORTER_H_INC |