|
|
|
@ -236,7 +236,6 @@ void Discreet3DSImporter::ParseMainChunk()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseMainChunk();
|
|
|
|
|
}
|
|
|
|
@ -271,7 +270,6 @@ void Discreet3DSImporter::ParseEditorChunk()
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseEditorChunk();
|
|
|
|
|
}
|
|
|
|
@ -310,43 +308,32 @@ void Discreet3DSImporter::ParseObjectChunk()
|
|
|
|
|
if (is_qnan(mClrAmbient.r))
|
|
|
|
|
{
|
|
|
|
|
// We failed to read the ambient base color.
|
|
|
|
|
// Set it to black so it won't have affect
|
|
|
|
|
// the rendering
|
|
|
|
|
mClrAmbient.r = 0.0f;
|
|
|
|
|
mClrAmbient.g = 0.0f;
|
|
|
|
|
mClrAmbient.b = 0.0f;
|
|
|
|
|
DefaultLogger::get()->error("3DS: Failed to read ambient base color");
|
|
|
|
|
mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Discreet3DS::CHUNK_BIT_MAP:
|
|
|
|
|
{
|
|
|
|
|
// Specifies the background image. The string
|
|
|
|
|
// should already be properly 0 terminated but we
|
|
|
|
|
// need to be sure
|
|
|
|
|
// 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();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseObjectChunk();
|
|
|
|
|
}
|
|
|
|
@ -386,23 +373,15 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
|
|
|
|
|
light->mPosition.y = stream->GetF4();
|
|
|
|
|
light->mPosition.z = stream->GetF4();
|
|
|
|
|
|
|
|
|
|
light->mColorDiffuse = aiColor3D(1.f,1.f,1.f);
|
|
|
|
|
|
|
|
|
|
// Now check for further subchunks (excluding color)
|
|
|
|
|
int8_t* p = stream->GetPtr();
|
|
|
|
|
ParseLightChunk();
|
|
|
|
|
|
|
|
|
|
// Now read the color
|
|
|
|
|
stream->SetPtr(p);
|
|
|
|
|
ParseColorChunk(&light->mColorDiffuse,true);
|
|
|
|
|
if (is_qnan(light->mColorDiffuse.r))
|
|
|
|
|
{
|
|
|
|
|
// it could be there is no color subchunk
|
|
|
|
|
light->mColorDiffuse = aiColor3D(1.f,1.f,1.f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The specular light color is identical to
|
|
|
|
|
// the diffuse light color. The ambient light
|
|
|
|
|
// color is equal to the ambient base color of
|
|
|
|
|
// the whole scene.
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
|
@ -421,10 +400,11 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
|
|
|
|
|
|
|
|
|
|
camera->mName.Set(std::string(name, num));
|
|
|
|
|
|
|
|
|
|
// The camera position and look-at vector are
|
|
|
|
|
// difficult to handle. Later we'll copy these
|
|
|
|
|
// values to the local transformation of the
|
|
|
|
|
// camera's node.
|
|
|
|
|
// Camera position and look-at vector are difficult to handle.
|
|
|
|
|
// If an animation track is given, we must make sure that
|
|
|
|
|
// the track is relative to these values - or , easier
|
|
|
|
|
// we must copy the information here to the node matrix of
|
|
|
|
|
// the camera's parent in the graph.
|
|
|
|
|
|
|
|
|
|
// First read the position of the camera
|
|
|
|
|
camera->mPosition.x = stream->GetF4();
|
|
|
|
@ -435,8 +415,6 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
|
|
|
|
|
camera->mLookAt.x = stream->GetF4() - camera->mPosition.x;
|
|
|
|
|
camera->mLookAt.y = stream->GetF4() - camera->mPosition.y;
|
|
|
|
|
camera->mLookAt.z = stream->GetF4() - camera->mPosition.z;
|
|
|
|
|
|
|
|
|
|
// We wouldn't need to normalize here, but we do it
|
|
|
|
|
camera->mLookAt.Normalize();
|
|
|
|
|
|
|
|
|
|
// And finally - the camera rotation angle, in
|
|
|
|
@ -446,13 +424,13 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
|
|
|
|
|
camera->mUp = quat.GetMatrix() * aiVector3D(0.f,1.f,0.f);
|
|
|
|
|
|
|
|
|
|
// Read the lense angle
|
|
|
|
|
// TODO
|
|
|
|
|
camera->mHorizontalFOV = AI_DEG_TO_RAD ( stream->GetF4() );
|
|
|
|
|
if (camera->mHorizontalFOV < 0.001f)
|
|
|
|
|
camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseChunk(name,num);
|
|
|
|
|
}
|
|
|
|
@ -467,7 +445,6 @@ void Discreet3DSImporter::ParseLightChunk()
|
|
|
|
|
switch (chunk.Flag)
|
|
|
|
|
{
|
|
|
|
|
case Discreet3DS::CHUNK_SPOTLIGHT:
|
|
|
|
|
{
|
|
|
|
|
// Now we can be sure that the light is a spot light
|
|
|
|
|
light->mType = aiLightSource_SPOT;
|
|
|
|
|
|
|
|
|
@ -479,20 +456,56 @@ void Discreet3DSImporter::ParseLightChunk()
|
|
|
|
|
|
|
|
|
|
// Now the hotspot and falloff angles - in degrees
|
|
|
|
|
light->mAngleInnerCone = AI_DEG_TO_RAD( stream->GetF4() );
|
|
|
|
|
light->mAngleOuterCone = AI_DEG_TO_RAD( stream->GetF4() );
|
|
|
|
|
|
|
|
|
|
// We assume linear attenuation
|
|
|
|
|
light->mAttenuationLinear = 1;
|
|
|
|
|
}
|
|
|
|
|
// 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();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseLightChunk();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
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();
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseCameraChunk();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
void Discreet3DSImporter::ParseKeyframeChunk()
|
|
|
|
|
{
|
|
|
|
@ -558,6 +571,34 @@ bool KeyUniqueCompare(const T& first, const T& second)
|
|
|
|
|
return first.mTime == second.mTime;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
void Discreet3DSImporter::SkipTCBInfo()
|
|
|
|
|
{
|
|
|
|
|
unsigned int flags = stream->GetI2();
|
|
|
|
|
|
|
|
|
|
if (!flags)
|
|
|
|
|
{
|
|
|
|
|
// ******************************************************************
|
|
|
|
|
// Currently we can't do anything with these values. They occur
|
|
|
|
|
// quite rare, so it wouldn't be worth the effort implementing
|
|
|
|
|
// them. 3DS ist not really suitable for complex animations,
|
|
|
|
|
// so full support is not required.
|
|
|
|
|
// ******************************************************************
|
|
|
|
|
DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (flags & Discreet3DS::KEY_USE_TENS)
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
if (flags & Discreet3DS::KEY_USE_BIAS)
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
if (flags & Discreet3DS::KEY_USE_CONT)
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
if (flags & Discreet3DS::KEY_USE_EASE_FROM)
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
if (flags & Discreet3DS::KEY_USE_EASE_TO)
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
{
|
|
|
|
@ -661,15 +702,13 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
case Discreet3DS::CHUNK_TRACKPOS:
|
|
|
|
|
{
|
|
|
|
|
stream->IncPtr(10);
|
|
|
|
|
unsigned int numFrames = stream->GetI2();
|
|
|
|
|
stream->IncPtr(2);
|
|
|
|
|
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)
|
|
|
|
|
if ( Discreet3DS::CHUNK_TRACKCAMTGT == parent || Discreet3DS::CHUNK_TRACKLIGTGT == parent)
|
|
|
|
|
{
|
|
|
|
|
l = & mCurrentNode->aTargetPositionKeys;
|
|
|
|
|
}
|
|
|
|
@ -678,13 +717,13 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
l->reserve(numFrames);
|
|
|
|
|
for (unsigned int i = 0; i < numFrames;++i)
|
|
|
|
|
{
|
|
|
|
|
unsigned int fidx = stream->GetI2();
|
|
|
|
|
const unsigned int fidx = stream->GetI4();
|
|
|
|
|
|
|
|
|
|
// Setup a new position key
|
|
|
|
|
aiVectorKey v;
|
|
|
|
|
v.mTime = (double)fidx;
|
|
|
|
|
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
SkipTCBInfo();
|
|
|
|
|
v.mValue.x = stream->GetF4();
|
|
|
|
|
v.mValue.y = stream->GetF4();
|
|
|
|
|
v.mValue.z = stream->GetF4();
|
|
|
|
@ -697,12 +736,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
l->push_back(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort all keys with ascending time values?
|
|
|
|
|
// Sort all keys with ascending time values and remove duplicates?
|
|
|
|
|
if (sortKeys)
|
|
|
|
|
{
|
|
|
|
|
std::sort (l->begin(),l->end());
|
|
|
|
|
std::unique (l->begin(),l->end(),
|
|
|
|
|
std::ptr_fun(&KeyUniqueCompare<aiVectorKey>));
|
|
|
|
|
std::stable_sort(l->begin(),l->end());
|
|
|
|
|
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
|
|
|
|
|
}}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
@ -721,20 +759,18 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
std::vector<aiFloatKey>* l = &mCurrentNode->aCameraRollKeys;
|
|
|
|
|
|
|
|
|
|
stream->IncPtr(10);
|
|
|
|
|
unsigned int numFrames = stream->GetI2();
|
|
|
|
|
const unsigned int numFrames = stream->GetI4();
|
|
|
|
|
l->reserve(numFrames);
|
|
|
|
|
stream->IncPtr(2);
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < numFrames;++i)
|
|
|
|
|
{
|
|
|
|
|
unsigned int fidx = stream->GetI2();
|
|
|
|
|
const unsigned int fidx = stream->GetI4();
|
|
|
|
|
|
|
|
|
|
// Setup a new position key
|
|
|
|
|
aiFloatKey v;
|
|
|
|
|
v.mTime = (double)fidx;
|
|
|
|
|
|
|
|
|
|
// This is just a single float
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
SkipTCBInfo();
|
|
|
|
|
v.mValue = stream->GetF4();
|
|
|
|
|
|
|
|
|
|
// Check whether we'll need to sort the keys
|
|
|
|
@ -745,12 +781,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
l->push_back(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort all keys with ascending time values?
|
|
|
|
|
// Sort all keys with ascending time values and remove duplicates?
|
|
|
|
|
if (sortKeys)
|
|
|
|
|
{
|
|
|
|
|
std::sort (l->begin(),l->end());
|
|
|
|
|
std::unique (l->begin(),l->end(),
|
|
|
|
|
std::ptr_fun(&KeyUniqueCompare<aiFloatKey>));
|
|
|
|
|
std::stable_sort(l->begin(),l->end());
|
|
|
|
|
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiFloatKey>), l->end() );
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -770,8 +805,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
case Discreet3DS::CHUNK_TRACKROTATE:
|
|
|
|
|
{
|
|
|
|
|
stream->IncPtr(10);
|
|
|
|
|
unsigned int numFrames = stream->GetI2();
|
|
|
|
|
stream->IncPtr(2);
|
|
|
|
|
const unsigned int numFrames = stream->GetI4();
|
|
|
|
|
|
|
|
|
|
bool sortKeys = false;
|
|
|
|
|
std::vector<aiQuatKey>* l = &mCurrentNode->aRotationKeys;
|
|
|
|
@ -779,15 +813,14 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < numFrames;++i)
|
|
|
|
|
{
|
|
|
|
|
unsigned int fidx = stream->GetI2();
|
|
|
|
|
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
const unsigned int fidx = stream->GetI4();
|
|
|
|
|
SkipTCBInfo();
|
|
|
|
|
|
|
|
|
|
aiQuatKey v;
|
|
|
|
|
v.mTime = (double)fidx;
|
|
|
|
|
|
|
|
|
|
// The rotation keyframe is given as an axis-angle pair
|
|
|
|
|
float rad = stream->GetF4();
|
|
|
|
|
const float rad = stream->GetF4();
|
|
|
|
|
aiVector3D axis;
|
|
|
|
|
axis.x = stream->GetF4();
|
|
|
|
|
axis.y = stream->GetF4();
|
|
|
|
@ -806,12 +839,11 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
// add the new keyframe to the list
|
|
|
|
|
l->push_back(v);
|
|
|
|
|
}
|
|
|
|
|
// Sort all keys with ascending time values?
|
|
|
|
|
// Sort all keys with ascending time values and remove duplicates?
|
|
|
|
|
if (sortKeys)
|
|
|
|
|
{
|
|
|
|
|
std::sort (l->begin(),l->end());
|
|
|
|
|
std::unique (l->begin(),l->end(),
|
|
|
|
|
std::ptr_fun(&KeyUniqueCompare<aiQuatKey>));
|
|
|
|
|
std::stable_sort(l->begin(),l->end());
|
|
|
|
|
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiQuatKey>), l->end() );
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -820,7 +852,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
case Discreet3DS::CHUNK_TRACKSCALE:
|
|
|
|
|
{
|
|
|
|
|
stream->IncPtr(10);
|
|
|
|
|
unsigned int numFrames = stream->GetI2();
|
|
|
|
|
const unsigned int numFrames = stream->GetI2();
|
|
|
|
|
stream->IncPtr(2);
|
|
|
|
|
|
|
|
|
|
bool sortKeys = false;
|
|
|
|
@ -829,8 +861,8 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < numFrames;++i)
|
|
|
|
|
{
|
|
|
|
|
unsigned int fidx = stream->GetI2();
|
|
|
|
|
stream->IncPtr(4);
|
|
|
|
|
const unsigned int fidx = stream->GetI4();
|
|
|
|
|
SkipTCBInfo();
|
|
|
|
|
|
|
|
|
|
// Setup a new key
|
|
|
|
|
aiVectorKey v;
|
|
|
|
@ -852,18 +884,16 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
|
|
|
|
|
|
|
|
|
|
l->push_back(v);
|
|
|
|
|
}
|
|
|
|
|
// Sort all keys with ascending time values?
|
|
|
|
|
// Sort all keys with ascending time values and remove duplicates?
|
|
|
|
|
if (sortKeys)
|
|
|
|
|
{
|
|
|
|
|
std::sort (l->begin(),l->end());
|
|
|
|
|
std::unique (l->begin(),l->end(),
|
|
|
|
|
std::ptr_fun(&KeyUniqueCompare<aiVectorKey>));
|
|
|
|
|
std::stable_sort(l->begin(),l->end());
|
|
|
|
|
l->erase ( std::unique (l->begin(),l->end(),&KeyUniqueCompare<aiVectorKey>), l->end() );
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseHierarchyChunk(parent);
|
|
|
|
|
}
|
|
|
|
@ -916,12 +946,11 @@ void Discreet3DSImporter::ParseFaceChunk()
|
|
|
|
|
{
|
|
|
|
|
DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
|
|
|
|
|
|
|
|
|
|
// *********************************************************
|
|
|
|
|
// ******************************************************************
|
|
|
|
|
// This material is not known. Ignore this. We will later
|
|
|
|
|
// assign the default material to all faces using *this*
|
|
|
|
|
// material. Use 0xcdcdcdcd as special value to indicate
|
|
|
|
|
// this.
|
|
|
|
|
// *********************************************************
|
|
|
|
|
// material. We use 0xcdcdcdcd as special value to indicate this.
|
|
|
|
|
// ******************************************************************
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now continue and read all material indices
|
|
|
|
@ -940,7 +969,6 @@ void Discreet3DSImporter::ParseFaceChunk()
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseFaceChunk();
|
|
|
|
|
}
|
|
|
|
@ -1062,7 +1090,6 @@ void Discreet3DSImporter::ParseMeshChunk()
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseMeshChunk();
|
|
|
|
|
}
|
|
|
|
@ -1101,7 +1128,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|
|
|
|
if (is_qnan(pc->r))
|
|
|
|
|
{
|
|
|
|
|
// color chunk is invalid. Simply ignore it
|
|
|
|
|
DefaultLogger::get()->error("Unable to read DIFFUSE chunk");
|
|
|
|
|
DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk");
|
|
|
|
|
pc->r = pc->g = pc->b = 1.0f;
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
@ -1114,7 +1141,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|
|
|
|
if (is_qnan(pc->r))
|
|
|
|
|
{
|
|
|
|
|
// color chunk is invalid. Simply ignore it
|
|
|
|
|
DefaultLogger::get()->error("Unable to read SPECULAR chunk");
|
|
|
|
|
DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk");
|
|
|
|
|
pc->r = pc->g = pc->b = 1.0f;
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
@ -1127,7 +1154,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|
|
|
|
if (is_qnan(pc->r))
|
|
|
|
|
{
|
|
|
|
|
// color chunk is invalid. Simply ignore it
|
|
|
|
|
DefaultLogger::get()->error("Unable to read AMBIENT chunk");
|
|
|
|
|
DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk");
|
|
|
|
|
pc->r = pc->g = pc->b = 0.0f;
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
@ -1140,7 +1167,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|
|
|
|
if (is_qnan(pc->r))
|
|
|
|
|
{
|
|
|
|
|
// color chunk is invalid. Simply ignore it
|
|
|
|
|
DefaultLogger::get()->error("Unable to read EMISSIVE chunk");
|
|
|
|
|
DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk");
|
|
|
|
|
pc->r = pc->g = pc->b = 0.0f;
|
|
|
|
|
}}
|
|
|
|
|
break;
|
|
|
|
@ -1187,11 +1214,10 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|
|
|
|
|
|
|
|
|
case Discreet3DS::CHUNK_MAT_SELF_ILPCT:
|
|
|
|
|
{ // This is the self illumination strength of the material
|
|
|
|
|
// TODO: need to multiply with emissive base color?
|
|
|
|
|
float* pcf = &mScene->mMaterials.back().sTexEmissive.mTextureBlend;
|
|
|
|
|
*pcf = ParsePercentageChunk();
|
|
|
|
|
if (is_qnan(*pcf))*pcf = 0.0f;
|
|
|
|
|
else *pcf = *pcf * (float)0xFFFF / 100.0f;
|
|
|
|
|
float f = ParsePercentageChunk();
|
|
|
|
|
if (is_qnan(f))f = 0.0f;
|
|
|
|
|
else f *= (float)0xFFFF / 100.0f;
|
|
|
|
|
mScene->mMaterials.back().mEmissive = aiColor3D(f,f,f);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
@ -1221,14 +1247,12 @@ void Discreet3DSImporter::ParseMaterialChunk()
|
|
|
|
|
ParseTextureChunk(&mScene->mMaterials.back().sTexEmissive);
|
|
|
|
|
break;
|
|
|
|
|
case Discreet3DS::CHUNK_MAT_REFLMAP:
|
|
|
|
|
|
|
|
|
|
// Reflection map - no support in Assimp
|
|
|
|
|
DefaultLogger::get()->warn("3DS: Found reflection map in file. This is not supported");
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
};
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseMaterialChunk();
|
|
|
|
|
}
|
|
|
|
@ -1301,7 +1325,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
|
|
|
|
|
|
|
|
|
|
case Discreet3DS::CHUNK_MAT_MAP_TILING:
|
|
|
|
|
{
|
|
|
|
|
uint16_t iFlags = stream->GetI2();
|
|
|
|
|
const uint16_t iFlags = stream->GetI2();
|
|
|
|
|
|
|
|
|
|
// Get the mapping mode (for both axes)
|
|
|
|
|
if (iFlags & 0x2u)
|
|
|
|
@ -1317,7 +1341,6 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ASSIMP_3DS_END_CHUNK();
|
|
|
|
|
|
|
|
|
|
// recursively continue processing this hierarchy level
|
|
|
|
|
return ParseTextureChunk(pcOut);
|
|
|
|
|
}
|
|
|
|
@ -1330,28 +1353,22 @@ float Discreet3DSImporter::ParsePercentageChunk()
|
|
|
|
|
ReadChunk(&chunk);
|
|
|
|
|
|
|
|
|
|
if (Discreet3DS::CHUNK_PERCENTF == chunk.Flag)
|
|
|
|
|
{
|
|
|
|
|
return stream->GetF4();
|
|
|
|
|
}
|
|
|
|
|
else if (Discreet3DS::CHUNK_PERCENTW == chunk.Flag)
|
|
|
|
|
{
|
|
|
|
|
return (float)((uint16_t)stream->GetI2()) / (float)0xFFFF;
|
|
|
|
|
}
|
|
|
|
|
return std::numeric_limits<float>::quiet_NaN();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
// Read a color chunk. If a percentage chunk is found instead, it will be converted
|
|
|
|
|
// to a grayscale color value
|
|
|
|
|
void Discreet3DSImporter::ParseColorChunk(aiColor3D* p_pcOut,
|
|
|
|
|
bool p_bAcceptPercent)
|
|
|
|
|
// 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(p_pcOut != NULL);
|
|
|
|
|
ai_assert(out != NULL);
|
|
|
|
|
|
|
|
|
|
// error return value
|
|
|
|
|
static const aiColor3D clrError = aiColor3D(std::numeric_limits<float>::quiet_NaN(),
|
|
|
|
|
std::numeric_limits<float>::quiet_NaN(),
|
|
|
|
|
std::numeric_limits<float>::quiet_NaN());
|
|
|
|
|
const float qnan = std::numeric_limits<float>::quiet_NaN();
|
|
|
|
|
static const aiColor3D clrError = aiColor3D(qnan,qnan,qnan);
|
|
|
|
|
|
|
|
|
|
Discreet3DS::Chunk chunk;
|
|
|
|
|
ReadChunk(&chunk);
|
|
|
|
@ -1368,12 +1385,12 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* p_pcOut,
|
|
|
|
|
case Discreet3DS::CHUNK_RGBF:
|
|
|
|
|
if (sizeof(float) * 3 > diff)
|
|
|
|
|
{
|
|
|
|
|
*p_pcOut = clrError;
|
|
|
|
|
*out = clrError;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
p_pcOut->r = stream->GetF4();
|
|
|
|
|
p_pcOut->g = stream->GetF4();
|
|
|
|
|
p_pcOut->b = stream->GetF4();
|
|
|
|
|
out->r = stream->GetF4();
|
|
|
|
|
out->g = stream->GetF4();
|
|
|
|
|
out->b = stream->GetF4();
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case Discreet3DS::CHUNK_LINRGBB:
|
|
|
|
@ -1381,49 +1398,37 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D* p_pcOut,
|
|
|
|
|
case Discreet3DS::CHUNK_RGBB:
|
|
|
|
|
if (sizeof(char) * 3 > diff)
|
|
|
|
|
{
|
|
|
|
|
*p_pcOut = clrError;
|
|
|
|
|
*out = clrError;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
p_pcOut->r = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
p_pcOut->g = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
p_pcOut->b = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
out->g = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
out->b = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// Percentage chunks: accepted to be compatible with various
|
|
|
|
|
// .3ds files with very curious content
|
|
|
|
|
// Percentage chunks are accepted, too.
|
|
|
|
|
case Discreet3DS::CHUNK_PERCENTF:
|
|
|
|
|
if (p_bAcceptPercent && 4 <= diff)
|
|
|
|
|
if (acceptPercent && 4 <= diff)
|
|
|
|
|
{
|
|
|
|
|
p_pcOut->r = stream->GetF4();
|
|
|
|
|
p_pcOut->g = p_pcOut->b = p_pcOut->r;
|
|
|
|
|
out->g = out->b = out->r = stream->GetF4();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*p_pcOut = clrError;
|
|
|
|
|
*out = clrError;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case Discreet3DS::CHUNK_PERCENTW:
|
|
|
|
|
if (p_bAcceptPercent && 1 <= diff)
|
|
|
|
|
if (acceptPercent && 1 <= diff)
|
|
|
|
|
{
|
|
|
|
|
p_pcOut->r = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
p_pcOut->g = p_pcOut->b = p_pcOut->r;
|
|
|
|
|
out->g = out->b = out->r = (float)(uint8_t)stream->GetI1() / 255.0f;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
*p_pcOut = clrError;
|
|
|
|
|
*out = clrError;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
stream->IncPtr(diff);
|
|
|
|
|
|
|
|
|
|
// skip unknown chunks, hope this won't cause any problems.
|
|
|
|
|
return ParseColorChunk(p_pcOut,p_bAcceptPercent);
|
|
|
|
|
// Skip unknown chunks, hope this won't cause any problems.
|
|
|
|
|
return ParseColorChunk(out,acceptPercent);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Do a gamma correction ... I'm not sure whether this is correct
|
|
|
|
|
// or not but I'm too tired now to think of it
|
|
|
|
|
if (bGamma)
|
|
|
|
|
{
|
|
|
|
|
p_pcOut->r = powf(p_pcOut->r, 1.0f / 2.2f);
|
|
|
|
|
p_pcOut->g = powf(p_pcOut->g, 1.0f / 2.2f);
|
|
|
|
|
p_pcOut->b = powf(p_pcOut->b, 1.0f / 2.2f);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|