vrshoot
diff libs/assimp/LWOMaterial.cpp @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/LWOMaterial.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,896 @@ 1.4 +/* 1.5 +--------------------------------------------------------------------------- 1.6 +Open Asset Import Library (assimp) 1.7 +--------------------------------------------------------------------------- 1.8 + 1.9 +Copyright (c) 2006-2012, assimp team 1.10 + 1.11 +All rights reserved. 1.12 + 1.13 +Redistribution and use of this software in source and binary forms, 1.14 +with or without modification, are permitted provided that the following 1.15 +conditions are met: 1.16 + 1.17 +* Redistributions of source code must retain the above 1.18 + copyright notice, this list of conditions and the 1.19 + following disclaimer. 1.20 + 1.21 +* Redistributions in binary form must reproduce the above 1.22 + copyright notice, this list of conditions and the 1.23 + following disclaimer in the documentation and/or other 1.24 + materials provided with the distribution. 1.25 + 1.26 +* Neither the name of the assimp team, nor the names of its 1.27 + contributors may be used to endorse or promote products 1.28 + derived from this software without specific prior 1.29 + written permission of the assimp team. 1.30 + 1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.42 +--------------------------------------------------------------------------- 1.43 +*/ 1.44 + 1.45 +/** @file Implementation of the material oart of the LWO importer class */ 1.46 + 1.47 + 1.48 +#include "AssimpPCH.h" 1.49 +#ifndef ASSIMP_BUILD_NO_LWO_IMPORTER 1.50 + 1.51 +// internal headers 1.52 +#include "LWOLoader.h" 1.53 +#include "ByteSwap.h" 1.54 + 1.55 +using namespace Assimp; 1.56 + 1.57 +// ------------------------------------------------------------------------------------------------ 1.58 +template <class T> 1.59 +T lerp(const T& one, const T& two, float val) 1.60 +{ 1.61 + return one + (two-one)*val; 1.62 +} 1.63 + 1.64 +// ------------------------------------------------------------------------------------------------ 1.65 +// Convert a lightwave mapping mode to our's 1.66 +inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) 1.67 +{ 1.68 + switch (in) 1.69 + { 1.70 + case LWO::Texture::REPEAT: 1.71 + return aiTextureMapMode_Wrap; 1.72 + 1.73 + case LWO::Texture::MIRROR: 1.74 + return aiTextureMapMode_Mirror; 1.75 + 1.76 + case LWO::Texture::RESET: 1.77 + DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET"); 1.78 + 1.79 + // fall though here 1.80 + case LWO::Texture::EDGE: 1.81 + return aiTextureMapMode_Clamp; 1.82 + } 1.83 + return (aiTextureMapMode)0; 1.84 +} 1.85 + 1.86 +// ------------------------------------------------------------------------------------------------ 1.87 +bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type) 1.88 +{ 1.89 + ai_assert(NULL != pcMat); 1.90 + 1.91 + unsigned int cur = 0, temp = 0; 1.92 + aiString s; 1.93 + bool ret = false; 1.94 + 1.95 + for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) { 1.96 + if (!(*it).enabled || !(*it).bCanUse) 1.97 + continue; 1.98 + ret = true; 1.99 + 1.100 + // Convert lightwave's mapping modes to ours. We let them 1.101 + // as they are, the GenUVcoords step will compute UV 1.102 + // channels if they're not there. 1.103 + 1.104 + aiTextureMapping mapping; 1.105 + switch ((*it).mapMode) 1.106 + { 1.107 + case LWO::Texture::Planar: 1.108 + mapping = aiTextureMapping_PLANE; 1.109 + break; 1.110 + case LWO::Texture::Cylindrical: 1.111 + mapping = aiTextureMapping_CYLINDER; 1.112 + break; 1.113 + case LWO::Texture::Spherical: 1.114 + mapping = aiTextureMapping_SPHERE; 1.115 + break; 1.116 + case LWO::Texture::Cubic: 1.117 + mapping = aiTextureMapping_BOX; 1.118 + break; 1.119 + case LWO::Texture::FrontProjection: 1.120 + DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection"); 1.121 + mapping = aiTextureMapping_OTHER; 1.122 + break; 1.123 + case LWO::Texture::UV: 1.124 + { 1.125 + if( UINT_MAX == (*it).mRealUVIndex ) { 1.126 + // We have no UV index for this texture, so we can't display it 1.127 + continue; 1.128 + } 1.129 + 1.130 + // add the UV source index 1.131 + temp = (*it).mRealUVIndex; 1.132 + pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur)); 1.133 + 1.134 + mapping = aiTextureMapping_UV; 1.135 + } 1.136 + break; 1.137 + default: 1.138 + ai_assert(false); 1.139 + }; 1.140 + 1.141 + if (mapping != aiTextureMapping_UV) { 1.142 + // Setup the main axis 1.143 + aiVector3D v; 1.144 + switch ((*it).majorAxis) { 1.145 + case Texture::AXIS_X: 1.146 + v = aiVector3D(1.f,0.f,0.f); 1.147 + break; 1.148 + case Texture::AXIS_Y: 1.149 + v = aiVector3D(0.f,1.f,0.f); 1.150 + break; 1.151 + default: // case Texture::AXIS_Z: 1.152 + v = aiVector3D(0.f,0.f,1.f); 1.153 + break; 1.154 + } 1.155 + 1.156 + pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur)); 1.157 + 1.158 + // Setup UV scalings for cylindric and spherical projections 1.159 + if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) { 1.160 + aiUVTransform trafo; 1.161 + trafo.mScaling.x = (*it).wrapAmountW; 1.162 + trafo.mScaling.y = (*it).wrapAmountH; 1.163 + 1.164 + BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5); 1.165 + pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur)); 1.166 + } 1.167 + DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping"); 1.168 + } 1.169 + 1.170 + // The older LWOB format does not use indirect references to clips. 1.171 + // The file name of a texture is directly specified in the tex chunk. 1.172 + if (mIsLWO2) { 1.173 + // find the corresponding clip 1.174 + ClipList::iterator clip = mClips.begin(); 1.175 + temp = (*it).mClipIdx; 1.176 + for (ClipList::iterator end = mClips.end(); clip != end; ++clip) { 1.177 + if ((*clip).idx == temp) 1.178 + break; 1.179 + 1.180 + } 1.181 + if (mClips.end() == clip) { 1.182 + DefaultLogger::get()->error("LWO2: Clip index is out of bounds"); 1.183 + temp = 0; 1.184 + 1.185 + // fixme: appearently some LWO files shipping with Doom3 don't 1.186 + // have clips at all ... check whether that's true or whether 1.187 + // it's a bug in the loader. 1.188 + 1.189 + s.Set("$texture.png"); 1.190 + 1.191 + //continue; 1.192 + } 1.193 + else { 1.194 + if (Clip::UNSUPPORTED == (*clip).type) { 1.195 + DefaultLogger::get()->error("LWO2: Clip type is not supported"); 1.196 + continue; 1.197 + } 1.198 + AdjustTexturePath((*clip).path); 1.199 + s.Set((*clip).path); 1.200 + 1.201 + // Additional image settings 1.202 + int flags = 0; 1.203 + if ((*clip).negate) { 1.204 + flags |= aiTextureFlags_Invert; 1.205 + } 1.206 + pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur)); 1.207 + } 1.208 + } 1.209 + else 1.210 + { 1.211 + std::string ss = (*it).mFileName; 1.212 + if (!ss.length()) { 1.213 + DefaultLogger::get()->error("LWOB: Empty file name"); 1.214 + continue; 1.215 + } 1.216 + AdjustTexturePath(ss); 1.217 + s.Set(ss); 1.218 + } 1.219 + pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur)); 1.220 + 1.221 + // add the blend factor 1.222 + pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur)); 1.223 + 1.224 + // add the blend operation 1.225 + switch ((*it).blendType) 1.226 + { 1.227 + case LWO::Texture::Normal: 1.228 + case LWO::Texture::Multiply: 1.229 + temp = (unsigned int)aiTextureOp_Multiply; 1.230 + break; 1.231 + 1.232 + case LWO::Texture::Subtractive: 1.233 + case LWO::Texture::Difference: 1.234 + temp = (unsigned int)aiTextureOp_Subtract; 1.235 + break; 1.236 + 1.237 + case LWO::Texture::Divide: 1.238 + temp = (unsigned int)aiTextureOp_Divide; 1.239 + break; 1.240 + 1.241 + case LWO::Texture::Additive: 1.242 + temp = (unsigned int)aiTextureOp_Add; 1.243 + break; 1.244 + 1.245 + default: 1.246 + temp = (unsigned int)aiTextureOp_Multiply; 1.247 + DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement"); 1.248 + 1.249 + } 1.250 + // Setup texture operation 1.251 + pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur)); 1.252 + 1.253 + // setup the mapping mode 1.254 + pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur)); 1.255 + 1.256 + // add the u-wrapping 1.257 + temp = (unsigned int)GetMapMode((*it).wrapModeWidth); 1.258 + pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur)); 1.259 + 1.260 + // add the v-wrapping 1.261 + temp = (unsigned int)GetMapMode((*it).wrapModeHeight); 1.262 + pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur)); 1.263 + 1.264 + ++cur; 1.265 + } 1.266 + return ret; 1.267 +} 1.268 + 1.269 +// ------------------------------------------------------------------------------------------------ 1.270 +void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat) 1.271 +{ 1.272 + // copy the name of the surface 1.273 + aiString st; 1.274 + st.Set(surf.mName); 1.275 + pcMat->AddProperty(&st,AI_MATKEY_NAME); 1.276 + 1.277 + const int i = surf.bDoubleSided ? 1 : 0; 1.278 + pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED); 1.279 + 1.280 + // add the refraction index and the bump intensity 1.281 + pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI); 1.282 + pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING); 1.283 + 1.284 + aiShadingMode m; 1.285 + if (surf.mSpecularValue && surf.mGlossiness) 1.286 + { 1.287 + float fGloss; 1.288 + if (mIsLWO2) { 1.289 + fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f); 1.290 + } 1.291 + else 1.292 + { 1.293 + if (16.0f >= surf.mGlossiness) 1.294 + fGloss = 6.0f; 1.295 + else if (64.0f >= surf.mGlossiness) 1.296 + fGloss = 20.0f; 1.297 + else if (256.0f >= surf.mGlossiness) 1.298 + fGloss = 50.0f; 1.299 + else fGloss = 80.0f; 1.300 + } 1.301 + 1.302 + pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH); 1.303 + pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS); 1.304 + m = aiShadingMode_Phong; 1.305 + } 1.306 + else m = aiShadingMode_Gouraud; 1.307 + 1.308 + // specular color 1.309 + aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights ); 1.310 + pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR); 1.311 + pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH); 1.312 + 1.313 + // emissive color 1.314 + // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good. 1.315 + clr.g = clr.b = clr.r = surf.mLuminosity*0.8f; 1.316 + pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE); 1.317 + 1.318 + // opacity ... either additive or default-blended, please 1.319 + if (0.f != surf.mAdditiveTransparency) { 1.320 + 1.321 + const int add = aiBlendMode_Additive; 1.322 + pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY); 1.323 + pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC); 1.324 + } 1.325 + 1.326 + else if (10e10f != surf.mTransparency) { 1.327 + const int def = aiBlendMode_Default; 1.328 + const float f = 1.0f-surf.mTransparency; 1.329 + pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY); 1.330 + pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC); 1.331 + } 1.332 + 1.333 + 1.334 + // ADD TEXTURES to the material 1.335 + // TODO: find out how we can handle COLOR textures correctly... 1.336 + bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE); 1.337 + b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE)); 1.338 + HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR); 1.339 + HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS); 1.340 + HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT); 1.341 + HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY); 1.342 + HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION); 1.343 + 1.344 + // Now we need to know which shader to use .. iterate through the shader list of 1.345 + // the surface and search for a name which we know ... 1.346 + for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();it != end;++it) { 1.347 + //if (!(*it).enabled)continue; 1.348 + 1.349 + if ((*it).functionName == "LW_SuperCelShader" || (*it).functionName == "AH_CelShader") { 1.350 + DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon"); 1.351 + 1.352 + m = aiShadingMode_Toon; 1.353 + break; 1.354 + } 1.355 + else if ((*it).functionName == "LW_RealFresnel" || (*it).functionName == "LW_FastFresnel") { 1.356 + DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel"); 1.357 + 1.358 + m = aiShadingMode_Fresnel; 1.359 + break; 1.360 + } 1.361 + else 1.362 + { 1.363 + DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName); 1.364 + } 1.365 + } 1.366 + if (surf.mMaximumSmoothAngle <= 0.0f) 1.367 + m = aiShadingMode_Flat; 1.368 + pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL); 1.369 + 1.370 + // (the diffuse value is just a scaling factor) 1.371 + // If a diffuse texture is set, we set this value to 1.0 1.372 + clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor); 1.373 + clr.r *= surf.mDiffuseValue; 1.374 + clr.g *= surf.mDiffuseValue; 1.375 + clr.b *= surf.mDiffuseValue; 1.376 + pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE); 1.377 +} 1.378 + 1.379 +// ------------------------------------------------------------------------------------------------ 1.380 +char LWOImporter::FindUVChannels(LWO::TextureList& list, 1.381 + LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next) 1.382 +{ 1.383 + char ret = 0; 1.384 + for (TextureList::iterator it = list.begin(), end = list.end();it != end;++it) { 1.385 + 1.386 + // Ignore textures with non-UV mappings for the moment. 1.387 + if (!(*it).enabled || !(*it).bCanUse || (*it).mapMode != LWO::Texture::UV) { 1.388 + continue; 1.389 + } 1.390 + 1.391 + if ((*it).mUVChannelIndex == uv.name) { 1.392 + ret = 1; 1.393 + 1.394 + // got it. 1.395 + if ((*it).mRealUVIndex == UINT_MAX || (*it).mRealUVIndex == next) 1.396 + { 1.397 + (*it).mRealUVIndex = next; 1.398 + } 1.399 + else { 1.400 + // channel mismatch. need to duplicate the material. 1.401 + DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]"); 1.402 + 1.403 + // TODO 1.404 + } 1.405 + } 1.406 + } 1.407 + return ret; 1.408 +} 1.409 + 1.410 +// ------------------------------------------------------------------------------------------------ 1.411 +void LWOImporter::FindUVChannels(LWO::Surface& surf, 1.412 + LWO::SortedRep& sorted,LWO::Layer& layer, 1.413 + unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS]) 1.414 +{ 1.415 + unsigned int next = 0, extra = 0, num_extra = 0; 1.416 + 1.417 + // Check whether we have an UV entry != 0 for one of the faces in 'sorted' 1.418 + for (unsigned int i = 0; i < layer.mUVChannels.size();++i) { 1.419 + LWO::UVChannel& uv = layer.mUVChannels[i]; 1.420 + 1.421 + for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) { 1.422 + 1.423 + LWO::Face& face = layer.mFaces[*it]; 1.424 + 1.425 + for (unsigned int n = 0; n < face.mNumIndices; ++n) { 1.426 + unsigned int idx = face.mIndices[n]; 1.427 + 1.428 + if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) { 1.429 + 1.430 + if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { 1.431 + 1.432 + DefaultLogger::get()->error("LWO: Maximum number of UV channels for " 1.433 + "this mesh reached. Skipping channel \'" + uv.name + "\'"); 1.434 + 1.435 + } 1.436 + else { 1.437 + // Search through all textures assigned to 'surf' and look for this UV channel 1.438 + char had = 0; 1.439 + had |= FindUVChannels(surf.mColorTextures,layer,uv,next); 1.440 + had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next); 1.441 + had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next); 1.442 + had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next); 1.443 + had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next); 1.444 + had |= FindUVChannels(surf.mBumpTextures,layer,uv,next); 1.445 + had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next); 1.446 + 1.447 + // We have a texture referencing this UV channel so we have to take special care 1.448 + // and are willing to drop unreferenced channels in favour of it. 1.449 + if (had != 0) { 1.450 + if (num_extra) { 1.451 + 1.452 + for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) { 1.453 + out[a+1] = out[a]; 1.454 + } 1.455 + } 1.456 + ++extra; 1.457 + out[next++] = i; 1.458 + } 1.459 + // Bäh ... seems not to be used at all. Push to end if enough space is available. 1.460 + else { 1.461 + out[extra++] = i; 1.462 + ++num_extra; 1.463 + } 1.464 + } 1.465 + it = sorted.end()-1; 1.466 + break; 1.467 + } 1.468 + } 1.469 + } 1.470 + } 1.471 + if (extra < AI_MAX_NUMBER_OF_TEXTURECOORDS) { 1.472 + out[extra] = UINT_MAX; 1.473 + } 1.474 +} 1.475 + 1.476 +// ------------------------------------------------------------------------------------------------ 1.477 +void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer, 1.478 + unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS]) 1.479 +{ 1.480 + unsigned int next = 0; 1.481 + 1.482 + // Check whether we have an vc entry != 0 for one of the faces in 'sorted' 1.483 + for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) { 1.484 + const LWO::VColorChannel& vc = layer.mVColorChannels[i]; 1.485 + 1.486 + if (surf.mVCMap == vc.name) { 1.487 + // The vertex color map is explicitely requested by the surface so we need to take special care of it 1.488 + for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) { 1.489 + out[a+1] = out[a]; 1.490 + } 1.491 + out[0] = i; 1.492 + ++next; 1.493 + } 1.494 + else { 1.495 + 1.496 + for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) { 1.497 + const LWO::Face& face = layer.mFaces[*it]; 1.498 + 1.499 + for (unsigned int n = 0; n < face.mNumIndices; ++n) { 1.500 + unsigned int idx = face.mIndices[n]; 1.501 + 1.502 + if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) { 1.503 + if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) { 1.504 + 1.505 + DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for " 1.506 + "this mesh reached. Skipping channel \'" + vc.name + "\'"); 1.507 + 1.508 + } 1.509 + else { 1.510 + out[next++] = i; 1.511 + } 1.512 + it = sorted.end()-1; 1.513 + break; 1.514 + } 1.515 + } 1.516 + } 1.517 + } 1.518 + } 1.519 + if (next != AI_MAX_NUMBER_OF_COLOR_SETS) { 1.520 + out[next] = UINT_MAX; 1.521 + } 1.522 +} 1.523 + 1.524 +// ------------------------------------------------------------------------------------------------ 1.525 +void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex ) 1.526 +{ 1.527 + LE_NCONST uint8_t* const end = mFileBuffer + size; 1.528 + while (true) 1.529 + { 1.530 + if (mFileBuffer + 6 >= end)break; 1.531 + LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); 1.532 + 1.533 + if (mFileBuffer + head->length > end) 1.534 + throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length"); 1.535 + 1.536 + uint8_t* const next = mFileBuffer+head->length; 1.537 + switch (head->type) 1.538 + { 1.539 + case AI_LWO_PROJ: 1.540 + tex.mapMode = (Texture::MappingMode)GetU2(); 1.541 + break; 1.542 + case AI_LWO_WRAP: 1.543 + tex.wrapModeWidth = (Texture::Wrap)GetU2(); 1.544 + tex.wrapModeHeight = (Texture::Wrap)GetU2(); 1.545 + break; 1.546 + case AI_LWO_AXIS: 1.547 + tex.majorAxis = (Texture::Axes)GetU2(); 1.548 + break; 1.549 + case AI_LWO_IMAG: 1.550 + tex.mClipIdx = GetU2(); 1.551 + break; 1.552 + case AI_LWO_VMAP: 1.553 + GetS0(tex.mUVChannelIndex,head->length); 1.554 + break; 1.555 + case AI_LWO_WRPH: 1.556 + tex.wrapAmountH = GetF4(); 1.557 + break; 1.558 + case AI_LWO_WRPW: 1.559 + tex.wrapAmountW = GetF4(); 1.560 + break; 1.561 + } 1.562 + mFileBuffer = next; 1.563 + } 1.564 +} 1.565 + 1.566 +// ------------------------------------------------------------------------------------------------ 1.567 +void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex ) 1.568 +{ 1.569 + // --- not supported at the moment 1.570 + DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported"); 1.571 + tex.bCanUse = false; 1.572 +} 1.573 + 1.574 +// ------------------------------------------------------------------------------------------------ 1.575 +void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex ) 1.576 +{ 1.577 + // --- not supported at the moment 1.578 + DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported"); 1.579 + tex.bCanUse = false; 1.580 +} 1.581 + 1.582 +// ------------------------------------------------------------------------------------------------ 1.583 +void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex ) 1.584 +{ 1.585 + LE_NCONST uint8_t* const end = mFileBuffer + size; 1.586 + 1.587 + // get the ordinal string 1.588 + GetS0( tex.ordinal, size); 1.589 + 1.590 + // we could crash later if this is an empty string ... 1.591 + if (!tex.ordinal.length()) 1.592 + { 1.593 + DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string"); 1.594 + tex.ordinal = "\x00"; 1.595 + } 1.596 + while (true) 1.597 + { 1.598 + if (mFileBuffer + 6 >= end)break; 1.599 + LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); 1.600 + 1.601 + if (mFileBuffer + head->length > end) 1.602 + throw DeadlyImportError("LWO2: Invalid texture header chunk length"); 1.603 + 1.604 + uint8_t* const next = mFileBuffer+head->length; 1.605 + switch (head->type) 1.606 + { 1.607 + case AI_LWO_CHAN: 1.608 + tex.type = GetU4(); 1.609 + break; 1.610 + case AI_LWO_ENAB: 1.611 + tex.enabled = GetU2() ? true : false; 1.612 + break; 1.613 + case AI_LWO_OPAC: 1.614 + tex.blendType = (Texture::BlendType)GetU2(); 1.615 + tex.mStrength = GetF4(); 1.616 + break; 1.617 + } 1.618 + mFileBuffer = next; 1.619 + } 1.620 +} 1.621 + 1.622 +// ------------------------------------------------------------------------------------------------ 1.623 +void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size ) 1.624 +{ 1.625 + ai_assert(!mSurfaces->empty()); 1.626 + LWO::Surface& surf = mSurfaces->back(); 1.627 + LWO::Texture tex; 1.628 + 1.629 + // load the texture header 1.630 + LoadLWO2TextureHeader(head->length,tex); 1.631 + size -= head->length + 6; 1.632 + 1.633 + // now get the exact type of the texture 1.634 + switch (head->type) 1.635 + { 1.636 + case AI_LWO_PROC: 1.637 + LoadLWO2Procedural(size,tex); 1.638 + break; 1.639 + case AI_LWO_GRAD: 1.640 + LoadLWO2Gradient(size,tex); 1.641 + break; 1.642 + case AI_LWO_IMAP: 1.643 + LoadLWO2ImageMap(size,tex); 1.644 + } 1.645 + 1.646 + // get the destination channel 1.647 + TextureList* listRef = NULL; 1.648 + switch (tex.type) 1.649 + { 1.650 + case AI_LWO_COLR: 1.651 + listRef = &surf.mColorTextures;break; 1.652 + case AI_LWO_DIFF: 1.653 + listRef = &surf.mDiffuseTextures;break; 1.654 + case AI_LWO_SPEC: 1.655 + listRef = &surf.mSpecularTextures;break; 1.656 + case AI_LWO_GLOS: 1.657 + listRef = &surf.mGlossinessTextures;break; 1.658 + case AI_LWO_BUMP: 1.659 + listRef = &surf.mBumpTextures;break; 1.660 + case AI_LWO_TRAN: 1.661 + listRef = &surf.mOpacityTextures;break; 1.662 + case AI_LWO_REFL: 1.663 + listRef = &surf.mReflectionTextures;break; 1.664 + default: 1.665 + DefaultLogger::get()->warn("LWO2: Encountered unknown texture type"); 1.666 + return; 1.667 + } 1.668 + 1.669 + // now attach the texture to the parent surface - sort by ordinal string 1.670 + for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) { 1.671 + if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { 1.672 + listRef->insert(it,tex); 1.673 + return; 1.674 + } 1.675 + } 1.676 + listRef->push_back(tex); 1.677 +} 1.678 + 1.679 +// ------------------------------------------------------------------------------------------------ 1.680 +void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size ) 1.681 +{ 1.682 + LE_NCONST uint8_t* const end = mFileBuffer + size; 1.683 + 1.684 + ai_assert(!mSurfaces->empty()); 1.685 + LWO::Surface& surf = mSurfaces->back(); 1.686 + LWO::Shader shader; 1.687 + 1.688 + // get the ordinal string 1.689 + GetS0( shader.ordinal, size); 1.690 + 1.691 + // we could crash later if this is an empty string ... 1.692 + if (!shader.ordinal.length()) 1.693 + { 1.694 + DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string"); 1.695 + shader.ordinal = "\x00"; 1.696 + } 1.697 + 1.698 + // read the header 1.699 + while (true) 1.700 + { 1.701 + if (mFileBuffer + 6 >= end)break; 1.702 + LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); 1.703 + 1.704 + if (mFileBuffer + head->length > end) 1.705 + throw DeadlyImportError("LWO2: Invalid shader header chunk length"); 1.706 + 1.707 + uint8_t* const next = mFileBuffer+head->length; 1.708 + switch (head->type) 1.709 + { 1.710 + case AI_LWO_ENAB: 1.711 + shader.enabled = GetU2() ? true : false; 1.712 + break; 1.713 + 1.714 + case AI_LWO_FUNC: 1.715 + GetS0( shader.functionName, head->length ); 1.716 + } 1.717 + mFileBuffer = next; 1.718 + } 1.719 + 1.720 + // now attach the shader to the parent surface - sort by ordinal string 1.721 + for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) { 1.722 + if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) { 1.723 + surf.mShaders.insert(it,shader); 1.724 + return; 1.725 + } 1.726 + } 1.727 + surf.mShaders.push_back(shader); 1.728 +} 1.729 + 1.730 +// ------------------------------------------------------------------------------------------------ 1.731 +void LWOImporter::LoadLWO2Surface(unsigned int size) 1.732 +{ 1.733 + LE_NCONST uint8_t* const end = mFileBuffer + size; 1.734 + 1.735 + mSurfaces->push_back( LWO::Surface () ); 1.736 + LWO::Surface& surf = mSurfaces->back(); 1.737 + 1.738 + GetS0(surf.mName,size); 1.739 + 1.740 + // check whether this surface was derived from any other surface 1.741 + std::string derived; 1.742 + GetS0(derived,(unsigned int)(end - mFileBuffer)); 1.743 + if (derived.length()) { 1.744 + // yes, find this surface 1.745 + for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) { 1.746 + if ((*it).mName == derived) { 1.747 + // we have it ... 1.748 + surf = *it; 1.749 + derived.clear();break; 1.750 + } 1.751 + } 1.752 + if (derived.size()) 1.753 + DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived); 1.754 + } 1.755 + 1.756 + while (true) 1.757 + { 1.758 + if (mFileBuffer + 6 >= end) 1.759 + break; 1.760 + LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer); 1.761 + 1.762 + if (mFileBuffer + head->length > end) 1.763 + throw DeadlyImportError("LWO2: Invalid surface chunk length"); 1.764 + 1.765 + uint8_t* const next = mFileBuffer+head->length; 1.766 + switch (head->type) 1.767 + { 1.768 + // diffuse color 1.769 + case AI_LWO_COLR: 1.770 + { 1.771 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12); 1.772 + surf.mColor.r = GetF4(); 1.773 + surf.mColor.g = GetF4(); 1.774 + surf.mColor.b = GetF4(); 1.775 + break; 1.776 + } 1.777 + // diffuse strength ... hopefully 1.778 + case AI_LWO_DIFF: 1.779 + { 1.780 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4); 1.781 + surf.mDiffuseValue = GetF4(); 1.782 + break; 1.783 + } 1.784 + // specular strength ... hopefully 1.785 + case AI_LWO_SPEC: 1.786 + { 1.787 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4); 1.788 + surf.mSpecularValue = GetF4(); 1.789 + break; 1.790 + } 1.791 + // transparency 1.792 + case AI_LWO_TRAN: 1.793 + { 1.794 + // transparency explicitly disabled? 1.795 + if (surf.mTransparency == 10e10f) 1.796 + break; 1.797 + 1.798 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4); 1.799 + surf.mTransparency = GetF4(); 1.800 + break; 1.801 + } 1.802 + // additive transparency 1.803 + case AI_LWO_ADTR: 1.804 + { 1.805 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4); 1.806 + surf.mAdditiveTransparency = GetF4(); 1.807 + break; 1.808 + } 1.809 + // wireframe mode 1.810 + case AI_LWO_LINE: 1.811 + { 1.812 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2); 1.813 + if (GetU2() & 0x1) 1.814 + surf.mWireframe = true; 1.815 + break; 1.816 + } 1.817 + // glossiness 1.818 + case AI_LWO_GLOS: 1.819 + { 1.820 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4); 1.821 + surf.mGlossiness = GetF4(); 1.822 + break; 1.823 + } 1.824 + // bump intensity 1.825 + case AI_LWO_BUMP: 1.826 + { 1.827 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4); 1.828 + surf.mBumpIntensity = GetF4(); 1.829 + break; 1.830 + } 1.831 + // color highlights 1.832 + case AI_LWO_CLRH: 1.833 + { 1.834 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4); 1.835 + surf.mColorHighlights = GetF4(); 1.836 + break; 1.837 + } 1.838 + // index of refraction 1.839 + case AI_LWO_RIND: 1.840 + { 1.841 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4); 1.842 + surf.mIOR = GetF4(); 1.843 + break; 1.844 + } 1.845 + // polygon sidedness 1.846 + case AI_LWO_SIDE: 1.847 + { 1.848 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2); 1.849 + surf.bDoubleSided = (3 == GetU2()); 1.850 + break; 1.851 + } 1.852 + // maximum smoothing angle 1.853 + case AI_LWO_SMAN: 1.854 + { 1.855 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4); 1.856 + surf.mMaximumSmoothAngle = fabs( GetF4() ); 1.857 + break; 1.858 + } 1.859 + // vertex color channel to be applied to the surface 1.860 + case AI_LWO_VCOL: 1.861 + { 1.862 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12); 1.863 + surf.mDiffuseValue *= GetF4(); // strength 1.864 + ReadVSizedIntLWO2(mFileBuffer); // skip envelope 1.865 + surf.mVCMapType = GetU4(); // type of the channel 1.866 + 1.867 + // name of the channel 1.868 + GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer )); 1.869 + break; 1.870 + } 1.871 + // surface bock entry 1.872 + case AI_LWO_BLOK: 1.873 + { 1.874 + AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4); 1.875 + LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer); 1.876 + 1.877 + switch (head2->type) 1.878 + { 1.879 + case AI_LWO_PROC: 1.880 + case AI_LWO_GRAD: 1.881 + case AI_LWO_IMAP: 1.882 + LoadLWO2TextureBlock(head2, head->length); 1.883 + break; 1.884 + case AI_LWO_SHDR: 1.885 + LoadLWO2ShaderBlock(head2, head->length); 1.886 + break; 1.887 + 1.888 + default: 1.889 + DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK"); 1.890 + }; 1.891 + 1.892 + break; 1.893 + } 1.894 + } 1.895 + mFileBuffer = next; 1.896 + } 1.897 +} 1.898 + 1.899 +#endif // !! ASSIMP_BUILD_NO_X_IMPORTER