📄 cpolygonobject.cpp
字号:
/*
============================================================================
* Name : CPolygonObject.cpp
* Part of : Example3D
* Description : Definition of CPolygonObject
* Copyright (c) 2005 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;
#ifdef GLES
delete[] iGlVerts;
delete[] iGlTexCoords;
delete[] iGlTris;
if( iTextureObject != KInvalidTextureObject )
{
glDeleteTextures( 1, &iTextureObject );
}
#endif
}
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 ];
#ifdef GLES
// OpenGl texture object handle
// valid texture handle is '0'
// so set the handle as KInvalidTextureObject here.
iTextureObject = KInvalidTextureObject;
#endif
}
void CPolygonObject::Draw( const TBitmap& aScreen, TMatrix* aRotateMatrix )
{
#ifdef GLES
// 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 );
#else
// Here is the software renderer
// Vertices are rotated with rotate matrix
// polygons are clipped against view frustrum
// remaining polygons are sorted by their distance to camera
// and then drawn to screen back to front ( painter's algorithm )
// rotate matrix from C3DRenderer
iRotateMatrix = aRotateMatrix;
iScreen = aScreen;
TFrustum& frustum = i3DBase->ViewFrustum();
// rotate vertices to iRVertex list
Rotate();
// clipped triangle has more than 3 vertices:
TDrawVertex polygon1[ 10 ];
TDrawVertex polygon2[ 10 ];
TBool clipped;
TInt inCount = 0;
// polygon's vertex distance from clipping plane
TInt d[ 10 ];
TInt numDrawn = 0;
TInt i;
for( i=0; i<iNumFaces; i++ )
{
TBool visible = ETrue;
clipped = EFalse;
TFace& f = iFace[ i ];
TVertex& v1 = iRVertex[ f.iV1 ];
TVertex& v2 = iRVertex[ f.iV2 ];
TVertex& v3 = iRVertex[ f.iV3 ];
polygon1[ 0 ] = TDrawVertex( v1, f.iTx1, f.iTy1 );
polygon1[ 1 ] = TDrawVertex( v2, f.iTx2, f.iTy2 );
polygon1[ 2 ] = TDrawVertex( v3, f.iTx3, f.iTy3 );
TDrawVertex* poly1 = polygon1;
TDrawVertex* poly2 = polygon2;
TInt numPoints = 3;
for( TInt n=0; n<frustum.iNumPlanes; n++ )
{
TInt vn = numPoints;
TInt p;
for( p=0; p<numPoints; p++ )
{
TVertex& mv1 = frustum.iPlane[ n ].iNormal;
TDrawVertex& mv2 = poly1[ p ];
// calculate dot product to get point distance to plane:
TInt l = mv1.iX * mv2.iX + mv1.iY * mv2.iY + mv1.iZ * mv2.iZ;
l += frustum.iPlane[ n ].iDistance;
if( l <= 0 ) vn--;
d[ p ] = l;
inCount++;
}
if( vn == numPoints )
{
// all visible, do not clip
continue;
}
if( vn == 0 )
{
// none visible, do not draw, do not continue clipping
visible = EFalse;
break;
}
clipped = ETrue;
TInt np = 0;
for( TInt p1=0; p1<numPoints; p1++ )
{
TInt p0 = p1-1;
TInt p2 = p1+1;
if( p0<0 ) p0 += numPoints;
if( p2>=numPoints ) p2 -= numPoints;
TDrawVertex& dv0 = poly1[ p0 ];
TDrawVertex& dv1 = poly1[ p1 ];
TDrawVertex& dv2 = poly1[ p2 ];
// if point is out of plane, check if one or more points can be
// added to drawarea's edge in straight line to other points
// ( actual clipping )
if( d[ p1 ] < 0 )
{
if( d[ p0 ] > 0 )
{
TInt s = ( d[ p0 ] << KShift ) / ( d[ p0 ]-d[ p1 ] );
poly2[ np ].iX = dv0.iX + ( ( s*( dv1.iX - dv0.iX ) ) >> KShift );
poly2[ np ].iY = dv0.iY + ( ( s*( dv1.iY - dv0.iY ) ) >> KShift );
poly2[ np ].iZ = dv0.iZ + ( ( s*( dv1.iZ - dv0.iZ ) ) >> KShift );
poly2[ np ].iTx = dv0.iTx + ( ( s*( dv1.iTx - dv0.iTx ) ) >> KShift );
poly2[ np ].iTy = dv0.iTy + ( ( s*( dv1.iTy - dv0.iTy ) ) >> KShift );
np++;
}
if( d[ p2 ] > 0 )
{
TInt s = ( d[ p2 ] << KShift ) / ( d[ p2 ]-d[ p1 ] );
poly2[ np ].iX = dv2.iX + ( ( s*( dv1.iX - dv2.iX ) ) >> KShift );
poly2[ np ].iY = dv2.iY + ( ( s*( dv1.iY - dv2.iY ) ) >> KShift );
poly2[ np ].iZ = dv2.iZ + ( ( s*( dv1.iZ - dv2.iZ ) ) >> KShift );
poly2[ np ].iTx = dv2.iTx + ( ( s*( dv1.iTx - dv2.iTx ) ) >> KShift );
poly2[ np ].iTy = dv2.iTy + ( ( s*( dv1.iTy - dv2.iTy ) ) >> KShift );
np++;
}
}
else
{
poly2[ np++ ] = poly1[ p1 ];
}
}
numPoints = np;
TDrawVertex* temp = poly1;
poly1 = poly2;
poly2 = temp;
}
TInt t;
if( visible )
{
if( numDrawn < iMaxNumFaces )
{
// split polygon to triangles:
// ( polygon draw other but triangles are not supported )
for( t=0; t<numPoints-2; t++ )
{
iDrawList[ numDrawn++ ] = TDrawFace( poly1[ 0 ], poly1[ 1 + t ], poly1[ 2 + t ] );
}
}
}
}
// draw if there's something to draw
if( numDrawn > 0 )
{
// add number of polygons to drawn counter
i3DBase->AddPolygonCount( numDrawn );
// project vertices in iRVertex list to screen coordinates
Project( iDrawList, numDrawn );
// sort faces by their Z-values
for( i=0; i<numDrawn; i++ )
{
TDrawFace& f = iDrawList[ i ];
iFaceZ[ i ] = f.iV1.iZ + f.iV2.iZ + f.iV3.iZ;
iFaceN[ i ] = i;
}
i3DBase->QSort( iFaceZ, iFaceN, 0, numDrawn-1 );
// and draw faces from back to front
for( i=numDrawn-1; i>=0; i-- )
{
TDrawFace& f = iDrawList[ iFaceN[ i ] ];
// textured
DrawTexTri( &f.iV1, &f.iV2, &f.iV3 );
}
}
#endif
}
#ifdef GLES
// OpenGl uses it's own texture handles
void CPolygonObject::SetTexture( TInt aTextureObjectHandle )
{
iTextureObject = aTextureObjectHandle;
}
#else
// Software renderer understands TBitmap-type textures
void CPolygonObject::SetTexture( TBitmap aTexture )
{
iTexture = aTexture.iData;
}
#endif
void CPolygonObject::Reset( TInt aNumVertices, TInt aNumFaces )
{
iMaxNumVertices = aNumVertices;
iMaxNumFaces = aNumFaces;
delete[] iFace;
iFace = new( ELeave )TFace[ iMaxNumFaces ];
iNumFaces = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -