Commit 535268ca85e2f079f8601ac65ade9bc69df730ce

Authored by greynaga
1 parent f53e80d9

obj-loader Tangent fix

The tangent was generated by vertex, and was changed to per normal, this will work if the normal are defined per vertex.

This patch is creating good results with the current models tested, but depends on the output of the exporter.

In case the tangents are not correct, the 3D model should be re-exported or generate the normals programmatically.

Change-Id: I35cdf2ce581974ab5fbc85709442bcb3a8112b8f
examples/rendering-basic-pbr/obj-loader.cpp
@@ -20,7 +20,6 @@ @@ -20,7 +20,6 @@
20 20
21 // EXTERNAL INCLUDES 21 // EXTERNAL INCLUDES
22 #include <dali/integration-api/debug.h> 22 #include <dali/integration-api/debug.h>
23 -#include <string>  
24 #include <sstream> 23 #include <sstream>
25 #include <string.h> 24 #include <string.h>
26 25
@@ -35,7 +34,7 @@ const int MAX_POINT_INDICES = 4; @@ -35,7 +34,7 @@ const int MAX_POINT_INDICES = 4;
35 ObjLoader::ObjLoader() 34 ObjLoader::ObjLoader()
36 : mSceneLoaded( false ), 35 : mSceneLoaded( false ),
37 mMaterialLoaded( false ), 36 mMaterialLoaded( false ),
38 - mHasTexturePoints( false ), 37 + mHasTextureUv( false ),
39 mHasDiffuseMap( false ), 38 mHasDiffuseMap( false ),
40 mHasNormalMap( false ), 39 mHasNormalMap( false ),
41 mHasSpecularMap( false ) 40 mHasSpecularMap( false )
@@ -58,10 +57,10 @@ bool ObjLoader::IsMaterialLoaded() @@ -58,10 +57,10 @@ bool ObjLoader::IsMaterialLoaded()
58 return mMaterialLoaded; 57 return mMaterialLoaded;
59 } 58 }
60 59
61 -void ObjLoader::CalculateHardFaceNormals( const Dali::Vector<Vector3>& vertices, Dali::Vector<TriIndex>& triangles, 60 +void ObjLoader::CalculateHardFaceNormals( const Dali::Vector<Vector3>& points, Dali::Vector<TriIndex>& triangles,
62 Dali::Vector<Vector3>& normals ) 61 Dali::Vector<Vector3>& normals )
63 { 62 {
64 - int numFaceVertices = 3 * triangles.Size(); //Vertex per face, as each point has different normals for each face. 63 + int numFaceVertices = 3 * triangles.Size(); //Vertices per face, as each vertex has different normals instance for each face.
65 int normalIndex = 0; //Tracks progress through the array of normals. 64 int normalIndex = 0; //Tracks progress through the array of normals.
66 65
67 normals.Clear(); 66 normals.Clear();
@@ -71,19 +70,19 @@ void ObjLoader::CalculateHardFaceNormals( const Dali::Vector&lt;Vector3&gt;&amp; vertices, @@ -71,19 +70,19 @@ void ObjLoader::CalculateHardFaceNormals( const Dali::Vector&lt;Vector3&gt;&amp; vertices,
71 for( unsigned long i = 0; i < triangles.Size(); i++ ) 70 for( unsigned long i = 0; i < triangles.Size(); i++ )
72 { 71 {
73 //Triangle vertices. 72 //Triangle vertices.
74 - const Vector3& v0 = vertices[triangles[i].pointIndex[0]];  
75 - const Vector3& v1 = vertices[triangles[i].pointIndex[1]];  
76 - const Vector3& v2 = vertices[triangles[i].pointIndex[2]]; 73 + const Vector3& v0 = points[triangles[i].pointIndex[0]];
  74 + const Vector3& v1 = points[triangles[i].pointIndex[1]];
  75 + const Vector3& v2 = points[triangles[i].pointIndex[2]];
77 76
78 //Triangle edges. 77 //Triangle edges.
79 Vector3 edge1 = v1 - v0; 78 Vector3 edge1 = v1 - v0;
80 Vector3 edge2 = v2 - v0; 79 Vector3 edge2 = v2 - v0;
81 80
82 - //Using edges as vectors on the plane, cross to get the normal. 81 + //Using edges as vectors on the plane, cross product to get the normal.
83 Vector3 normalVector = edge1.Cross(edge2); 82 Vector3 normalVector = edge1.Cross(edge2);
84 normalVector.Normalize(); 83 normalVector.Normalize();
85 84
86 - //Assign normals to points. 85 + //Assign normal index to triangle vertex and set the normal vector to the list of normals.
87 for( unsigned long j = 0; j < 3; j++, normalIndex++ ) 86 for( unsigned long j = 0; j < 3; j++, normalIndex++ )
88 { 87 {
89 triangles[i].normalIndex[j] = normalIndex; 88 triangles[i].normalIndex[j] = normalIndex;
@@ -92,22 +91,22 @@ void ObjLoader::CalculateHardFaceNormals( const Dali::Vector&lt;Vector3&gt;&amp; vertices, @@ -92,22 +91,22 @@ void ObjLoader::CalculateHardFaceNormals( const Dali::Vector&lt;Vector3&gt;&amp; vertices,
92 } 91 }
93 } 92 }
94 93
95 -void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector<Vector3>& vertices, Dali::Vector<TriIndex>& triangles, 94 +void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector<Vector3>& points, Dali::Vector<TriIndex>& triangles,
96 Dali::Vector<Vector3>& normals ) 95 Dali::Vector<Vector3>& normals )
97 { 96 {
98 int normalIndex = 0; //Tracks progress through the array of normals. 97 int normalIndex = 0; //Tracks progress through the array of normals.
99 98
100 normals.Clear(); 99 normals.Clear();
101 - normals.Resize( vertices.Size() ); //One (averaged) normal per point. 100 + normals.Resize( points.Size() ); //One (averaged) normal per point.
102 101
103 //For each triangle, calculate the normal by crossing two vectors on the triangle's plane 102 //For each triangle, calculate the normal by crossing two vectors on the triangle's plane
104 //We then add the triangle's normal to the cumulative normals at each point of it 103 //We then add the triangle's normal to the cumulative normals at each point of it
105 for( unsigned long i = 0; i < triangles.Size(); i++ ) 104 for( unsigned long i = 0; i < triangles.Size(); i++ )
106 { 105 {
107 - //Triangle vertices.  
108 - const Vector3& v0 = vertices[triangles[i].pointIndex[0]];  
109 - const Vector3& v1 = vertices[triangles[i].pointIndex[1]];  
110 - const Vector3& v2 = vertices[triangles[i].pointIndex[2]]; 106 + //Triangle points.
  107 + const Vector3& v0 = points[triangles[i].pointIndex[0]];
  108 + const Vector3& v1 = points[triangles[i].pointIndex[1]];
  109 + const Vector3& v2 = points[triangles[i].pointIndex[2]];
111 110
112 //Triangle edges. 111 //Triangle edges.
113 Vector3 edge1 = v1 - v0; 112 Vector3 edge1 = v1 - v0;
@@ -116,11 +115,12 @@ void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector&lt;Vector3&gt;&amp; vertices, @@ -116,11 +115,12 @@ void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector&lt;Vector3&gt;&amp; vertices,
116 //Using edges as vectors on the plane, cross to get the normal. 115 //Using edges as vectors on the plane, cross to get the normal.
117 Vector3 normalVector = edge1.Cross(edge2); 116 Vector3 normalVector = edge1.Cross(edge2);
118 117
119 - //Add this triangle's normal to the cumulative normal of each constituent point and set the index of the normal accordingly.  
120 - for( unsigned long j = 0; j < 3; j++, normalIndex++ ) 118 + //Add this triangle's normal to the cumulative normal of each constituent triangle point and set the index of the normal accordingly.
  119 + for( unsigned long j = 0; j < 3; j++)
121 { 120 {
122 - triangles[i].normalIndex[j] = triangles[i].pointIndex[j]; //Normal index matches up to vertex index, as one normal per vertex.  
123 - normals[triangles[i].normalIndex[j]] += normalVector; 121 + normalIndex = triangles[i].pointIndex[j];
  122 + triangles[i].normalIndex[j] = normalIndex; //Normal index matches up to vertex index, as one normal per vertex.
  123 + normals[normalIndex] += normalVector;
124 } 124 }
125 } 125 }
126 126
@@ -135,9 +135,9 @@ void ObjLoader::CalculateTangentFrame() @@ -135,9 +135,9 @@ void ObjLoader::CalculateTangentFrame()
135 { 135 {
136 //Reset tangent vector to hold new values. 136 //Reset tangent vector to hold new values.
137 mTangents.Clear(); 137 mTangents.Clear();
138 - mTangents.Resize( mPoints.Size() ); 138 + mTangents.Resize( mNormals.Size() );
139 139
140 - //For each triangle, calculate the tangent vector and then add it to the total tangent vector of each point. 140 + //For each triangle, calculate the tangent vector and then add it to the total tangent vector of each normal.
141 for ( unsigned long a = 0; a < mTriangles.Size(); a++ ) 141 for ( unsigned long a = 0; a < mTriangles.Size(); a++ )
142 { 142 {
143 Vector3 tangentVector; 143 Vector3 tangentVector;
@@ -149,27 +149,29 @@ void ObjLoader::CalculateTangentFrame() @@ -149,27 +149,29 @@ void ObjLoader::CalculateTangentFrame()
149 Vector3 edge1 = v1 - v0; 149 Vector3 edge1 = v1 - v0;
150 Vector3 edge2 = v2 - v0; 150 Vector3 edge2 = v2 - v0;
151 151
152 - const Vector2& w0 = mTextures[mTriangles[a].textureIndex[0]];  
153 - const Vector2& w1 = mTextures[mTriangles[a].textureIndex[1]];  
154 - const Vector2& w2 = mTextures[mTriangles[a].textureIndex[2]]; 152 + const Vector2& w0 = mTextureUv[mTriangles[a].textureIndex[0]];
  153 + const Vector2& w1 = mTextureUv[mTriangles[a].textureIndex[1]];
  154 + const Vector2& w2 = mTextureUv[mTriangles[a].textureIndex[2]];
155 155
156 float deltaU1 = w1.x - w0.x; 156 float deltaU1 = w1.x - w0.x;
157 float deltaV1 = w1.y - w0.y; 157 float deltaV1 = w1.y - w0.y;
158 float deltaU2 = w2.x - w0.x; 158 float deltaU2 = w2.x - w0.x;
159 float deltaV2 = w2.y - w0.y; 159 float deltaV2 = w2.y - w0.y;
160 160
161 - float f = 1.0f / (deltaU1 * deltaV2 - deltaU2 * deltaV1); 161 + // 1.0/f could cause division by zero in some cases, this factor will act
  162 + // as a weight of the tangent vector and it is fixed when it is normalised.
  163 + float f = (deltaU1 * deltaV2 - deltaU2 * deltaV1);
162 164
163 tangentVector.x = f * ( deltaV2 * edge1.x - deltaV1 * edge2.x ); 165 tangentVector.x = f * ( deltaV2 * edge1.x - deltaV1 * edge2.x );
164 tangentVector.y = f * ( deltaV2 * edge1.y - deltaV1 * edge2.y ); 166 tangentVector.y = f * ( deltaV2 * edge1.y - deltaV1 * edge2.y );
165 tangentVector.z = f * ( deltaV2 * edge1.z - deltaV1 * edge2.z ); 167 tangentVector.z = f * ( deltaV2 * edge1.z - deltaV1 * edge2.z );
166 168
167 - mTangents[mTriangles[a].pointIndex[0]] += tangentVector;  
168 - mTangents[mTriangles[a].pointIndex[1]] += tangentVector;  
169 - mTangents[mTriangles[a].pointIndex[2]] += tangentVector; 169 + mTangents[mTriangles[a].normalIndex[0]] += tangentVector;
  170 + mTangents[mTriangles[a].normalIndex[1]] += tangentVector;
  171 + mTangents[mTriangles[a].normalIndex[2]] += tangentVector;
170 } 172 }
171 173
172 - //Orthogonalize tangents and set binormals. 174 + //Orthogonalize tangents.
173 for ( unsigned long a = 0; a < mTangents.Size(); a++ ) 175 for ( unsigned long a = 0; a < mTangents.Size(); a++ )
174 { 176 {
175 const Vector3& n = mNormals[a]; 177 const Vector3& n = mNormals[a];
@@ -219,14 +221,15 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions, @@ -219,14 +221,15 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions,
219 bool mustCalculateTangents = ( mTangents.Size() == 0 ) || ( mTangents.Size() != mNormals.Size() ); 221 bool mustCalculateTangents = ( mTangents.Size() == 0 ) || ( mTangents.Size() != mNormals.Size() );
220 222
221 //However, we don't need to do this if the object doesn't use textures to begin with. 223 //However, we don't need to do this if the object doesn't use textures to begin with.
222 - mustCalculateTangents &= mHasTexturePoints; 224 + mustCalculateTangents &= mHasTextureUv;
223 225
224 - //We also have to recalculate the normals if we need to calculate tangents,  
225 - // as we need just one normal, tangent per vertex, rather than the supplied per-face vertices.  
226 - //Alternatively, we need to calculate the normals if there weren't any to begin with.  
227 - if( mNormals.Size() == 0 || mustCalculateTangents ) 226 + // We calculate the normals if hard normals(flat normals) is set.
  227 + // Use the normals provided by the file to make the tangent calculation per normal,
  228 + // the correct results depends of normal generated by file, otherwise we need to recalculate
  229 + // the normal programmatically.
  230 + if( ( ( mNormals.Size() == 0 ) && mustCalculateTangents ) || !useSoftNormals )
228 { 231 {
229 - if( useSoftNormals || mustCalculateTangents ) 232 + if( useSoftNormals )
230 { 233 {
231 CalculateSoftFaceNormals( mPoints, mTriangles, mNormals ); 234 CalculateSoftFaceNormals( mPoints, mTriangles, mNormals );
232 } 235 }
@@ -236,16 +239,16 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions, @@ -236,16 +239,16 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions,
236 } 239 }
237 } 240 }
238 241
239 - if( mHasTexturePoints && mustCalculateTangents ) 242 + if( mHasTextureUv && mustCalculateTangents )
240 { 243 {
241 CalculateTangentFrame(); 244 CalculateTangentFrame();
242 } 245 }
243 246
244 - bool mapsCorrespond; //True if the sizes of the arrays necessary for the object agree. 247 + bool mapsCorrespond; //True if the sizes of the arrays necessary to draw the object match.
245 248
246 - if ( mHasTexturePoints ) 249 + if ( mHasTextureUv )
247 { 250 {
248 - mapsCorrespond = ( mPoints.Size() == mTextures.Size() ) && ( mTextures.Size() == mNormals.Size() ); 251 + mapsCorrespond = ( mPoints.Size() == mTextureUv.Size() ) && ( mTextureUv.Size() == mNormals.Size() );
249 } 252 }
250 else 253 else
251 { 254 {
@@ -278,9 +281,9 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions, @@ -278,9 +281,9 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions,
278 281
279 normals[mTriangles[ui].pointIndex[j]] = mNormals[mTriangles[ui].normalIndex[j]]; 282 normals[mTriangles[ui].pointIndex[j]] = mNormals[mTriangles[ui].normalIndex[j]];
280 283
281 - if ( mHasTexturePoints ) 284 + if ( mHasTextureUv )
282 { 285 {
283 - textures[mTriangles[ui].pointIndex[j]] = mTextures[mTriangles[ui].textureIndex[j]]; 286 + textures[mTriangles[ui].pointIndex[j]] = mTextureUv[mTriangles[ui].textureIndex[j]];
284 tangents[mTriangles[ui].pointIndex[j]] = mTangents[mTriangles[ui].normalIndex[j]]; 287 tangents[mTriangles[ui].pointIndex[j]] = mTangents[mTriangles[ui].normalIndex[j]];
285 } 288 }
286 } 289 }
@@ -304,9 +307,9 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions, @@ -304,9 +307,9 @@ void ObjLoader::CreateGeometryArray( Dali::Vector&lt;Vector3&gt;&amp; positions,
304 positions[index] = mPoints[mTriangles[ui].pointIndex[j]]; 307 positions[index] = mPoints[mTriangles[ui].pointIndex[j]];
305 normals[index] = mNormals[mTriangles[ui].normalIndex[j]]; 308 normals[index] = mNormals[mTriangles[ui].normalIndex[j]];
306 309
307 - if( mHasTexturePoints ) 310 + if( mHasTextureUv )
308 { 311 {
309 - textures[index] = mTextures[mTriangles[ui].textureIndex[j]]; 312 + textures[index] = mTextureUv[mTriangles[ui].textureIndex[j]];
310 tangents[index] = mTangents[mTriangles[ui].normalIndex[j]]; 313 tangents[index] = mTangents[mTriangles[ui].normalIndex[j]];
311 } 314 }
312 315
@@ -335,7 +338,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) @@ -335,7 +338,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize )
335 338
336 std::string strMatActual; 339 std::string strMatActual;
337 340
338 - std::string input = objBuffer; 341 + std::string input( objBuffer, fileSize );
339 std::istringstream ss(input); 342 std::istringstream ss(input);
340 ss.imbue( std::locale( "C" ) ); 343 ss.imbue( std::locale( "C" ) );
341 344
@@ -388,9 +391,8 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) @@ -388,9 +391,8 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize )
388 { 391 {
389 isline >> texture.x; 392 isline >> texture.x;
390 isline >> texture.y; 393 isline >> texture.y;
391 -  
392 texture.y = 1.0-texture.y; 394 texture.y = 1.0-texture.y;
393 - mTextures.PushBack( texture ); 395 + mTextureUv.PushBack( texture );
394 } 396 }
395 else if ( tag == "#_#vt1" ) 397 else if ( tag == "#_#vt1" )
396 { 398 {
@@ -398,7 +400,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) @@ -398,7 +400,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize )
398 isline >> texture.y; 400 isline >> texture.y;
399 401
400 texture.y = 1.0-texture.y; 402 texture.y = 1.0-texture.y;
401 - mTextures2.PushBack( texture ); 403 + mTextureUv2.PushBack( texture );
402 } 404 }
403 else if ( tag == "s" ) 405 else if ( tag == "s" )
404 { 406 {
@@ -413,7 +415,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) @@ -413,7 +415,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize )
413 } 415 }
414 416
415 int numIndices = 0; 417 int numIndices = 0;
416 - while( isline >> vet[numIndices] && numIndices < MAX_POINT_INDICES ) 418 + while( ( numIndices < MAX_POINT_INDICES ) && ( isline >> vet[numIndices] ) )
417 { 419 {
418 numIndices++; 420 numIndices++;
419 } 421 }
@@ -523,7 +525,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) @@ -523,7 +525,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize )
523 { 525 {
524 CenterAndScale( true, mPoints ); 526 CenterAndScale( true, mPoints );
525 mSceneLoaded = true; 527 mSceneLoaded = true;
526 - mHasTexturePoints = hasTexture; 528 + mHasTextureUv = hasTexture;
527 return true; 529 return true;
528 } 530 }
529 531
@@ -627,7 +629,7 @@ Geometry ObjLoader::CreateGeometry( int objectProperties, bool useSoftNormals ) @@ -627,7 +629,7 @@ Geometry ObjLoader::CreateGeometry( int objectProperties, bool useSoftNormals )
627 surface.AddVertexBuffer( normalBuffer ); 629 surface.AddVertexBuffer( normalBuffer );
628 630
629 //Some need tangent 631 //Some need tangent
630 - if( ( objectProperties & TANGENTS ) && mHasTexturePoints ) 632 + if( ( objectProperties & TANGENTS ) && mHasTextureUv )
631 { 633 {
632 Property::Map tangentMap; 634 Property::Map tangentMap;
633 tangentMap["aTangent"] = Property::VECTOR3; 635 tangentMap["aTangent"] = Property::VECTOR3;
@@ -638,7 +640,7 @@ Geometry ObjLoader::CreateGeometry( int objectProperties, bool useSoftNormals ) @@ -638,7 +640,7 @@ Geometry ObjLoader::CreateGeometry( int objectProperties, bool useSoftNormals )
638 } 640 }
639 641
640 //Some need texture coordinates 642 //Some need texture coordinates
641 - if( ( objectProperties & TEXTURE_COORDINATES ) && mHasTexturePoints ) 643 + if( ( objectProperties & TEXTURE_COORDINATES ) && mHasTextureUv )
642 { 644 {
643 Property::Map textCoordMap; 645 Property::Map textCoordMap;
644 textCoordMap["aTexCoord"] = Property::VECTOR2; 646 textCoordMap["aTexCoord"] = Property::VECTOR2;
@@ -672,8 +674,8 @@ Vector3 ObjLoader::GetSize() @@ -672,8 +674,8 @@ Vector3 ObjLoader::GetSize()
672 void ObjLoader::ClearArrays() 674 void ObjLoader::ClearArrays()
673 { 675 {
674 mPoints.Clear(); 676 mPoints.Clear();
675 - mTextures.Clear();  
676 - mTextures2.Clear(); 677 + mTextureUv.Clear();
  678 + mTextureUv2.Clear();
677 mNormals.Clear(); 679 mNormals.Clear();
678 mTangents.Clear(); 680 mTangents.Clear();
679 mBiTangents.Clear(); 681 mBiTangents.Clear();
@@ -685,7 +687,7 @@ void ObjLoader::ClearArrays() @@ -685,7 +687,7 @@ void ObjLoader::ClearArrays()
685 687
686 bool ObjLoader::IsTexturePresent() 688 bool ObjLoader::IsTexturePresent()
687 { 689 {
688 - return mHasTexturePoints; 690 + return mHasTextureUv;
689 } 691 }
690 692
691 bool ObjLoader::IsDiffuseMapPresent() 693 bool ObjLoader::IsDiffuseMapPresent()
examples/rendering-basic-pbr/obj-loader.h
@@ -95,8 +95,8 @@ public: @@ -95,8 +95,8 @@ public:
95 private: 95 private:
96 96
97 Dali::Vector<Vector3> mPoints; 97 Dali::Vector<Vector3> mPoints;
98 - Dali::Vector<Vector2> mTextures;  
99 - Dali::Vector<Vector2> mTextures2; 98 + Dali::Vector<Vector2> mTextureUv;
  99 + Dali::Vector<Vector2> mTextureUv2;
100 Dali::Vector<Vector3> mNormals; 100 Dali::Vector<Vector3> mNormals;
101 Dali::Vector<Vector3> mTangents; 101 Dali::Vector<Vector3> mTangents;
102 Dali::Vector<Vector3> mBiTangents; 102 Dali::Vector<Vector3> mBiTangents;
@@ -106,7 +106,7 @@ private: @@ -106,7 +106,7 @@ private:
106 106
107 bool mSceneLoaded; 107 bool mSceneLoaded;
108 bool mMaterialLoaded; 108 bool mMaterialLoaded;
109 - bool mHasTexturePoints; 109 + bool mHasTextureUv;
110 110
111 //Material file properties. 111 //Material file properties.
112 bool mHasDiffuseMap; 112 bool mHasDiffuseMap;