graphicstest/uibench/s60/src/geometrystructs.cpp
author Gareth Stockwell <gareth.stockwell@accenture.com>
Fri, 05 Nov 2010 17:31:20 +0000
branchbug235_bringup_0
changeset 215 097e92a68d68
parent 0 5d03bc08d59c
permissions -rw-r--r--
Added GLES 1.x spinning cube-rendering code to eglbringuptest The coordinate, color and index data are uploaded to server-side buffers by the CGLES1Cube::KhrSetup function. CGLES1Cube::KhrPaint just sets the view matrix and issues a draw command. Which demo to display can be selected by passing its name on the command line, e.g. eglbringuptest vgline eglbringuptest gles1cube If no name is provided, the application defaults to vgline.

// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//

/*
 * Portions of this code, in particular the fghCircleTable function and the code to 
 * calculate the vertices for the solid sphere, is ported from freeglut_geometry.cpp 
 * which is distributed under the following terms:
 * 
 ****************************************************************** 
 * Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved.
 * Written by Pawel W. Olszta, <olszta@sourceforge.net>
 * Creation date: Fri Dec 3 1999
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *********************************************************************
 * Apart from porting to use Open GL ES instead of Open GL the other major change is 
 * to separate out the code that calculates vertices from the code that draws the shape.   
 */


#include "geometrystructs.h"

#include <GLES/gl.h>
#include <e32math.h>


float sin(float x)
	{
	double t = x;
	double r;
	TInt error = Math::Sin(r,t);
	ASSERT(error==KErrNone);
	return r;
	}

float cos(float x)
	{
	double t = x;
	double r;
	TInt error = Math::Cos(r,t);
	ASSERT(error==KErrNone);
	return r;
	}

int abs(int x)
	{
	return Abs(x);
	}

Vertex3F::Vertex3F(float x, float y, float z)
	:iX(x), iY(y), iZ(z)
	{
	}

Vertex3F::Vertex3F()
:iX(0), iY(0), iZ(0)
	{
	}

int fghCircleTable(float **sint,float **cost,const int n)
{
    int i;

    /* Table size, the sign of n flips the circle direction */
    const int size = abs(n);

    /* Determine the angle between samples */
    const float angle = 2*KPi/(float)( ( n == 0 ) ? 1 : n );

    /* Allocate memory for n samples, plus duplicate of first entry at the end */
    *sint = new float[sizeof(float) * size+1];
    
    if(*sint==NULL)
		{
		return KErrNoMemory;
		}
		
    *cost = new float[sizeof(float) * size+1];
    
    if(*cost==NULL)
		{
		delete[] sint;
		return KErrNoMemory;
		}
    
    /* Compute cos and sin around the circle */
    (*sint)[0] = 0.0;
    (*cost)[0] = 1.0;

    for (i=1; i<size; i++)
    {
    (*sint)[i] = sin(angle*i);
    (*cost)[i] = cos(angle*i);
    }

    /* Last sample is duplicate of the first */

    (*sint)[size] = (*sint)[0];
    (*cost)[size] = (*cost)[0];
    return KErrNone;
}

CSolidSphere* CSolidSphere::NewLC(TReal aRadius, TInt aSlices, TInt aStacks)
	{
	CSolidSphere* self = new(ELeave) CSolidSphere(aSlices, aStacks);
	CleanupStack::PushL(self);
	self->ConstructL(aRadius);
	return self;
	}

CSolidSphere::~CSolidSphere()
	{
	delete[] iTopVertices;
	delete[] iTopNormals;
	delete[] iBottomVertices;
	delete[] iBottomNormals;
	delete[] iStackVertices;
	delete[] iStackNormals;
	}

void CSolidSphere::Draw() const
	{
//top fan
	glVertexPointer(3, GL_FLOAT, 0, iTopVertices);
	glNormalPointer(GL_FLOAT, 0, iTopNormals);
	glDrawArrays(GL_TRIANGLE_FAN, 0, iSlices+2);
//stacks, one at a time	
	glVertexPointer(3, GL_FLOAT, 0, iStackVertices);
	glNormalPointer(GL_FLOAT, 0, iStackNormals);
	TInt offset = 0;
	TInt verticesPerStack = (iSlices+1)*2;
	for(TInt i=1; i<iStacks-1; i++ )
		{
		glDrawArrays(GL_TRIANGLE_STRIP, offset, verticesPerStack);
		offset+=verticesPerStack;
		}
//bottom fan
	glVertexPointer(3, GL_FLOAT, 0, iBottomVertices);
	glNormalPointer(GL_FLOAT, 0, iBottomNormals);
	glDrawArrays(GL_TRIANGLE_FAN, 0, iSlices+2);
	}

