00001 #ifndef _NVMeshMender_H_ 00002 #define _NVMeshMender_H_ 00003 00004 /*********************************************************************NVMH2**** 00005 Copyright (C) 1999, 2000, 2001, 2002 NVIDIA Corporation 00006 This file is provided without support, instruction, or implied warranty of any 00007 kind. NVIDIA makes no guarantee of its fitness for a particular purpose and is 00008 not liable under any circumstances for any damages or loss whatsoever arising 00009 from the use or inability to use this file or items derived from it. 00010 00011 Questions to sim.dietrich@nvidia.com 00012 00013 Comments: 00014 00015 This tool is designed to help condition meshes for use in vertex & pixel shaders. 00016 00017 It can generate normals, texture coordinates, and perhaps most importantly, texture space 00018 basis matrices. It also can fix common texuring problems that come up when bump mapping, including 00019 00020 Texture Mirroring - When two one halves of a character use the same part of a texture. 00021 00022 Cylindrical TexGen - When the rendering relies on cylindrical wrapping, texture space computation 00023 won't work right. 00024 00025 Stretched Basis - When two adjacend faces use wildly different texture mappings, causing stretching 00026 that can ruin per-pixel lighting. 00027 00028 00029 Here is an example usage scenario : 00030 00031 Say you have positions & indices & normals, and want textures, and tangents, and binormals. 00032 and assume that positions, indices, and normals are in STL arrays: vpos, triIndices and vnor respectively. 00033 00034 std::vector<float> vpos; 00035 std::vector<int> triIndices; 00036 std::vector<float> vnor; 00037 ... 00038 00039 NVMeshMender aMender; 00040 00041 00042 std::vector<NVMeshMender::VertexAttribute> inputAtts; // What you have 00043 std::vector<NVMeshMender::VertexAttribute> outputAtts; // What you want. 00044 00045 NVMeshMender::VertexAttribute posAtt; 00046 posAtt.Name_ = "position"; 00047 posAtt.floatVector_ = vpos; 00048 00049 NVMeshMender::VertexAttribute triIndAtt; 00050 triIndAtt.Name_ = "indices"; 00051 triIndAtt.intVector_ = triIndices; 00052 00053 NVMeshMender::VertexAttribute norAtt; 00054 norAtt.Name_ = "normal"; 00055 norAtt.floatVector_ = vnor; 00056 00057 std::vector<float> texCoords; 00058 NVMeshMender::VertexAttribute texCoordAtt; 00059 texCoordAtt.Name_ = "tex0"; 00060 texCoordAtt.floatVector_;// = texCoords; 00061 00062 NVMeshMender::VertexAttribute tgtSpaceAtt; 00063 tgtSpaceAtt.Name_ = "tangent"; 00064 00065 NVMeshMender::VertexAttribute binormalAtt; 00066 binormalAtt.Name_ = "binormal"; 00067 00068 inputAtts.push_back(posAtt); 00069 inputAtts.push_back(triIndAtt); 00070 inputAtts.push_back(norAtt); 00071 00072 outputAtts.push_back(posAtt); 00073 outputAtts.push_back(triIndAtt); 00074 outputAtts.push_back(norAtt); 00075 outputAtts.push_back(texCoordAtt); 00076 outputAtts.push_back(tgtSpaceAtt); 00077 outputAtts.push_back(binormalAtt); 00078 00079 // All inputs except for indices are assumed to be sets of 3 floats 00080 00081 // "indices" are assumed to be unsigned ints 00082 00083 // "tex0" is used for the tangent space calculation 00084 00085 // "tex0" is the only coordinate set generated, and the texture matrix applies only to it 00086 00087 // All unknown attribute types, including "tex1", "tex2", "random_attribute", "weights", "bones", etc. 00088 // are simply passed through. They will be duplicated as needed just like positions, normals, etc. 00089 00090 bool bSuccess = aMender.Munge( inputAtts, // these are my positions & indices 00091 outputAtts, // these are the outputs I requested, plus extra stuff generated on my behalf 00092 3.141592654f / 2.5f, // tangent space smooth angle 00093 NULL, // no Texture matrix applied to my tex0 coords 00094 FixTangents, // fix degenerate bases & texture mirroring 00095 FixCylindricalTexGen // handle cylidrically mapped textures via vertex duplication 00096 WeightNormalsByFaceSize // weight vertex normals by the triangle's size 00097 ); 00098 00099 00100 if ( !bSuccess ) return false; 00101 00102 vpos = outputAtts[0].floatVector_; // Note that there may be more vertices than you sent in. 00103 vnor = outputAtts[2].floatVector_; 00104 std::vector<float> texCoords = outputAtts[3].floatVector_; // texcoords 00105 std::vector<float> vtgt = outputAtts[4].floatVector_; // tgts 00106 triIndices = outputAtts[1].intVector_; // new indices. 00107 std::vector<float> vbin = outputAtts[5].floatVector_; // binormals. 00108 00109 // Now the outputAtts may contain more vertex then you sent in ! 00110 // This is because in handling tangent space smoothing, and solving texture mirroring & 00111 // cylindrical texture wrapping problems, we partially duplicate vertices. 00112 00113 // All attributes are duplicated, even unknowns. 00114 00115 // You may also get things you didn't ask for. For instance, if you ask for tangent space, 00116 // in other words, you ask for "tangent" or "binormal", you will get "normal", "tex0", 00117 // "tangent" and "binormal". You can then ignore things in the output vector that you don't want. 00118 00119 // If you ask for FixCylindricalTexGen, it will fix any absolute change in texture coordinates > 0.5 00120 // across a single edge. Therefore, if you pass in a single quad or cube, it won't work. Any more 00121 // complicated or tessellated mesh should work fine. 00122 00123 00124 ******************************************************************************/ 00125 00126 #include <vector> 00127 #include <string> 00128 00129 00130 00131 00132 class NVMeshMender 00133 { 00134 private : 00135 00136 mutable std::vector< std::string > LastErrors_; 00137 00138 00139 struct Edge 00140 { 00141 unsigned int v0; 00142 unsigned int v1; 00143 00144 unsigned int face; 00145 unsigned int face2; 00146 00147 bool operator==( const Edge& rhs ) const 00148 { 00149 return ( ( v0 == rhs.v0 ) && ( v1 == rhs.v1 ) ); 00150 } 00151 00152 bool operator<( const Edge& rhs ) const 00153 { 00154 if ( v0 < rhs.v0 ) 00155 { 00156 return true; 00157 } 00158 00159 if ( v0 > rhs.v0 ) 00160 { 00161 return false; 00162 } 00163 00164 return ( v1 < rhs.v1 ); 00165 } 00166 }; 00167 00168 public : 00169 00170 void SetLastError( const std::string& rhs ) const 00171 { 00172 LastErrors_.push_back( rhs ); 00173 } 00174 00175 std::string GetLastError() const 00176 { 00177 std::string aString; 00178 00179 if ( LastErrors_.size() > 0 ) 00180 { 00181 aString = LastErrors_.back(); 00182 } 00183 return aString; 00184 } 00185 00186 struct VertexAttribute 00187 { 00188 std::string Name_; 00189 00190 typedef std::vector< int > IntVector; 00191 IntVector intVector_; 00192 00193 00194 typedef std::vector< float > FloatVector; 00195 FloatVector floatVector_; 00196 00197 VertexAttribute& operator=( const VertexAttribute& rhs ) 00198 { 00199 Name_ = rhs.Name_; 00200 intVector_ = rhs.intVector_; 00201 floatVector_ = rhs.floatVector_; 00202 return *this; 00203 } 00204 00205 VertexAttribute( const char* pName = "" ) : Name_(pName) {;} 00206 00207 VertexAttribute( const VertexAttribute& rhs ) 00208 { 00209 *this = rhs; 00210 } 00211 00212 bool operator==( const VertexAttribute& rhs ) 00213 { 00214 return ( Name_ == rhs.Name_ ); 00215 } 00216 00217 bool operator<( const VertexAttribute& rhs ) 00218 { 00219 return ( Name_ < rhs.Name_ ); 00220 } 00221 00222 }; 00223 00224 typedef std::vector< VertexAttribute > VAVector; 00225 00226 enum Option 00227 { 00228 FixTangents, 00229 DontFixTangents, 00230 00231 FixCylindricalTexGen, 00232 DontFixCylindricalTexGen, 00233 00234 WeightNormalsByFaceSize, 00235 DontWeightNormalsByFaceSize 00236 }; 00237 00238 bool NVMeshMender::Munge( const NVMeshMender::VAVector& input, 00239 NVMeshMender::VAVector& output, 00240 const float bSmoothCreaseAngleRadians = 3.141592654f / 3.0f, 00241 const float* pTextureMatrix = 0, 00242 const Option _FixTangents = FixTangents, 00243 const Option _FixCylindricalTexGen = FixCylindricalTexGen, 00244 const Option _WeightNormalsByFaceSize = WeightNormalsByFaceSize 00245 ); 00246 bool NVMeshMender::MungeD3DX( const NVMeshMender::VAVector& input, 00247 NVMeshMender::VAVector& output, 00248 const float bSmoothCreaseAngleRadians = 3.141592654f / 3.0f, 00249 const float* pTextureMatrix = 0, 00250 const Option _FixTangents = FixTangents, 00251 const Option _FixCylindricalTexGen = FixCylindricalTexGen, 00252 const Option _WeightNormalsByFaceSize = WeightNormalsByFaceSize 00253 ); 00254 }; 00255 00256 #endif //_NVMeshMender_H_ 00257