sl@0: // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: sl@0: #include "model.h" sl@0: #include "geometrystructs.h" sl@0: #include "egldefs.h" sl@0: #include "eglerror.h" sl@0: sl@0: #include sl@0: sl@0: sl@0: const TInt KMoonPositionCount = 100; sl@0: const TInt KSunPositionCount = 100; sl@0: sl@0: const TInt KSunOrbitRadius = 2000; //heliocentric sl@0: const TInt KMoonOrbitRadius = 100; sl@0: const TInt KModelDistanceFromCamera = 200; sl@0: sl@0: const TInt KMinResolution = 5; sl@0: const TInt KMaxResolution = 50; sl@0: const TInt KDefaultResolution = 50; sl@0: sl@0: const TInt KSunRadius=100; sl@0: const TInt KPlanetRadius=50; sl@0: const TInt KMoonRadius = 10; sl@0: sl@0: _LIT(KRed, "red"); sl@0: _LIT(KGreen, "green"); sl@0: _LIT(KBlue, "blue"); sl@0: _LIT(KBlack, "black"); sl@0: sl@0: sl@0: CModel* CModel::NewL(EGLDisplay aDisplay, EGLSurface aSurface) sl@0: { sl@0: TPtrC defaultColor(KBlack); sl@0: return NewL(aDisplay, aSurface, defaultColor); sl@0: } sl@0: sl@0: CModel* CModel::NewL(EGLDisplay aDisplay, EGLSurface aSurface, TPtrC aBackgroundColor) sl@0: { sl@0: CModel* self = new(ELeave) CModel(aDisplay, aSurface); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aBackgroundColor); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: void CModel::PrecalculateOrbitL(TInt aOrbitingDistance, RArray& aVertices, TInt aPositionCount, TReal aAngle) sl@0: { sl@0: //fghCircleTable allocates for sin and cos tables, sl@0: //so we must not fail to append vertices to the array, sl@0: //so we must reserve all the space we need. sl@0: aVertices.ReserveL(aPositionCount); sl@0: //precalculate the positions of the sun sl@0: TReal32 *sint1,*cost1; sl@0: User::LeaveIfError(fghCircleTable(&sint1,&cost1, aPositionCount)); sl@0: sl@0: TReal radians = aAngle*(KPi/180); sl@0: TReal32 cosA = cos(radians); sl@0: TReal32 sinA = sin(radians); sl@0: sl@0: TReal32 x,y = 0; sl@0: TReal32 cosCalc = aOrbitingDistance * cosA; sl@0: TReal32 sinCalc = aOrbitingDistance * sinA; sl@0: for(TInt i = 0; i < aPositionCount; i++) sl@0: { sl@0: x = cost1[i] * cosCalc; sl@0: y = cost1[i] * sinCalc; sl@0: sl@0: Vertex3F v(x,y, sint1[i]*aOrbitingDistance); sl@0: User::LeaveIfError(aVertices.Append(v)); sl@0: } sl@0: delete[] sint1; sl@0: delete[] cost1; sl@0: } sl@0: sl@0: void CModel::ConstructL(TPtrC aBackgroundColor) sl@0: { sl@0: iResolution=KDefaultResolution; sl@0: sl@0: CSolidSphere* newSun = CSolidSphere::NewLC(KSunRadius, iResolution, iResolution); sl@0: CSolidSphere* newPlanet = CSolidSphere::NewLC(KPlanetRadius, iResolution, iResolution); sl@0: CSolidSphere* newMoon = CSolidSphere::NewLC(KMoonRadius, iResolution, iResolution); sl@0: SetShapes(newSun, newPlanet, newMoon); sl@0: CleanupStack::Pop(3, newSun); sl@0: sl@0: PrecalculateOrbitL(KSunOrbitRadius, iSunPositions, KSunPositionCount, 135); sl@0: PrecalculateOrbitL(KMoonOrbitRadius, iMoonPositions, KMoonPositionCount, 23.5); sl@0: if(aBackgroundColor == KRed) sl@0: { sl@0: iBackgroundColor[ERed] = 0.5; sl@0: } sl@0: else if (aBackgroundColor == KGreen) sl@0: { sl@0: iBackgroundColor[EGreen] = 0.5; sl@0: } sl@0: else if (aBackgroundColor == KBlue) sl@0: { sl@0: iBackgroundColor[EBlue] = 0.5; sl@0: } sl@0: } sl@0: sl@0: CModel::CModel(EGLDisplay aDisplay, EGLSurface aSurface) sl@0: :iDisplay(aDisplay), iSurface(aSurface) sl@0: { sl@0: } sl@0: sl@0: CModel::~CModel() sl@0: { sl@0: delete iSun; sl@0: delete iPlanet; sl@0: delete iMoon; sl@0: iSunPositions.Close(); sl@0: iMoonPositions.Close(); sl@0: } sl@0: sl@0: void CModel::SetShapes(CSolidSphere* aSun, CSolidSphere* aPlanet, CSolidSphere* aMoon) sl@0: { sl@0: delete iSun; sl@0: iSun = aSun; sl@0: sl@0: delete iPlanet; sl@0: iPlanet = aPlanet; sl@0: sl@0: delete iMoon; sl@0: iMoon = aMoon; sl@0: } sl@0: sl@0: void CModel::DrawToBuffer(TInt aTime) const sl@0: { sl@0: InitialiseFrame(); sl@0: DrawModelData(aTime); sl@0: } sl@0: sl@0: void CModel::InitialiseFrame() const sl@0: { sl@0: glEnable(GL_CULL_FACE); sl@0: glEnable(GL_DEPTH_TEST); sl@0: glEnable(GL_COLOR_ARRAY); sl@0: glEnable(GL_LIGHTING); sl@0: glEnable(GL_LIGHT0); sl@0: glEnableClientState(GL_VERTEX_ARRAY); sl@0: glEnableClientState(GL_NORMAL_ARRAY); sl@0: sl@0: glClearColor(iBackgroundColor[ERed], iBackgroundColor[EGreen], iBackgroundColor[EBlue], iBackgroundColor[EAlpha]); sl@0: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); sl@0: sl@0: glCullFace(GL_FRONT); sl@0: glShadeModel (GL_SMOOTH); sl@0: sl@0: // Set the projection parameters sl@0: glMatrixMode(GL_PROJECTION); sl@0: glLoadIdentity(); sl@0: sl@0: EGLint height; sl@0: if(!eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &height)) sl@0: { sl@0: ProcessEglError(); sl@0: } sl@0: EGLint width; sl@0: if(!eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &width)) sl@0: { sl@0: ProcessEglError(); sl@0: } sl@0: sl@0: GLfloat widthf = width; sl@0: GLfloat heightf = height; sl@0: GLfloat aspectRatio = widthf/heightf; sl@0: glFrustumf( -(aspectRatio*KFrustumHeight), (aspectRatio*KFrustumHeight), sl@0: -KFrustumHeight, KFrustumHeight, sl@0: KFrustumNear, KFrustumFar); sl@0: } sl@0: sl@0: void CModel::DrawModelData(TInt aTime) const sl@0: { sl@0: //draw a light source where the sun is sl@0: glMatrixMode(GL_MODELVIEW); sl@0: glLoadIdentity(); sl@0: GLfloat sun_color[] = { 1.0, 1.0, 0.5333, 1 }; sl@0: Vertex3F vSun = iSunPositions[aTime%KSunPositionCount]; sl@0: vSun.iZ-=KModelDistanceFromCamera; sl@0: GLfloat light0position[] = {vSun.iX, vSun.iY, vSun.iZ, 1.0 }; sl@0: glLightfv(GL_LIGHT0, GL_POSITION, light0position); sl@0: glLightfv(GL_LIGHT0, GL_SPECULAR, sun_color); sl@0: sl@0: //draw the sun sl@0: glMatrixMode(GL_MODELVIEW); sl@0: glLoadIdentity(); sl@0: //this is obviously wrong: I don't understand why the z-coord for the sl@0: //sun needs to be the negation of the z-coord for the light source position, sl@0: //in order for the light to appear to come from the sun! sl@0: glTranslatef(vSun.iX, vSun.iY, -vSun.iZ); sl@0: sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, sun_color); sl@0: sl@0: iSun->Draw(); sl@0: //draw the planet sl@0: glMatrixMode(GL_MODELVIEW); sl@0: glLoadIdentity(); sl@0: glTranslatef(0, 0, -KModelDistanceFromCamera); sl@0: sl@0: GLfloat mat_planet_color[] = { 0.459, 0.679, 0.8, 1 }; sl@0: GLfloat mat_planet_shininess[] = { 30.0 }; sl@0: GLfloat mat_no_emission[] = {0, 0, 0, 0}; sl@0: sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_planet_color); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_planet_color); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_planet_color); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_planet_shininess); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_no_emission); sl@0: iPlanet->Draw(); sl@0: sl@0: //draw the moon sl@0: glMatrixMode(GL_MODELVIEW); sl@0: glLoadIdentity(); sl@0: Vertex3F vMoon = iMoonPositions[aTime%KMoonPositionCount]; sl@0: vMoon.iZ-=KModelDistanceFromCamera; sl@0: glTranslatef(vMoon.iX, vMoon.iY, vMoon.iZ); sl@0: sl@0: GLfloat mat_moon_specular[] = { 0.5, 0.5, 0.5, 1.0 }; sl@0: GLfloat mat_moon_shininess[] = { 500.0 }; sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_moon_specular); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_moon_specular); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_moon_specular); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_moon_shininess); sl@0: glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, mat_no_emission); sl@0: sl@0: iMoon->Draw(); sl@0: } sl@0: sl@0: void CModel::SetResolutionL(TInt aResolution) sl@0: { sl@0: aResolution *= 5; sl@0: if(aResolution > KMaxResolution) sl@0: { sl@0: aResolution = KMaxResolution; sl@0: } sl@0: if(aResolution < KMinResolution) sl@0: { sl@0: aResolution = KMinResolution; sl@0: } sl@0: iResolution = aResolution; sl@0: CSolidSphere* newSun = CSolidSphere::NewLC(KSunRadius, iResolution, iResolution); sl@0: CSolidSphere* newPlanet = CSolidSphere::NewLC(KPlanetRadius, iResolution, iResolution); sl@0: CSolidSphere* newMoon = CSolidSphere::NewLC(KMoonRadius, iResolution, iResolution); sl@0: SetShapes(newSun, newPlanet, newMoon); sl@0: CleanupStack::Pop(3, newSun); sl@0: } sl@0: