⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nvmeshmender.cpp

📁 linux 下的机器人足球仿真平台
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************NVMH2****Copyright (C) 1999, 2000, 2001, 2002 NVIDIA CorporationThis file is provided without support, instruction, or implied warranty of anykind.  NVIDIA makes no guarantee of its fitness for a particular purpose and isnot liable under any circumstances for any damages or loss whatsoever arisingfrom the use or inability to use this file or items derived from it.Questions to sim.dietrich@nvidia.comComments:    This tool is designed to help condition meshes for use in vertex & pixel shaders.    It can generate normals, texture coordinates, and perhaps most importantly, texture space   basis matrices.  It also can fix common texuring problems that come up when bump mapping, including  Texture Mirroring -  When two one halves of a character use the same part of a texture.  Cylindrical TexGen - When the rendering relies on cylindrical wrapping, texture space computation                        won't work right.  Stretched Basis -    When two adjacend faces use wildly different texture mappings, causing stretching                        that can ruin per-pixel lighting.   Here is an example usage scenario :   Say you have positions & indices, and want textures, normals, and tangents.  NVMeshMender aMender;  MVMeshMender::VAVector inputAtts;  // this is what you have  MVMeshMender::VAVector outputAtts; // this is what you want  MVMeshMender::VertexAttribute att;  // this is my working attribute  att.Name_ = "position";  for ( int p = 0; p < number_of_vertices; ++p )  {    att.floatVector_.push_back( myPositions[ p ].x );    att.floatVector_.push_back( myPositions[ p ].y );    att.floatVector_.push_back( myPositions[ p ].z );  }  att.floatVector.clear();  att.Name_ = "indices";  for ( int i = 0; i < number_of_indices; ++i )  {    att.intVector_.push_back( myIndices[ i ] );  }  // All inputs except for indices are assumed to be sets of 3 floats  // "indices" are assumed to be unsigned ints  // "tex0" is used for the tangent space calculation  // "tex0" is the only coordinate set generated, and the texture matrix applies only to it  //  All unknown attribute types, including "tex1", "tex2", "random_attribute", "weights", "bones", etc.  // are simply passed through.  They will be duplicated as needed just like positions, normals, etc.  bool bSuccess = aMender.Munge( inputAtts,              // these are my positions & indices                                 outputAtts,             // these are the outputs I requested, plus extra stuff generated on my behalf                                 3.141592654f / 2.5f,    // tangent space smooth angle                                 NULL,                   // no Texture matrix applied to my tex0 coords                                 FixTangents,            // fix degenerate bases & texture mirroring                                 FixCylindricalTexGen    // handle cylidrically mapped textures via vertex duplication                                 WeightNormalsByFaceSize // weight vertex normals by the triangle's size                                 );  if ( !bSuccess ) return false;  // Now the outputAtts may contain more vertex then you sent in !  //  This is because in handling tangent space smoothing, and solving texture mirroring &   // cylindrical texture wrapping problems, we partially duplicate vertices.  // All attributes are duplicated, even unknowns.  //  You may also get things you didn't ask for.  For instance, if you ask for tangent space,  // in other words, you ask for "tangent" or "binormal",  you will get "normal", "tex0",   // "tangent" and "binormal".  You can then ignore things in the output vector that you don't want.  //   If you ask for FixCylindricalTexGen, it will fix any absolute change in texture coordinates > 0.5   // across a single edge.  Therefore, if you pass in a single quad or cube, it won't work.  Any more   // complicated or tessellated mesh should work fine.******************************************************************************/#ifdef _WIN32#  pragma warning (disable : 4786)#endif#include "NVMeshMender.h"#include "nv_math/nv_math.h"#include <map>#include <set>#include <assert.h>bool NVMeshMender::Munge(  const NVMeshMender::VAVector& input, 			               NVMeshMender::VAVector& output, 					       const float bSmoothCreaseAngleRadians,					       const float* pTextureMatrix,					       const Option _FixTangents,					       const Option _FixCylindricalTexGen,                           const Option _WeightNormalsByFaceSize ){    typedef std::map< std::string, unsigned int > Mapping;	typedef std::set< Edge > EdgeSet;    typedef std::vector< std::set< unsigned int > > IdenticalVertices;    IdenticalVertices IdenticalVertices_;    // make room for potential tex coords, normals, binormals and tangents    output.resize( input.size() + 4 );     Mapping inmap;    Mapping outmap;    for ( unsigned int a = 0; a < input.size(); ++a )    {        inmap[ input[ a ].Name_ ] = a;    }    for ( unsigned int b = 0; b < output.size(); ++b )    {        output[ b ].intVector_.clear();        output[ b ].floatVector_.clear();        outmap[ output[ b ].Name_ ] = b;    }    for ( unsigned int c = 0; c < output.size(); ++c )    {        // for every output that has a match in the input, just copy it over        Mapping::iterator in = inmap.find( output[ c ].Name_ );        if ( in != inmap.end() )        {            // copy over existing indices, position, or whatever            output[ c ] = input[ (*in).second ];        }    }    if ( inmap.find( "indices" ) == inmap.end() )    {        SetLastError( "Missing indices from input" );        return false;    }    if ( outmap.find( "indices" ) == outmap.end() )    {        SetLastError( "Missing indices from output" );        return false;    }    // Go through all required outputs & generate as necessary    if ( inmap.find( "position" ) == inmap.end() )    {        SetLastError( "Missing position from input" );        return false;    }    if ( outmap.find( "position" ) == outmap.end() )    {        SetLastError( "Missing position from output" );        return false;    }    Mapping::iterator pos = outmap.find( "position" );    VertexAttribute::FloatVector& positions = output[ (*pos).second ].floatVector_;    vec3* pPositions = (vec3*)( &( positions[ 0 ] ) );    std::set< unsigned int > EmptySet;    for ( unsigned int i = 0; i < positions.size(); i += 3 )    {        IdenticalVertices_.push_back( EmptySet );    }	// initialize all attributes	for ( unsigned int att = 0; att < output.size(); ++att )	{		if ( output[ att ].Name_ != "indices" )		{			if ( output[ att ].floatVector_.size() == 0 )			{				output[ att ].floatVector_ = positions;			}		}	}    Mapping::iterator ind = outmap.find( "indices" );    VertexAttribute::IntVector& indices = output[ (*ind).second ].intVector_;    int* pIndices = (int*)( &( indices[ 0 ] ) );    vec3* pNormals = 0;    //vec3* pBiNormals = 0;    //vec3* pTangents = 0;    vec3* pTex0 = 0;    bool bNeedNormals = false;    bool bNeedTexCoords = false;    bool bComputeTangentSpace = false;    // see if texture coords are needed    if ( outmap.find( "tex0" ) != outmap.end() )    {        bNeedTexCoords = true;    }    // see if tangent or binormal are needed    if ( ( outmap.find( "binormal" ) != outmap.end() ) ||          ( outmap.find( "tangent" ) != outmap.end() ) )    {        bComputeTangentSpace = true;    }    // see if normals are needed    if ( outmap.find( "normal" ) != outmap.end() )    {        bNeedNormals = true;    }    // Compute normals.    Mapping::iterator want = outmap.find( "normal" );    bool have_normals = ( inmap.find( "normal" ) != inmap.end() ) ? true : false;    if ( bNeedNormals || bComputeTangentSpace )    {        // see if normals are provided        if ( !have_normals )        {            // create normals            if ( want == outmap.end() )			{	            VertexAttribute norAtt;	            norAtt.Name_ = "normal";                output.push_back( norAtt );                outmap[ "normal" ] = output.size() - 1;                want = outmap.find( "normal" );            }			// just initialize array so it's the correct size			output[ (*want).second ].floatVector_ = positions;            //VertexAttribute::FloatVector& normals = output[ (*want).second ].floatVector_;            // zero out normals            for ( unsigned n = 0; n < positions.size(); ++n )            {                output[ (*want).second ].floatVector_[ n ] = nv_zero;            }            pNormals = (vec3*)( &( output[ (*want).second ].floatVector_[0] ) );            // calculate face normals for each face            //  & add its normal to vertex normal total            for ( unsigned int t = 0; t < indices.size(); t += 3 )            {                vec3 edge0;                vec3 edge1;                edge0 = pPositions[ indices[ t + 1 ] ] - pPositions[ indices[ t + 0 ] ];                edge1 = pPositions[ indices[ t + 2 ] ] - pPositions[ indices[ t + 0 ] ];				edge0.normalize();				edge1.normalize();			                vec3 faceNormal = edge0 ^ edge1;                if ( _WeightNormalsByFaceSize == DontWeightNormalsByFaceSize )                {                    // Renormalize face normal, so it's not weighted by face size					faceNormal.normalize();                }                else                {                    // Leave it as-is, to weight by face size naturally by the cross product result                }                pNormals[ indices[ t + 0 ] ] += faceNormal;                pNormals[ indices[ t + 1 ] ] += faceNormal;                pNormals[ indices[ t + 2 ] ] += faceNormal;            }            // Renormalize each vertex normal            for ( unsigned int v = 0; v < output[ (*want).second ].floatVector_.size() / 3; ++v )				pNormals[v].normalize();        }    }    // Compute texture coordinates.    if ( bNeedTexCoords || bComputeTangentSpace )    {        if ( outmap.find("tex0") == outmap.end() )		{	        VertexAttribute texCoordAtt;	        texCoordAtt.Name_ = "tex0";            output.push_back( texCoordAtt );            outmap[ "tex0" ] = output.size() - 1;        }    	want = outmap.find("tex0");		Mapping::iterator have = inmap.find( "tex0" );        bool have_texcoords = (have != inmap.end());        // see if texcoords are provided        if ( have_texcoords )			output[ (*want).second ].floatVector_ = input[ (*have).second ].floatVector_;        else {			// just initialize array so it's the correct size			output[ (*want).second ].floatVector_ = positions;            pTex0 = (vec3*)( &(output[ (*want).second ].floatVector_[ 0 ]) );			// Generate cylindrical coordinates			// Find min and max positions for object bounding box			vec3 maxPosition( -FLT_MAX, -FLT_MAX, -FLT_MAX  );			vec3 minPosition(  FLT_MAX,   FLT_MAX,    FLT_MAX );			// there are 1/3 as many vectors as floats			const unsigned int theCount = static_cast<unsigned int>(positions.size() / 3.0f);			for ( unsigned int i = 0; i < theCount; ++i )			{				maxPosition.x = nv_max( maxPosition.x, pPositions[ i ].x );				maxPosition.y = nv_max( maxPosition.y, pPositions[ i ].y );				maxPosition.z = nv_max( maxPosition.z, pPositions[ i ].z );				minPosition.x = nv_min( minPosition.x, pPositions[ i ].x );				minPosition.y = nv_min( minPosition.y, pPositions[ i ].y );				minPosition.z = nv_min( minPosition.z, pPositions[ i ].z );			}			// Find major, minor and other axis for cylindrical texgen			vec3 delta = maxPosition - minPosition;			delta.x = (float)fabs( delta.x );			delta.y = (float)fabs( delta.y );			delta.z = (float)fabs( delta.z );			bool maxx,maxy,maxz;			maxx = maxy = maxz = false;			bool minz,miny,minx;			minx = miny = minz = false;			float deltaMajor = 0.0;			if ( ( delta.x >= delta.y ) && ( delta.x >= delta.z ) )			{				maxx = true;				deltaMajor = delta.x;				if ( delta.y > delta.z )				{					minz = true;				}				else				{					miny = true;				}			}			else			if ( ( delta.z >= delta.y ) && ( delta.z >= delta.x ) )			{				maxz = true;				deltaMajor = delta.z;				if ( delta.y > delta.x )				{					minx = true;				}				else				{					miny = true;				}			}			else			if ( ( delta.y >= delta.z ) && ( delta.y >= delta.x ) )			{				maxy = true;				deltaMajor = delta.y;				if ( delta.x > delta.z )				{					minz = true;				}				else				{					minx = true;				}			}			for ( unsigned int p = 0; p < theCount; ++p )			{				// Find position relative to center of bounding box				vec3 texCoords = ( ( maxPosition + minPosition ) / 2.0f ) - pPositions[ p ];								float Major = 0.0, Minor = 0.0, Other = nv_zero;				if ( maxx )				{					Major = texCoords.x;					if ( miny )					{						Minor = texCoords.y;						Other = texCoords.z;					} else {						Minor = texCoords.z;						Other = texCoords.y;					}				}				else				if ( maxy )				{					Major = texCoords.y;					if ( minx )					{						Minor = texCoords.x;						Other = texCoords.z;					} else {						Minor = texCoords.z;						Other = texCoords.x;					}				}				else				if ( maxz )				{					Major = texCoords.z;					if ( miny )					{						Minor = texCoords.y;						Other = texCoords.x;					} else {						Minor = texCoords.x;						Other = texCoords.y;					}				}				float longitude = nv_zero;				// Prevent zero or near-zero from being passed into atan2				if ( fabs( Other ) < 0.0001f )				{					if ( Other >= nv_zero )					{						Other = 0.0001f;					} else {						Other = -0.0001f;					}				}				// perform cylindrical mapping onto object, and remap from -pi,pi to -1,1				longitude = (float)(( atan2( Minor, Other ) ) / 3.141592654);				texCoords.x = 0.5f * longitude + 0.5f;				texCoords.y = (Major/deltaMajor) + 0.5f;				texCoords.x = nv_max( texCoords.x, nv_zero );				texCoords.y = nv_max( texCoords.y, nv_zero );				texCoords.x = nv_min( texCoords.x, 1.0f );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -