summaryrefslogtreecommitdiff
path: root/libs/assimp/code/AssetLib/3DS/3DSLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/assimp/code/AssetLib/3DS/3DSLoader.cpp')
-rw-r--r--libs/assimp/code/AssetLib/3DS/3DSLoader.cpp1336
1 files changed, 0 insertions, 1336 deletions
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