CSolidSphere::CSolidSphere(TInt aSlices, TInt aStacks)
	:iSlices(aSlices), iStacks(aStacks)
	{
	}

void CSolidSphere::ConstructL(TReal aRadius)
	{
	//* Pre-computed circle 
	float* sint1 = NULL;
	float* cost1 = NULL;
	float* sint2 = NULL;
	float* cost2 = NULL;
	
	
	fghCircleTable(&sint1,&cost1,-iSlices);
	CleanupArrayDeletePushL(sint1);
	CleanupArrayDeletePushL(cost1);
		
	fghCircleTable(&sint2,&cost2,iStacks*2);
	CleanupArrayDeletePushL(sint2);
	CleanupArrayDeletePushL(cost2);

	//* The top stack is covered with a triangle fan 
	int i,j;
	//* Adjust z and radius as stacks are drawn. 
	float z0,z1;
	float r0,r1;
	
	z0 = 1.0;
	z1 = cost2[(iStacks>0)?1:0];
	r0 = 0.0;
	r1 = sint2[(iStacks>0)?1:0];
	
	iTopVertices = new (ELeave) Vertex3F[iSlices+2];
	iTopNormals = new (ELeave) Vertex3F[iSlices+2];
	TInt topVerticesIndex = 0;
	iTopVertices[topVerticesIndex] = Vertex3F(0,0,aRadius);
	iTopNormals[topVerticesIndex] = Vertex3F(0,0,1);
	for(j=iSlices; j>=0; j--)
	  	{
	  	topVerticesIndex++;
	    Vertex3F vertex(cost1[j]*r1*aRadius, sint1[j]*r1*aRadius, z1*aRadius);
	    iTopVertices[topVerticesIndex] = vertex;
	    Vertex3F normal(cost1[j]*r1,        sint1[j]*r1,        z1       );
	    iTopNormals[topVerticesIndex] = normal;
	    }
	
	//*calculate the vertices for each stack
	TInt stackVertexCount = ((iSlices+1)*2) *iStacks; 
	iStackVertices = new (ELeave) Vertex3F[stackVertexCount];
	iStackNormals = new (ELeave) Vertex3F[stackVertexCount];	
	TInt stackIndex = 0;
	for( i=1; i<iStacks-1; i++ )
	    {
	    z0 = z1; z1 = cost2[i+1];
	    r0 = r1; r1 = sint2[i+1];
	    for(j=0; j<=iSlices; j++)
	       {
	       Vertex3F v1(cost1[j]*r1*aRadius, sint1[j]*r1*aRadius, z1*aRadius);
	       Vertex3F v2(cost1[j]*r0*aRadius, sint1[j]*r0*aRadius, z0*aRadius);
	       iStackVertices[stackIndex*2] = v1;
	       iStackVertices[(stackIndex*2)+1] = v2;	                 
		   Vertex3F n1(cost1[j]*r1,        sint1[j]*r1,        z1);
		   Vertex3F n2(cost1[j]*r0,        sint1[j]*r0,        z0);
		   iStackNormals[stackIndex*2] = n1;
		   iStackNormals[(stackIndex*2)+1] = n2;
		   stackIndex++;
		   }
	    }
	//* The bottom stack is covered with a triangle fan 
	z0 = z1;
	r0 = r1;

	iBottomVertices = new (ELeave) Vertex3F[iSlices+2];
	iBottomNormals = new (ELeave) Vertex3F[iSlices+2];
	
	iBottomVertices[0] = Vertex3F(0,0,-aRadius);
	iBottomNormals[0] = Vertex3F(0,0,-1);
    for(j=0; j<=iSlices; j++)
    	{
	    Vertex3F vertex(cost1[j]*r0*aRadius, sint1[j]*r0*aRadius, z0*aRadius);
	    iBottomVertices[j+1] = vertex;
	    Vertex3F normal(cost1[j]*r0, sint1[j]*r0, z0);
	    iBottomNormals[j+1] = normal;
	    }
    //* Release sin and cos tables 
    CleanupStack::PopAndDestroy(4);
	}