123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897 |
- /*
- ---------------------------------------------------------------------------
- Open Asset Import Library (assimp)
- ---------------------------------------------------------------------------
- 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
- conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the assimp team, nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of the assimp team.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------
- */
- /** @file Implementation of the material oart of the LWO importer class */
- #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
- // internal headers
- #include "LWOLoader.h"
- #include "ByteSwapper.h"
- using namespace Assimp;
- // ------------------------------------------------------------------------------------------------
- template <class T>
- T lerp(const T& one, const T& two, float 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;
- }
- // ------------------------------------------------------------------------------------------------
- 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 (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.0,0.0,0.0);
- break;
- case Texture::AXIS_Y:
- v = aiVector3D(0.0,1.0,0.0);
- break;
- default: // case Texture::AXIS_Z:
- v = aiVector3D(0.0,0.0,1.0);
- 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(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 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 = std::pow( surf.mGlossiness*ai_real( 10.0 )+ ai_real( 2.0 ), ai_real( 2.0 ) );
- }
- else
- {
- if (16.0 >= surf.mGlossiness)
- fGloss = 6.0;
- else if (64.0 >= surf.mGlossiness)
- fGloss = 20.0;
- else if (256.0 >= surf.mGlossiness)
- fGloss = 50.0;
- else fGloss = 80.0;
- }
- 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.0,1.0,1.0), 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*ai_real( 0.8 );
- pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
- // opacity ... either additive or default-blended, please
- if (0.0 != 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.0)
- 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.0,1.0,1.0) : 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)
- {
- 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])
- {
- 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 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.0,0.0,0.0,1.0)) {
- 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 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;
- }
- // ------------------------------------------------------------------------------------------------
- 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;
- }
- // ------------------------------------------------------------------------------------------------
- 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;
- 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);
- }
- // ------------------------------------------------------------------------------------------------
- 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;
- 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;
- 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 = std::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
|