X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fdali-toolkit.git;a=blobdiff_plain;f=dali-toolkit%2Finternal%2Fcontrols%2Fmodel3d-view%2Fobj-loader.cpp;h=fe03a5422b48a004acbcb336e59922281d882726;hp=c950b9d921569e173aeaaaee2623f61a5be9345a;hb=HEAD;hpb=f758f35a6f525b556a101b0785f797e3ee3c4b1a diff --git a/dali-toolkit/internal/controls/model3d-view/obj-loader.cpp b/dali-toolkit/internal/controls/model3d-view/obj-loader.cpp index c950b9d..fe03a54 100644 --- a/dali-toolkit/internal/controls/model3d-view/obj-loader.cpp +++ b/dali-toolkit/internal/controls/model3d-view/obj-loader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2021 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,25 +19,31 @@ #include "obj-loader.h" // EXTERNAL INCLUDES -#include -#include +#include #include +#include +#include namespace Dali { - namespace Toolkit { - namespace Internal { - +namespace +{ +const int MAX_POINT_INDICES = 4; +} using namespace Dali; ObjLoader::ObjLoader() { - mSceneLoaded = false; - mMaterialLoaded = false; + mSceneLoaded = false; + mMaterialLoaded = false; + mHasTexturePoints = false; + mHasDiffuseMap = false; + mHasNormalMap = false; + mHasSpecularMap = false; mSceneAABB.Init(); } @@ -56,82 +62,131 @@ bool ObjLoader::IsMaterialLoaded() return mMaterialLoaded; } -//TODO: Use a function that can generate more than one normal/tangent per vertex (using angle) -void ObjLoader::CalculateTangentArray(const Dali::Vector& vertex, - const Dali::Vector& texcoord, - Dali::Vector& triangle, - Dali::Vector& normal, - Dali::Vector& tangent) +void ObjLoader::CalculateHardFaceNormals(const Dali::Vector& vertices, Dali::Vector& triangles, Dali::Vector& normals) { - normal.Clear(); - normal.Resize(vertex.Size()); + int numFaceVertices = 3 * triangles.Size(); //Vertex per face, as each point has different normals for each face. + int normalIndex = 0; //Tracks progress through the array of normals. - Vector3 *tan1 = new Vector3[vertex.Size() * 2]; + normals.Clear(); + normals.Resize(numFaceVertices); - memset(tan1, 0, normal.Size() * sizeof(Vector3) * 2); - memset(&normal[0], 0, normal.Size() * sizeof(Vector3) * 2); - - for (unsigned long a = 0; a < triangle.Size(); a++) + //For each triangle, calculate the normal by crossing two vectors on the triangle's plane. + for(unsigned long i = 0; i < triangles.Size(); i++) { - Vector3 Tangent, Bitangent, Normal; + //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 = vertex[triangle[a].pntIndex[0]]; - const Vector3& v1 = vertex[triangle[a].pntIndex[1]]; - const Vector3& v2 = vertex[triangle[a].pntIndex[2]]; + //Triangle edges. + Vector3 edge1 = v1 - v0; + Vector3 edge2 = v2 - v0; - Vector3 Edge1 = v1 - v0; - Vector3 Edge2 = v2 - v0; + //Using edges as vectors on the plane, cross to get the normal. + Vector3 normalVector = edge1.Cross(edge2); + normalVector.Normalize(); - Normal = Edge1.Cross(Edge2); + //Assign normals to points. + for(unsigned long j = 0; j < 3; j++, normalIndex++) + { + triangles[i].normalIndex[j] = normalIndex; + normals[normalIndex] = normalVector; + } + } +} - const Vector2& w0 = texcoord[triangle[a].texIndex[0]]; - const Vector2& w1 = texcoord[triangle[a].texIndex[1]]; - const Vector2& w2 = texcoord[triangle[a].texIndex[2]]; +void ObjLoader::CalculateSoftFaceNormals(const Dali::Vector& vertices, Dali::Vector& triangles, Dali::Vector& normals) +{ + int normalIndex = 0; //Tracks progress through the array of normals. - float DeltaU1 = w1.x - w0.x; - float DeltaV1 = w1.y - w0.y; - float DeltaU2 = w2.x - w0.x; - float DeltaV2 = w2.y - w0.y; + normals.Clear(); + normals.Resize(vertices.Size()); //One (averaged) normal per point. - float f = 1.0f / (DeltaU1 * DeltaV2 - DeltaU2 * DeltaV1); + //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]]; - Tangent.x = f * (DeltaV2 * Edge1.x - DeltaV1 * Edge2.x); - Tangent.y = f * (DeltaV2 * Edge1.y - DeltaV1 * Edge2.y); - Tangent.z = f * (DeltaV2 * Edge1.z - DeltaV1 * Edge2.z); + //Triangle edges. + Vector3 edge1 = v1 - v0; + Vector3 edge2 = v2 - v0; - tan1[triangle[a].pntIndex[0]] += Tangent; - tan1[triangle[a].pntIndex[1]] += Tangent; - tan1[triangle[a].pntIndex[2]] += Tangent; + //Using edges as vectors on the plane, cross to get the normal. + Vector3 normalVector = edge1.Cross(edge2); - normal[triangle[a].pntIndex[0]] += Normal; - normal[triangle[a].pntIndex[1]] += Normal; - normal[triangle[a].pntIndex[2]] += Normal; + //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++) + { + 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; + } } - for (unsigned long a = 0; a < triangle.Size(); a++) + //Normalise the normals. + for(unsigned long i = 0; i < normals.Size(); i++) { - for (unsigned long j = 0; j < 3; j++) - { - triangle[a].nrmIndex[j] = triangle[a].pntIndex[j]; - } + normals[i].Normalize(); } +} + +//TODO: Use a function that can generate more than one normal/tangent per vertex (using angle) +void ObjLoader::CalculateTangentFrame() +{ + //Reset tangent and bitangent vectors to hold new values. + mTangents.Clear(); + mBiTangents.Clear(); + mTangents.Resize(mPoints.Size()); + mBiTangents.Resize(mPoints.Size()); - for (unsigned long a = 0; a < normal.Size(); a++) + //For each triangle, calculate the tangent vector and then add it to the total tangent vector of each point. + for(unsigned long a = 0; a < mTriangles.Size(); a++) { - normal[a].Normalize(); + Vector3 tangentVector; - const Vector3& n = normal[a]; - const Vector3& t = tan1[a]; + const Vector3& v0 = mPoints[mTriangles[a].pointIndex[0]]; + const Vector3& v1 = mPoints[mTriangles[a].pointIndex[1]]; + const Vector3& v2 = mPoints[mTriangles[a].pointIndex[2]]; - // Gram-Schmidt orthogonalize - Vector3 calc = t - n * n.Dot(t); - calc.Normalize(); - tangent[a] = Vector3(calc.x,calc.y,calc.z); + 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]]; + + 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); + + 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; } - delete[] tan1; -} + //Orthogonalize tangents and set binormals. + for(unsigned long a = 0; a < mTangents.Size(); a++) + { + const Vector3& n = mNormals[a]; + const Vector3& t = mTangents[a]; + // Gram-Schmidt orthogonalize + mTangents[a] = t - n * n.Dot(t); + mTangents[a].Normalize(); + + mBiTangents[a] = mNormals[a].Cross(mTangents[a]); + } +} void ObjLoader::CenterAndScale(bool center, Dali::Vector& points) { @@ -140,18 +195,17 @@ void ObjLoader::CenterAndScale(bool center, Dali::Vector& points) Vector3 sceneSize = GetSize(); float biggestDimension = sceneSize.x; - if( sceneSize.y > biggestDimension ) + if(sceneSize.y > biggestDimension) { biggestDimension = sceneSize.y; } - if( sceneSize.z > biggestDimension ) + if(sceneSize.z > biggestDimension) { biggestDimension = sceneSize.z; } - newAABB.Init(); - for( unsigned int ui = 0; ui < points.Size(); ++ui) + for(unsigned int ui = 0; ui < points.Size(); ++ui) { points[ui] = points[ui] - GetCenter(); points[ui] = points[ui] / biggestDimension; @@ -161,112 +215,165 @@ void ObjLoader::CenterAndScale(bool center, Dali::Vector& points) mSceneAABB = newAABB; } -void ObjLoader::CreateGeometryArray(Dali::Vector & vertices, - Dali::Vector & textures, - Dali::Vector & verticesExt, - Dali::Vector & indices) +void ObjLoader::CreateGeometryArray(Dali::Vector& vertices, + Dali::Vector& textures, + Dali::Vector& verticesExt, + Dali::Vector& indices, + bool useSoftNormals) { - //If we don't have tangents, calculate them - //we need to recalculate the normals too, because we need just one normal,tangent, bitangent per vertex - //TODO: Use a better function to calculate tangents - if( mTangents.Size() == 0 ) + //We must calculate the tangents and bitangents if they weren't supplied, or if they don't match up. + bool mustCalculateTangents = mTangents.Size() == 0 || mBiTangents.Size() == 0 || + mTangents.Size() != mBiTangents.Size() || mTangents.Size() != mNormals.Size() || + mBiTangents.Size() != mNormals.Size(); + + //However, we don't need to do this if the object doesn't use textures to begin with. + mustCalculateTangents &= mHasTexturePoints; + + //We also have to recalculate the normals if we need to calculate tangents, + // as we need just one normal, tangent and bitangent 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) { - mTangents.Resize(mNormals.Size()); - mBiTangents.Resize(mNormals.Size()); - CalculateTangentArray(mPoints, mTextures, mTriangles, mNormals, mTangents); - for (unsigned int ui = 0 ; ui < mNormals.Size() ; ++ui ) + if(useSoftNormals || mustCalculateTangents) { - mBiTangents[ui] = mNormals[ui].Cross(mTangents[ui]); + CalculateSoftFaceNormals(mPoints, mTriangles, mNormals); } + else + { + CalculateHardFaceNormals(mPoints, mTriangles, mNormals); + } + } + + //TODO: Use a better function to calculate tangents + if(mHasTexturePoints && mustCalculateTangents) + { + CalculateTangentFrame(); + } + + bool mapsCorrespond; //True if the sizes of the arrays necessary for the object agree. + + if(mHasTexturePoints) + { + mapsCorrespond = (mPoints.Size() == mTextures.Size()) && (mTextures.Size() == mNormals.Size()); + } + else + { + mapsCorrespond = (mPoints.Size() == mNormals.Size()); } //Check the number of points textures and normals - if ((mPoints.Size() == mTextures.Size()) && (mTextures.Size() == mNormals.Size())) + if(mapsCorrespond) { + int numPoints = mPoints.Size(); + int numIndices = 3 * mTriangles.Size(); + vertices.Resize(numPoints); + textures.Resize(numPoints); + verticesExt.Resize(numPoints); + indices.Resize(numIndices); + //We create the vertices array. For now we just copy points info - for (unsigned int ui = 0 ; ui < mPoints.Size() ; ++ui ) + for(unsigned int ui = 0; ui < mPoints.Size(); ++ui) { Vertex vertex; vertex.position = mPoints[ui]; - vertices.PushBack(vertex); + vertices[ui] = vertex; - textures.PushBack(Vector2()); - verticesExt.PushBack(VertexExt()); + if(mHasTexturePoints) + { + textures[ui] = Vector2(); + verticesExt[ui] = VertexExt(); + } } + int indiceIndex = 0; + //We copy the indices - for (unsigned int ui = 0 ; ui < mTriangles.Size() ; ++ui ) + for(unsigned int ui = 0; ui < mTriangles.Size(); ++ui) { - for (int j = 0 ; j < 3 ; ++j) + for(int j = 0; j < 3; ++j) { - indices.PushBack(mTriangles[ui].pntIndex[j]); - - vertices[mTriangles[ui].pntIndex[j]].normal = mNormals[mTriangles[ui].nrmIndex[j]]; + indices[indiceIndex] = mTriangles[ui].pointIndex[j]; + indiceIndex++; - textures[mTriangles[ui].pntIndex[j]] = mTextures[mTriangles[ui].texIndex[j]]; + vertices[mTriangles[ui].pointIndex[j]].normal = mNormals[mTriangles[ui].normalIndex[j]]; - verticesExt[mTriangles[ui].pntIndex[j]].tangent = mTangents[mTriangles[ui].nrmIndex[j]]; - verticesExt[mTriangles[ui].pntIndex[j]].bitangent = mBiTangents[mTriangles[ui].nrmIndex[j]]; + if(mHasTexturePoints) + { + textures[mTriangles[ui].pointIndex[j]] = mTextures[mTriangles[ui].textureIndex[j]]; + verticesExt[mTriangles[ui].pointIndex[j]].tangent = mTangents[mTriangles[ui].normalIndex[j]]; + verticesExt[mTriangles[ui].pointIndex[j]].bitangent = mBiTangents[mTriangles[ui].normalIndex[j]]; + } } } } else { + int numVertices = 3 * mTriangles.Size(); + vertices.Resize(numVertices); + textures.Resize(numVertices); + verticesExt.Resize(numVertices); + + int index = 0; + //We have to normalize the arrays so we can draw we just one index array - for (unsigned int ui = 0 ; ui < mTriangles.Size() ; ++ui ) + for(unsigned int ui = 0; ui < mTriangles.Size(); ++ui) { - for (int j = 0 ; j < 3 ; ++j) + for(int j = 0; j < 3; ++j) { Vertex vertex; - vertex.position = mPoints[mTriangles[ui].pntIndex[j]]; - vertex.normal = mNormals[mTriangles[ui].nrmIndex[j]]; - vertices.PushBack(vertex); + vertex.position = mPoints[mTriangles[ui].pointIndex[j]]; + vertex.normal = mNormals[mTriangles[ui].normalIndex[j]]; + vertices[index] = vertex; - textures.PushBack(mTextures[mTriangles[ui].texIndex[j]]); + if(mHasTexturePoints) + { + textures[index] = mTextures[mTriangles[ui].textureIndex[j]]; + VertexExt vertexExt; + vertexExt.tangent = mTangents[mTriangles[ui].normalIndex[j]]; + vertexExt.bitangent = mBiTangents[mTriangles[ui].normalIndex[j]]; + verticesExt[index] = vertexExt; + } - VertexExt vertexExt; - vertexExt.tangent = mTangents[mTriangles[ui].nrmIndex[j]]; - vertexExt.bitangent = mBiTangents[mTriangles[ui].nrmIndex[j]]; - verticesExt.PushBack(vertexExt); + index++; } } } } -bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& materialFile) +bool ObjLoader::LoadObject(char* objBuffer, std::streampos fileSize) { - Vector3 point; - Vector2 texture; - std::string vet[4], name; - int ptIdx[4]; - int nrmIdx[4]; - int texIdx[4]; - TriIndex triangle,triangle2; - int pntAcum = 0, texAcum = 0, nrmAcum = 0; - bool iniObj = false; - int face = 0; + Vector3 point; + Vector2 texture; + std::string vet[MAX_POINT_INDICES], name; + int ptIdx[MAX_POINT_INDICES]; + int nrmIdx[MAX_POINT_INDICES]; + int texIdx[MAX_POINT_INDICES]; + TriIndex triangle, triangle2; + int pntAcum = 0, texAcum = 0, nrmAcum = 0; + bool iniObj = false; + bool hasTexture = false; + int face = 0; //Init AABB for the file mSceneAABB.Init(); std::string strMatActual; - std::string input = objBuffer; + std::string input(objBuffer, fileSize); std::istringstream ss(input); ss.imbue(std::locale("C")); - std::string line; std::getline(ss, line); - while (std::getline(ss, line)) + while(std::getline(ss, line)) { std::istringstream isline(line, std::istringstream::in); - std::string tag; + std::string tag; isline >> tag; - if (tag == "v") + if(tag == "v") { //Two different objects in the same file isline >> point.x; @@ -276,7 +383,7 @@ bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& mate mSceneAABB.ConsiderNewPointInVolume(point); } - else if (tag == "vn") + else if(tag == "vn") { isline >> point.x; isline >> point.y; @@ -284,7 +391,7 @@ bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& mate mNormals.PushBack(point); } - else if (tag == "#_#tangent") + else if(tag == "#_#tangent") { isline >> point.x; isline >> point.y; @@ -292,7 +399,7 @@ bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& mate mTangents.PushBack(point); } - else if (tag == "#_#binormal") + else if(tag == "#_#binormal") { isline >> point.x; isline >> point.y; @@ -300,28 +407,28 @@ bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& mate mBiTangents.PushBack(point); } - else if (tag == "vt") + else if(tag == "vt") { isline >> texture.x; isline >> texture.y; - texture.y = 1.0-texture.y; + texture.y = 1.0 - texture.y; mTextures.PushBack(texture); } - else if (tag == "#_#vt1") + else if(tag == "#_#vt1") { isline >> texture.x; isline >> texture.y; - texture.y = 1.0-texture.y; + texture.y = 1.0 - texture.y; mTextures2.PushBack(texture); } - else if (tag == "s") + else if(tag == "s") { } - else if (tag == "f") + else if(tag == "f") { - if (!iniObj) + if(!iniObj) { //name assign @@ -329,34 +436,55 @@ bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& mate } int numIndices = 0; - while( isline >> vet[numIndices] ) + while((numIndices < MAX_POINT_INDICES) && (isline >> vet[numIndices])) { numIndices++; } + //Hold slashes that separate attributes of the same point. char separator; char separator2; - //File could not have texture Coordinates - if (strstr(vet[0].c_str(),"//")) + + const char* subString; //A pointer to the position in the string as we move through it. + + subString = strstr(vet[0].c_str(), "/"); //Search for the first '/' + + if(subString) { - for( int i = 0 ; i < numIndices; i++) + if(subString[1] == '/') // Of the form A//C, so has points and normals but no texture coordinates. { - std::istringstream isindex(vet[i]); - isindex >> ptIdx[i] >> separator >> nrmIdx[i]; - texIdx[i] = 0; + for(int i = 0; i < numIndices; i++) + { + std::istringstream isindex(vet[i]); + isindex >> ptIdx[i] >> separator >> separator2 >> nrmIdx[i]; + texIdx[i] = 0; + } } - } - else if (strstr(vet[0].c_str(),"/")) - { - for( int i = 0 ; i < numIndices; i++) + else if(strstr(subString, "/")) // Of the form A/B/C, so has points, textures and normals. { - std::istringstream isindex(vet[i]); - isindex >> ptIdx[i] >> separator >> texIdx[i] >> separator2 >> nrmIdx[i]; + for(int i = 0; i < numIndices; i++) + { + std::istringstream isindex(vet[i]); + isindex >> ptIdx[i] >> separator >> texIdx[i] >> separator2 >> nrmIdx[i]; + } + + hasTexture = true; + } + else // Of the form A/B, so has points and textures but no normals. + { + for(int i = 0; i < numIndices; i++) + { + std::istringstream isindex(vet[i]); + isindex >> ptIdx[i] >> separator >> texIdx[i]; + nrmIdx[i] = 0; + } + + hasTexture = true; } } - else + else // Simply of the form A, as in, point indices only. { - for( int i = 0 ; i < numIndices; i++) + for(int i = 0; i < numIndices; i++) { std::istringstream isindex(vet[i]); isindex >> ptIdx[i]; @@ -366,194 +494,178 @@ bool ObjLoader::Load(char* objBuffer, std::streampos fileSize, std::string& mate } //If it is a triangle - if( numIndices == 3 ) + if(numIndices == 3) { - for( int i = 0 ; i < 3; i++) + for(int i = 0; i < 3; i++) { - triangle.pntIndex[i] = ptIdx[i] - 1 - pntAcum; - triangle.nrmIndex[i] = nrmIdx[i] - 1 - nrmAcum; - triangle.texIndex[i] = texIdx[i] - 1 - texAcum; + triangle.pointIndex[i] = ptIdx[i] - 1 - pntAcum; + triangle.normalIndex[i] = nrmIdx[i] - 1 - nrmAcum; + triangle.textureIndex[i] = texIdx[i] - 1 - texAcum; } mTriangles.PushBack(triangle); face++; } //If on the other hand it is a quad, we will create two triangles - else if( numIndices == 4 ) + else if(numIndices == 4) { - for( int i = 0 ; i < 3; i++) + for(int i = 0; i < 3; i++) { - triangle.pntIndex[i] = ptIdx[i] - 1 - pntAcum; - triangle.nrmIndex[i] = nrmIdx[i] - 1 - nrmAcum; - triangle.texIndex[i] = texIdx[i] - 1 - texAcum; + triangle.pointIndex[i] = ptIdx[i] - 1 - pntAcum; + triangle.normalIndex[i] = nrmIdx[i] - 1 - nrmAcum; + triangle.textureIndex[i] = texIdx[i] - 1 - texAcum; } mTriangles.PushBack(triangle); face++; - for( int i = 0 ; i < 3; i++) + for(int i = 0; i < 3; i++) { - int idx = (i+2) % numIndices; - triangle2.pntIndex[i] = ptIdx[idx] - 1 - pntAcum; - triangle2.nrmIndex[i] = nrmIdx[idx] - 1 - nrmAcum; - triangle2.texIndex[i] = texIdx[idx] - 1 - texAcum; + int idx = (i + 2) % numIndices; + triangle2.pointIndex[i] = ptIdx[idx] - 1 - pntAcum; + triangle2.normalIndex[i] = nrmIdx[idx] - 1 - nrmAcum; + triangle2.textureIndex[i] = texIdx[idx] - 1 - texAcum; } mTriangles.PushBack(triangle2); face++; } } - else if (tag == "usemtl") + else if(tag == "usemtl") { isline >> strMatActual; } - else if (tag == "mtllib") + else if(tag == "mtllib") { isline >> strMatActual; } - else if (tag == "g") + else if(tag == "g") { isline >> name; } - else - { - } } - if (iniObj) + if(iniObj) { - pntAcum += (int)mPoints.Size(); - texAcum += (int)mTextures.Size(); - nrmAcum += (int)mNormals.Size(); - CenterAndScale(true, mPoints); - - face = 0; - - mSceneLoaded = true; - + mSceneLoaded = true; + mHasTexturePoints = hasTexture; return true; } return false; - } -void ObjLoader::LoadMaterial(char* objBuffer, std::streampos fileSize, std::string& texture0Url, std::string& texture1Url, std::string& texture2Url) +void ObjLoader::LoadMaterial(char* objBuffer, std::streampos fileSize, std::string& diffuseTextureUrl, std::string& normalTextureUrl, std::string& glossTextureUrl) { - float fR,fG,fB; + float fR, fG, fB; std::string info; - std::string input = objBuffer; + std::string input(objBuffer, fileSize); std::istringstream ss(input); ss.imbue(std::locale("C")); std::string line; std::getline(ss, line); - while (std::getline(ss, line)) + while(std::getline(ss, line)) { std::istringstream isline(line, std::istringstream::in); - std::string tag; + std::string tag; isline >> tag; - if (tag == "newmtl") //name of the material + if(tag == "newmtl") //name of the material { isline >> info; } - else if (tag == "Kd") //diffuse color + else if(tag == "Ka") //ambient color + { + isline >> fR >> fG >> fB; + } + else if(tag == "Kd") //diffuse color { isline >> fR >> fG >> fB; } - else if (tag == "Kd") //Ambient color + else if(tag == "Ks") //specular color { isline >> fR >> fG >> fB; } - else if (tag == "Tf") //color + else if(tag == "Tf") //color { } - else if (tag == "Ni") + else if(tag == "Ni") { } - else if (tag == "map_Kd") + else if(tag == "map_Kd") { isline >> info; - texture0Url = info; + diffuseTextureUrl = info; + mHasDiffuseMap = true; } - else if (tag == "bump") + else if(tag == "bump") { isline >> info; - texture1Url = info; + normalTextureUrl = info; + mHasNormalMap = true; } - else if (tag == "map_Ks") + else if(tag == "map_Ks") { isline >> info; - texture2Url = info; + glossTextureUrl = info; + mHasSpecularMap = true; } } mMaterialLoaded = true; } -Geometry ObjLoader::CreateGeometry(Toolkit::Model3dView::IlluminationType illuminationType) +Geometry ObjLoader::CreateGeometry(int objectProperties, bool useSoftNormals) { - Dali::Vector vertices; - Dali::Vector textures; - Dali::Vector verticesExt; - Dali::Vector indices; + Geometry surface = Geometry::New(); - CreateGeometryArray(vertices, textures, verticesExt, indices); + Dali::Vector vertices; + Dali::Vector textures; + Dali::Vector verticesExt; + Dali::Vector indices; + + CreateGeometryArray(vertices, textures, verticesExt, indices, useSoftNormals); //All vertices need at least Position and Normal Property::Map vertexFormat; - vertexFormat["aPosition"] = Property::VECTOR3; - vertexFormat["aNormal"] = Property::VECTOR3; - PropertyBuffer surfaceVertices = PropertyBuffer::New( vertexFormat, vertices.Size() ); - surfaceVertices.SetData( &vertices[0] ); - - Geometry surface = Geometry::New(); - surface.AddVertexBuffer( surfaceVertices ); + vertexFormat["aPosition"] = Property::VECTOR3; + vertexFormat["aNormal"] = Property::VECTOR3; + VertexBuffer surfaceVertices = VertexBuffer::New(vertexFormat); + surfaceVertices.SetData(&vertices[0], vertices.Size()); + surface.AddVertexBuffer(surfaceVertices); //Some need texture coordinates - if( (illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP ) || (illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_TEXTURE ) ) + if((objectProperties & TEXTURE_COORDINATES) && mHasTexturePoints && mHasDiffuseMap) { Property::Map textureFormat; textureFormat["aTexCoord"] = Property::VECTOR2; - PropertyBuffer extraVertices = PropertyBuffer::New( textureFormat, textures.Size() ); - extraVertices.SetData( &textures[0] ); + VertexBuffer extraVertices = VertexBuffer::New(textureFormat); + extraVertices.SetData(&textures[0], textures.Size()); - surface.AddVertexBuffer( extraVertices ); + surface.AddVertexBuffer(extraVertices); } //Some need tangent and bitangent - if( illuminationType == Toolkit::Model3dView::DIFFUSE_WITH_NORMAL_MAP ) + if((objectProperties & TANGENTS) && (objectProperties & BINORMALS) && mHasTexturePoints) { Property::Map vertexExtFormat; - vertexExtFormat["aTangent"] = Property::VECTOR3; + vertexExtFormat["aTangent"] = Property::VECTOR3; vertexExtFormat["aBiNormal"] = Property::VECTOR3; - PropertyBuffer extraVertices = PropertyBuffer::New( vertexExtFormat, verticesExt.Size() ); - extraVertices.SetData( &verticesExt[0] ); + VertexBuffer extraVertices = VertexBuffer::New(vertexExtFormat); + extraVertices.SetData(&verticesExt[0], verticesExt.Size()); - surface.AddVertexBuffer( extraVertices ); + surface.AddVertexBuffer(extraVertices); } - if (indices.Size()) + //If indices are required, we set them. + if(indices.Size()) { - //Indices - Property::Map indicesVertexFormat; - indicesVertexFormat["aIndices"] = Property::INTEGER; - PropertyBuffer indicesToVertices = PropertyBuffer::New( indicesVertexFormat, indices.Size() ); - indicesToVertices.SetData(&indices[0]); - - surface.SetIndexBuffer ( indicesToVertices ); + surface.SetIndexBuffer(&indices[0], indices.Size()); } - surface.SetRequiresDepthTesting(true); - //surface.SetProperty(Geometry::Property::GEOMETRY_HALF_EXTENTS, GetSize() * 0.5); - - vertices.Clear(); - verticesExt.Clear(); - indices.Clear(); - return surface; } @@ -582,6 +694,26 @@ void ObjLoader::ClearArrays() mSceneLoaded = false; } +bool ObjLoader::IsTexturePresent() +{ + return mHasTexturePoints; +} + +bool ObjLoader::IsDiffuseMapPresent() +{ + return mHasDiffuseMap; +} + +bool ObjLoader::IsNormalMapPresent() +{ + return mHasNormalMap; +} + +bool ObjLoader::IsSpecularMapPresent() +{ + return mHasSpecularMap; +} + } // namespace Internal } // namespace Toolkit } // namespace Dali