LWOMaterial.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*
  2. ---------------------------------------------------------------------------
  3. Open Asset Import Library (ASSIMP)
  4. ---------------------------------------------------------------------------
  5. Copyright (c) 2006-2008, ASSIMP Development Team
  6. All rights reserved.
  7. Redistribution and use of this software in source and binary forms,
  8. with or without modification, are permitted provided that the following
  9. conditions are met:
  10. * Redistributions of source code must retain the above
  11. copyright notice, this list of conditions and the
  12. following disclaimer.
  13. * Redistributions in binary form must reproduce the above
  14. copyright notice, this list of conditions and the
  15. following disclaimer in the documentation and/or other
  16. materials provided with the distribution.
  17. * Neither the name of the ASSIMP team, nor the names of its
  18. contributors may be used to endorse or promote products
  19. derived from this software without specific prior
  20. written permission of the ASSIMP Development Team.
  21. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. ---------------------------------------------------------------------------
  33. */
  34. /** @file Implementation of the material oart of the LWO importer class */
  35. #include "AssimpPCH.h"
  36. // internal headers
  37. #include "LWOLoader.h"
  38. #include "MaterialSystem.h"
  39. #include "ByteSwap.h"
  40. using namespace Assimp;
  41. // ------------------------------------------------------------------------------------------------
  42. template <class T>
  43. T lerp(const T& one, const T& two, float val)
  44. {
  45. return one + (two-one)*val;
  46. }
  47. // ------------------------------------------------------------------------------------------------
  48. inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
  49. {
  50. switch (in)
  51. {
  52. case LWO::Texture::REPEAT:
  53. return aiTextureMapMode_Wrap;
  54. case LWO::Texture::MIRROR:
  55. return aiTextureMapMode_Mirror;
  56. case LWO::Texture::RESET:
  57. DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
  58. case LWO::Texture::EDGE:
  59. return aiTextureMapMode_Clamp;
  60. }
  61. return (aiTextureMapMode)0;
  62. }
  63. // ------------------------------------------------------------------------------------------------
  64. bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, const char* type)
  65. {
  66. ai_assert(NULL != pcMat && NULL != type);
  67. unsigned int cur = 0, temp = 0;
  68. char buffer[512];
  69. aiString s;
  70. bool ret = false;
  71. for (TextureList::const_iterator it = in.begin(), end = in.end();
  72. it != end;++it)
  73. {
  74. if (!(*it).enabled || !(*it).bCanUse || 0xffffffff == (*it).mRealUVIndex)continue;
  75. ret = true;
  76. // add the path to the texture
  77. sprintf(buffer,"$tex.file.%s[%i]",type,cur);
  78. // The older LWOB format does not use indirect references to clips.
  79. // The file name of a texture is directly specified in the tex chunk.
  80. if (mIsLWO2)
  81. {
  82. // find the corresponding clip
  83. ClipList::iterator clip = mClips.begin();
  84. temp = (*it).mClipIdx;
  85. for (ClipList::iterator end = mClips.end(); clip != end; ++clip)
  86. {
  87. if ((*clip).idx == temp)
  88. {
  89. break;
  90. }
  91. }
  92. if (mClips.end() == clip)
  93. {
  94. DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
  95. temp = 0;
  96. }
  97. if (Clip::UNSUPPORTED == (*clip).type)
  98. {
  99. DefaultLogger::get()->error("LWO2: Clip type is not supported");
  100. continue;
  101. }
  102. AdjustTexturePath((*clip).path);
  103. s.Set((*clip).path);
  104. }
  105. else
  106. {
  107. std::string ss = (*it).mFileName;
  108. if (!ss.length())
  109. {
  110. DefaultLogger::get()->error("LWOB: Empty file name");
  111. continue;
  112. }
  113. AdjustTexturePath(ss);
  114. s.Set(ss);
  115. }
  116. pcMat->AddProperty(&s,buffer);
  117. // add the blend factor
  118. sprintf(buffer,"$tex.blend.%s[%i]",type,cur);
  119. pcMat->AddProperty(&(*it).mStrength,1,buffer);
  120. // add the blend operation
  121. sprintf(buffer,"$tex.op.%s[%i]",type,cur);
  122. switch ((*it).blendType)
  123. {
  124. case LWO::Texture::Normal:
  125. case LWO::Texture::Multiply:
  126. temp = (unsigned int)aiTextureOp_Multiply;
  127. break;
  128. case LWO::Texture::Subtractive:
  129. case LWO::Texture::Difference:
  130. temp = (unsigned int)aiTextureOp_Subtract;
  131. break;
  132. case LWO::Texture::Divide:
  133. temp = (unsigned int)aiTextureOp_Divide;
  134. break;
  135. case LWO::Texture::Additive:
  136. temp = (unsigned int)aiTextureOp_Add;
  137. break;
  138. default:
  139. temp = (unsigned int)aiTextureOp_Multiply;
  140. DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
  141. }
  142. pcMat->AddProperty<int>((int*)&temp,1,buffer);
  143. // add the UV source index
  144. sprintf(buffer,"$tex.uvw.%s[%i]",type,cur);
  145. temp = (*it).mRealUVIndex;
  146. pcMat->AddProperty<int>((int*)&temp,1,buffer);
  147. // add the u-wrapping
  148. sprintf(buffer,"$tex.mapmodeu.%s[%i]",type,cur);
  149. temp = (unsigned int)GetMapMode((*it).wrapModeWidth);
  150. pcMat->AddProperty<int>((int*)&temp,1,buffer);
  151. // add the v-wrapping
  152. sprintf(buffer,"$tex.mapmodev.%s[%i]",type,cur);
  153. temp = (unsigned int)GetMapMode((*it).wrapModeHeight);
  154. pcMat->AddProperty<int>((int*)&temp,1,buffer);
  155. ++cur;
  156. }
  157. return ret;
  158. }
  159. // ------------------------------------------------------------------------------------------------
  160. void LWOImporter::ConvertMaterial(const LWO::Surface& surf,MaterialHelper* pcMat)
  161. {
  162. // copy the name of the surface
  163. aiString st;
  164. st.Set(surf.mName);
  165. pcMat->AddProperty(&st,AI_MATKEY_NAME);
  166. int i = surf.bDoubleSided ? 1 : 0;
  167. pcMat->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
  168. // add the refraction index and the bump intensity
  169. pcMat->AddProperty<float>(&surf.mIOR,1,AI_MATKEY_REFRACTI);
  170. pcMat->AddProperty<float>(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
  171. aiShadingMode m;
  172. if (surf.mSpecularValue && surf.mGlossiness)
  173. {
  174. float fGloss;
  175. if (mIsLWO2)
  176. {
  177. fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
  178. }
  179. else
  180. {
  181. if (16.0f >= surf.mGlossiness)fGloss = 6.0f;
  182. else if (64.0f >= surf.mGlossiness)fGloss = 20.0f;
  183. else if (256.0f >= surf.mGlossiness)fGloss = 50.0f;
  184. else fGloss = 80.0f;
  185. }
  186. pcMat->AddProperty<float>(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
  187. pcMat->AddProperty<float>(&fGloss,1,AI_MATKEY_SHININESS);
  188. m = aiShadingMode_Phong;
  189. }
  190. else m = aiShadingMode_Gouraud;
  191. // specular color
  192. aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
  193. pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_SPECULAR);
  194. pcMat->AddProperty<float>(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
  195. // emissive color
  196. // (luminosity is not really the same but it affects the surface in
  197. // a similar way. However, some scalings seems to be necessary)
  198. clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
  199. pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
  200. // opacity
  201. float f = 1.0f-surf.mTransparency;
  202. pcMat->AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
  203. // ADD TEXTURES to the material
  204. // TODO: find out how we can handle COLOR textures correctly...
  205. bool b = HandleTextures(pcMat,surf.mColorTextures,"diffuse");
  206. b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,"diffuse"));
  207. HandleTextures(pcMat,surf.mSpecularTextures,"specular");
  208. HandleTextures(pcMat,surf.mGlossinessTextures,"shininess");
  209. HandleTextures(pcMat,surf.mBumpTextures,"height");
  210. HandleTextures(pcMat,surf.mOpacityTextures,"opacity");
  211. // now we need to know which shader we must use
  212. // iterate through the shader list of the surface and
  213. // search for a name we know
  214. for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();
  215. it != end;++it)
  216. {
  217. if (!(*it).enabled)continue;
  218. if ((*it).functionName == "LW_SuperCelShader" ||
  219. (*it).functionName == "AH_CelShader")
  220. {
  221. m = aiShadingMode_Toon;
  222. break;
  223. }
  224. else if ((*it).functionName == "LW_RealFresnel" ||
  225. (*it).functionName == "LW_FastFresnel")
  226. {
  227. m = aiShadingMode_Fresnel;
  228. break;
  229. }
  230. else
  231. {
  232. DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName);
  233. }
  234. }
  235. if (surf.mMaximumSmoothAngle <= 0.0f)m = aiShadingMode_Flat;
  236. pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
  237. // (the diffuse value is just a scaling factor)
  238. // If a diffuse texture is set, we set this value to 1.0
  239. clr = (b ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
  240. clr.r *= surf.mDiffuseValue;
  241. clr.g *= surf.mDiffuseValue;
  242. clr.b *= surf.mDiffuseValue;
  243. pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
  244. }
  245. // ------------------------------------------------------------------------------------------------
  246. void LWOImporter::FindUVChannels(LWO::TextureList& list, LWO::Layer& layer,
  247. unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS], unsigned int& next)
  248. {
  249. for (TextureList::iterator it = list.begin(), end = list.end();
  250. it != end;++it)
  251. {
  252. if (!(*it).enabled || !(*it).bCanUse || 0xffffffff != (*it).mRealUVIndex)continue;
  253. switch ((*it).mapMode)
  254. {
  255. // TODO: implement these special mappings ...
  256. case LWO::Texture::Spherical:
  257. case LWO::Texture::Cylindrical:
  258. case LWO::Texture::Cubic:
  259. case LWO::Texture::Planar:
  260. case LWO::Texture::FrontProjection:
  261. DefaultLogger::get()->warn("LWO2: Only UV mapping is currently supported.");
  262. continue;
  263. default: ;
  264. }
  265. for (unsigned int i = 0; i < layer.mUVChannels.size();++i)
  266. {
  267. if ((*it).mUVChannelIndex == layer.mUVChannels[i].name)
  268. {
  269. // check whether we have this channel already
  270. for (unsigned int m = 0; m < next;++m)
  271. {
  272. if (i == out[m])
  273. {
  274. (*it).mRealUVIndex = m;
  275. }
  276. }
  277. if (0xffffffff == (*it).mRealUVIndex)
  278. {
  279. (*it).mRealUVIndex = next;
  280. out[next++] = i;
  281. if (AI_MAX_NUMBER_OF_TEXTURECOORDS != next)
  282. out[next] = 0xffffffff;
  283. break;
  284. }
  285. }
  286. }
  287. if (0xffffffff == (*it).mRealUVIndex)
  288. DefaultLogger::get()->error("LWO2: Unable to find matching UV channel for a texture");
  289. }
  290. }
  291. // ------------------------------------------------------------------------------------------------
  292. void LWOImporter::FindUVChannels(LWO::Surface& surf, LWO::Layer& layer,
  293. unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
  294. {
  295. out[0] = 0xffffffff;
  296. unsigned int next = 0;
  297. FindUVChannels(surf.mColorTextures,layer,out,next);
  298. FindUVChannels(surf.mDiffuseTextures,layer,out,next);
  299. FindUVChannels(surf.mSpecularTextures,layer,out,next);
  300. FindUVChannels(surf.mGlossinessTextures,layer,out,next);
  301. FindUVChannels(surf.mOpacityTextures,layer,out,next);
  302. FindUVChannels(surf.mBumpTextures,layer,out,next);
  303. }
  304. // ------------------------------------------------------------------------------------------------
  305. void LWOImporter::FindVCChannels(const LWO::Surface& surf, const LWO::Layer& layer,
  306. unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
  307. {
  308. out[0] = 0xffffffff;
  309. if (surf.mVCMap.length())
  310. {
  311. for (unsigned int i = 0; i < layer.mVColorChannels.size();++i)
  312. {
  313. if (surf.mVCMap == layer.mVColorChannels[i].name)
  314. {
  315. out[0] = i;
  316. out[1] = 0xffffffff;
  317. return;
  318. }
  319. }
  320. DefaultLogger::get()->warn("LWO2: Unable to find vertex color channel: " + surf.mVCMap);
  321. }
  322. }
  323. // ------------------------------------------------------------------------------------------------
  324. void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
  325. {
  326. LE_NCONST uint8_t* const end = mFileBuffer + size;
  327. while (true)
  328. {
  329. if (mFileBuffer + 6 >= end)break;
  330. LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
  331. if (mFileBuffer + head->length > end)
  332. throw new ImportErrorException("LWO2: Invalid SURF.BLOCK chunk length");
  333. uint8_t* const next = mFileBuffer+head->length;
  334. switch (head->type)
  335. {
  336. case AI_LWO_PROJ:
  337. tex.wrapModeWidth = (Texture::Wrap)GetU2();
  338. tex.wrapModeHeight = (Texture::Wrap)GetU2();
  339. break;
  340. case AI_LWO_AXIS:
  341. tex.majorAxis = (Texture::Axes)GetU2();
  342. break;
  343. case AI_LWO_IMAG:
  344. tex.mClipIdx = GetU2();
  345. break;
  346. case AI_LWO_VMAP:
  347. GetS0(tex.mUVChannelIndex,head->length);
  348. break;
  349. case AI_LWO_WRPH:
  350. tex.wrapAmountH = GetF4();
  351. break;
  352. case AI_LWO_WRPW:
  353. tex.wrapAmountW = GetF4();
  354. break;
  355. }
  356. mFileBuffer = next;
  357. }
  358. }
  359. // ------------------------------------------------------------------------------------------------
  360. void LWOImporter::LoadLWO2Procedural(unsigned int size, LWO::Texture& tex )
  361. {
  362. // --- not supported at the moment
  363. DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
  364. tex.bCanUse = false;
  365. }
  366. // ------------------------------------------------------------------------------------------------
  367. void LWOImporter::LoadLWO2Gradient(unsigned int size, LWO::Texture& tex )
  368. {
  369. // --- not supported at the moment
  370. DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
  371. tex.bCanUse = false;
  372. }
  373. // ------------------------------------------------------------------------------------------------
  374. void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
  375. {
  376. LE_NCONST uint8_t* const end = mFileBuffer + size;
  377. // get the ordinal string
  378. GetS0( tex.ordinal, size);
  379. // we could crash later if this is an empty string ...
  380. if (!tex.ordinal.length())
  381. {
  382. DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
  383. tex.ordinal = "\x00";
  384. }
  385. while (true)
  386. {
  387. if (mFileBuffer + 6 >= end)break;
  388. LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
  389. if (mFileBuffer + head->length > end)
  390. throw new ImportErrorException("LWO2: Invalid texture header chunk length");
  391. uint8_t* const next = mFileBuffer+head->length;
  392. switch (head->type)
  393. {
  394. case AI_LWO_CHAN:
  395. tex.type = GetU4();
  396. break;
  397. case AI_LWO_ENAB:
  398. tex.enabled = GetU2() ? true : false;
  399. break;
  400. case AI_LWO_OPAC:
  401. tex.blendType = (Texture::BlendType)GetU2();
  402. tex.mStrength = GetF4();
  403. break;
  404. }
  405. mFileBuffer = next;
  406. }
  407. }
  408. // ------------------------------------------------------------------------------------------------
  409. void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
  410. {
  411. ai_assert(!mSurfaces->empty());
  412. LWO::Surface& surf = mSurfaces->back();
  413. LWO::Texture tex;
  414. // load the texture header
  415. LoadLWO2TextureHeader(head->length,tex);
  416. size -= head->length + 6;
  417. // now get the exact type of the texture
  418. switch (head->type)
  419. {
  420. case AI_LWO_PROC:
  421. LoadLWO2Procedural(size,tex);
  422. break;
  423. case AI_LWO_GRAD:
  424. LoadLWO2Gradient(size,tex);
  425. break;
  426. case AI_LWO_IMAP:
  427. LoadLWO2ImageMap(size,tex);
  428. }
  429. // get the destination channel
  430. TextureList* listRef = NULL;
  431. switch (tex.type)
  432. {
  433. case AI_LWO_COLR:
  434. listRef = &surf.mColorTextures;break;
  435. case AI_LWO_DIFF:
  436. listRef = &surf.mDiffuseTextures;break;
  437. case AI_LWO_SPEC:
  438. listRef = &surf.mSpecularTextures;break;
  439. case AI_LWO_GLOS:
  440. listRef = &surf.mGlossinessTextures;break;
  441. case AI_LWO_BUMP:
  442. listRef = &surf.mBumpTextures;break;
  443. case AI_LWO_TRAN:
  444. listRef = &surf.mOpacityTextures;break;
  445. default:
  446. DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
  447. return;
  448. }
  449. // now attach the texture to the parent surface - sort by ordinal string
  450. for (TextureList::iterator it = listRef->begin();
  451. it != listRef->end(); ++it)
  452. {
  453. if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0)
  454. {
  455. listRef->insert(it,tex);
  456. return;
  457. }
  458. }
  459. listRef->push_back(tex);
  460. }
  461. // ------------------------------------------------------------------------------------------------
  462. void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
  463. {
  464. LE_NCONST uint8_t* const end = mFileBuffer + size;
  465. ai_assert(!mSurfaces->empty());
  466. LWO::Surface& surf = mSurfaces->back();
  467. LWO::Shader shader;
  468. // get the ordinal string
  469. GetS0( shader.ordinal, size);
  470. // we could crash later if this is an empty string ...
  471. if (!shader.ordinal.length())
  472. {
  473. DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
  474. shader.ordinal = "\x00";
  475. }
  476. // read the header
  477. while (true)
  478. {
  479. if (mFileBuffer + 6 >= end)break;
  480. LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
  481. if (mFileBuffer + head->length > end)
  482. throw new ImportErrorException("LWO2: Invalid shader header chunk length");
  483. uint8_t* const next = mFileBuffer+head->length;
  484. switch (head->type)
  485. {
  486. case AI_LWO_ENAB:
  487. shader.enabled = GetU2() ? true : false;
  488. }
  489. mFileBuffer = next;
  490. }
  491. // process other subchunks ...
  492. while (true)
  493. {
  494. if (mFileBuffer + 6 >= end)break;
  495. LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
  496. if (mFileBuffer + head->length > end)
  497. throw new ImportErrorException("LWO2: Invalid shader data chunk length");
  498. uint8_t* const next = mFileBuffer+head->length;
  499. switch (head->type)
  500. {
  501. case AI_LWO_FUNC:
  502. GetS0( shader.functionName, head->length );
  503. }
  504. mFileBuffer = next;
  505. }
  506. // now attach the shader to the parent surface - sort by ordinal string
  507. for (ShaderList::iterator it = surf.mShaders.begin();
  508. it != surf.mShaders.end(); ++it)
  509. {
  510. if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0)
  511. {
  512. surf.mShaders.insert(it,shader);
  513. return;
  514. }
  515. }
  516. surf.mShaders.push_back(shader);
  517. }
  518. // ------------------------------------------------------------------------------------------------
  519. void LWOImporter::LoadLWO2Surface(unsigned int size)
  520. {
  521. LE_NCONST uint8_t* const end = mFileBuffer + size;
  522. mSurfaces->push_back( LWO::Surface () );
  523. LWO::Surface& surf = mSurfaces->back();
  524. GetS0(surf.mName,size);
  525. // check whether this surface was derived from any other surface
  526. std::string derived;
  527. GetS0(derived,(unsigned int)(end - mFileBuffer));
  528. if (derived.length())
  529. {
  530. // yes, find this surface
  531. for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1;
  532. it != end; ++it)
  533. {
  534. if ((*it).mName == derived)
  535. {
  536. // we have it ...
  537. surf = *it;
  538. derived.clear();
  539. }
  540. }
  541. if (!derived.size())
  542. DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
  543. }
  544. while (true)
  545. {
  546. if (mFileBuffer + 6 >= end)break;
  547. LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
  548. if (mFileBuffer + head->length > end)
  549. throw new ImportErrorException("LWO2: Invalid surface chunk length");
  550. uint8_t* const next = mFileBuffer+head->length;
  551. switch (head->type)
  552. {
  553. // diffuse color
  554. case AI_LWO_COLR:
  555. {
  556. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
  557. surf.mColor.r = GetF4();
  558. surf.mColor.g = GetF4();
  559. surf.mColor.b = GetF4();
  560. break;
  561. }
  562. // diffuse strength ... hopefully
  563. case AI_LWO_DIFF:
  564. {
  565. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
  566. surf.mDiffuseValue = GetF4();
  567. break;
  568. }
  569. // specular strength ... hopefully
  570. case AI_LWO_SPEC:
  571. {
  572. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
  573. surf.mSpecularValue = GetF4();
  574. break;
  575. }
  576. // transparency
  577. case AI_LWO_TRAN:
  578. {
  579. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
  580. surf.mTransparency = GetF4();
  581. break;
  582. }
  583. // glossiness
  584. case AI_LWO_GLOS:
  585. {
  586. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
  587. surf.mGlossiness = GetF4();
  588. break;
  589. }
  590. // bump intensity
  591. case AI_LWO_BUMP:
  592. {
  593. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
  594. surf.mBumpIntensity = GetF4();
  595. break;
  596. }
  597. // color highlights
  598. case AI_LWO_CLRH:
  599. {
  600. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
  601. surf.mColorHighlights = GetF4();
  602. break;
  603. }
  604. // index of refraction
  605. case AI_LWO_RIND:
  606. {
  607. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
  608. surf.mIOR = GetF4();
  609. break;
  610. }
  611. // polygon sidedness
  612. case AI_LWO_SIDE:
  613. {
  614. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
  615. surf.bDoubleSided = (3 == GetU2());
  616. break;
  617. }
  618. // maximum smoothing angle
  619. case AI_LWO_SMAN:
  620. {
  621. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
  622. surf.mMaximumSmoothAngle = GetF4();
  623. break;
  624. }
  625. // surface bock entry
  626. case AI_LWO_BLOK:
  627. {
  628. AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
  629. LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
  630. switch (head2->type)
  631. {
  632. case AI_LWO_PROC:
  633. case AI_LWO_GRAD:
  634. case AI_LWO_IMAP:
  635. LoadLWO2TextureBlock(head2, head->length);
  636. break;
  637. case AI_LWO_SHDR:
  638. LoadLWO2ShaderBlock(head2, head->length);
  639. break;
  640. default:
  641. DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
  642. };
  643. break;
  644. }
  645. }
  646. mFileBuffer = next;
  647. }
  648. }