port from perforce
This commit is contained in:
646
evoke-64k/trunk/ev10/ObjMesh.cpp
Normal file
646
evoke-64k/trunk/ev10/ObjMesh.cpp
Normal file
@@ -0,0 +1,646 @@
|
||||
#include "intrin.h"
|
||||
#include "OBJMesh.h"
|
||||
#include "BinMeshData.h"
|
||||
|
||||
#ifdef EXTRACODE
|
||||
#include "StringHelper.h"
|
||||
#include "TextFileReader.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#endif
|
||||
|
||||
ObjMesh g_objMesh;
|
||||
|
||||
#ifdef EXTRACODE
|
||||
|
||||
float ObjMesh::m_fMaxRoundError= 0.0f;
|
||||
float ObjMesh::RoundFloat( float f, int iBits )
|
||||
{
|
||||
DWORD dw= *((DWORD*)&f);
|
||||
int e= ( ( dw >> 23 ) & 0xff ) - 127;
|
||||
if( e == - 127)
|
||||
{
|
||||
m_fMaxRoundError= max( fabs( f ), m_fMaxRoundError );
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
DWORD dwMask= 0xffffffff << ( 32 - iBits );
|
||||
float Add= powf( 2.0f, (float)( e - iBits + 8 ) );
|
||||
|
||||
const int iTests= 7;
|
||||
float fValues[ iTests ];
|
||||
for( int i= 0; i < iTests; ++i )
|
||||
{
|
||||
fValues[ i ]= f + Add * (float)( i - iTests / 2 ) ;
|
||||
((DWORD*)(fValues))[ i ]&= dwMask;
|
||||
}
|
||||
int iNearest= 0;
|
||||
for( int i= 1; i < iTests; ++i )
|
||||
{
|
||||
if( fabs( f - fValues[ iNearest ] ) > fabs( f - fValues[ i ] ) )
|
||||
{
|
||||
iNearest= i;
|
||||
}
|
||||
}
|
||||
|
||||
m_fMaxRoundError= max( fabs( f - fValues[ iNearest ] ), m_fMaxRoundError );
|
||||
return fValues[ iNearest ];
|
||||
}
|
||||
|
||||
std::vector< unsigned char > TopologyRaw;
|
||||
std::vector<BinVertex> VertexRaw;
|
||||
|
||||
|
||||
bool ObjMesh::LoadMesh(
|
||||
const char* pcFileName,
|
||||
int FloatBits,
|
||||
bool bFlatten,
|
||||
BinMesh& bm,
|
||||
int& IndexBytes,
|
||||
int& VertexBytes )
|
||||
{
|
||||
std::map< VertexInfo, int > mapVertexData;
|
||||
std::vector< Vertex > VertexData;
|
||||
std::vector< int > Topology;
|
||||
std::vector< Vertex > PrePos;
|
||||
std::vector< Vertex > PreNormal;
|
||||
|
||||
Topology.reserve( 1000 );
|
||||
PrePos.reserve( 1000 );
|
||||
PreNormal.reserve( 1000 );
|
||||
|
||||
FrameWork::TextFileReader tfrData;
|
||||
|
||||
if( !tfrData.read( pcFileName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_FaceCount= 0;
|
||||
|
||||
for( int i= 0; i < (int)tfrData.getFileLines().size(); ++i )
|
||||
{
|
||||
std::string strAct= tfrData.getFileLines()[ i ];
|
||||
std::string strCommand;
|
||||
if( FrameWork::StringHelper::splitAt( strAct, " ", strCommand ) )
|
||||
{
|
||||
FrameWork::StringHelper::trim(
|
||||
strCommand,
|
||||
FrameWork::StringHelper::getSpaceTab() );
|
||||
FrameWork::StringHelper::toUpper( strCommand );
|
||||
}
|
||||
|
||||
if( strCommand == "V" )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << strAct;
|
||||
|
||||
Vertex vxPos;
|
||||
vxPos.position.x= 0;
|
||||
vxPos.position.y= 0;
|
||||
vxPos.position.z= 0;
|
||||
|
||||
ss >> vxPos.position.x;
|
||||
ss >> vxPos.position.y;
|
||||
ss >> vxPos.position.z;
|
||||
|
||||
PrePos.push_back( vxPos );
|
||||
}
|
||||
else if( strCommand == "VN" )
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << strAct;
|
||||
|
||||
Vertex vxNorm;
|
||||
vxNorm.normal.x= 0;
|
||||
vxNorm.normal.y= 0;
|
||||
vxNorm.normal.z= 0;
|
||||
|
||||
ss >> vxNorm.normal.x;
|
||||
ss >> vxNorm.normal.y;
|
||||
ss >> vxNorm.normal.z;
|
||||
|
||||
PreNormal.push_back( vxNorm );
|
||||
}
|
||||
else if( strCommand == "F" )
|
||||
{
|
||||
FrameWork::StringHelper::trim(
|
||||
strAct,
|
||||
FrameWork::StringHelper::getSpaceTab() );
|
||||
|
||||
std::vector< std::string > strVerts;
|
||||
FrameWork::StringHelper::tokenize(
|
||||
strAct, " ", strVerts );
|
||||
|
||||
std::vector< int > Read;
|
||||
|
||||
for( size_t j= 0; j < strVerts.size(); ++j )
|
||||
{
|
||||
std::vector< std::string > vecIndex;
|
||||
std::string strIndex= strVerts[ j ];
|
||||
FrameWork::StringHelper::trim(
|
||||
strIndex,
|
||||
FrameWork::StringHelper::getSpaceTab() );
|
||||
|
||||
FrameWork::StringHelper::tokenize(
|
||||
strIndex, "/", vecIndex );
|
||||
for( int jj= 0; jj < 3; ++jj )
|
||||
{
|
||||
std::stringstream ss;
|
||||
if( jj < (int)vecIndex.size() )
|
||||
{
|
||||
ss << vecIndex[ jj ];
|
||||
}
|
||||
|
||||
int iValue= -1;
|
||||
ss >> iValue;
|
||||
Read.push_back( iValue );
|
||||
}
|
||||
}
|
||||
|
||||
m_FaceCount++;
|
||||
Topology.push_back( Read.size() / 3 );
|
||||
for( int i=0; i < (int)Read.size(); i+= 3 )
|
||||
{
|
||||
int iIndex= i;
|
||||
|
||||
VertexInfo vInfo;
|
||||
vInfo.m_iPos= Read[ iIndex ];
|
||||
vInfo.m_iUV= Read[ iIndex + 1];
|
||||
vInfo.m_iNormal= Read[ iIndex + 2];
|
||||
|
||||
int iMapIndex;
|
||||
std::map< VertexInfo, int >::iterator it=
|
||||
mapVertexData.find( vInfo );
|
||||
if( it != mapVertexData.end() )
|
||||
{
|
||||
iMapIndex= it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
iMapIndex= (int)VertexData.size();
|
||||
mapVertexData[ vInfo ]= iMapIndex;
|
||||
Vertex vNew;
|
||||
vNew.position= PrePos[ vInfo.m_iPos - 1 ].position;
|
||||
if( (size_t)vInfo.m_iNormal - 1 >= PreNormal.size() )
|
||||
{
|
||||
// Normalen werden sowieso generiert
|
||||
vNew.normal= D3DXVECTOR3(0, 0, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
vNew.normal= PreNormal[ vInfo.m_iNormal - 1 ].normal;
|
||||
}
|
||||
VertexData.push_back( vNew );
|
||||
}
|
||||
Topology.push_back( iMapIndex );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//neuordnen der Topology koennte Speicherplatz sparen bei der Kompression
|
||||
|
||||
D3DXVECTOR3 PosPredictor( 0.0f, 0.0f, 0.0f );
|
||||
int IndexPredictor= 0;
|
||||
|
||||
TopologyRaw.resize( 0 );
|
||||
VertexRaw.resize( 0 );
|
||||
std::map< int, int > IndexMapping;
|
||||
|
||||
bm.m_PrimitiveCount= 0;
|
||||
|
||||
for(size_t i= 0; i < Topology.size(); ++i )
|
||||
{
|
||||
int iCount= Topology[ i ];
|
||||
for( int j= 0; j < iCount; ++j )
|
||||
{
|
||||
int iIndex= Topology[ i + 1 + j ];
|
||||
|
||||
//Index schon gespeichert?
|
||||
std::map< int, int >::iterator it= IndexMapping.find( iIndex );
|
||||
if( it == IndexMapping.end() )
|
||||
{
|
||||
//Vertex ist neu
|
||||
D3DXVECTOR3 PosData= VertexData[ iIndex ].position - PosPredictor;
|
||||
IndexMapping[ iIndex ]= VertexRaw.size();
|
||||
BinVertex v;
|
||||
v.m_Pos[ 0 ]= PosData.x;
|
||||
v.m_Pos[ 1 ]= PosData.y;
|
||||
v.m_Pos[ 2 ]= PosData.z;
|
||||
|
||||
if( bFlatten )
|
||||
{
|
||||
v.m_Pos[ 2 ]= 0.0f;
|
||||
}
|
||||
|
||||
//Positionswert hier runden macht Kompression besser
|
||||
v.m_Pos[ 0 ]= RoundFloat( v.m_Pos[ 0 ], FloatBits );
|
||||
v.m_Pos[ 1 ]= RoundFloat( v.m_Pos[ 1 ], FloatBits );
|
||||
v.m_Pos[ 2 ]= RoundFloat( v.m_Pos[ 2 ], FloatBits );
|
||||
|
||||
VertexRaw.push_back( v );
|
||||
//PosPredictor+= D3DXVECTOR3( v.m_Pos[ 0 ], v.m_Pos[ 1 ], v.m_Pos[ 2 ] );
|
||||
|
||||
TopologyRaw.push_back( 0 );
|
||||
IndexPredictor++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Vertex schon vorhanden
|
||||
int iIndexTransformed= IndexPredictor - it->second;
|
||||
while( iIndexTransformed >= BinMesh::c_FarVertex )
|
||||
{
|
||||
iIndexTransformed-= BinMesh::c_FarVertex;
|
||||
TopologyRaw.push_back( BinMesh::c_FarVertex );
|
||||
}
|
||||
TopologyRaw.push_back( iIndexTransformed );
|
||||
}
|
||||
}
|
||||
TopologyRaw.push_back( BinMesh::c_FinishPoly );
|
||||
bm.m_PrimitiveCount++;
|
||||
i+= iCount;
|
||||
}
|
||||
|
||||
bm.m_pTopology= &(TopologyRaw[ 0 ]);
|
||||
bm.m_pVertex= &(VertexRaw[ 0 ]);
|
||||
IndexBytes= TopologyRaw.size();
|
||||
VertexBytes= VertexRaw.size() * sizeof(BinVertex);
|
||||
return LoadMesh( &bm );
|
||||
|
||||
m_VertexCount= (unsigned int)VertexData.size();
|
||||
m_IndexCount= (unsigned int)Topology.size();
|
||||
|
||||
for(size_t i= 0; i < VertexData.size(); ++i )
|
||||
{
|
||||
m_VertexBuffer[ i ]= VertexData[ i ];
|
||||
}
|
||||
for(size_t i= 0; i < Topology.size(); ++i )
|
||||
{
|
||||
m_IndexBuffer[ i ]= Topology[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool ObjMesh::LoadMesh( BinMesh* pBinMesh )
|
||||
{
|
||||
m_IndexCount= 0;
|
||||
m_FaceCount= 0;
|
||||
m_VertexCount= 0;
|
||||
|
||||
int IndexPredictor= 0;
|
||||
unsigned char* pData= pBinMesh->m_pTopology;
|
||||
|
||||
int iFaceType= 0;
|
||||
int iVertex= IndexPredictor;
|
||||
int New= 1;
|
||||
while( m_FaceCount < pBinMesh->m_PrimitiveCount )
|
||||
{
|
||||
unsigned char c= *pData++;
|
||||
switch( c )
|
||||
{
|
||||
case BinMesh::c_FinishPoly:
|
||||
m_IndexBuffer[ m_IndexCount ]= iFaceType;
|
||||
m_IndexCount+= iFaceType + 1;
|
||||
m_FaceCount++;
|
||||
iFaceType= 0;
|
||||
break;
|
||||
case BinMesh::c_FarVertex:
|
||||
iVertex-= BinMesh::c_FarVertex;
|
||||
New= 0;
|
||||
break;
|
||||
case 0:
|
||||
IndexPredictor+= New;
|
||||
m_VertexCount+= New;
|
||||
default:
|
||||
iFaceType++;
|
||||
m_IndexBuffer[ m_IndexCount + iFaceType ]= iVertex - c;
|
||||
iVertex= IndexPredictor;
|
||||
New= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D3DXVECTOR3 PosPredictor( 0.0f, 0.0f, 0.0f );
|
||||
for( int i= 0; i < m_VertexCount; ++i )
|
||||
{
|
||||
D3DXVECTOR3 p(
|
||||
pBinMesh->m_pVertex[ i ].m_Pos[ 0 ],
|
||||
pBinMesh->m_pVertex[ i ].m_Pos[ 1 ],
|
||||
pBinMesh->m_pVertex[ i ].m_Pos[ 2 ] );
|
||||
PosPredictor= p;
|
||||
m_VertexBuffer[ i ].position= PosPredictor;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjMesh::GenerateNormals()
|
||||
{
|
||||
for( int i= 0; i < m_VertexCount; ++i )
|
||||
{
|
||||
m_VertexBuffer[ i ].normal= D3DXVECTOR3( 0, 0, 0);
|
||||
}
|
||||
|
||||
for(int i= 0; i < m_IndexCount; )
|
||||
{
|
||||
int iCount= m_IndexBuffer[ i ];
|
||||
++i;
|
||||
for( int j= 0; j < iCount; ++j )
|
||||
{
|
||||
int iIndex= m_IndexBuffer[ i + j ];
|
||||
int iIndexPrev= m_IndexBuffer[ i + ( ( j + iCount - 1 ) % iCount ) ];
|
||||
int iIndexNext= m_IndexBuffer[ i + ( ( j + 1 ) % iCount ) ];
|
||||
D3DXVECTOR3 p1( m_VertexBuffer[ iIndexPrev ].position - m_VertexBuffer[ iIndex ].position );
|
||||
D3DXVECTOR3 p2( m_VertexBuffer[ iIndexNext ].position - m_VertexBuffer[ iIndex ].position );
|
||||
D3DXVec3Cross( &p1, &p2, &p1 );
|
||||
m_VertexBuffer[ iIndex ].normal+= p1;
|
||||
}
|
||||
i+= iCount;
|
||||
}
|
||||
|
||||
for( int i= 0; i < m_VertexCount; ++i )
|
||||
{
|
||||
D3DXVec3Normalize( &( m_VertexBuffer[ i ].normal ), &( m_VertexBuffer[ i ].normal ) );
|
||||
}
|
||||
}
|
||||
|
||||
void ObjMesh::UnIndex()
|
||||
{
|
||||
m_OP.Reset();
|
||||
m_OP.m_NextVertexCount= 0;
|
||||
for(int i= 0; i < m_IndexCount; )
|
||||
{
|
||||
int iCount= m_IndexBuffer[ i ];
|
||||
++i;
|
||||
for( int j= 0; j < iCount; ++j )
|
||||
{
|
||||
int iIndex= m_IndexBuffer[ i + j ];
|
||||
m_OP.m_NextVB[ m_OP.m_NextVertexCount ]= m_VertexBuffer[ iIndex ];
|
||||
m_IndexBuffer[ i + j ]= m_OP.m_NextVertexCount;
|
||||
m_OP.m_NextVertexCount++;
|
||||
}
|
||||
i+= iCount;
|
||||
}
|
||||
|
||||
//Klatteratatsch ins Mesh kopieren...
|
||||
mymemcpy( m_VertexBuffer, m_OP.m_NextVB, sizeof( m_VertexBuffer ) );
|
||||
m_VertexCount= m_OP.m_NextVertexCount;
|
||||
}
|
||||
|
||||
|
||||
void ObjMesh::CatmullClarkSubdivide()
|
||||
{
|
||||
if( m_IndexCount >= MaxIndexBuffer / 4 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( m_VertexCount >= MaxVertexBuffer * 9 / 4 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// neuer VB ist so:
|
||||
// alter VB bzw. verschobene Originalpunkte
|
||||
// ein Vertex pro Face (FacePunkte)
|
||||
// ein Vertex pro Edge (EdgePunkte)
|
||||
|
||||
//neuer IB ist so:
|
||||
// 4 / alte Ecke0 / EdgePunkt / FaceFacePunkt / EdgePunkt
|
||||
// 4 / alte Ecke1 / EdgePunkt / FaceFacePunkt / EdgePunkt
|
||||
//...
|
||||
// 4 / alte EckeN / EdgePunkt / FaceFacePunkt / EdgePunkt ( N== Vertexcount )
|
||||
//beim kopieren dann ueberall noch 4
|
||||
|
||||
m_OP.Reset();
|
||||
m_OP.m_NextVertexCount= m_VertexCount + m_FaceCount; //Basis Vertices sind die alte Ecken und die neuen FacePunkte
|
||||
|
||||
int iFace= 0;
|
||||
for(int i= 0; i < m_IndexCount; )
|
||||
{
|
||||
int iCount= m_IndexBuffer[ i ];
|
||||
++i;
|
||||
D3DXVECTOR3& fp= m_OP.m_NextVB[ m_VertexCount + iFace ].position;
|
||||
unsigned short int* pIB= m_OP.m_NextIB + m_OP.m_NextIndexCount;
|
||||
|
||||
for( int j= 0; j < iCount; ++j )
|
||||
{
|
||||
int iIndex= m_IndexBuffer[ i + j ];
|
||||
fp+= m_VertexBuffer[ iIndex ].position;
|
||||
pIB[ j * 5 ]= 4;
|
||||
pIB[ j * 5 + 1]= iIndex;
|
||||
pIB[ j * 5 + 3 ]= m_VertexCount + iFace; // erste Haelfte IB fertig
|
||||
}
|
||||
fp/= (float)iCount; // jetzt ist der FacePunkt fertig
|
||||
|
||||
for( int j= 0; j < iCount; ++j )
|
||||
{
|
||||
int iIndex= m_IndexBuffer[ i + j ];
|
||||
int iIndexNext= m_IndexBuffer[ i + ( ( j + 1 ) % iCount ) ];
|
||||
int Edge= m_OP.MakeEdgeID( iIndex, iIndexNext );
|
||||
m_OP.m_NextVB[ m_OP.m_EdgeID[ Edge ] ].position+= fp; // Summe aller FacePunkte zu dieser Ecke sind hier
|
||||
|
||||
pIB[ j * 5 + 2 ]= m_OP.m_EdgeID[ Edge ];
|
||||
pIB[ ( j * 5 + 9 ) % ( iCount * 5 ) ]= m_OP.m_EdgeID[ Edge ]; // IB fertig!
|
||||
|
||||
m_OP.m_NextVB[ iIndex ].position+= fp; //Summe aller FacePunkte die an diesen Originalpunkt grenzen
|
||||
}
|
||||
|
||||
i+= iCount;
|
||||
iFace++;
|
||||
m_OP.m_NextIndexCount+= iCount * 5;
|
||||
m_OP.m_NextFaceCount+= iCount;
|
||||
}
|
||||
|
||||
// Originalpunkte verschieben
|
||||
for( int i= 0; i < m_VertexCount; ++i )
|
||||
{
|
||||
bool bOpenEdges= false; // gab es offene Kanten (d.h. einseitig benutze?)
|
||||
D3DXVECTOR3 vEdges(0,0,0);
|
||||
D3DXVECTOR3 vOpenEdges(0,0,0);
|
||||
int iEdgeCount= 0;
|
||||
int iOpenEdgeCount= 0;
|
||||
|
||||
for( int j=0; j < m_OP.m_iEdgeCount; ++j )
|
||||
{
|
||||
int V1= ( m_OP.m_EdgeConfiguration[ j ] & 0x0000ffff );
|
||||
int V2= ( m_OP.m_EdgeConfiguration[ j ] & 0xffff0000 ) >> 16;
|
||||
if( V1 == i || V2 == i )
|
||||
{
|
||||
D3DXVECTOR3 vMid= m_VertexBuffer[ V1 ].position + m_VertexBuffer[ V2 ].position;
|
||||
if( m_OP.m_EdgeUsage[ j ] == 1 )
|
||||
{
|
||||
bOpenEdges= true;
|
||||
iOpenEdgeCount++;
|
||||
vOpenEdges+= vMid;
|
||||
}
|
||||
iEdgeCount++;
|
||||
vEdges+= vMid;
|
||||
}
|
||||
}
|
||||
|
||||
if( bOpenEdges )
|
||||
{
|
||||
m_OP.m_NextVB[ i ].position= vOpenEdges / (float)( iOpenEdgeCount * 4 ) +
|
||||
m_VertexBuffer[ i ].position * 0.5f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OP.m_NextVB[ i ].position=
|
||||
m_OP.m_NextVB[ i ].position / (float)iEdgeCount +
|
||||
vEdges / (float)iEdgeCount +
|
||||
m_VertexBuffer[ i ].position * (float)( iEdgeCount - 3 );
|
||||
m_OP.m_NextVB[ i ].position/= (float)iEdgeCount;
|
||||
}
|
||||
}
|
||||
|
||||
//EdgePunkte anpassen
|
||||
for( int j=0; j < m_OP.m_iEdgeCount; ++j )
|
||||
{
|
||||
int V1= ( m_OP.m_EdgeConfiguration[ j ] & 0x0000ffff );
|
||||
int V2= ( m_OP.m_EdgeConfiguration[ j ] & 0xffff0000 ) >> 16;
|
||||
if( m_OP.m_EdgeUsage[ j ] < 2 )
|
||||
{
|
||||
m_OP.m_NextVB[ m_OP.m_EdgeID[ j ] ].position= D3DXVECTOR3( 0,0,0 );
|
||||
m_OP.m_EdgeUsage[ j ]= 0;
|
||||
}
|
||||
|
||||
m_OP.m_NextVB[ m_OP.m_EdgeID[ j ] ].position+= m_VertexBuffer[ V1 ].position;
|
||||
m_OP.m_NextVB[ m_OP.m_EdgeID[ j ] ].position+= m_VertexBuffer[ V2 ].position;
|
||||
m_OP.m_NextVB[ m_OP.m_EdgeID[ j ] ].position/= (float)(m_OP.m_EdgeUsage[ j ] + 2 );
|
||||
}
|
||||
|
||||
//Klatteratatsch ins Mesh kopieren...
|
||||
mymemcpy( m_VertexBuffer, m_OP.m_NextVB, sizeof( m_VertexBuffer ) );
|
||||
mymemcpy( m_IndexBuffer, m_OP.m_NextIB, sizeof( m_IndexBuffer ) );
|
||||
m_VertexCount= m_OP.m_NextVertexCount;
|
||||
m_IndexCount= m_OP.m_NextIndexCount;
|
||||
m_FaceCount= m_OP.m_NextFaceCount;
|
||||
}
|
||||
|
||||
void ObjMesh::Extrude( float fExtend )
|
||||
{
|
||||
m_OP.Reset();
|
||||
|
||||
for(int i= 0; i < m_IndexCount; )
|
||||
{
|
||||
int iCount= m_IndexBuffer[ i ];
|
||||
m_IndexBuffer[ i + m_IndexCount ]= iCount;
|
||||
++i;
|
||||
|
||||
for( int j= 0; j < iCount; ++j )
|
||||
{
|
||||
int iIndex= m_IndexBuffer[ i + j ];
|
||||
int iIndexNext= m_IndexBuffer[ i + ( ( j + 1 ) % iCount ) ];
|
||||
int ID= m_OP.MakeEdgeID( iIndex, iIndexNext );
|
||||
if( iIndex > iIndexNext )
|
||||
{
|
||||
m_OP.m_EdgeUsage[ ID ]+= 0x80;
|
||||
}
|
||||
m_IndexBuffer[ i + m_IndexCount + iCount - j - 1 ]= iIndex + m_VertexCount;
|
||||
}
|
||||
i+= iCount;
|
||||
}
|
||||
for( int i= 0; i < m_VertexCount; ++i )
|
||||
{
|
||||
m_VertexBuffer[ i + m_VertexCount].position= m_VertexBuffer[ i ].position;
|
||||
m_VertexBuffer[ i ].position.z-= fExtend;
|
||||
m_VertexBuffer[ i + m_VertexCount].position.z+= fExtend;
|
||||
}
|
||||
m_IndexCount*= 2;
|
||||
m_FaceCount*= 2;
|
||||
|
||||
for( int i= 0; i < m_OP.m_iEdgeCount; ++i )
|
||||
{
|
||||
if( (m_OP.m_EdgeUsage[ i ] & 0x7f ) == 1 )
|
||||
{
|
||||
int iAdd= m_OP.m_EdgeUsage[ i ] == 1 ? 0 : m_VertexCount;
|
||||
int V1= ( m_OP.m_EdgeConfiguration[ i ] & 0x0000ffff );
|
||||
int V2= ( m_OP.m_EdgeConfiguration[ i ] & 0xffff0000 ) >> 16;
|
||||
m_IndexBuffer[ m_IndexCount++ ]= 4;
|
||||
m_IndexBuffer[ m_IndexCount++ ]= V1+ iAdd;
|
||||
iAdd= m_VertexCount - iAdd;
|
||||
m_IndexBuffer[ m_IndexCount++ ]= V1+ iAdd;
|
||||
m_IndexBuffer[ m_IndexCount++ ]= V2+ iAdd;
|
||||
iAdd= m_VertexCount - iAdd;
|
||||
m_IndexBuffer[ m_IndexCount++ ]= V2+ iAdd;
|
||||
m_FaceCount+= 1;
|
||||
}
|
||||
}
|
||||
m_VertexCount*= 2;
|
||||
|
||||
}
|
||||
|
||||
void ObjMesh::SuperEllip( float fStrength )
|
||||
{
|
||||
if( m_VertexCount == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
float fMax= m_VertexBuffer[ 0 ].position.z;
|
||||
float fMin= m_VertexBuffer[ 0 ].position.z;
|
||||
for( int i= 1; i < m_VertexCount; ++i )
|
||||
{
|
||||
fMax= maximum( m_VertexBuffer[ i ].position.z, fMax );
|
||||
fMin= minimum( m_VertexBuffer[ i ].position.z, fMin );
|
||||
}
|
||||
|
||||
float fMid= ( fMax + fMin ) * 0.5f;
|
||||
float fExt= ( fMax - fMin ) * 0.5f;
|
||||
|
||||
for( int i= 0; i < m_VertexCount; ++i )
|
||||
{
|
||||
float Pos= ( m_VertexBuffer[ i ].position.z - fMid ) / fExt;
|
||||
Pos= signpow( Pos, fStrength );
|
||||
m_VertexBuffer[ i ].position.z= fMid + Pos * fExt;
|
||||
}
|
||||
}
|
||||
|
||||
void ObjMesh::OpInfo::Reset()
|
||||
{
|
||||
mymemset( m_NextVB, 0, sizeof( m_NextVB ) );
|
||||
mymemset( m_NextIB, 0, sizeof( m_NextIB ) );
|
||||
mymemset( m_EdgeConfiguration, 0, sizeof( m_EdgeConfiguration ) );
|
||||
mymemset( m_EdgeUsage, 0, sizeof( m_EdgeUsage ) );
|
||||
mymemset( m_EdgeID, 0, sizeof( m_EdgeID ) );
|
||||
|
||||
m_NextVertexCount= 0;
|
||||
m_NextIndexCount= 0;
|
||||
m_NextFaceCount= 0;
|
||||
|
||||
m_iEdgeCount= 0;
|
||||
}
|
||||
|
||||
int ObjMesh::OpInfo::MakeEdgeID( unsigned short VertexA, unsigned short VertexB )
|
||||
{
|
||||
unsigned int EdgeConfiguration= VertexA > VertexB ? ( VertexA << 16 | VertexB ) : ( VertexB << 16 | VertexA );
|
||||
for( int i=0; i < m_iEdgeCount; ++i )
|
||||
{
|
||||
if( m_EdgeConfiguration[ i ] == EdgeConfiguration )
|
||||
{
|
||||
m_EdgeUsage[ i ]++;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
m_EdgeConfiguration[ m_iEdgeCount ]= EdgeConfiguration;
|
||||
m_EdgeUsage[ m_iEdgeCount ]++;
|
||||
m_EdgeID[ m_iEdgeCount ]= m_NextVertexCount;
|
||||
m_NextVertexCount++;
|
||||
return m_iEdgeCount++;
|
||||
}
|
||||
|
||||
/* Vertex m_NextVB[ ObjMesh::MaxVertexBuffer ];
|
||||
unsigned short int m_NextIB[ ObjMesh::MaxIndexBuffer ];
|
||||
int m_NextVertexCount;
|
||||
int m_NextIndexCount;
|
||||
int m_NextFaceCount;
|
||||
|
||||
int m_iEdgeCount;
|
||||
unsigned int m_EdgeConfiguration[ ObjMesh::MaxIndexBuffer ];
|
||||
unsigned char m_EdgeUsage[ ObjMesh::MaxIndexBuffer ];
|
||||
|
||||
unsigned short int m_EdgeID[ ObjMesh::MaxIndexBuffer ];
|
||||
}*/
|
||||
Reference in New Issue
Block a user