appMesh.cpp
Engine/source/ts/loader/appMesh.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "ts/loader/appMesh.h" 25#include "ts/loader/tsShapeLoader.h" 26 27Vector<AppMaterial*> AppMesh::appMaterials; 28 29AppMesh::AppMesh() 30 : flags(0), vertsPerFrame(0),numFrames(0), numMatFrames(0), detailSize(1) 31{ 32} 33 34AppMesh::~AppMesh() 35{ 36} 37 38void AppMesh::computeBounds(Box3F& bounds) 39{ 40 bounds = Box3F::Invalid; 41 42 if ( isSkin() ) 43 { 44 // Need to skin the mesh before we can compute the bounds 45 46 // Setup bone transforms 47 Vector<MatrixF> boneTransforms; 48 boneTransforms.setSize( nodeIndex.size() ); 49 for (S32 iBone = 0; iBone < boneTransforms.size(); iBone++) 50 { 51 MatrixF nodeMat = bones[iBone]->getNodeTransform( TSShapeLoader::DefaultTime ); 52 TSShapeLoader::zapScale(nodeMat); 53 boneTransforms[iBone].mul( nodeMat, initialTransforms[iBone] ); 54 } 55 56 // Multiply verts by weighted bone transforms 57 for (S32 iVert = 0; iVert < initialVerts.size(); iVert++) 58 points[iVert].set( Point3F::Zero ); 59 60 for (S32 iWeight = 0; iWeight < vertexIndex.size(); iWeight++) 61 { 62 const S32& vertIndex = vertexIndex[iWeight]; 63 const MatrixF& deltaTransform = boneTransforms[ boneIndex[iWeight] ]; 64 65 Point3F v; 66 deltaTransform.mulP( initialVerts[vertIndex], &v ); 67 v *= weight[iWeight]; 68 69 points[vertIndex] += v; 70 } 71 72 // compute bounds for the skinned mesh 73 for (S32 iVert = 0; iVert < initialVerts.size(); iVert++) 74 bounds.extend( points[iVert] ); 75 } 76 else 77 { 78 MatrixF transform = getMeshTransform(TSShapeLoader::DefaultTime); 79 TSShapeLoader::zapScale(transform); 80 81 for (S32 iVert = 0; iVert < points.size(); iVert++) 82 { 83 Point3F p; 84 transform.mulP(points[iVert], &p); 85 bounds.extend(p); 86 } 87 } 88} 89 90void AppMesh::computeNormals() 91{ 92 // Clear normals 93 normals.setSize( points.size() ); 94 for (S32 iNorm = 0; iNorm < normals.size(); iNorm++) 95 normals[iNorm] = Point3F::Zero; 96 97 // Sum triangle normals for each vertex 98 for (S32 iPrim = 0; iPrim < primitives.size(); iPrim++) 99 { 100 const TSDrawPrimitive& prim = primitives[iPrim]; 101 102 for (S32 iInd = 0; iInd < prim.numElements; iInd += 3) 103 { 104 // Compute the normal for this triangle 105 S32 idx0 = indices[prim.start + iInd + 0]; 106 S32 idx1 = indices[prim.start + iInd + 1]; 107 S32 idx2 = indices[prim.start + iInd + 2]; 108 109 const Point3F& v0 = points[idx0]; 110 const Point3F& v1 = points[idx1]; 111 const Point3F& v2 = points[idx2]; 112 113 Point3F n; 114 mCross(v2 - v0, v1 - v0, &n); 115 n.normalize(); // remove this to use 'weighted' normals (large triangles will have more effect) 116 117 normals[idx0] += n; 118 normals[idx1] += n; 119 normals[idx2] += n; 120 } 121 } 122 123 // Normalize the vertex normals (this takes care of averaging the triangle normals) 124 for (S32 iNorm = 0; iNorm < normals.size(); iNorm++) 125 normals[iNorm].normalize(); 126} 127 128TSMesh* AppMesh::constructTSMesh() 129{ 130 TSMesh* tsmesh; 131 if (isSkin()) 132 { 133 TSSkinMesh* tsskin = new TSSkinMesh(); 134 tsmesh = tsskin; 135 136 // Copy skin elements 137 tsskin->weight = weight; 138 tsskin->boneIndex = boneIndex; 139 tsskin->vertexIndex = vertexIndex; 140 tsskin->batchData.nodeIndex = nodeIndex; 141 tsskin->batchData.initialTransforms = initialTransforms; 142 tsskin->batchData.initialVerts = initialVerts; 143 tsskin->batchData.initialNorms = initialNorms; 144 } 145 else 146 { 147 tsmesh = new TSMesh(); 148 } 149 150 // Copy mesh elements 151 tsmesh->mVerts = points; 152 tsmesh->mNorms = normals; 153 tsmesh->mTverts = uvs; 154 tsmesh->mPrimitives = primitives; 155 tsmesh->mIndices = indices; 156 tsmesh->mColors = colors; 157 tsmesh->mTverts2 = uv2s; 158 159 // Finish initializing the shape 160 tsmesh->setFlags(flags); 161 tsmesh->updateMeshFlags(); 162 tsmesh->computeBounds(); 163 tsmesh->numFrames = numFrames; 164 tsmesh->numMatFrames = numMatFrames; 165 tsmesh->vertsPerFrame = vertsPerFrame; 166 tsmesh->createTangents(tsmesh->mVerts, tsmesh->mNorms); 167 tsmesh->mEncodedNorms.set(NULL,0); 168 169 return tsmesh; 170} 171 172bool AppMesh::isBillboard() 173{ 174 return !dStrnicmp(getName(),"BB::",4) || !dStrnicmp(getName(),"BB_",3) || isBillboardZAxis(); 175} 176 177bool AppMesh::isBillboardZAxis() 178{ 179 return !dStrnicmp(getName(),"BBZ::",5) || !dStrnicmp(getName(),"BBZ_",4); 180} 181