1 /* 2 Copyright (c) 2008-2009 NetAllied Systems GmbH 3 4 This file is part of COLLADAMax. 5 6 Portions of the code are: 7 Copyright (c) 2005-2007 Feeling Software Inc. 8 Copyright (c) 2005-2007 Sony Computer Entertainment America 9 10 Based on the 3dsMax COLLADASW Tools: 11 Copyright (c) 2005-2006 Autodesk Media Entertainment 12 13 Licensed under the MIT Open Source License, 14 for details please see LICENSE file or the website 15 http://www.opensource.org/licenses/mit-license.php 16 */ 17 18 #include "COLLADAMaxStableHeaders.h" 19 #include "COLLADAMaxTexTangentCalculator.h" 20 21 22 23 namespace COLLADAMax 24 { 25 TexTangentCalculator(IMeshAccess * mesh)26 TexTangentCalculator::TexTangentCalculator( IMeshAccess* mesh ) 27 : mMesh(mesh) 28 , mTexTangentsCount(0) 29 { 30 } 31 32 //------------------------------ ~TexTangentCalculator()33 TexTangentCalculator::~TexTangentCalculator() 34 { 35 deleteTexTangentInfo(); 36 } 37 38 computeTangent(Vector3 textureVertex[3],Vector3 geometryVertex[3],Vector3 & texTangent)39 void TexTangentCalculator::computeTangent( Vector3 textureVertex[3], Vector3 geometryVertex[3], Vector3& texTangent ) 40 { 41 const Vector3& w1 = textureVertex[0]; 42 const Vector3& w2 = textureVertex[1]; 43 const Vector3& w3 = textureVertex[2]; 44 45 const Vector3& v1 = geometryVertex[0]; 46 const Vector3& v2 = geometryVertex[1]; 47 const Vector3& v3 = geometryVertex[2]; 48 49 Real x1 = v2.x - v1.x; 50 Real x2 = v3.x - v1.x; 51 Real y1 = v2.y - v1.y; 52 Real y2 = v3.y - v1.y; 53 Real z1 = v2.z - v1.z; 54 Real z2 = v3.z - v1.z; 55 56 Real s1 = w2.x - w1.x; 57 Real s2 = w3.x - w1.x; 58 Real t1 = w2.y - w1.y; 59 Real t2 = w3.y - w1.y; 60 61 Real determinant = s1 * t2 - s2 * t1; 62 63 if( !COLLADABU::Math::Utils::equalsZero( determinant ) ) 64 { 65 Real r = (Real)1.0 / determinant; 66 texTangent.set( (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); 67 // tDir.set( (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); 68 } 69 else 70 { 71 texTangent.set( x1, y1, z1 ); 72 } 73 74 texTangent.normalise(); 75 } 76 77 78 79 //--------------------------------------------------------------- calculateTriangleMeshTextangents()80 void TexTangentCalculator::calculateTriangleMeshTextangents() 81 { 82 mTexTangents.clear(); 83 84 //Mesh mesh = mTriObject->GetMesh(); 85 86 int numFaces = mMesh->getFaceCount(); 87 88 mIndices.reserve( numFaces * 3 ); 89 90 Vector3 geometryVertex[3]; 91 Vector3 textureVertex[3]; 92 Vector3 normalVertex[3]; 93 Vector3 texTangent[3]; 94 Vector3 computetTexTangent; 95 /* Vector3 basisVectors[2]; 96 Vector3 basisVectors2[2]; 97 */ 98 99 // MeshMap& meshMap = mTriObject->GetMesh().Map ( channelIndex ); 100 101 // TVFace* mapFaces = meshMap.tf; 102 // UVVert* mapVerts = meshMap.tv; 103 104 105 for ( int i = 0; i < numFaces; ++i) 106 { 107 /* Face& geomFace = mesh.faces[i]; 108 int index1 = geomFace.v[0]; 109 int index2 = geomFace.v[1]; 110 int index3 = geomFace.v[2]; 111 */ 112 int vertexIndex1 = mMesh->getPositionIndex(i, 0); 113 int vertexIndex2 = mMesh->getPositionIndex(i, 1); 114 int vertexIndex3 = mMesh->getPositionIndex(i, 2); 115 116 geometryVertex[0] = mMesh->getVertex(vertexIndex1); 117 geometryVertex[1] = mMesh->getVertex(vertexIndex2); 118 geometryVertex[2] = mMesh->getVertex(vertexIndex3); 119 120 /* TVFace& mapFace = mapFaces[i]; 121 textureVertex[0] = mapVerts[ mapFace.t[0] ]; 122 textureVertex[1] = mapVerts[ mapFace.t[1] ]; 123 textureVertex[2] = mapVerts[ mapFace.t[2] ]; 124 */ 125 int textureIndex1 = mMesh->getTexcoordIndex(i, 0); 126 int textureIndex2 = mMesh->getTexcoordIndex(i, 1); 127 int textureIndex3 = mMesh->getTexcoordIndex(i, 2); 128 129 textureVertex[0] = mMesh->getTexcoord( textureIndex1 ); 130 textureVertex[1] = mMesh->getTexcoord( textureIndex2 ); 131 textureVertex[2] = mMesh->getTexcoord( textureIndex3 ); 132 133 computeTangent( textureVertex, geometryVertex, computetTexTangent ); 134 135 /* Point3 mapNormal = FNormalize( (textureVertex[1] - textureVertex[0]) ^ (textureVertex[2] - textureVertex[1]) ); 136 if( mapNormal.z<0 ) 137 { 138 basisVectors[1] = -basisVectors[1]; //is the UV face flipped? flip the binormal 139 } 140 */ 141 142 int normalIndex1 = mMesh->getNormalIndex(i, 0); 143 int normalIndex2 = mMesh->getNormalIndex(i, 1); 144 int normalIndex3 = mMesh->getNormalIndex(i, 2); 145 146 normalVertex[0] = mMesh->getNormal( normalIndex1 ); 147 normalVertex[1] = mMesh->getNormal( normalIndex2 ); 148 normalVertex[2] = mMesh->getNormal( normalIndex3 ); 149 150 texTangent[0] = computetTexTangent - normalVertex[0] * (normalVertex[0].dotProduct(computetTexTangent)); 151 texTangent[1] = computetTexTangent - normalVertex[1] * (normalVertex[1].dotProduct(computetTexTangent)); 152 texTangent[2] = computetTexTangent - normalVertex[2] * (normalVertex[2].dotProduct(computetTexTangent)); 153 154 mIndices.push_back(addTexTangent( vertexIndex1, normalIndex1, textureIndex1, texTangent[0] )); 155 mIndices.push_back(addTexTangent( vertexIndex2, normalIndex2, textureIndex2, texTangent[1] )); 156 mIndices.push_back(addTexTangent( vertexIndex3, normalIndex3, textureIndex3, texTangent[2] )); 157 158 } 159 160 normalizeTangentsAndCalculateBiTangents(); 161 } 162 163 //--------------------------------------------------------------- addTexTangent(int vertexIndex,int normalIndex,int textureIndex,const Vector3 & texTangent)164 unsigned long TexTangentCalculator::addTexTangent( int vertexIndex, int normalIndex, int textureIndex, const Vector3& texTangent ) 165 { 166 VertexIdentifier vertexIdentifier; 167 vertexIdentifier.positionIndex = vertexIndex; 168 vertexIdentifier.normalIndex = normalIndex; 169 vertexIdentifier.textureIndex = textureIndex; 170 VertexIdentifierVertexTexTangentInfoMap::iterator it = mVertexIdentifierVertexTexTangentInfoMap.find(vertexIdentifier); 171 if ( it == mVertexIdentifierVertexTexTangentInfoMap.end() ) 172 { 173 VertexTexTangentInfo* vertexTexTangentInfo = new VertexTexTangentInfo; 174 vertexTexTangentInfo->tangent = texTangent; 175 vertexTexTangentInfo->count = 1; 176 vertexTexTangentInfo->index = mTexTangentsCount++; 177 mTexTangents.push_back(vertexTexTangentInfo); 178 mVertexIdentifierVertexTexTangentInfoMap.insert(std::make_pair(vertexIdentifier, vertexTexTangentInfo)); 179 return vertexTexTangentInfo->index; 180 } 181 else 182 { 183 VertexTexTangentInfo& vertexTexTangentInfo = *it->second; 184 vertexTexTangentInfo.tangent += texTangent; 185 vertexTexTangentInfo.count++; 186 return vertexTexTangentInfo.index; 187 } 188 } 189 190 //--------------------------------------------------------------- normalizeTangentsAndCalculateBiTangents()191 void TexTangentCalculator::normalizeTangentsAndCalculateBiTangents() 192 { 193 VertexIdentifierVertexTexTangentInfoMap::iterator it = mVertexIdentifierVertexTexTangentInfoMap.begin(); 194 VertexIdentifierVertexTexTangentInfoMap::iterator endIt = mVertexIdentifierVertexTexTangentInfoMap.end(); 195 for ( ; it != endIt; ++it) 196 { 197 VertexTexTangentInfo& vertexTexTangentInfo = *it->second; 198 vertexTexTangentInfo.tangent = vertexTexTangentInfo.tangent / (Real)(vertexTexTangentInfo.count); 199 200 const VertexIdentifier& vertexIdentifier = it->first; 201 Vector3 normal = mMesh->getNormal( vertexIdentifier.normalIndex ); 202 203 vertexTexTangentInfo.biTangent = vertexTexTangentInfo.tangent.crossProduct( normal ); 204 vertexTexTangentInfo.biTangent.normalise(); 205 } 206 } 207 208 //--------------------------------------------------------------- clearTexTangentData()209 void TexTangentCalculator::clearTexTangentData() 210 { 211 mTexTangents.clear(); 212 deleteTexTangentInfo(); 213 mVertexIdentifierVertexTexTangentInfoMap.clear(); 214 } 215 216 //--------------------------------------------------------------- deleteTexTangentInfo()217 void TexTangentCalculator::deleteTexTangentInfo() 218 { 219 VertexIdentifierVertexTexTangentInfoMap::iterator it = mVertexIdentifierVertexTexTangentInfoMap.begin(); 220 VertexIdentifierVertexTexTangentInfoMap::iterator endIt = mVertexIdentifierVertexTexTangentInfoMap.end(); 221 for ( ; it != endIt; ++it) 222 { 223 delete it->second; 224 } 225 } 226 227 //--------------------------------------------------------------- operator <(const VertexIdentifier & rhs) const228 bool TexTangentCalculator::VertexIdentifier::operator<( const VertexIdentifier& rhs ) const 229 { 230 if ( positionIndex < rhs.positionIndex ) 231 return true; 232 233 if ( positionIndex > rhs.positionIndex ) 234 return false; 235 236 if ( normalIndex < rhs.normalIndex ) 237 return true; 238 239 if ( normalIndex > rhs.normalIndex ) 240 return false; 241 242 if ( textureIndex < rhs.textureIndex ) 243 return true; 244 245 if ( textureIndex > rhs.textureIndex ) 246 return false; 247 248 return false; 249 } 250 251 } // namespace COLLADAMax 252