summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/assimp/code/LWOMaterial.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/assimp/code/LWOMaterial.cpp')
-rw-r--r--src/3rdparty/assimp/code/LWOMaterial.cpp1569
1 files changed, 784 insertions, 785 deletions
diff --git a/src/3rdparty/assimp/code/LWOMaterial.cpp b/src/3rdparty/assimp/code/LWOMaterial.cpp
index 70da0d675..24a2458cf 100644
--- a/src/3rdparty/assimp/code/LWOMaterial.cpp
+++ b/src/3rdparty/assimp/code/LWOMaterial.cpp
@@ -3,12 +3,12 @@
Open Asset Import Library (assimp)
---------------------------------------------------------------------------
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2016, 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
+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
@@ -25,16 +25,16 @@ conditions are met:
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
+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
+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
+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
+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.
---------------------------------------------------------------------------
*/
@@ -42,12 +42,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file Implementation of the material oart of the LWO importer class */
-#include "AssimpPCH.h"
+
#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
// internal headers
#include "LWOLoader.h"
-#include "ByteSwap.h"
+#include "ByteSwapper.h"
+
using namespace Assimp;
@@ -55,844 +56,842 @@ using namespace Assimp;
template <class T>
T lerp(const T& one, const T& two, float val)
{
- return one + (two-one)*val;
+ return one + (two-one)*val;
}
// ------------------------------------------------------------------------------------------------
// Convert a lightwave mapping mode to our's
inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
{
- switch (in)
- {
- case LWO::Texture::REPEAT:
- return aiTextureMapMode_Wrap;
-
- case LWO::Texture::MIRROR:
- return aiTextureMapMode_Mirror;
-
- case LWO::Texture::RESET:
- DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
-
- // fall though here
- case LWO::Texture::EDGE:
- return aiTextureMapMode_Clamp;
- }
- return (aiTextureMapMode)0;
+ switch (in)
+ {
+ case LWO::Texture::REPEAT:
+ return aiTextureMapMode_Wrap;
+
+ case LWO::Texture::MIRROR:
+ return aiTextureMapMode_Mirror;
+
+ case LWO::Texture::RESET:
+ DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
+
+ // fall though here
+ case LWO::Texture::EDGE:
+ return aiTextureMapMode_Clamp;
+ }
+ return (aiTextureMapMode)0;
}
// ------------------------------------------------------------------------------------------------
bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type)
{
- ai_assert(NULL != pcMat);
-
- unsigned int cur = 0, temp = 0;
- aiString s;
- bool ret = false;
-
- for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) {
- if (!(*it).enabled || !(*it).bCanUse)
- continue;
- ret = true;
-
- // Convert lightwave's mapping modes to ours. We let them
- // as they are, the GenUVcoords step will compute UV
- // channels if they're not there.
-
- aiTextureMapping mapping;
- switch ((*it).mapMode)
- {
- case LWO::Texture::Planar:
- mapping = aiTextureMapping_PLANE;
- break;
- case LWO::Texture::Cylindrical:
- mapping = aiTextureMapping_CYLINDER;
- break;
- case LWO::Texture::Spherical:
- mapping = aiTextureMapping_SPHERE;
- break;
- case LWO::Texture::Cubic:
- mapping = aiTextureMapping_BOX;
- break;
- case LWO::Texture::FrontProjection:
- DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
- mapping = aiTextureMapping_OTHER;
- break;
- case LWO::Texture::UV:
- {
- if( UINT_MAX == (*it).mRealUVIndex ) {
- // We have no UV index for this texture, so we can't display it
- continue;
- }
-
- // add the UV source index
- temp = (*it).mRealUVIndex;
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
-
- mapping = aiTextureMapping_UV;
- }
- break;
- default:
- ai_assert(false);
- };
-
- if (mapping != aiTextureMapping_UV) {
- // Setup the main axis
- aiVector3D v;
- switch ((*it).majorAxis) {
- case Texture::AXIS_X:
- v = aiVector3D(1.f,0.f,0.f);
- break;
- case Texture::AXIS_Y:
- v = aiVector3D(0.f,1.f,0.f);
- break;
- default: // case Texture::AXIS_Z:
- v = aiVector3D(0.f,0.f,1.f);
- break;
- }
-
- pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
-
- // Setup UV scalings for cylindric and spherical projections
- if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
- aiUVTransform trafo;
- trafo.mScaling.x = (*it).wrapAmountW;
- trafo.mScaling.y = (*it).wrapAmountH;
-
- BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5);
- pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
- }
- DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
- }
-
- // The older LWOB format does not use indirect references to clips.
- // The file name of a texture is directly specified in the tex chunk.
- if (mIsLWO2) {
- // find the corresponding clip (take the last one if multiple
- // share the same index)
- ClipList::iterator end = mClips.end(), candidate = end;
- temp = (*it).mClipIdx;
- for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) {
- if ((*clip).idx == temp) {
- candidate = clip;
- }
-
- }
- if (candidate == end) {
- DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
- temp = 0;
-
- // fixme: apparently some LWO files shipping with Doom3 don't
- // have clips at all ... check whether that's true or whether
- // it's a bug in the loader.
-
- s.Set("$texture.png");
-
- //continue;
- }
- else {
- if (Clip::UNSUPPORTED == (*candidate).type) {
- DefaultLogger::get()->error("LWO2: Clip type is not supported");
- continue;
- }
- AdjustTexturePath((*candidate).path);
- s.Set((*candidate).path);
-
- // Additional image settings
- int flags = 0;
- if ((*candidate).negate) {
- flags |= aiTextureFlags_Invert;
- }
- pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
- }
- }
- else
- {
- std::string ss = (*it).mFileName;
- if (!ss.length()) {
- DefaultLogger::get()->error("LWOB: Empty file name");
- continue;
- }
- AdjustTexturePath(ss);
- s.Set(ss);
- }
- pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
-
- // add the blend factor
- pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
-
- // add the blend operation
- switch ((*it).blendType)
- {
- case LWO::Texture::Normal:
- case LWO::Texture::Multiply:
- temp = (unsigned int)aiTextureOp_Multiply;
- break;
-
- case LWO::Texture::Subtractive:
- case LWO::Texture::Difference:
- temp = (unsigned int)aiTextureOp_Subtract;
- break;
-
- case LWO::Texture::Divide:
- temp = (unsigned int)aiTextureOp_Divide;
- break;
-
- case LWO::Texture::Additive:
- temp = (unsigned int)aiTextureOp_Add;
- break;
-
- default:
- temp = (unsigned int)aiTextureOp_Multiply;
- DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
-
- }
- // Setup texture operation
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
-
- // setup the mapping mode
- pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
-
- // add the u-wrapping
- temp = (unsigned int)GetMapMode((*it).wrapModeWidth);
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
-
- // add the v-wrapping
- temp = (unsigned int)GetMapMode((*it).wrapModeHeight);
- pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
-
- ++cur;
- }
- return ret;
+ ai_assert(NULL != pcMat);
+
+ unsigned int cur = 0, temp = 0;
+ aiString s;
+ bool ret = false;
+
+ for (const auto &texture : in) {
+ if (!texture.enabled || !texture.bCanUse)
+ continue;
+ ret = true;
+
+ // Convert lightwave's mapping modes to ours. We let them
+ // as they are, the GenUVcoords step will compute UV
+ // channels if they're not there.
+
+ aiTextureMapping mapping;
+ switch (texture.mapMode)
+ {
+ case LWO::Texture::Planar:
+ mapping = aiTextureMapping_PLANE;
+ break;
+ case LWO::Texture::Cylindrical:
+ mapping = aiTextureMapping_CYLINDER;
+ break;
+ case LWO::Texture::Spherical:
+ mapping = aiTextureMapping_SPHERE;
+ break;
+ case LWO::Texture::Cubic:
+ mapping = aiTextureMapping_BOX;
+ break;
+ case LWO::Texture::FrontProjection:
+ DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
+ mapping = aiTextureMapping_OTHER;
+ break;
+ case LWO::Texture::UV:
+ {
+ if( UINT_MAX == texture.mRealUVIndex ) {
+ // We have no UV index for this texture, so we can't display it
+ continue;
+ }
+
+ // add the UV source index
+ temp = texture.mRealUVIndex;
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
+
+ mapping = aiTextureMapping_UV;
+ }
+ break;
+ default:
+ ai_assert(false);
+ };
+
+ if (mapping != aiTextureMapping_UV) {
+ // Setup the main axis
+ aiVector3D v;
+ switch (texture.majorAxis) {
+ case Texture::AXIS_X:
+ v = aiVector3D(1.f,0.f,0.f);
+ break;
+ case Texture::AXIS_Y:
+ v = aiVector3D(0.f,1.f,0.f);
+ break;
+ default: // case Texture::AXIS_Z:
+ v = aiVector3D(0.f,0.f,1.f);
+ break;
+ }
+
+ pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
+
+ // Setup UV scalings for cylindric and spherical projections
+ if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
+ aiUVTransform trafo;
+ trafo.mScaling.x = texture.wrapAmountW;
+ trafo.mScaling.y = texture.wrapAmountH;
+
+ static_assert(sizeof(aiUVTransform)/sizeof(float) == 5, "sizeof(aiUVTransform)/sizeof(float) == 5");
+ pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
+ }
+ DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
+ }
+
+ // The older LWOB format does not use indirect references to clips.
+ // The file name of a texture is directly specified in the tex chunk.
+ if (mIsLWO2) {
+ // find the corresponding clip (take the last one if multiple
+ // share the same index)
+ ClipList::iterator end = mClips.end(), candidate = end;
+ temp = texture.mClipIdx;
+ for (ClipList::iterator clip = mClips.begin(); clip != end; ++clip) {
+ if ((*clip).idx == temp) {
+ candidate = clip;
+ }
+
+ }
+ if (candidate == end) {
+ DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
+ temp = 0;
+
+ // fixme: apparently some LWO files shipping with Doom3 don't
+ // have clips at all ... check whether that's true or whether
+ // it's a bug in the loader.
+
+ s.Set("$texture.png");
+
+ //continue;
+ }
+ else {
+ if (Clip::UNSUPPORTED == (*candidate).type) {
+ DefaultLogger::get()->error("LWO2: Clip type is not supported");
+ continue;
+ }
+ AdjustTexturePath((*candidate).path);
+ s.Set((*candidate).path);
+
+ // Additional image settings
+ int flags = 0;
+ if ((*candidate).negate) {
+ flags |= aiTextureFlags_Invert;
+ }
+ pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
+ }
+ }
+ else
+ {
+ std::string ss = texture.mFileName;
+ if (!ss.length()) {
+ DefaultLogger::get()->error("LWOB: Empty file name");
+ continue;
+ }
+ AdjustTexturePath(ss);
+ s.Set(ss);
+ }
+ pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
+
+ // add the blend factor
+ pcMat->AddProperty<float>(&texture.mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
+
+ // add the blend operation
+ switch (texture.blendType)
+ {
+ case LWO::Texture::Normal:
+ case LWO::Texture::Multiply:
+ temp = (unsigned int)aiTextureOp_Multiply;
+ break;
+
+ case LWO::Texture::Subtractive:
+ case LWO::Texture::Difference:
+ temp = (unsigned int)aiTextureOp_Subtract;
+ break;
+
+ case LWO::Texture::Divide:
+ temp = (unsigned int)aiTextureOp_Divide;
+ break;
+
+ case LWO::Texture::Additive:
+ temp = (unsigned int)aiTextureOp_Add;
+ break;
+
+ default:
+ temp = (unsigned int)aiTextureOp_Multiply;
+ DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
+
+ }
+ // Setup texture operation
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
+
+ // setup the mapping mode
+ pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
+
+ // add the u-wrapping
+ temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
+
+ // add the v-wrapping
+ temp = (unsigned int)GetMapMode(texture.wrapModeHeight);
+ pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
+
+ ++cur;
+ }
+ return ret;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
{
- // copy the name of the surface
- aiString st;
- st.Set(surf.mName);
- pcMat->AddProperty(&st,AI_MATKEY_NAME);
-
- const int i = surf.bDoubleSided ? 1 : 0;
- pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
-
- // add the refraction index and the bump intensity
- pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI);
- pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
-
- aiShadingMode m;
- if (surf.mSpecularValue && surf.mGlossiness)
- {
- float fGloss;
- if (mIsLWO2) {
- fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
- }
- else
- {
- if (16.0f >= surf.mGlossiness)
- fGloss = 6.0f;
- else if (64.0f >= surf.mGlossiness)
- fGloss = 20.0f;
- else if (256.0f >= surf.mGlossiness)
- fGloss = 50.0f;
- else fGloss = 80.0f;
- }
-
- pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
- pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS);
- m = aiShadingMode_Phong;
- }
- else m = aiShadingMode_Gouraud;
-
- // specular color
- aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
- pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
- pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
-
- // emissive color
- // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
- clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
-
- // opacity ... either additive or default-blended, please
- if (0.f != surf.mAdditiveTransparency) {
-
- const int add = aiBlendMode_Additive;
- pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
- pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
- }
-
- else if (10e10f != surf.mTransparency) {
- const int def = aiBlendMode_Default;
- const float f = 1.0f-surf.mTransparency;
- pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
- pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC);
- }
-
-
- // ADD TEXTURES to the material
- // TODO: find out how we can handle COLOR textures correctly...
- bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
- b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
- HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
- HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
- HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
- HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
- HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
-
- // Now we need to know which shader to use .. iterate through the shader list of
- // the surface and search for a name which we know ...
- for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();it != end;++it) {
- //if (!(*it).enabled)continue;
-
- if ((*it).functionName == "LW_SuperCelShader" || (*it).functionName == "AH_CelShader") {
- DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
-
- m = aiShadingMode_Toon;
- break;
- }
- else if ((*it).functionName == "LW_RealFresnel" || (*it).functionName == "LW_FastFresnel") {
- DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
-
- m = aiShadingMode_Fresnel;
- break;
- }
- else
- {
- DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName);
- }
- }
- if (surf.mMaximumSmoothAngle <= 0.0f)
- m = aiShadingMode_Flat;
- pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
-
- // (the diffuse value is just a scaling factor)
- // If a diffuse texture is set, we set this value to 1.0
- clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
- clr.r *= surf.mDiffuseValue;
- clr.g *= surf.mDiffuseValue;
- clr.b *= surf.mDiffuseValue;
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+ // copy the name of the surface
+ aiString st;
+ st.Set(surf.mName);
+ pcMat->AddProperty(&st,AI_MATKEY_NAME);
+
+ const int i = surf.bDoubleSided ? 1 : 0;
+ pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
+
+ // add the refraction index and the bump intensity
+ pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI);
+ pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
+
+ aiShadingMode m;
+ if (surf.mSpecularValue && surf.mGlossiness)
+ {
+ float fGloss;
+ if (mIsLWO2) {
+ fGloss = std::pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
+ }
+ else
+ {
+ if (16.0f >= surf.mGlossiness)
+ fGloss = 6.0f;
+ else if (64.0f >= surf.mGlossiness)
+ fGloss = 20.0f;
+ else if (256.0f >= surf.mGlossiness)
+ fGloss = 50.0f;
+ else fGloss = 80.0f;
+ }
+
+ pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
+ pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS);
+ m = aiShadingMode_Phong;
+ }
+ else m = aiShadingMode_Gouraud;
+
+ // specular color
+ aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
+ pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
+ pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
+
+ // emissive color
+ // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
+ clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
+ pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
+
+ // opacity ... either additive or default-blended, please
+ if (0.f != surf.mAdditiveTransparency) {
+
+ const int add = aiBlendMode_Additive;
+ pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
+ pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
+ }
+
+ else if (10e10f != surf.mTransparency) {
+ const int def = aiBlendMode_Default;
+ const float f = 1.0f-surf.mTransparency;
+ pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
+ pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC);
+ }
+
+
+ // ADD TEXTURES to the material
+ // TODO: find out how we can handle COLOR textures correctly...
+ bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
+ b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
+ HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
+ HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
+ HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
+ HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
+ HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
+
+ // Now we need to know which shader to use .. iterate through the shader list of
+ // the surface and search for a name which we know ...
+ for (const auto &shader : surf.mShaders) {
+ if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader") {
+ DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
+
+ m = aiShadingMode_Toon;
+ break;
+ }
+ else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel") {
+ DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
+
+ m = aiShadingMode_Fresnel;
+ break;
+ }
+ else
+ {
+ DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + shader.functionName);
+ }
+ }
+ if (surf.mMaximumSmoothAngle <= 0.0f)
+ m = aiShadingMode_Flat;
+ pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
+
+ // (the diffuse value is just a scaling factor)
+ // If a diffuse texture is set, we set this value to 1.0
+ clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
+ clr.r *= surf.mDiffuseValue;
+ clr.g *= surf.mDiffuseValue;
+ clr.b *= surf.mDiffuseValue;
+ pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
}
// ------------------------------------------------------------------------------------------------
char LWOImporter::FindUVChannels(LWO::TextureList& list,
- LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
+ LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
{
- char ret = 0;
- for (TextureList::iterator it = list.begin(), end = list.end();it != end;++it) {
-
- // Ignore textures with non-UV mappings for the moment.
- if (!(*it).enabled || !(*it).bCanUse || (*it).mapMode != LWO::Texture::UV) {
- continue;
- }
-
- if ((*it).mUVChannelIndex == uv.name) {
- ret = 1;
-
- // got it.
- if ((*it).mRealUVIndex == UINT_MAX || (*it).mRealUVIndex == next)
- {
- (*it).mRealUVIndex = next;
- }
- else {
- // channel mismatch. need to duplicate the material.
- DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
-
- // TODO
- }
- }
- }
- return ret;
+ char ret = 0;
+ for (auto &texture : list) {
+
+ // Ignore textures with non-UV mappings for the moment.
+ if (!texture.enabled || !texture.bCanUse || texture.mapMode != LWO::Texture::UV) {
+ continue;
+ }
+
+ if (texture.mUVChannelIndex == uv.name) {
+ ret = 1;
+
+ // got it.
+ if (texture.mRealUVIndex == UINT_MAX || texture.mRealUVIndex == next)
+ {
+ texture.mRealUVIndex = next;
+ }
+ else {
+ // channel mismatch. need to duplicate the material.
+ DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
+
+ // TODO
+ }
+ }
+ }
+ return ret;
}
// ------------------------------------------------------------------------------------------------
-void LWOImporter::FindUVChannels(LWO::Surface& surf,
- LWO::SortedRep& sorted,LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
+void LWOImporter::FindUVChannels(LWO::Surface& surf,
+ LWO::SortedRep& sorted,LWO::Layer& layer,
+ unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
{
- unsigned int next = 0, extra = 0, num_extra = 0;
-
- // Check whether we have an UV entry != 0 for one of the faces in 'sorted'
- for (unsigned int i = 0; i < layer.mUVChannels.size();++i) {
- LWO::UVChannel& uv = layer.mUVChannels[i];
-
- for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
-
- LWO::Face& face = layer.mFaces[*it];
-
- for (unsigned int n = 0; n < face.mNumIndices; ++n) {
- unsigned int idx = face.mIndices[n];
-
- if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
-
- if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
-
- DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
- "this mesh reached. Skipping channel \'" + uv.name + "\'");
-
- }
- else {
- // Search through all textures assigned to 'surf' and look for this UV channel
- char had = 0;
- had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
- had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
- had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
- had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
- had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
- had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
- had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
-
- // We have a texture referencing this UV channel so we have to take special care
- // and are willing to drop unreferenced channels in favour of it.
- if (had != 0) {
- if (num_extra) {
-
- for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {
- out[a+1] = out[a];
- }
- }
- ++extra;
- out[next++] = i;
- }
- // Bäh ... seems not to be used at all. Push to end if enough space is available.
- else {
- out[extra++] = i;
- ++num_extra;
- }
- }
- it = sorted.end()-1;
- break;
- }
- }
- }
- }
- if (extra < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
- out[extra] = UINT_MAX;
- }
+ unsigned int next = 0, extra = 0, num_extra = 0;
+
+ // Check whether we have an UV entry != 0 for one of the faces in 'sorted'
+ for (unsigned int i = 0; i < layer.mUVChannels.size();++i) {
+ LWO::UVChannel& uv = layer.mUVChannels[i];
+
+ for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
+
+ LWO::Face& face = layer.mFaces[*it];
+
+ for (unsigned int n = 0; n < face.mNumIndices; ++n) {
+ unsigned int idx = face.mIndices[n];
+
+ if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
+
+ if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+
+ DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
+ "this mesh reached. Skipping channel \'" + uv.name + "\'");
+
+ }
+ else {
+ // Search through all textures assigned to 'surf' and look for this UV channel
+ char had = 0;
+ had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
+ had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
+
+ // We have a texture referencing this UV channel so we have to take special care
+ // and are willing to drop unreferenced channels in favour of it.
+ if (had != 0) {
+ if (num_extra) {
+
+ for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {
+ out[a+1] = out[a];
+ }
+ }
+ ++extra;
+ out[next++] = i;
+ }
+ // B�h ... seems not to be used at all. Push to end if enough space is available.
+ else {
+ out[extra++] = i;
+ ++num_extra;
+ }
+ }
+ it = sorted.end()-1;
+ break;
+ }
+ }
+ }
+ }
+ if (extra < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+ out[extra] = UINT_MAX;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer,
- unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
+ unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
{
- unsigned int next = 0;
-
- // Check whether we have an vc entry != 0 for one of the faces in 'sorted'
- for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) {
- const LWO::VColorChannel& vc = layer.mVColorChannels[i];
-
- if (surf.mVCMap == vc.name) {
- // The vertex color map is explicitely requested by the surface so we need to take special care of it
- for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
- out[a+1] = out[a];
- }
- out[0] = i;
- ++next;
- }
- else {
-
- for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
- const LWO::Face& face = layer.mFaces[*it];
-
- for (unsigned int n = 0; n < face.mNumIndices; ++n) {
- unsigned int idx = face.mIndices[n];
-
- if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) {
- if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
-
- DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
- "this mesh reached. Skipping channel \'" + vc.name + "\'");
-
- }
- else {
- out[next++] = i;
- }
- it = sorted.end()-1;
- break;
- }
- }
- }
- }
- }
- if (next != AI_MAX_NUMBER_OF_COLOR_SETS) {
- out[next] = UINT_MAX;
- }
+ unsigned int next = 0;
+
+ // Check whether we have an vc entry != 0 for one of the faces in 'sorted'
+ for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) {
+ const LWO::VColorChannel& vc = layer.mVColorChannels[i];
+
+ if (surf.mVCMap == vc.name) {
+ // The vertex color map is explicitely requested by the surface so we need to take special care of it
+ for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
+ out[a+1] = out[a];
+ }
+ out[0] = i;
+ ++next;
+ }
+ else {
+
+ for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
+ const LWO::Face& face = layer.mFaces[*it];
+
+ for (unsigned int n = 0; n < face.mNumIndices; ++n) {
+ unsigned int idx = face.mIndices[n];
+
+ if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) {
+ if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
+
+ DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
+ "this mesh reached. Skipping channel \'" + vc.name + "\'");
+
+ }
+ else {
+ out[next++] = i;
+ }
+ it = sorted.end()-1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (next != AI_MAX_NUMBER_OF_COLOR_SETS) {
+ out[next] = UINT_MAX;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- case AI_LWO_PROJ:
- tex.mapMode = (Texture::MappingMode)GetU2();
- break;
- case AI_LWO_WRAP:
- tex.wrapModeWidth = (Texture::Wrap)GetU2();
- tex.wrapModeHeight = (Texture::Wrap)GetU2();
- break;
- case AI_LWO_AXIS:
- tex.majorAxis = (Texture::Axes)GetU2();
- break;
- case AI_LWO_IMAG:
- tex.mClipIdx = GetU2();
- break;
- case AI_LWO_VMAP:
- GetS0(tex.mUVChannelIndex,head->length);
- break;
- case AI_LWO_WRPH:
- tex.wrapAmountH = GetF4();
- break;
- case AI_LWO_WRPW:
- tex.wrapAmountW = GetF4();
- break;
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ LE_NCONST IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ case AI_LWO_PROJ:
+ tex.mapMode = (Texture::MappingMode)GetU2();
+ break;
+ case AI_LWO_WRAP:
+ tex.wrapModeWidth = (Texture::Wrap)GetU2();
+ tex.wrapModeHeight = (Texture::Wrap)GetU2();
+ break;
+ case AI_LWO_AXIS:
+ tex.majorAxis = (Texture::Axes)GetU2();
+ break;
+ case AI_LWO_IMAG:
+ tex.mClipIdx = GetU2();
+ break;
+ case AI_LWO_VMAP:
+ GetS0(tex.mUVChannelIndex,head.length);
+ break;
+ case AI_LWO_WRPH:
+ tex.wrapAmountH = GetF4();
+ break;
+ case AI_LWO_WRPW:
+ tex.wrapAmountW = GetF4();
+ break;
+ }
+ mFileBuffer = next;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
{
- // --- not supported at the moment
- DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
- tex.bCanUse = false;
+ // --- not supported at the moment
+ DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
+ tex.bCanUse = false;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex )
{
- // --- not supported at the moment
- DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
- tex.bCanUse = false;
+ // --- not supported at the moment
+ DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
+ tex.bCanUse = false;
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- // get the ordinal string
- GetS0( tex.ordinal, size);
-
- // we could crash later if this is an empty string ...
- if (!tex.ordinal.length())
- {
- DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
- tex.ordinal = "\x00";
- }
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid texture header chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- case AI_LWO_CHAN:
- tex.type = GetU4();
- break;
- case AI_LWO_ENAB:
- tex.enabled = GetU2() ? true : false;
- break;
- case AI_LWO_OPAC:
- tex.blendType = (Texture::BlendType)GetU2();
- tex.mStrength = GetF4();
- break;
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ // get the ordinal string
+ GetS0( tex.ordinal, size);
+
+ // we could crash later if this is an empty string ...
+ if (!tex.ordinal.length())
+ {
+ DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
+ tex.ordinal = "\x00";
+ }
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid texture header chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ case AI_LWO_CHAN:
+ tex.type = GetU4();
+ break;
+ case AI_LWO_ENAB:
+ tex.enabled = GetU2() ? true : false;
+ break;
+ case AI_LWO_OPAC:
+ tex.blendType = (Texture::BlendType)GetU2();
+ tex.mStrength = GetF4();
+ break;
+ }
+ mFileBuffer = next;
+ }
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
{
- ai_assert(!mSurfaces->empty());
- LWO::Surface& surf = mSurfaces->back();
- LWO::Texture tex;
-
- // load the texture header
- LoadLWO2TextureHeader(head->length,tex);
- size -= head->length + 6;
-
- // now get the exact type of the texture
- switch (head->type)
- {
- case AI_LWO_PROC:
- LoadLWO2Procedural(size,tex);
- break;
- case AI_LWO_GRAD:
- LoadLWO2Gradient(size,tex);
- break;
- case AI_LWO_IMAP:
- LoadLWO2ImageMap(size,tex);
- }
-
- // get the destination channel
- TextureList* listRef = NULL;
- switch (tex.type)
- {
- case AI_LWO_COLR:
- listRef = &surf.mColorTextures;break;
- case AI_LWO_DIFF:
- listRef = &surf.mDiffuseTextures;break;
- case AI_LWO_SPEC:
- listRef = &surf.mSpecularTextures;break;
- case AI_LWO_GLOS:
- listRef = &surf.mGlossinessTextures;break;
- case AI_LWO_BUMP:
- listRef = &surf.mBumpTextures;break;
- case AI_LWO_TRAN:
- listRef = &surf.mOpacityTextures;break;
- case AI_LWO_REFL:
- listRef = &surf.mReflectionTextures;break;
- default:
- DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
- return;
- }
-
- // now attach the texture to the parent surface - sort by ordinal string
- for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) {
- if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
- listRef->insert(it,tex);
- return;
- }
- }
- listRef->push_back(tex);
+ ai_assert(!mSurfaces->empty());
+ LWO::Surface& surf = mSurfaces->back();
+ LWO::Texture tex;
+
+ // load the texture header
+ LoadLWO2TextureHeader(head->length,tex);
+ size -= head->length + 6;
+
+ // now get the exact type of the texture
+ switch (head->type)
+ {
+ case AI_LWO_PROC:
+ LoadLWO2Procedural(size,tex);
+ break;
+ case AI_LWO_GRAD:
+ LoadLWO2Gradient(size,tex);
+ break;
+ case AI_LWO_IMAP:
+ LoadLWO2ImageMap(size,tex);
+ }
+
+ // get the destination channel
+ TextureList* listRef = NULL;
+ switch (tex.type)
+ {
+ case AI_LWO_COLR:
+ listRef = &surf.mColorTextures;break;
+ case AI_LWO_DIFF:
+ listRef = &surf.mDiffuseTextures;break;
+ case AI_LWO_SPEC:
+ listRef = &surf.mSpecularTextures;break;
+ case AI_LWO_GLOS:
+ listRef = &surf.mGlossinessTextures;break;
+ case AI_LWO_BUMP:
+ listRef = &surf.mBumpTextures;break;
+ case AI_LWO_TRAN:
+ listRef = &surf.mOpacityTextures;break;
+ case AI_LWO_REFL:
+ listRef = &surf.mReflectionTextures;break;
+ default:
+ DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
+ return;
+ }
+
+ // now attach the texture to the parent surface - sort by ordinal string
+ for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) {
+ if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
+ listRef->insert(it,tex);
+ return;
+ }
+ }
+ listRef->push_back(tex);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size )
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- ai_assert(!mSurfaces->empty());
- LWO::Surface& surf = mSurfaces->back();
- LWO::Shader shader;
-
- // get the ordinal string
- GetS0( shader.ordinal, size);
-
- // we could crash later if this is an empty string ...
- if (!shader.ordinal.length())
- {
- DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
- shader.ordinal = "\x00";
- }
-
- // read the header
- while (true)
- {
- if (mFileBuffer + 6 >= end)break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid shader header chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- case AI_LWO_ENAB:
- shader.enabled = GetU2() ? true : false;
- break;
-
- case AI_LWO_FUNC:
- GetS0( shader.functionName, head->length );
- }
- mFileBuffer = next;
- }
-
- // now attach the shader to the parent surface - sort by ordinal string
- for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) {
- if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
- surf.mShaders.insert(it,shader);
- return;
- }
- }
- surf.mShaders.push_back(shader);
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ ai_assert(!mSurfaces->empty());
+ LWO::Surface& surf = mSurfaces->back();
+ LWO::Shader shader;
+
+ // get the ordinal string
+ GetS0( shader.ordinal, size);
+
+ // we could crash later if this is an empty string ...
+ if (!shader.ordinal.length())
+ {
+ DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
+ shader.ordinal = "\x00";
+ }
+
+ // read the header
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)break;
+ const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid shader header chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ case AI_LWO_ENAB:
+ shader.enabled = GetU2() ? true : false;
+ break;
+
+ case AI_LWO_FUNC:
+ GetS0( shader.functionName, head.length );
+ }
+ mFileBuffer = next;
+ }
+
+ // now attach the shader to the parent surface - sort by ordinal string
+ for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) {
+ if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
+ surf.mShaders.insert(it,shader);
+ return;
+ }
+ }
+ surf.mShaders.push_back(shader);
}
// ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWO2Surface(unsigned int size)
{
- LE_NCONST uint8_t* const end = mFileBuffer + size;
-
- mSurfaces->push_back( LWO::Surface () );
- LWO::Surface& surf = mSurfaces->back();
-
- GetS0(surf.mName,size);
-
- // check whether this surface was derived from any other surface
- std::string derived;
- GetS0(derived,(unsigned int)(end - mFileBuffer));
- if (derived.length()) {
- // yes, find this surface
- for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
- if ((*it).mName == derived) {
- // we have it ...
- surf = *it;
- derived.clear();break;
- }
- }
- if (derived.size())
- DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
- }
-
- while (true)
- {
- if (mFileBuffer + 6 >= end)
- break;
- LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
-
- if (mFileBuffer + head->length > end)
- throw DeadlyImportError("LWO2: Invalid surface chunk length");
-
- uint8_t* const next = mFileBuffer+head->length;
- switch (head->type)
- {
- // diffuse color
- case AI_LWO_COLR:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
- surf.mColor.r = GetF4();
- surf.mColor.g = GetF4();
- surf.mColor.b = GetF4();
- break;
- }
- // diffuse strength ... hopefully
- case AI_LWO_DIFF:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
- surf.mDiffuseValue = GetF4();
- break;
- }
- // specular strength ... hopefully
- case AI_LWO_SPEC:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
- surf.mSpecularValue = GetF4();
- break;
- }
- // transparency
- case AI_LWO_TRAN:
- {
- // transparency explicitly disabled?
- if (surf.mTransparency == 10e10f)
- break;
-
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
- surf.mTransparency = GetF4();
- break;
- }
- // additive transparency
- case AI_LWO_ADTR:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4);
- surf.mAdditiveTransparency = GetF4();
- break;
- }
- // wireframe mode
- case AI_LWO_LINE:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2);
- if (GetU2() & 0x1)
- surf.mWireframe = true;
- break;
- }
- // glossiness
- case AI_LWO_GLOS:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
- surf.mGlossiness = GetF4();
- break;
- }
- // bump intensity
- case AI_LWO_BUMP:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
- surf.mBumpIntensity = GetF4();
- break;
- }
- // color highlights
- case AI_LWO_CLRH:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
- surf.mColorHighlights = GetF4();
- break;
- }
- // index of refraction
- case AI_LWO_RIND:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
- surf.mIOR = GetF4();
- break;
- }
- // polygon sidedness
- case AI_LWO_SIDE:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
- surf.bDoubleSided = (3 == GetU2());
- break;
- }
- // maximum smoothing angle
- case AI_LWO_SMAN:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
- surf.mMaximumSmoothAngle = fabs( GetF4() );
- break;
- }
- // vertex color channel to be applied to the surface
- case AI_LWO_VCOL:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12);
- surf.mDiffuseValue *= GetF4(); // strength
- ReadVSizedIntLWO2(mFileBuffer); // skip envelope
- surf.mVCMapType = GetU4(); // type of the channel
-
- // name of the channel
- GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
- break;
- }
- // surface bock entry
- case AI_LWO_BLOK:
- {
- AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
- LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
-
- switch (head2->type)
- {
- case AI_LWO_PROC:
- case AI_LWO_GRAD:
- case AI_LWO_IMAP:
- LoadLWO2TextureBlock(head2, head->length);
- break;
- case AI_LWO_SHDR:
- LoadLWO2ShaderBlock(head2, head->length);
- break;
-
- default:
- DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
- };
-
- break;
- }
- }
- mFileBuffer = next;
- }
+ LE_NCONST uint8_t* const end = mFileBuffer + size;
+
+ mSurfaces->push_back( LWO::Surface () );
+ LWO::Surface& surf = mSurfaces->back();
+
+ GetS0(surf.mName,size);
+
+ // check whether this surface was derived from any other surface
+ std::string derived;
+ GetS0(derived,(unsigned int)(end - mFileBuffer));
+ if (derived.length()) {
+ // yes, find this surface
+ for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
+ if ((*it).mName == derived) {
+ // we have it ...
+ surf = *it;
+ derived.clear();break;
+ }
+ }
+ if (derived.size())
+ DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
+ }
+
+ while (true)
+ {
+ if (mFileBuffer + 6 >= end)
+ break;
+ const IFF::SubChunkHeader head = IFF::LoadSubChunk(mFileBuffer);
+
+ if (mFileBuffer + head.length > end)
+ throw DeadlyImportError("LWO2: Invalid surface chunk length");
+
+ uint8_t* const next = mFileBuffer+head.length;
+ switch (head.type)
+ {
+ // diffuse color
+ case AI_LWO_COLR:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,12);
+ surf.mColor.r = GetF4();
+ surf.mColor.g = GetF4();
+ surf.mColor.b = GetF4();
+ break;
+ }
+ // diffuse strength ... hopefully
+ case AI_LWO_DIFF:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,4);
+ surf.mDiffuseValue = GetF4();
+ break;
+ }
+ // specular strength ... hopefully
+ case AI_LWO_SPEC:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,4);
+ surf.mSpecularValue = GetF4();
+ break;
+ }
+ // transparency
+ case AI_LWO_TRAN:
+ {
+ // transparency explicitly disabled?
+ if (surf.mTransparency == 10e10f)
+ break;
+
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,4);
+ surf.mTransparency = GetF4();
+ break;
+ }
+ // additive transparency
+ case AI_LWO_ADTR:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,ADTR,4);
+ surf.mAdditiveTransparency = GetF4();
+ break;
+ }
+ // wireframe mode
+ case AI_LWO_LINE:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LINE,2);
+ if (GetU2() & 0x1)
+ surf.mWireframe = true;
+ break;
+ }
+ // glossiness
+ case AI_LWO_GLOS:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,4);
+ surf.mGlossiness = GetF4();
+ break;
+ }
+ // bump intensity
+ case AI_LWO_BUMP:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BUMP,4);
+ surf.mBumpIntensity = GetF4();
+ break;
+ }
+ // color highlights
+ case AI_LWO_CLRH:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,CLRH,4);
+ surf.mColorHighlights = GetF4();
+ break;
+ }
+ // index of refraction
+ case AI_LWO_RIND:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,RIND,4);
+ surf.mIOR = GetF4();
+ break;
+ }
+ // polygon sidedness
+ case AI_LWO_SIDE:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SIDE,2);
+ surf.bDoubleSided = (3 == GetU2());
+ break;
+ }
+ // maximum smoothing angle
+ case AI_LWO_SMAN:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
+ surf.mMaximumSmoothAngle = fabs( GetF4() );
+ break;
+ }
+ // vertex color channel to be applied to the surface
+ case AI_LWO_VCOL:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,VCOL,12);
+ surf.mDiffuseValue *= GetF4(); // strength
+ ReadVSizedIntLWO2(mFileBuffer); // skip envelope
+ surf.mVCMapType = GetU4(); // type of the channel
+
+ // name of the channel
+ GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
+ break;
+ }
+ // surface bock entry
+ case AI_LWO_BLOK:
+ {
+ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,BLOK,4);
+ IFF::SubChunkHeader head2 = IFF::LoadSubChunk(mFileBuffer);
+
+ switch (head2.type)
+ {
+ case AI_LWO_PROC:
+ case AI_LWO_GRAD:
+ case AI_LWO_IMAP:
+ LoadLWO2TextureBlock(&head2, head.length);
+ break;
+ case AI_LWO_SHDR:
+ LoadLWO2ShaderBlock(&head2, head.length);
+ break;
+
+ default:
+ DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
+ };
+
+ break;
+ }
+ }
+ mFileBuffer = next;
+ }
}
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER