📄 cpolygonobject.cpp
字号:
/*
============================================================================
* Name : CPolygonObject.cpp
* Part of : Example3D
* Description : Definition of CPolygonObject
* Copyright (c) 2007 Nokia Corporation
============================================================================
*/
// INCLUDES
#include "CPolygonObject.h"
#include <e32math.h>
#include <e32svr.h> // for debug prints
// CONSTANTS
const TUint KInvalidTextureObject = 0xffffffff;
// MEMBER FUNCTIONS
CPolygonObject* CPolygonObject::NewL( C3DBase* a3DBase, TInt aNumVertices, TInt aNumFaces )
{
CPolygonObject* self = new( ELeave )CPolygonObject( a3DBase, aNumVertices, aNumFaces );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
CPolygonObject::~CPolygonObject()
{
delete[] iFace;
delete[] iVertex;
delete[] iRVertex;
delete[] iDrawList;
delete[] iFaceZ;
delete[] iFaceN;
delete[] iGlVerts;
delete[] iGlTexCoords;
delete[] iGlTris;
if( iTextureObject != KInvalidTextureObject )
{
glDeleteTextures( 1, &iTextureObject );
}
}
CPolygonObject::CPolygonObject( C3DBase* a3DBase, TInt aNumVertices, TInt aNumFaces )
: i3DBase( a3DBase )
, iMaxNumVertices( aNumVertices )
, iMaxNumFaces( aNumFaces )
{
}
void CPolygonObject::ConstructL()
{
iFace = new( ELeave )TFace[ iMaxNumFaces ];
iVertex = new( ELeave )TVertex[ iMaxNumVertices ];
iRVertex = new( ELeave )TVertex[ iMaxNumVertices ];
iCos = i3DBase->CosTable();
iSin = i3DBase->SinTable();
iFaceN = new( ELeave )TInt[ iMaxNumFaces ];
iFaceZ = new( ELeave )TInt[ iMaxNumFaces ];
iDrawList = new( ELeave )TDrawFace[ iMaxNumFaces ];
// OpenGl texture object handle
// valid texture handle is '0'
// so set the handle as KInvalidTextureObject here.
iTextureObject = KInvalidTextureObject;
}
void CPolygonObject::Draw( const TBitmap& aScreen, TMatrix* aRotateMatrix )
{
// Here the drawing is done with OpenGl ES
// We are using Z-buffered draw with opengl
// so we don't need to sort the polygons
const TInt glShift = 16;
// shift adjustor
// OpenGl uses 16-bit decimals
// and this example uses KShift-bit decimals
// this is the difference to convert values to same decimal depth
const TInt shift = glShift - KShift;
const TInt mul = 1 << shift;
glMatrixMode (GL_MODELVIEW);
// Generate rotate matrix for OpenGl from example's rotate matrix
GLfixed mat[4*4]={ (*aRotateMatrix)[0]*mul, -(*aRotateMatrix)[4]*mul, -(*aRotateMatrix)[ 8]*mul, 0,
(*aRotateMatrix)[1]*mul, -(*aRotateMatrix)[5]*mul, -(*aRotateMatrix)[ 9]*mul, 0,
(*aRotateMatrix)[2]*mul, -(*aRotateMatrix)[6]*mul, -(*aRotateMatrix)[10]*mul, 0,
(*aRotateMatrix)[3]*mul, -(*aRotateMatrix)[7]*mul, -(*aRotateMatrix)[11]*mul, 1 << glShift };
// Init OpenGl for drawing
glLoadMatrixx( mat );
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 3, GL_FIXED, 0, iGlVerts );
if( iTextureObject != KInvalidTextureObject )
{
glBindTexture( GL_TEXTURE_2D, iTextureObject );
glEnable( GL_TEXTURE_2D );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer( 2, GL_FIXED, 0, iGlTexCoords );
}
else
{
glDisable( GL_TEXTURE_2D );
glDisableClientState ( GL_TEXTURE_COORD_ARRAY );
}
glColor4x( 1<<glShift, 1<<glShift, 1<<glShift, 1<<glShift );
glDrawElements( GL_TRIANGLES, iGlTriCount, GL_UNSIGNED_SHORT, iGlTris );
// This isn't really accurate number of polygons drawn
// but number of polygons feeded to OpenGL drawing pipeline
// some of the polygons are backface culled off etc.
i3DBase->AddPolygonCount( iGlTriCount );
}
// OpenGl uses it's own texture handles
void CPolygonObject::SetTexture( TInt aTextureObjectHandle )
{
iTextureObject = aTextureObjectHandle;
}
void CPolygonObject::Reset( TInt aNumVertices, TInt aNumFaces )
{
iMaxNumVertices = aNumVertices;
iMaxNumFaces = aNumFaces;
delete[] iFace;
iFace = new( ELeave )TFace[ iMaxNumFaces ];
iNumFaces = 0;
delete[] iVertex;
iVertex = new( ELeave )TVertex[ iMaxNumVertices ];
delete[] iRVertex;
iRVertex = new( ELeave )TVertex[ iMaxNumVertices ];
iNumVertices = 0;
delete[] iFaceN;
iFaceN = new( ELeave )TInt[ iMaxNumFaces ];
delete[] iFaceZ;
iFaceZ = new( ELeave )TInt[ iMaxNumFaces ];
delete[] iDrawList;
iDrawList = new( ELeave )TDrawFace[ iMaxNumFaces ];
}
TInt CPolygonObject::AddVertex( const TVertex& aVertex )
{
__ASSERT_DEBUG( iNumVertices < iMaxNumVertices, User::Panic( _L("Too many vertices"), iNumVertices ) );
iVertex[ iNumVertices++ ] = aVertex;
return iNumVertices-1;
}
void CPolygonObject::SetVertex( TInt aIndex, const TVertex& aVertex )
{
__ASSERT_DEBUG( aIndex < iNumVertices, User::Panic( _L("Illegal vertex index"), aIndex ) );
iVertex[ aIndex ] = aVertex;
}
TInt CPolygonObject::AddFace( const TFace& aFace )
{
__ASSERT_DEBUG( iNumFaces < iMaxNumFaces, User::Panic( _L("Too many faces"), iNumFaces ) );
iFace[ iNumFaces++ ] = aFace;
return iNumFaces;
}
void CPolygonObject::Init()
{
//
// Calculate bounding radius for object clipping
//
TInt r = 0;
TInt i;
for( i=0; i<iNumVertices; i++ )
{
TVertex& v = iVertex[ i ];
TInt r2 = v.iX * v.iX + v.iY * v.iY + v.iZ * v.iZ;
if( r2 > r ) r = r2;
}
TReal ra;
Math::Sqrt( ra, r );
iBoundingRadius = ( TInt )ra;
// if using OpenGL ES, convert vertices and faces
// to opengl world
delete[] iGlVerts;
delete[] iGlTexCoords;
delete[] iGlTris;
iGlTriCount = iNumFaces*3;
iGlVerts=new GLfixed[ iGlTriCount*3];
iGlTexCoords=new GLfixed[ iGlTriCount*2 ];
iGlTris=new GLushort[ iGlTriCount ];
TInt ic=0;
TInt vc=0;
const TInt textureSize = 256;
const TInt GlShift = 16;
const TInt shift = GlShift - KShift;
for (i=0;i<iNumFaces;i++)
{
int a,b,c;
a=iFace[i].iV1;
b=iFace[i].iV2;
c=iFace[i].iV3;
iGlVerts[vc*3] = iVertex[a].iX << shift;
iGlVerts[vc*3+1] = iVertex[a].iY << shift;
iGlVerts[vc*3+2] = iVertex[a].iZ << shift;
iGlTexCoords[vc*2] = ( iFace[i].iTx1 << GlShift ) / textureSize;
iGlTexCoords[vc*2+1] = ( iFace[i].iTy1 << GlShift ) / textureSize;
iGlTris[ic] = (GLushort)vc;
ic++;
vc++;
iGlVerts[vc*3] = iVertex[b].iX << shift;
iGlVerts[vc*3+1] = iVertex[b].iY << shift;
iGlVerts[vc*3+2] = iVertex[b].iZ << shift;
iGlTexCoords[vc*2] = ( iFace[i].iTx2 << GlShift ) / textureSize;
iGlTexCoords[vc*2+1] = ( iFace[i].iTy2 << GlShift ) / textureSize;
iGlTris[ic] = (GLushort)vc;
ic++;
vc++;
iGlVerts[vc*3] = iVertex[c].iX << shift;
iGlVerts[vc*3+1] = iVertex[c].iY << shift;
iGlVerts[vc*3+2] = iVertex[c].iZ << shift;
iGlTexCoords[vc*2] = ( iFace[i].iTx3 << GlShift) / textureSize;
iGlTexCoords[vc*2+1] = ( iFace[i].iTy3 << GlShift) / textureSize;
iGlTris[ic] = (GLushort)vc;
ic++;
vc++;
}
}
void CPolygonObject::Rotate()
{
// multiply all vertices by rotate matrix
// rotate matrix is calculated by C3DRenderer
for( TInt i=0; i<iNumVertices; i++ )
{
iRVertex[ i ] = iVertex[ i ];
iRVertex[ i ].MulMatrix( iRotateMatrix );
}
}
void CPolygonObject::Project( TDrawFace* aFaceList, TInt aNumFaces )
{
const TInt mul = 512;
TInt i;
TInt mx = iScreen.iSize.iWidth / 2;
TInt my = iScreen.iSize.iHeight / 2;
for( i=0; i<aNumFaces; i++ )
{
TDrawFace& f = aFaceList[ i ];
f.iV1.iX = f.iV1.iX * mul / f.iV1.iZ + mx;
f.iV1.iY = f.iV1.iY * mul / f.iV1.iZ + my;
f.iV2.iX = f.iV2.iX * mul / f.iV2.iZ + mx;
f.iV2.iY = f.iV2.iY * mul / f.iV2.iZ + my;
f.iV3.iX = f.iV3.iX * mul / f.iV3.iZ + mx;
f.iV3.iY = f.iV3.iY * mul / f.iV3.iZ + my;
}
}
inline void CPolygonObject::Swap( TAny* aV1, TAny* aV2 )
{
TUint32 temp = *(TUint32*)aV1;
*(TUint32*)aV1 = *(TUint32*)aV2;
*(TUint32*)aV2 = temp;
}
// disable warning of local variable may be used without initialized
// these variables are always initialized but compiler doesn't know it.
#pragma warning( disable : 4701 )
void CPolygonObject::DrawTexTri( TDrawVertex* aV1, TDrawVertex* aV2, TDrawVertex* aV3 )
{
TInt d = ( aV1->iX - aV3->iX ) * ( aV2->iY - aV3->iY ) -
( aV2->iX - aV3->iX ) * ( aV1->iY - aV3->iY );
if( d <= 0 ) return;
TInt id = ( 1 << 24 ) / d;
TInt dudx = ( ( aV1->iTx - aV3->iTx ) * ( aV2->iY - aV3->iY ) -
( aV2->iTx - aV3->iTx ) * ( aV1->iY - aV3->iY ) ) * id / ( 1 << 16 );
TInt dvdx = ( ( aV1->iTy - aV3->iTy ) * ( aV2->iY - aV3->iY ) -
( aV2->iTy - aV3->iTy ) * ( aV1->iY - aV3->iY ) ) * id / ( 1 << 16 );
if( aV1->iY > aV2->iY ) { Swap( &aV1, &aV2 ); d = -d; }
if( aV2->iY > aV3->iY ) { Swap( &aV2, &aV3 ); d = -d; }
if( aV1->iY > aV2->iY ) { Swap( &aV1, &aV2 ); d = -d; }
TInt h1 = ( aV2->iY - aV1->iY );
TInt h2 = ( aV3->iY - aV2->iY );
TInt h3 = ( aV3->iY - aV1->iY );
if( h3 == 0 ) return;
TInt h1i = 0;
if( h1 ) h1i = 65536 / h1;
TInt h2i = 0;
if( h2 ) h2i = 65536 / h2;
TInt h3i = 65536 / h3;
TInt y = aV1->iY;
TInt x1, x2;
TInt x1a, x2a;
TInt txya;
TInt tyya;
TInt otx;
TInt oty;
for( ;; )
{
//
// First half:
//
if( y==aV1->iY )
{
x1 = 256 * aV1->iX;
x2 = x1;
if( d > 0 ) // long side left
{
x1a = h3i * ( aV3->iX - aV1->iX ) >> 8;
x2a = h1i * ( aV2->iX - aV1->iX ) >> 8;
txya = h3i * ( aV3->iTx - aV1->iTx ) >> 8;
tyya = h3i * ( aV3->iTy - aV1->iTy ) >> 8;
otx = aV1->iTx << 8;
oty = aV1->iTy << 8;
}
else // long side right
{
x1a = h1i * ( aV2->iX - aV1->iX ) >> 8;
x2a = h3i * ( aV3->iX - aV1->iX ) >> 8;
txya = h1i * ( aV2->iTx - aV1->iTx ) >> 8;
tyya = h1i * ( aV2->iTy - aV1->iTy ) >> 8;
otx = aV1->iTx << 8;
oty = aV1->iTy << 8;
}
}
//
// Second half:
//
if( y==aV2->iY )
{
if( d > 0 ) // long side left
{
x1a = h3i * ( aV3->iX - aV1->iX ) >> 8;
x2a = h2i * ( aV3->iX - aV2->iX ) >> 8;
x1 = 256 * aV1->iX + x1a * h1;
x2 = 256 * aV2->iX;
txya = h3i * ( aV3->iTx - aV1->iTx ) >> 8;
tyya = h3i * ( aV3->iTy - aV1->iTy ) >> 8;
otx = 256 * aV1->iTx + txya * h1;
oty = 256 * aV1->iTy + tyya * h1;
}
else // long side right
{
x1a = h2i * ( aV3->iX - aV2->iX ) >> 8;
x2a = h3i * ( aV3->iX - aV1->iX ) >> 8;
x1 = 256 * aV2->iX;
x2 = 256 * aV1->iX + x2a * h1;
txya = h2i * ( aV3->iTx - aV2->iTx ) >> 8;
tyya = h2i * ( aV3->iTy - aV2->iTy ) >> 8;
otx = 256 * aV2->iTx;
oty = 256 * aV2->iTy;
}
}
//
// End of polygon
//
if( y==aV3->iY )
{
break;
}
// Left edge pointer
TUint16* p = (TUint16*)iScreen.iData + y * iScreen.iSize.iWidth;
// Right edge pointer
TUint16* p2 = p + ( x2 >> 8 );
p += x1 >> 8;
TInt tx = otx;
TInt ty = oty;
// scanline filler
register TUint16* sp = iTexture;
register TInt txa = dudx;
register TInt tya = dvdx;
while( p <= p2 )
{
*p++ = sp[ ( tx >> 8 ) + ( ty & 0xff00 ) ];
tx += txa;
ty += tya;
}
x1 += x1a;
x2 += x2a;
otx += txya;
oty += tyya;
y++;
}
}
// enable warning "local variable may be used without initialized"
#pragma warning( default : 4701 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -