rev |
line source |
nuclear@0
|
1 /*
|
nuclear@0
|
2 ---------------------------------------------------------------------------
|
nuclear@0
|
3 Open Asset Import Library (assimp)
|
nuclear@0
|
4 ---------------------------------------------------------------------------
|
nuclear@0
|
5
|
nuclear@0
|
6 Copyright (c) 2006-2012, assimp team
|
nuclear@0
|
7
|
nuclear@0
|
8 All rights reserved.
|
nuclear@0
|
9
|
nuclear@0
|
10 Redistribution and use of this software in source and binary forms,
|
nuclear@0
|
11 with or without modification, are permitted provided that the following
|
nuclear@0
|
12 conditions are met:
|
nuclear@0
|
13
|
nuclear@0
|
14 * Redistributions of source code must retain the above
|
nuclear@0
|
15 copyright notice, this list of conditions and the
|
nuclear@0
|
16 following disclaimer.
|
nuclear@0
|
17
|
nuclear@0
|
18 * Redistributions in binary form must reproduce the above
|
nuclear@0
|
19 copyright notice, this list of conditions and the
|
nuclear@0
|
20 following disclaimer in the documentation and/or other
|
nuclear@0
|
21 materials provided with the distribution.
|
nuclear@0
|
22
|
nuclear@0
|
23 * Neither the name of the assimp team, nor the names of its
|
nuclear@0
|
24 contributors may be used to endorse or promote products
|
nuclear@0
|
25 derived from this software without specific prior
|
nuclear@0
|
26 written permission of the assimp team.
|
nuclear@0
|
27
|
nuclear@0
|
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
nuclear@0
|
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
nuclear@0
|
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
nuclear@0
|
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
nuclear@0
|
32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
nuclear@0
|
33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
nuclear@0
|
34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
nuclear@0
|
35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
nuclear@0
|
36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
nuclear@0
|
37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
nuclear@0
|
38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
nuclear@0
|
39 ---------------------------------------------------------------------------
|
nuclear@0
|
40 */
|
nuclear@0
|
41
|
nuclear@0
|
42 /** @file Implementation of the material oart of the LWO importer class */
|
nuclear@0
|
43
|
nuclear@0
|
44
|
nuclear@0
|
45 #include "AssimpPCH.h"
|
nuclear@0
|
46 #ifndef ASSIMP_BUILD_NO_LWO_IMPORTER
|
nuclear@0
|
47
|
nuclear@0
|
48 // internal headers
|
nuclear@0
|
49 #include "LWOLoader.h"
|
nuclear@0
|
50 #include "ByteSwap.h"
|
nuclear@0
|
51
|
nuclear@0
|
52 using namespace Assimp;
|
nuclear@0
|
53
|
nuclear@0
|
54 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
55 template <class T>
|
nuclear@0
|
56 T lerp(const T& one, const T& two, float val)
|
nuclear@0
|
57 {
|
nuclear@0
|
58 return one + (two-one)*val;
|
nuclear@0
|
59 }
|
nuclear@0
|
60
|
nuclear@0
|
61 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
62 // Convert a lightwave mapping mode to our's
|
nuclear@0
|
63 inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
|
nuclear@0
|
64 {
|
nuclear@0
|
65 switch (in)
|
nuclear@0
|
66 {
|
nuclear@0
|
67 case LWO::Texture::REPEAT:
|
nuclear@0
|
68 return aiTextureMapMode_Wrap;
|
nuclear@0
|
69
|
nuclear@0
|
70 case LWO::Texture::MIRROR:
|
nuclear@0
|
71 return aiTextureMapMode_Mirror;
|
nuclear@0
|
72
|
nuclear@0
|
73 case LWO::Texture::RESET:
|
nuclear@0
|
74 DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
|
nuclear@0
|
75
|
nuclear@0
|
76 // fall though here
|
nuclear@0
|
77 case LWO::Texture::EDGE:
|
nuclear@0
|
78 return aiTextureMapMode_Clamp;
|
nuclear@0
|
79 }
|
nuclear@0
|
80 return (aiTextureMapMode)0;
|
nuclear@0
|
81 }
|
nuclear@0
|
82
|
nuclear@0
|
83 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
84 bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTextureType type)
|
nuclear@0
|
85 {
|
nuclear@0
|
86 ai_assert(NULL != pcMat);
|
nuclear@0
|
87
|
nuclear@0
|
88 unsigned int cur = 0, temp = 0;
|
nuclear@0
|
89 aiString s;
|
nuclear@0
|
90 bool ret = false;
|
nuclear@0
|
91
|
nuclear@0
|
92 for (TextureList::const_iterator it = in.begin(), end = in.end();it != end;++it) {
|
nuclear@0
|
93 if (!(*it).enabled || !(*it).bCanUse)
|
nuclear@0
|
94 continue;
|
nuclear@0
|
95 ret = true;
|
nuclear@0
|
96
|
nuclear@0
|
97 // Convert lightwave's mapping modes to ours. We let them
|
nuclear@0
|
98 // as they are, the GenUVcoords step will compute UV
|
nuclear@0
|
99 // channels if they're not there.
|
nuclear@0
|
100
|
nuclear@0
|
101 aiTextureMapping mapping;
|
nuclear@0
|
102 switch ((*it).mapMode)
|
nuclear@0
|
103 {
|
nuclear@0
|
104 case LWO::Texture::Planar:
|
nuclear@0
|
105 mapping = aiTextureMapping_PLANE;
|
nuclear@0
|
106 break;
|
nuclear@0
|
107 case LWO::Texture::Cylindrical:
|
nuclear@0
|
108 mapping = aiTextureMapping_CYLINDER;
|
nuclear@0
|
109 break;
|
nuclear@0
|
110 case LWO::Texture::Spherical:
|
nuclear@0
|
111 mapping = aiTextureMapping_SPHERE;
|
nuclear@0
|
112 break;
|
nuclear@0
|
113 case LWO::Texture::Cubic:
|
nuclear@0
|
114 mapping = aiTextureMapping_BOX;
|
nuclear@0
|
115 break;
|
nuclear@0
|
116 case LWO::Texture::FrontProjection:
|
nuclear@0
|
117 DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
|
nuclear@0
|
118 mapping = aiTextureMapping_OTHER;
|
nuclear@0
|
119 break;
|
nuclear@0
|
120 case LWO::Texture::UV:
|
nuclear@0
|
121 {
|
nuclear@0
|
122 if( UINT_MAX == (*it).mRealUVIndex ) {
|
nuclear@0
|
123 // We have no UV index for this texture, so we can't display it
|
nuclear@0
|
124 continue;
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@0
|
127 // add the UV source index
|
nuclear@0
|
128 temp = (*it).mRealUVIndex;
|
nuclear@0
|
129 pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_UVWSRC(type,cur));
|
nuclear@0
|
130
|
nuclear@0
|
131 mapping = aiTextureMapping_UV;
|
nuclear@0
|
132 }
|
nuclear@0
|
133 break;
|
nuclear@0
|
134 default:
|
nuclear@0
|
135 ai_assert(false);
|
nuclear@0
|
136 };
|
nuclear@0
|
137
|
nuclear@0
|
138 if (mapping != aiTextureMapping_UV) {
|
nuclear@0
|
139 // Setup the main axis
|
nuclear@0
|
140 aiVector3D v;
|
nuclear@0
|
141 switch ((*it).majorAxis) {
|
nuclear@0
|
142 case Texture::AXIS_X:
|
nuclear@0
|
143 v = aiVector3D(1.f,0.f,0.f);
|
nuclear@0
|
144 break;
|
nuclear@0
|
145 case Texture::AXIS_Y:
|
nuclear@0
|
146 v = aiVector3D(0.f,1.f,0.f);
|
nuclear@0
|
147 break;
|
nuclear@0
|
148 default: // case Texture::AXIS_Z:
|
nuclear@0
|
149 v = aiVector3D(0.f,0.f,1.f);
|
nuclear@0
|
150 break;
|
nuclear@0
|
151 }
|
nuclear@0
|
152
|
nuclear@0
|
153 pcMat->AddProperty(&v,1,AI_MATKEY_TEXMAP_AXIS(type,cur));
|
nuclear@0
|
154
|
nuclear@0
|
155 // Setup UV scalings for cylindric and spherical projections
|
nuclear@0
|
156 if (mapping == aiTextureMapping_CYLINDER || mapping == aiTextureMapping_SPHERE) {
|
nuclear@0
|
157 aiUVTransform trafo;
|
nuclear@0
|
158 trafo.mScaling.x = (*it).wrapAmountW;
|
nuclear@0
|
159 trafo.mScaling.y = (*it).wrapAmountH;
|
nuclear@0
|
160
|
nuclear@0
|
161 BOOST_STATIC_ASSERT(sizeof(aiUVTransform)/sizeof(float) == 5);
|
nuclear@0
|
162 pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
|
nuclear@0
|
163 }
|
nuclear@0
|
164 DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
|
nuclear@0
|
165 }
|
nuclear@0
|
166
|
nuclear@0
|
167 // The older LWOB format does not use indirect references to clips.
|
nuclear@0
|
168 // The file name of a texture is directly specified in the tex chunk.
|
nuclear@0
|
169 if (mIsLWO2) {
|
nuclear@0
|
170 // find the corresponding clip
|
nuclear@0
|
171 ClipList::iterator clip = mClips.begin();
|
nuclear@0
|
172 temp = (*it).mClipIdx;
|
nuclear@0
|
173 for (ClipList::iterator end = mClips.end(); clip != end; ++clip) {
|
nuclear@0
|
174 if ((*clip).idx == temp)
|
nuclear@0
|
175 break;
|
nuclear@0
|
176
|
nuclear@0
|
177 }
|
nuclear@0
|
178 if (mClips.end() == clip) {
|
nuclear@0
|
179 DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
|
nuclear@0
|
180 temp = 0;
|
nuclear@0
|
181
|
nuclear@0
|
182 // fixme: appearently some LWO files shipping with Doom3 don't
|
nuclear@0
|
183 // have clips at all ... check whether that's true or whether
|
nuclear@0
|
184 // it's a bug in the loader.
|
nuclear@0
|
185
|
nuclear@0
|
186 s.Set("$texture.png");
|
nuclear@0
|
187
|
nuclear@0
|
188 //continue;
|
nuclear@0
|
189 }
|
nuclear@0
|
190 else {
|
nuclear@0
|
191 if (Clip::UNSUPPORTED == (*clip).type) {
|
nuclear@0
|
192 DefaultLogger::get()->error("LWO2: Clip type is not supported");
|
nuclear@0
|
193 continue;
|
nuclear@0
|
194 }
|
nuclear@0
|
195 AdjustTexturePath((*clip).path);
|
nuclear@0
|
196 s.Set((*clip).path);
|
nuclear@0
|
197
|
nuclear@0
|
198 // Additional image settings
|
nuclear@0
|
199 int flags = 0;
|
nuclear@0
|
200 if ((*clip).negate) {
|
nuclear@0
|
201 flags |= aiTextureFlags_Invert;
|
nuclear@0
|
202 }
|
nuclear@0
|
203 pcMat->AddProperty(&flags,1,AI_MATKEY_TEXFLAGS(type,cur));
|
nuclear@0
|
204 }
|
nuclear@0
|
205 }
|
nuclear@0
|
206 else
|
nuclear@0
|
207 {
|
nuclear@0
|
208 std::string ss = (*it).mFileName;
|
nuclear@0
|
209 if (!ss.length()) {
|
nuclear@0
|
210 DefaultLogger::get()->error("LWOB: Empty file name");
|
nuclear@0
|
211 continue;
|
nuclear@0
|
212 }
|
nuclear@0
|
213 AdjustTexturePath(ss);
|
nuclear@0
|
214 s.Set(ss);
|
nuclear@0
|
215 }
|
nuclear@0
|
216 pcMat->AddProperty(&s,AI_MATKEY_TEXTURE(type,cur));
|
nuclear@0
|
217
|
nuclear@0
|
218 // add the blend factor
|
nuclear@0
|
219 pcMat->AddProperty<float>(&(*it).mStrength,1,AI_MATKEY_TEXBLEND(type,cur));
|
nuclear@0
|
220
|
nuclear@0
|
221 // add the blend operation
|
nuclear@0
|
222 switch ((*it).blendType)
|
nuclear@0
|
223 {
|
nuclear@0
|
224 case LWO::Texture::Normal:
|
nuclear@0
|
225 case LWO::Texture::Multiply:
|
nuclear@0
|
226 temp = (unsigned int)aiTextureOp_Multiply;
|
nuclear@0
|
227 break;
|
nuclear@0
|
228
|
nuclear@0
|
229 case LWO::Texture::Subtractive:
|
nuclear@0
|
230 case LWO::Texture::Difference:
|
nuclear@0
|
231 temp = (unsigned int)aiTextureOp_Subtract;
|
nuclear@0
|
232 break;
|
nuclear@0
|
233
|
nuclear@0
|
234 case LWO::Texture::Divide:
|
nuclear@0
|
235 temp = (unsigned int)aiTextureOp_Divide;
|
nuclear@0
|
236 break;
|
nuclear@0
|
237
|
nuclear@0
|
238 case LWO::Texture::Additive:
|
nuclear@0
|
239 temp = (unsigned int)aiTextureOp_Add;
|
nuclear@0
|
240 break;
|
nuclear@0
|
241
|
nuclear@0
|
242 default:
|
nuclear@0
|
243 temp = (unsigned int)aiTextureOp_Multiply;
|
nuclear@0
|
244 DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
|
nuclear@0
|
245
|
nuclear@0
|
246 }
|
nuclear@0
|
247 // Setup texture operation
|
nuclear@0
|
248 pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
|
nuclear@0
|
249
|
nuclear@0
|
250 // setup the mapping mode
|
nuclear@0
|
251 pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
|
nuclear@0
|
252
|
nuclear@0
|
253 // add the u-wrapping
|
nuclear@0
|
254 temp = (unsigned int)GetMapMode((*it).wrapModeWidth);
|
nuclear@0
|
255 pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_U(type,cur));
|
nuclear@0
|
256
|
nuclear@0
|
257 // add the v-wrapping
|
nuclear@0
|
258 temp = (unsigned int)GetMapMode((*it).wrapModeHeight);
|
nuclear@0
|
259 pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_MAPPINGMODE_V(type,cur));
|
nuclear@0
|
260
|
nuclear@0
|
261 ++cur;
|
nuclear@0
|
262 }
|
nuclear@0
|
263 return ret;
|
nuclear@0
|
264 }
|
nuclear@0
|
265
|
nuclear@0
|
266 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
267 void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
|
nuclear@0
|
268 {
|
nuclear@0
|
269 // copy the name of the surface
|
nuclear@0
|
270 aiString st;
|
nuclear@0
|
271 st.Set(surf.mName);
|
nuclear@0
|
272 pcMat->AddProperty(&st,AI_MATKEY_NAME);
|
nuclear@0
|
273
|
nuclear@0
|
274 const int i = surf.bDoubleSided ? 1 : 0;
|
nuclear@0
|
275 pcMat->AddProperty(&i,1,AI_MATKEY_TWOSIDED);
|
nuclear@0
|
276
|
nuclear@0
|
277 // add the refraction index and the bump intensity
|
nuclear@0
|
278 pcMat->AddProperty(&surf.mIOR,1,AI_MATKEY_REFRACTI);
|
nuclear@0
|
279 pcMat->AddProperty(&surf.mBumpIntensity,1,AI_MATKEY_BUMPSCALING);
|
nuclear@0
|
280
|
nuclear@0
|
281 aiShadingMode m;
|
nuclear@0
|
282 if (surf.mSpecularValue && surf.mGlossiness)
|
nuclear@0
|
283 {
|
nuclear@0
|
284 float fGloss;
|
nuclear@0
|
285 if (mIsLWO2) {
|
nuclear@0
|
286 fGloss = pow( surf.mGlossiness*10.0f+2.0f, 2.0f);
|
nuclear@0
|
287 }
|
nuclear@0
|
288 else
|
nuclear@0
|
289 {
|
nuclear@0
|
290 if (16.0f >= surf.mGlossiness)
|
nuclear@0
|
291 fGloss = 6.0f;
|
nuclear@0
|
292 else if (64.0f >= surf.mGlossiness)
|
nuclear@0
|
293 fGloss = 20.0f;
|
nuclear@0
|
294 else if (256.0f >= surf.mGlossiness)
|
nuclear@0
|
295 fGloss = 50.0f;
|
nuclear@0
|
296 else fGloss = 80.0f;
|
nuclear@0
|
297 }
|
nuclear@0
|
298
|
nuclear@0
|
299 pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
|
nuclear@0
|
300 pcMat->AddProperty(&fGloss,1,AI_MATKEY_SHININESS);
|
nuclear@0
|
301 m = aiShadingMode_Phong;
|
nuclear@0
|
302 }
|
nuclear@0
|
303 else m = aiShadingMode_Gouraud;
|
nuclear@0
|
304
|
nuclear@0
|
305 // specular color
|
nuclear@0
|
306 aiColor3D clr = lerp( aiColor3D(1.f,1.f,1.f), surf.mColor, surf.mColorHighlights );
|
nuclear@0
|
307 pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_SPECULAR);
|
nuclear@0
|
308 pcMat->AddProperty(&surf.mSpecularValue,1,AI_MATKEY_SHININESS_STRENGTH);
|
nuclear@0
|
309
|
nuclear@0
|
310 // emissive color
|
nuclear@0
|
311 // luminosity is not really the same but it affects the surface in a similar way. Some scaling looks good.
|
nuclear@0
|
312 clr.g = clr.b = clr.r = surf.mLuminosity*0.8f;
|
nuclear@0
|
313 pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_EMISSIVE);
|
nuclear@0
|
314
|
nuclear@0
|
315 // opacity ... either additive or default-blended, please
|
nuclear@0
|
316 if (0.f != surf.mAdditiveTransparency) {
|
nuclear@0
|
317
|
nuclear@0
|
318 const int add = aiBlendMode_Additive;
|
nuclear@0
|
319 pcMat->AddProperty(&surf.mAdditiveTransparency,1,AI_MATKEY_OPACITY);
|
nuclear@0
|
320 pcMat->AddProperty(&add,1,AI_MATKEY_BLEND_FUNC);
|
nuclear@0
|
321 }
|
nuclear@0
|
322
|
nuclear@0
|
323 else if (10e10f != surf.mTransparency) {
|
nuclear@0
|
324 const int def = aiBlendMode_Default;
|
nuclear@0
|
325 const float f = 1.0f-surf.mTransparency;
|
nuclear@0
|
326 pcMat->AddProperty(&f,1,AI_MATKEY_OPACITY);
|
nuclear@0
|
327 pcMat->AddProperty(&def,1,AI_MATKEY_BLEND_FUNC);
|
nuclear@0
|
328 }
|
nuclear@0
|
329
|
nuclear@0
|
330
|
nuclear@0
|
331 // ADD TEXTURES to the material
|
nuclear@0
|
332 // TODO: find out how we can handle COLOR textures correctly...
|
nuclear@0
|
333 bool b = HandleTextures(pcMat,surf.mColorTextures,aiTextureType_DIFFUSE);
|
nuclear@0
|
334 b = (b || HandleTextures(pcMat,surf.mDiffuseTextures,aiTextureType_DIFFUSE));
|
nuclear@0
|
335 HandleTextures(pcMat,surf.mSpecularTextures,aiTextureType_SPECULAR);
|
nuclear@0
|
336 HandleTextures(pcMat,surf.mGlossinessTextures,aiTextureType_SHININESS);
|
nuclear@0
|
337 HandleTextures(pcMat,surf.mBumpTextures,aiTextureType_HEIGHT);
|
nuclear@0
|
338 HandleTextures(pcMat,surf.mOpacityTextures,aiTextureType_OPACITY);
|
nuclear@0
|
339 HandleTextures(pcMat,surf.mReflectionTextures,aiTextureType_REFLECTION);
|
nuclear@0
|
340
|
nuclear@0
|
341 // Now we need to know which shader to use .. iterate through the shader list of
|
nuclear@0
|
342 // the surface and search for a name which we know ...
|
nuclear@0
|
343 for (ShaderList::const_iterator it = surf.mShaders.begin(), end = surf.mShaders.end();it != end;++it) {
|
nuclear@0
|
344 //if (!(*it).enabled)continue;
|
nuclear@0
|
345
|
nuclear@0
|
346 if ((*it).functionName == "LW_SuperCelShader" || (*it).functionName == "AH_CelShader") {
|
nuclear@0
|
347 DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
|
nuclear@0
|
348
|
nuclear@0
|
349 m = aiShadingMode_Toon;
|
nuclear@0
|
350 break;
|
nuclear@0
|
351 }
|
nuclear@0
|
352 else if ((*it).functionName == "LW_RealFresnel" || (*it).functionName == "LW_FastFresnel") {
|
nuclear@0
|
353 DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
|
nuclear@0
|
354
|
nuclear@0
|
355 m = aiShadingMode_Fresnel;
|
nuclear@0
|
356 break;
|
nuclear@0
|
357 }
|
nuclear@0
|
358 else
|
nuclear@0
|
359 {
|
nuclear@0
|
360 DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + (*it).functionName);
|
nuclear@0
|
361 }
|
nuclear@0
|
362 }
|
nuclear@0
|
363 if (surf.mMaximumSmoothAngle <= 0.0f)
|
nuclear@0
|
364 m = aiShadingMode_Flat;
|
nuclear@0
|
365 pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
|
nuclear@0
|
366
|
nuclear@0
|
367 // (the diffuse value is just a scaling factor)
|
nuclear@0
|
368 // If a diffuse texture is set, we set this value to 1.0
|
nuclear@0
|
369 clr = (b && false ? aiColor3D(1.f,1.f,1.f) : surf.mColor);
|
nuclear@0
|
370 clr.r *= surf.mDiffuseValue;
|
nuclear@0
|
371 clr.g *= surf.mDiffuseValue;
|
nuclear@0
|
372 clr.b *= surf.mDiffuseValue;
|
nuclear@0
|
373 pcMat->AddProperty<aiColor3D>(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
|
nuclear@0
|
374 }
|
nuclear@0
|
375
|
nuclear@0
|
376 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
377 char LWOImporter::FindUVChannels(LWO::TextureList& list,
|
nuclear@0
|
378 LWO::Layer& /*layer*/,LWO::UVChannel& uv, unsigned int next)
|
nuclear@0
|
379 {
|
nuclear@0
|
380 char ret = 0;
|
nuclear@0
|
381 for (TextureList::iterator it = list.begin(), end = list.end();it != end;++it) {
|
nuclear@0
|
382
|
nuclear@0
|
383 // Ignore textures with non-UV mappings for the moment.
|
nuclear@0
|
384 if (!(*it).enabled || !(*it).bCanUse || (*it).mapMode != LWO::Texture::UV) {
|
nuclear@0
|
385 continue;
|
nuclear@0
|
386 }
|
nuclear@0
|
387
|
nuclear@0
|
388 if ((*it).mUVChannelIndex == uv.name) {
|
nuclear@0
|
389 ret = 1;
|
nuclear@0
|
390
|
nuclear@0
|
391 // got it.
|
nuclear@0
|
392 if ((*it).mRealUVIndex == UINT_MAX || (*it).mRealUVIndex == next)
|
nuclear@0
|
393 {
|
nuclear@0
|
394 (*it).mRealUVIndex = next;
|
nuclear@0
|
395 }
|
nuclear@0
|
396 else {
|
nuclear@0
|
397 // channel mismatch. need to duplicate the material.
|
nuclear@0
|
398 DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
|
nuclear@0
|
399
|
nuclear@0
|
400 // TODO
|
nuclear@0
|
401 }
|
nuclear@0
|
402 }
|
nuclear@0
|
403 }
|
nuclear@0
|
404 return ret;
|
nuclear@0
|
405 }
|
nuclear@0
|
406
|
nuclear@0
|
407 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
408 void LWOImporter::FindUVChannels(LWO::Surface& surf,
|
nuclear@0
|
409 LWO::SortedRep& sorted,LWO::Layer& layer,
|
nuclear@0
|
410 unsigned int out[AI_MAX_NUMBER_OF_TEXTURECOORDS])
|
nuclear@0
|
411 {
|
nuclear@0
|
412 unsigned int next = 0, extra = 0, num_extra = 0;
|
nuclear@0
|
413
|
nuclear@0
|
414 // Check whether we have an UV entry != 0 for one of the faces in 'sorted'
|
nuclear@0
|
415 for (unsigned int i = 0; i < layer.mUVChannels.size();++i) {
|
nuclear@0
|
416 LWO::UVChannel& uv = layer.mUVChannels[i];
|
nuclear@0
|
417
|
nuclear@0
|
418 for (LWO::SortedRep::const_iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
nuclear@0
|
419
|
nuclear@0
|
420 LWO::Face& face = layer.mFaces[*it];
|
nuclear@0
|
421
|
nuclear@0
|
422 for (unsigned int n = 0; n < face.mNumIndices; ++n) {
|
nuclear@0
|
423 unsigned int idx = face.mIndices[n];
|
nuclear@0
|
424
|
nuclear@0
|
425 if (uv.abAssigned[idx] && ((aiVector2D*)&uv.rawData[0])[idx] != aiVector2D()) {
|
nuclear@0
|
426
|
nuclear@0
|
427 if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
nuclear@0
|
428
|
nuclear@0
|
429 DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
|
nuclear@0
|
430 "this mesh reached. Skipping channel \'" + uv.name + "\'");
|
nuclear@0
|
431
|
nuclear@0
|
432 }
|
nuclear@0
|
433 else {
|
nuclear@0
|
434 // Search through all textures assigned to 'surf' and look for this UV channel
|
nuclear@0
|
435 char had = 0;
|
nuclear@0
|
436 had |= FindUVChannels(surf.mColorTextures,layer,uv,next);
|
nuclear@0
|
437 had |= FindUVChannels(surf.mDiffuseTextures,layer,uv,next);
|
nuclear@0
|
438 had |= FindUVChannels(surf.mSpecularTextures,layer,uv,next);
|
nuclear@0
|
439 had |= FindUVChannels(surf.mGlossinessTextures,layer,uv,next);
|
nuclear@0
|
440 had |= FindUVChannels(surf.mOpacityTextures,layer,uv,next);
|
nuclear@0
|
441 had |= FindUVChannels(surf.mBumpTextures,layer,uv,next);
|
nuclear@0
|
442 had |= FindUVChannels(surf.mReflectionTextures,layer,uv,next);
|
nuclear@0
|
443
|
nuclear@0
|
444 // We have a texture referencing this UV channel so we have to take special care
|
nuclear@0
|
445 // and are willing to drop unreferenced channels in favour of it.
|
nuclear@0
|
446 if (had != 0) {
|
nuclear@0
|
447 if (num_extra) {
|
nuclear@0
|
448
|
nuclear@0
|
449 for (unsigned int a = next; a < std::min( extra, AI_MAX_NUMBER_OF_TEXTURECOORDS-1u ); ++a) {
|
nuclear@0
|
450 out[a+1] = out[a];
|
nuclear@0
|
451 }
|
nuclear@0
|
452 }
|
nuclear@0
|
453 ++extra;
|
nuclear@0
|
454 out[next++] = i;
|
nuclear@0
|
455 }
|
nuclear@0
|
456 // Bäh ... seems not to be used at all. Push to end if enough space is available.
|
nuclear@0
|
457 else {
|
nuclear@0
|
458 out[extra++] = i;
|
nuclear@0
|
459 ++num_extra;
|
nuclear@0
|
460 }
|
nuclear@0
|
461 }
|
nuclear@0
|
462 it = sorted.end()-1;
|
nuclear@0
|
463 break;
|
nuclear@0
|
464 }
|
nuclear@0
|
465 }
|
nuclear@0
|
466 }
|
nuclear@0
|
467 }
|
nuclear@0
|
468 if (extra < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
|
nuclear@0
|
469 out[extra] = UINT_MAX;
|
nuclear@0
|
470 }
|
nuclear@0
|
471 }
|
nuclear@0
|
472
|
nuclear@0
|
473 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
474 void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorted, const LWO::Layer& layer,
|
nuclear@0
|
475 unsigned int out[AI_MAX_NUMBER_OF_COLOR_SETS])
|
nuclear@0
|
476 {
|
nuclear@0
|
477 unsigned int next = 0;
|
nuclear@0
|
478
|
nuclear@0
|
479 // Check whether we have an vc entry != 0 for one of the faces in 'sorted'
|
nuclear@0
|
480 for (unsigned int i = 0; i < layer.mVColorChannels.size();++i) {
|
nuclear@0
|
481 const LWO::VColorChannel& vc = layer.mVColorChannels[i];
|
nuclear@0
|
482
|
nuclear@0
|
483 if (surf.mVCMap == vc.name) {
|
nuclear@0
|
484 // The vertex color map is explicitely requested by the surface so we need to take special care of it
|
nuclear@0
|
485 for (unsigned int a = 0; a < std::min(next,AI_MAX_NUMBER_OF_COLOR_SETS-1u); ++a) {
|
nuclear@0
|
486 out[a+1] = out[a];
|
nuclear@0
|
487 }
|
nuclear@0
|
488 out[0] = i;
|
nuclear@0
|
489 ++next;
|
nuclear@0
|
490 }
|
nuclear@0
|
491 else {
|
nuclear@0
|
492
|
nuclear@0
|
493 for (LWO::SortedRep::iterator it = sorted.begin(); it != sorted.end(); ++it) {
|
nuclear@0
|
494 const LWO::Face& face = layer.mFaces[*it];
|
nuclear@0
|
495
|
nuclear@0
|
496 for (unsigned int n = 0; n < face.mNumIndices; ++n) {
|
nuclear@0
|
497 unsigned int idx = face.mIndices[n];
|
nuclear@0
|
498
|
nuclear@0
|
499 if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.f,0.f,0.f,1.f)) {
|
nuclear@0
|
500 if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
|
nuclear@0
|
501
|
nuclear@0
|
502 DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
|
nuclear@0
|
503 "this mesh reached. Skipping channel \'" + vc.name + "\'");
|
nuclear@0
|
504
|
nuclear@0
|
505 }
|
nuclear@0
|
506 else {
|
nuclear@0
|
507 out[next++] = i;
|
nuclear@0
|
508 }
|
nuclear@0
|
509 it = sorted.end()-1;
|
nuclear@0
|
510 break;
|
nuclear@0
|
511 }
|
nuclear@0
|
512 }
|
nuclear@0
|
513 }
|
nuclear@0
|
514 }
|
nuclear@0
|
515 }
|
nuclear@0
|
516 if (next != AI_MAX_NUMBER_OF_COLOR_SETS) {
|
nuclear@0
|
517 out[next] = UINT_MAX;
|
nuclear@0
|
518 }
|
nuclear@0
|
519 }
|
nuclear@0
|
520
|
nuclear@0
|
521 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
522 void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
|
nuclear@0
|
523 {
|
nuclear@0
|
524 LE_NCONST uint8_t* const end = mFileBuffer + size;
|
nuclear@0
|
525 while (true)
|
nuclear@0
|
526 {
|
nuclear@0
|
527 if (mFileBuffer + 6 >= end)break;
|
nuclear@0
|
528 LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
nuclear@0
|
529
|
nuclear@0
|
530 if (mFileBuffer + head->length > end)
|
nuclear@0
|
531 throw DeadlyImportError("LWO2: Invalid SURF.BLOCK chunk length");
|
nuclear@0
|
532
|
nuclear@0
|
533 uint8_t* const next = mFileBuffer+head->length;
|
nuclear@0
|
534 switch (head->type)
|
nuclear@0
|
535 {
|
nuclear@0
|
536 case AI_LWO_PROJ:
|
nuclear@0
|
537 tex.mapMode = (Texture::MappingMode)GetU2();
|
nuclear@0
|
538 break;
|
nuclear@0
|
539 case AI_LWO_WRAP:
|
nuclear@0
|
540 tex.wrapModeWidth = (Texture::Wrap)GetU2();
|
nuclear@0
|
541 tex.wrapModeHeight = (Texture::Wrap)GetU2();
|
nuclear@0
|
542 break;
|
nuclear@0
|
543 case AI_LWO_AXIS:
|
nuclear@0
|
544 tex.majorAxis = (Texture::Axes)GetU2();
|
nuclear@0
|
545 break;
|
nuclear@0
|
546 case AI_LWO_IMAG:
|
nuclear@0
|
547 tex.mClipIdx = GetU2();
|
nuclear@0
|
548 break;
|
nuclear@0
|
549 case AI_LWO_VMAP:
|
nuclear@0
|
550 GetS0(tex.mUVChannelIndex,head->length);
|
nuclear@0
|
551 break;
|
nuclear@0
|
552 case AI_LWO_WRPH:
|
nuclear@0
|
553 tex.wrapAmountH = GetF4();
|
nuclear@0
|
554 break;
|
nuclear@0
|
555 case AI_LWO_WRPW:
|
nuclear@0
|
556 tex.wrapAmountW = GetF4();
|
nuclear@0
|
557 break;
|
nuclear@0
|
558 }
|
nuclear@0
|
559 mFileBuffer = next;
|
nuclear@0
|
560 }
|
nuclear@0
|
561 }
|
nuclear@0
|
562
|
nuclear@0
|
563 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
564 void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
|
nuclear@0
|
565 {
|
nuclear@0
|
566 // --- not supported at the moment
|
nuclear@0
|
567 DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
|
nuclear@0
|
568 tex.bCanUse = false;
|
nuclear@0
|
569 }
|
nuclear@0
|
570
|
nuclear@0
|
571 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
572 void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex )
|
nuclear@0
|
573 {
|
nuclear@0
|
574 // --- not supported at the moment
|
nuclear@0
|
575 DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
|
nuclear@0
|
576 tex.bCanUse = false;
|
nuclear@0
|
577 }
|
nuclear@0
|
578
|
nuclear@0
|
579 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
580 void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
|
nuclear@0
|
581 {
|
nuclear@0
|
582 LE_NCONST uint8_t* const end = mFileBuffer + size;
|
nuclear@0
|
583
|
nuclear@0
|
584 // get the ordinal string
|
nuclear@0
|
585 GetS0( tex.ordinal, size);
|
nuclear@0
|
586
|
nuclear@0
|
587 // we could crash later if this is an empty string ...
|
nuclear@0
|
588 if (!tex.ordinal.length())
|
nuclear@0
|
589 {
|
nuclear@0
|
590 DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
|
nuclear@0
|
591 tex.ordinal = "\x00";
|
nuclear@0
|
592 }
|
nuclear@0
|
593 while (true)
|
nuclear@0
|
594 {
|
nuclear@0
|
595 if (mFileBuffer + 6 >= end)break;
|
nuclear@0
|
596 LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
nuclear@0
|
597
|
nuclear@0
|
598 if (mFileBuffer + head->length > end)
|
nuclear@0
|
599 throw DeadlyImportError("LWO2: Invalid texture header chunk length");
|
nuclear@0
|
600
|
nuclear@0
|
601 uint8_t* const next = mFileBuffer+head->length;
|
nuclear@0
|
602 switch (head->type)
|
nuclear@0
|
603 {
|
nuclear@0
|
604 case AI_LWO_CHAN:
|
nuclear@0
|
605 tex.type = GetU4();
|
nuclear@0
|
606 break;
|
nuclear@0
|
607 case AI_LWO_ENAB:
|
nuclear@0
|
608 tex.enabled = GetU2() ? true : false;
|
nuclear@0
|
609 break;
|
nuclear@0
|
610 case AI_LWO_OPAC:
|
nuclear@0
|
611 tex.blendType = (Texture::BlendType)GetU2();
|
nuclear@0
|
612 tex.mStrength = GetF4();
|
nuclear@0
|
613 break;
|
nuclear@0
|
614 }
|
nuclear@0
|
615 mFileBuffer = next;
|
nuclear@0
|
616 }
|
nuclear@0
|
617 }
|
nuclear@0
|
618
|
nuclear@0
|
619 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
620 void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsigned int size )
|
nuclear@0
|
621 {
|
nuclear@0
|
622 ai_assert(!mSurfaces->empty());
|
nuclear@0
|
623 LWO::Surface& surf = mSurfaces->back();
|
nuclear@0
|
624 LWO::Texture tex;
|
nuclear@0
|
625
|
nuclear@0
|
626 // load the texture header
|
nuclear@0
|
627 LoadLWO2TextureHeader(head->length,tex);
|
nuclear@0
|
628 size -= head->length + 6;
|
nuclear@0
|
629
|
nuclear@0
|
630 // now get the exact type of the texture
|
nuclear@0
|
631 switch (head->type)
|
nuclear@0
|
632 {
|
nuclear@0
|
633 case AI_LWO_PROC:
|
nuclear@0
|
634 LoadLWO2Procedural(size,tex);
|
nuclear@0
|
635 break;
|
nuclear@0
|
636 case AI_LWO_GRAD:
|
nuclear@0
|
637 LoadLWO2Gradient(size,tex);
|
nuclear@0
|
638 break;
|
nuclear@0
|
639 case AI_LWO_IMAP:
|
nuclear@0
|
640 LoadLWO2ImageMap(size,tex);
|
nuclear@0
|
641 }
|
nuclear@0
|
642
|
nuclear@0
|
643 // get the destination channel
|
nuclear@0
|
644 TextureList* listRef = NULL;
|
nuclear@0
|
645 switch (tex.type)
|
nuclear@0
|
646 {
|
nuclear@0
|
647 case AI_LWO_COLR:
|
nuclear@0
|
648 listRef = &surf.mColorTextures;break;
|
nuclear@0
|
649 case AI_LWO_DIFF:
|
nuclear@0
|
650 listRef = &surf.mDiffuseTextures;break;
|
nuclear@0
|
651 case AI_LWO_SPEC:
|
nuclear@0
|
652 listRef = &surf.mSpecularTextures;break;
|
nuclear@0
|
653 case AI_LWO_GLOS:
|
nuclear@0
|
654 listRef = &surf.mGlossinessTextures;break;
|
nuclear@0
|
655 case AI_LWO_BUMP:
|
nuclear@0
|
656 listRef = &surf.mBumpTextures;break;
|
nuclear@0
|
657 case AI_LWO_TRAN:
|
nuclear@0
|
658 listRef = &surf.mOpacityTextures;break;
|
nuclear@0
|
659 case AI_LWO_REFL:
|
nuclear@0
|
660 listRef = &surf.mReflectionTextures;break;
|
nuclear@0
|
661 default:
|
nuclear@0
|
662 DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
|
nuclear@0
|
663 return;
|
nuclear@0
|
664 }
|
nuclear@0
|
665
|
nuclear@0
|
666 // now attach the texture to the parent surface - sort by ordinal string
|
nuclear@0
|
667 for (TextureList::iterator it = listRef->begin();it != listRef->end(); ++it) {
|
nuclear@0
|
668 if (::strcmp(tex.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
|
nuclear@0
|
669 listRef->insert(it,tex);
|
nuclear@0
|
670 return;
|
nuclear@0
|
671 }
|
nuclear@0
|
672 }
|
nuclear@0
|
673 listRef->push_back(tex);
|
nuclear@0
|
674 }
|
nuclear@0
|
675
|
nuclear@0
|
676 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
677 void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, unsigned int size )
|
nuclear@0
|
678 {
|
nuclear@0
|
679 LE_NCONST uint8_t* const end = mFileBuffer + size;
|
nuclear@0
|
680
|
nuclear@0
|
681 ai_assert(!mSurfaces->empty());
|
nuclear@0
|
682 LWO::Surface& surf = mSurfaces->back();
|
nuclear@0
|
683 LWO::Shader shader;
|
nuclear@0
|
684
|
nuclear@0
|
685 // get the ordinal string
|
nuclear@0
|
686 GetS0( shader.ordinal, size);
|
nuclear@0
|
687
|
nuclear@0
|
688 // we could crash later if this is an empty string ...
|
nuclear@0
|
689 if (!shader.ordinal.length())
|
nuclear@0
|
690 {
|
nuclear@0
|
691 DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
|
nuclear@0
|
692 shader.ordinal = "\x00";
|
nuclear@0
|
693 }
|
nuclear@0
|
694
|
nuclear@0
|
695 // read the header
|
nuclear@0
|
696 while (true)
|
nuclear@0
|
697 {
|
nuclear@0
|
698 if (mFileBuffer + 6 >= end)break;
|
nuclear@0
|
699 LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
nuclear@0
|
700
|
nuclear@0
|
701 if (mFileBuffer + head->length > end)
|
nuclear@0
|
702 throw DeadlyImportError("LWO2: Invalid shader header chunk length");
|
nuclear@0
|
703
|
nuclear@0
|
704 uint8_t* const next = mFileBuffer+head->length;
|
nuclear@0
|
705 switch (head->type)
|
nuclear@0
|
706 {
|
nuclear@0
|
707 case AI_LWO_ENAB:
|
nuclear@0
|
708 shader.enabled = GetU2() ? true : false;
|
nuclear@0
|
709 break;
|
nuclear@0
|
710
|
nuclear@0
|
711 case AI_LWO_FUNC:
|
nuclear@0
|
712 GetS0( shader.functionName, head->length );
|
nuclear@0
|
713 }
|
nuclear@0
|
714 mFileBuffer = next;
|
nuclear@0
|
715 }
|
nuclear@0
|
716
|
nuclear@0
|
717 // now attach the shader to the parent surface - sort by ordinal string
|
nuclear@0
|
718 for (ShaderList::iterator it = surf.mShaders.begin();it != surf.mShaders.end(); ++it) {
|
nuclear@0
|
719 if (::strcmp(shader.ordinal.c_str(),(*it).ordinal.c_str()) < 0) {
|
nuclear@0
|
720 surf.mShaders.insert(it,shader);
|
nuclear@0
|
721 return;
|
nuclear@0
|
722 }
|
nuclear@0
|
723 }
|
nuclear@0
|
724 surf.mShaders.push_back(shader);
|
nuclear@0
|
725 }
|
nuclear@0
|
726
|
nuclear@0
|
727 // ------------------------------------------------------------------------------------------------
|
nuclear@0
|
728 void LWOImporter::LoadLWO2Surface(unsigned int size)
|
nuclear@0
|
729 {
|
nuclear@0
|
730 LE_NCONST uint8_t* const end = mFileBuffer + size;
|
nuclear@0
|
731
|
nuclear@0
|
732 mSurfaces->push_back( LWO::Surface () );
|
nuclear@0
|
733 LWO::Surface& surf = mSurfaces->back();
|
nuclear@0
|
734
|
nuclear@0
|
735 GetS0(surf.mName,size);
|
nuclear@0
|
736
|
nuclear@0
|
737 // check whether this surface was derived from any other surface
|
nuclear@0
|
738 std::string derived;
|
nuclear@0
|
739 GetS0(derived,(unsigned int)(end - mFileBuffer));
|
nuclear@0
|
740 if (derived.length()) {
|
nuclear@0
|
741 // yes, find this surface
|
nuclear@0
|
742 for (SurfaceList::iterator it = mSurfaces->begin(), end = mSurfaces->end()-1; it != end; ++it) {
|
nuclear@0
|
743 if ((*it).mName == derived) {
|
nuclear@0
|
744 // we have it ...
|
nuclear@0
|
745 surf = *it;
|
nuclear@0
|
746 derived.clear();break;
|
nuclear@0
|
747 }
|
nuclear@0
|
748 }
|
nuclear@0
|
749 if (derived.size())
|
nuclear@0
|
750 DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
|
nuclear@0
|
751 }
|
nuclear@0
|
752
|
nuclear@0
|
753 while (true)
|
nuclear@0
|
754 {
|
nuclear@0
|
755 if (mFileBuffer + 6 >= end)
|
nuclear@0
|
756 break;
|
nuclear@0
|
757 LE_NCONST IFF::SubChunkHeader* const head = IFF::LoadSubChunk(mFileBuffer);
|
nuclear@0
|
758
|
nuclear@0
|
759 if (mFileBuffer + head->length > end)
|
nuclear@0
|
760 throw DeadlyImportError("LWO2: Invalid surface chunk length");
|
nuclear@0
|
761
|
nuclear@0
|
762 uint8_t* const next = mFileBuffer+head->length;
|
nuclear@0
|
763 switch (head->type)
|
nuclear@0
|
764 {
|
nuclear@0
|
765 // diffuse color
|
nuclear@0
|
766 case AI_LWO_COLR:
|
nuclear@0
|
767 {
|
nuclear@0
|
768 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,COLR,12);
|
nuclear@0
|
769 surf.mColor.r = GetF4();
|
nuclear@0
|
770 surf.mColor.g = GetF4();
|
nuclear@0
|
771 surf.mColor.b = GetF4();
|
nuclear@0
|
772 break;
|
nuclear@0
|
773 }
|
nuclear@0
|
774 // diffuse strength ... hopefully
|
nuclear@0
|
775 case AI_LWO_DIFF:
|
nuclear@0
|
776 {
|
nuclear@0
|
777 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,DIFF,4);
|
nuclear@0
|
778 surf.mDiffuseValue = GetF4();
|
nuclear@0
|
779 break;
|
nuclear@0
|
780 }
|
nuclear@0
|
781 // specular strength ... hopefully
|
nuclear@0
|
782 case AI_LWO_SPEC:
|
nuclear@0
|
783 {
|
nuclear@0
|
784 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SPEC,4);
|
nuclear@0
|
785 surf.mSpecularValue = GetF4();
|
nuclear@0
|
786 break;
|
nuclear@0
|
787 }
|
nuclear@0
|
788 // transparency
|
nuclear@0
|
789 case AI_LWO_TRAN:
|
nuclear@0
|
790 {
|
nuclear@0
|
791 // transparency explicitly disabled?
|
nuclear@0
|
792 if (surf.mTransparency == 10e10f)
|
nuclear@0
|
793 break;
|
nuclear@0
|
794
|
nuclear@0
|
795 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,TRAN,4);
|
nuclear@0
|
796 surf.mTransparency = GetF4();
|
nuclear@0
|
797 break;
|
nuclear@0
|
798 }
|
nuclear@0
|
799 // additive transparency
|
nuclear@0
|
800 case AI_LWO_ADTR:
|
nuclear@0
|
801 {
|
nuclear@0
|
802 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,ADTR,4);
|
nuclear@0
|
803 surf.mAdditiveTransparency = GetF4();
|
nuclear@0
|
804 break;
|
nuclear@0
|
805 }
|
nuclear@0
|
806 // wireframe mode
|
nuclear@0
|
807 case AI_LWO_LINE:
|
nuclear@0
|
808 {
|
nuclear@0
|
809 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,LINE,2);
|
nuclear@0
|
810 if (GetU2() & 0x1)
|
nuclear@0
|
811 surf.mWireframe = true;
|
nuclear@0
|
812 break;
|
nuclear@0
|
813 }
|
nuclear@0
|
814 // glossiness
|
nuclear@0
|
815 case AI_LWO_GLOS:
|
nuclear@0
|
816 {
|
nuclear@0
|
817 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,GLOS,4);
|
nuclear@0
|
818 surf.mGlossiness = GetF4();
|
nuclear@0
|
819 break;
|
nuclear@0
|
820 }
|
nuclear@0
|
821 // bump intensity
|
nuclear@0
|
822 case AI_LWO_BUMP:
|
nuclear@0
|
823 {
|
nuclear@0
|
824 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BUMP,4);
|
nuclear@0
|
825 surf.mBumpIntensity = GetF4();
|
nuclear@0
|
826 break;
|
nuclear@0
|
827 }
|
nuclear@0
|
828 // color highlights
|
nuclear@0
|
829 case AI_LWO_CLRH:
|
nuclear@0
|
830 {
|
nuclear@0
|
831 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,CLRH,4);
|
nuclear@0
|
832 surf.mColorHighlights = GetF4();
|
nuclear@0
|
833 break;
|
nuclear@0
|
834 }
|
nuclear@0
|
835 // index of refraction
|
nuclear@0
|
836 case AI_LWO_RIND:
|
nuclear@0
|
837 {
|
nuclear@0
|
838 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,RIND,4);
|
nuclear@0
|
839 surf.mIOR = GetF4();
|
nuclear@0
|
840 break;
|
nuclear@0
|
841 }
|
nuclear@0
|
842 // polygon sidedness
|
nuclear@0
|
843 case AI_LWO_SIDE:
|
nuclear@0
|
844 {
|
nuclear@0
|
845 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SIDE,2);
|
nuclear@0
|
846 surf.bDoubleSided = (3 == GetU2());
|
nuclear@0
|
847 break;
|
nuclear@0
|
848 }
|
nuclear@0
|
849 // maximum smoothing angle
|
nuclear@0
|
850 case AI_LWO_SMAN:
|
nuclear@0
|
851 {
|
nuclear@0
|
852 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,SMAN,4);
|
nuclear@0
|
853 surf.mMaximumSmoothAngle = fabs( GetF4() );
|
nuclear@0
|
854 break;
|
nuclear@0
|
855 }
|
nuclear@0
|
856 // vertex color channel to be applied to the surface
|
nuclear@0
|
857 case AI_LWO_VCOL:
|
nuclear@0
|
858 {
|
nuclear@0
|
859 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,VCOL,12);
|
nuclear@0
|
860 surf.mDiffuseValue *= GetF4(); // strength
|
nuclear@0
|
861 ReadVSizedIntLWO2(mFileBuffer); // skip envelope
|
nuclear@0
|
862 surf.mVCMapType = GetU4(); // type of the channel
|
nuclear@0
|
863
|
nuclear@0
|
864 // name of the channel
|
nuclear@0
|
865 GetS0(surf.mVCMap, (unsigned int) (next - mFileBuffer ));
|
nuclear@0
|
866 break;
|
nuclear@0
|
867 }
|
nuclear@0
|
868 // surface bock entry
|
nuclear@0
|
869 case AI_LWO_BLOK:
|
nuclear@0
|
870 {
|
nuclear@0
|
871 AI_LWO_VALIDATE_CHUNK_LENGTH(head->length,BLOK,4);
|
nuclear@0
|
872 LE_NCONST IFF::SubChunkHeader* head2 = IFF::LoadSubChunk(mFileBuffer);
|
nuclear@0
|
873
|
nuclear@0
|
874 switch (head2->type)
|
nuclear@0
|
875 {
|
nuclear@0
|
876 case AI_LWO_PROC:
|
nuclear@0
|
877 case AI_LWO_GRAD:
|
nuclear@0
|
878 case AI_LWO_IMAP:
|
nuclear@0
|
879 LoadLWO2TextureBlock(head2, head->length);
|
nuclear@0
|
880 break;
|
nuclear@0
|
881 case AI_LWO_SHDR:
|
nuclear@0
|
882 LoadLWO2ShaderBlock(head2, head->length);
|
nuclear@0
|
883 break;
|
nuclear@0
|
884
|
nuclear@0
|
885 default:
|
nuclear@0
|
886 DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
|
nuclear@0
|
887 };
|
nuclear@0
|
888
|
nuclear@0
|
889 break;
|
nuclear@0
|
890 }
|
nuclear@0
|
891 }
|
nuclear@0
|
892 mFileBuffer = next;
|
nuclear@0
|
893 }
|
nuclear@0
|
894 }
|
nuclear@0
|
895
|
nuclear@0
|
896 #endif // !! ASSIMP_BUILD_NO_X_IMPORTER
|