diff --git a/examples/rendering-basic-pbr/obj-loader.cpp b/examples/rendering-basic-pbr/obj-loader.cpp index ee711ba..bb21c9c 100644 --- a/examples/rendering-basic-pbr/obj-loader.cpp +++ b/examples/rendering-basic-pbr/obj-loader.cpp @@ -20,7 +20,6 @@ // EXTERNAL INCLUDES #include -#include #include #include @@ -35,7 +34,7 @@ const int MAX_POINT_INDICES = 4; ObjLoader::ObjLoader() : mSceneLoaded( false ), mMaterialLoaded( false ), - mHasTexturePoints( false ), + mHasTextureUv( false ), mHasDiffuseMap( false ), mHasNormalMap( false ), mHasSpecularMap( false ) @@ -58,10 +57,10 @@ bool ObjLoader::IsMaterialLoaded() return mMaterialLoaded; } -void ObjLoader::CalculateHardFaceNormals( const Dali::Vector& vertices, Dali::Vector& triangles, +void ObjLoader::CalculateHardFaceNormals( const Dali::Vector& points, Dali::Vector& triangles, Dali::Vector& normals ) { - int numFaceVertices = 3 * triangles.Size(); //Vertex per face, as each point has different normals for each face. + int numFaceVertices = 3 * triangles.Size(); //Vertices per face, as each vertex has different normals instance for each face. int normalIndex = 0; //Tracks progress through the array of normals. normals.Clear(); @@ -71,19 +70,19 @@ void ObjLoader::CalculateHardFaceNormals( const Dali::Vector& vertices, for( unsigned long i = 0; i < triangles.Size(); i++ ) { //Triangle vertices. - const Vector3& v0 = vertices[triangles[i].pointIndex[0]]; - const Vector3& v1 = vertices[triangles[i].pointIndex[1]]; - const Vector3& v2 = vertices[triangles[i].pointIndex[2]]; + const Vector3& v0 = points[triangles[i].pointIndex[0]]; + const Vector3& v1 = points[triangles[i].pointIndex[1]]; + const Vector3& v2 = points[triangles[i].pointIndex[2]]; //Triangle edges. Vector3 edge1 = v1 - v0; Vector3 edge2 = v2 - v0; - //Using edges as vectors on the plane, cross to get the normal. + //Using edges as vectors on the plane, cross product to get the normal. Vector3 normalVector = edge1.Cross(edge2); normalVector.Normalize(); - //Assign normals to points. + //Assign normal index to triangle vertex and set the normal vector to the list of normals. for( unsigned long j = 0; j < 3; j++, normalIndex++ ) { triangles[i].normalIndex[j] = normalIndex; @@ -92,22 +91,22 @@ void ObjLoader::CalculateHardFaceNormals( const Dali::Vector& vertices, } } -void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector& vertices, Dali::Vector& triangles, +void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector& points, Dali::Vector& triangles, Dali::Vector& normals ) { int normalIndex = 0; //Tracks progress through the array of normals. normals.Clear(); - normals.Resize( vertices.Size() ); //One (averaged) normal per point. + normals.Resize( points.Size() ); //One (averaged) normal per point. //For each triangle, calculate the normal by crossing two vectors on the triangle's plane //We then add the triangle's normal to the cumulative normals at each point of it for( unsigned long i = 0; i < triangles.Size(); i++ ) { - //Triangle vertices. - const Vector3& v0 = vertices[triangles[i].pointIndex[0]]; - const Vector3& v1 = vertices[triangles[i].pointIndex[1]]; - const Vector3& v2 = vertices[triangles[i].pointIndex[2]]; + //Triangle points. + const Vector3& v0 = points[triangles[i].pointIndex[0]]; + const Vector3& v1 = points[triangles[i].pointIndex[1]]; + const Vector3& v2 = points[triangles[i].pointIndex[2]]; //Triangle edges. Vector3 edge1 = v1 - v0; @@ -116,11 +115,12 @@ void ObjLoader::CalculateSoftFaceNormals( const Dali::Vector& vertices, //Using edges as vectors on the plane, cross to get the normal. Vector3 normalVector = edge1.Cross(edge2); - //Add this triangle's normal to the cumulative normal of each constituent point and set the index of the normal accordingly. - for( unsigned long j = 0; j < 3; j++, normalIndex++ ) + //Add this triangle's normal to the cumulative normal of each constituent triangle point and set the index of the normal accordingly. + for( unsigned long j = 0; j < 3; j++) { - triangles[i].normalIndex[j] = triangles[i].pointIndex[j]; //Normal index matches up to vertex index, as one normal per vertex. - normals[triangles[i].normalIndex[j]] += normalVector; + normalIndex = triangles[i].pointIndex[j]; + triangles[i].normalIndex[j] = normalIndex; //Normal index matches up to vertex index, as one normal per vertex. + normals[normalIndex] += normalVector; } } @@ -135,9 +135,9 @@ void ObjLoader::CalculateTangentFrame() { //Reset tangent vector to hold new values. mTangents.Clear(); - mTangents.Resize( mPoints.Size() ); + mTangents.Resize( mNormals.Size() ); - //For each triangle, calculate the tangent vector and then add it to the total tangent vector of each point. + //For each triangle, calculate the tangent vector and then add it to the total tangent vector of each normal. for ( unsigned long a = 0; a < mTriangles.Size(); a++ ) { Vector3 tangentVector; @@ -149,27 +149,29 @@ void ObjLoader::CalculateTangentFrame() Vector3 edge1 = v1 - v0; Vector3 edge2 = v2 - v0; - const Vector2& w0 = mTextures[mTriangles[a].textureIndex[0]]; - const Vector2& w1 = mTextures[mTriangles[a].textureIndex[1]]; - const Vector2& w2 = mTextures[mTriangles[a].textureIndex[2]]; + const Vector2& w0 = mTextureUv[mTriangles[a].textureIndex[0]]; + const Vector2& w1 = mTextureUv[mTriangles[a].textureIndex[1]]; + const Vector2& w2 = mTextureUv[mTriangles[a].textureIndex[2]]; float deltaU1 = w1.x - w0.x; float deltaV1 = w1.y - w0.y; float deltaU2 = w2.x - w0.x; float deltaV2 = w2.y - w0.y; - float f = 1.0f / (deltaU1 * deltaV2 - deltaU2 * deltaV1); + // 1.0/f could cause division by zero in some cases, this factor will act + // as a weight of the tangent vector and it is fixed when it is normalised. + float f = (deltaU1 * deltaV2 - deltaU2 * deltaV1); tangentVector.x = f * ( deltaV2 * edge1.x - deltaV1 * edge2.x ); tangentVector.y = f * ( deltaV2 * edge1.y - deltaV1 * edge2.y ); tangentVector.z = f * ( deltaV2 * edge1.z - deltaV1 * edge2.z ); - mTangents[mTriangles[a].pointIndex[0]] += tangentVector; - mTangents[mTriangles[a].pointIndex[1]] += tangentVector; - mTangents[mTriangles[a].pointIndex[2]] += tangentVector; + mTangents[mTriangles[a].normalIndex[0]] += tangentVector; + mTangents[mTriangles[a].normalIndex[1]] += tangentVector; + mTangents[mTriangles[a].normalIndex[2]] += tangentVector; } - //Orthogonalize tangents and set binormals. + //Orthogonalize tangents. for ( unsigned long a = 0; a < mTangents.Size(); a++ ) { const Vector3& n = mNormals[a]; @@ -219,14 +221,15 @@ void ObjLoader::CreateGeometryArray( Dali::Vector& positions, bool mustCalculateTangents = ( mTangents.Size() == 0 ) || ( mTangents.Size() != mNormals.Size() ); //However, we don't need to do this if the object doesn't use textures to begin with. - mustCalculateTangents &= mHasTexturePoints; + mustCalculateTangents &= mHasTextureUv; - //We also have to recalculate the normals if we need to calculate tangents, - // as we need just one normal, tangent per vertex, rather than the supplied per-face vertices. - //Alternatively, we need to calculate the normals if there weren't any to begin with. - if( mNormals.Size() == 0 || mustCalculateTangents ) + // We calculate the normals if hard normals(flat normals) is set. + // Use the normals provided by the file to make the tangent calculation per normal, + // the correct results depends of normal generated by file, otherwise we need to recalculate + // the normal programmatically. + if( ( ( mNormals.Size() == 0 ) && mustCalculateTangents ) || !useSoftNormals ) { - if( useSoftNormals || mustCalculateTangents ) + if( useSoftNormals ) { CalculateSoftFaceNormals( mPoints, mTriangles, mNormals ); } @@ -236,16 +239,16 @@ void ObjLoader::CreateGeometryArray( Dali::Vector& positions, } } - if( mHasTexturePoints && mustCalculateTangents ) + if( mHasTextureUv && mustCalculateTangents ) { CalculateTangentFrame(); } - bool mapsCorrespond; //True if the sizes of the arrays necessary for the object agree. + bool mapsCorrespond; //True if the sizes of the arrays necessary to draw the object match. - if ( mHasTexturePoints ) + if ( mHasTextureUv ) { - mapsCorrespond = ( mPoints.Size() == mTextures.Size() ) && ( mTextures.Size() == mNormals.Size() ); + mapsCorrespond = ( mPoints.Size() == mTextureUv.Size() ) && ( mTextureUv.Size() == mNormals.Size() ); } else { @@ -278,9 +281,9 @@ void ObjLoader::CreateGeometryArray( Dali::Vector& positions, normals[mTriangles[ui].pointIndex[j]] = mNormals[mTriangles[ui].normalIndex[j]]; - if ( mHasTexturePoints ) + if ( mHasTextureUv ) { - textures[mTriangles[ui].pointIndex[j]] = mTextures[mTriangles[ui].textureIndex[j]]; + textures[mTriangles[ui].pointIndex[j]] = mTextureUv[mTriangles[ui].textureIndex[j]]; tangents[mTriangles[ui].pointIndex[j]] = mTangents[mTriangles[ui].normalIndex[j]]; } } @@ -304,9 +307,9 @@ void ObjLoader::CreateGeometryArray( Dali::Vector& positions, positions[index] = mPoints[mTriangles[ui].pointIndex[j]]; normals[index] = mNormals[mTriangles[ui].normalIndex[j]]; - if( mHasTexturePoints ) + if( mHasTextureUv ) { - textures[index] = mTextures[mTriangles[ui].textureIndex[j]]; + textures[index] = mTextureUv[mTriangles[ui].textureIndex[j]]; tangents[index] = mTangents[mTriangles[ui].normalIndex[j]]; } @@ -335,7 +338,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) std::string strMatActual; - std::string input = objBuffer; + std::string input( objBuffer, fileSize ); std::istringstream ss(input); ss.imbue( std::locale( "C" ) ); @@ -388,9 +391,8 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) { isline >> texture.x; isline >> texture.y; - texture.y = 1.0-texture.y; - mTextures.PushBack( texture ); + mTextureUv.PushBack( texture ); } else if ( tag == "#_#vt1" ) { @@ -398,7 +400,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) isline >> texture.y; texture.y = 1.0-texture.y; - mTextures2.PushBack( texture ); + mTextureUv2.PushBack( texture ); } else if ( tag == "s" ) { @@ -413,7 +415,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) } int numIndices = 0; - while( isline >> vet[numIndices] && numIndices < MAX_POINT_INDICES ) + while( ( numIndices < MAX_POINT_INDICES ) && ( isline >> vet[numIndices] ) ) { numIndices++; } @@ -523,7 +525,7 @@ bool ObjLoader::LoadObject( char* objBuffer, std::streampos fileSize ) { CenterAndScale( true, mPoints ); mSceneLoaded = true; - mHasTexturePoints = hasTexture; + mHasTextureUv = hasTexture; return true; } @@ -627,7 +629,7 @@ Geometry ObjLoader::CreateGeometry( int objectProperties, bool useSoftNormals ) surface.AddVertexBuffer( normalBuffer ); //Some need tangent - if( ( objectProperties & TANGENTS ) && mHasTexturePoints ) + if( ( objectProperties & TANGENTS ) && mHasTextureUv ) { Property::Map tangentMap; tangentMap["aTangent"] = Property::VECTOR3; @@ -638,7 +640,7 @@ Geometry ObjLoader::CreateGeometry( int objectProperties, bool useSoftNormals ) } //Some need texture coordinates - if( ( objectProperties & TEXTURE_COORDINATES ) && mHasTexturePoints ) + if( ( objectProperties & TEXTURE_COORDINATES ) && mHasTextureUv ) { Property::Map textCoordMap; textCoordMap["aTexCoord"] = Property::VECTOR2; @@ -672,8 +674,8 @@ Vector3 ObjLoader::GetSize() void ObjLoader::ClearArrays() { mPoints.Clear(); - mTextures.Clear(); - mTextures2.Clear(); + mTextureUv.Clear(); + mTextureUv2.Clear(); mNormals.Clear(); mTangents.Clear(); mBiTangents.Clear(); @@ -685,7 +687,7 @@ void ObjLoader::ClearArrays() bool ObjLoader::IsTexturePresent() { - return mHasTexturePoints; + return mHasTextureUv; } bool ObjLoader::IsDiffuseMapPresent() diff --git a/examples/rendering-basic-pbr/obj-loader.h b/examples/rendering-basic-pbr/obj-loader.h index cd0bdb5..11d289c 100644 --- a/examples/rendering-basic-pbr/obj-loader.h +++ b/examples/rendering-basic-pbr/obj-loader.h @@ -95,8 +95,8 @@ public: private: Dali::Vector mPoints; - Dali::Vector mTextures; - Dali::Vector mTextures2; + Dali::Vector mTextureUv; + Dali::Vector mTextureUv2; Dali::Vector mNormals; Dali::Vector mTangents; Dali::Vector mBiTangents; @@ -106,7 +106,7 @@ private: bool mSceneLoaded; bool mMaterialLoaded; - bool mHasTexturePoints; + bool mHasTextureUv; //Material file properties. bool mHasDiffuseMap;