www.pudn.com > RCApp-src.zip > SpaceDome.cpp


/* 
	RedEye Project (http://members.ozemail.com.au/~ndmcevoy/) 
	Copyright (C) 2003  Nick McEvoy 
 
	This library is free software; you can redistribute it and/or 
	modify it under the terms of the GNU Library General Public 
	License as published by the Free Software Foundation; either 
	version 2 of the License, or (at your option) any later version. 
 
	This library is distributed in the hope that it will be useful, 
	but WITHOUT ANY WARRANTY; without even the implied warranty of 
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
	Library General Public License for more details. 
 
	You should have received a copy of the GNU Library General Public 
	License along with this library; if not, write to the Free 
	Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 
	----------------------------------------------------------------- 
 
		Commented for use with Doxygen (http://www.doxygen.org) 
 
	----------------------------------------------------------------- 
*/ 
 
/*! \file SpaceDome.cpp 
 *	\brief Game space dome. 
 * 
 *		This file contains the game space dome. 
 */ 
 
// System includes 
#include  
#include  
 
// PLIB includes 
#include  
#include  
 
// RedEye includes 
#include "SpaceDome.h" 
 
 
 
 
static int 
sgStarPreDraw(ssgEntity* e) 
{ 
	ssgLeaf* f = (ssgLeaf*)e; 
 
	if (f->hasState()) 
		f->getState()->apply(); 
 
	glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_FOG_BIT); 
 
	glDisable(GL_DEPTH_TEST); 
	glDisable(GL_FOG); 
 
	return true; 
} 
 
 
 
 
static int 
sgStarPostDraw(ssgEntity* e) 
{ 
	glPopAttrib(); 
 
	return true; 
} 
 
 
 
 
reSpaceDome::reSpaceDome() 
{ 
	// Initialise data 
	mpStars = NULL; 
	mpStarsFixedTransform = NULL; 
	mpStarsMovingTransform = NULL; 
	mpStateFixed = NULL; 
	mpStateMoving = NULL; 
	mpColourListFixed = NULL; 
	mpVertexListFixed = NULL; 
	mpColourListMoving = NULL; 
	mpVertexListMoving = NULL; 
	mfRadius = 0.0f; 
	sgZeroVec3(mLastStarPos); 
} 
 
 
 
 
reSpaceDome::~reSpaceDome() 
{ 
	if (mpStars) 
	{ 
		ssgDeRefDelete(mpStars); 
	} 
} 
 
 
 
 
ssgBranch* 
reSpaceDome::Build(int iNumFixedStars, int iNumMovingStars, float fRadius) 
{ 
	// Clean-up any previous build 
	if (mpStars) 
	{ 
		ssgDeRefDelete(mpStars); 
	} 
 
	mpStars = new ssgBranch; 
	mfRadius = fRadius; 
 
	if (iNumFixedStars > 0) 
	{ 
		sgVec4 colour; 
 
		// Set up the stars mpStateFixed 
		mpStateFixed = new ssgSimpleState(); 
		mpStateFixed->disable(GL_LIGHTING); 
		mpStateFixed->disable(GL_CULL_FACE); 
		mpStateFixed->disable(GL_TEXTURE_2D); 
		mpStateFixed->enable(GL_COLOR_MATERIAL); 
		mpStateFixed->setColourMaterial(GL_AMBIENT_AND_DIFFUSE); 
		mpStateFixed->setMaterial(GL_EMISSION, 0, 0, 0, 1); 
		mpStateFixed->setMaterial(GL_SPECULAR, 0, 0, 0, 1); 
		mpStateFixed->enable(GL_BLEND); 
		mpStateFixed->disable(GL_ALPHA_TEST); 
 
		mpVertexListFixed = new ssgVertexArray(iNumFixedStars); 
		mpColourListFixed = new ssgColourArray(iNumFixedStars); 
 
		// Build the fixed stars sphere 
		sgVec3 p; 
		for (int i = 0; i < iNumFixedStars; i++) 
		{ 
			float fRndA = (float)rand(); 
			float fRndB = (float)rand(); 
 
			float fA = fRndA/(float)RAND_MAX; 
			float fB = fRndB/(float)RAND_MAX; 
			float theta = fA * 2 * SG_PI; 
			float fF = (2 * fB) - 1; 
			float phi = (float)asin(fF); 
			float x = mfRadius * (float)cos(theta)*(float)cos(phi); 
			float y = mfRadius * (float)sin(theta)*(float)cos(phi); 
			float z = mfRadius * (float)sin(phi); 
 
			// Position the fixed stars 
			sgSetVec3(p, x, y, z); 
			mpVertexListFixed->add(p); 
 
			// Colour (magnitude) 
			float fRed = (float)rand()/(float)RAND_MAX; 
			float fGreen = (float)rand()/(float)RAND_MAX; 
			float fBlue = (float)rand()/(float)RAND_MAX; 
			float fAlpha = (float)rand()/(float)RAND_MAX; 
			sgSetVec4(colour, fRed, fGreen, fBlue, fAlpha); 
			mpColourListFixed->add(colour); 
		} 
 
		ssgLeaf *stars_obj =  
		new ssgVtxTable(GL_POINTS, mpVertexListFixed, NULL, NULL, mpColourListFixed); 
		stars_obj->setState(mpStateFixed); 
		stars_obj->setCallback(SSG_CALLBACK_PREDRAW, sgStarPreDraw); 
		stars_obj->setCallback(SSG_CALLBACK_POSTDRAW, sgStarPostDraw); 
 
		mpStarsFixedTransform = new ssgTransform; 
 
		mpStarsFixedTransform->addKid(stars_obj); 
 
		mpStars->addKid(mpStarsFixedTransform); 
	} 
 
	if (iNumMovingStars > 0) 
	{ 
		sgVec4 colour; 
 
		// Set up the stars mpStateMoving 
		mpStateMoving = new ssgSimpleState(); 
		mpStateMoving->disable(GL_LIGHTING); 
		mpStateMoving->disable(GL_CULL_FACE); 
		mpStateMoving->disable(GL_TEXTURE_2D); 
		mpStateMoving->enable(GL_COLOR_MATERIAL); 
		mpStateMoving->setColourMaterial(GL_AMBIENT_AND_DIFFUSE); 
		mpStateMoving->setMaterial(GL_EMISSION, 0, 0, 0, 1); 
		mpStateMoving->setMaterial(GL_SPECULAR, 0, 0, 0, 1); 
		mpStateMoving->enable(GL_BLEND); 
		mpStateMoving->disable(GL_ALPHA_TEST); 
 
		mpVertexListMoving = new ssgVertexArray(iNumMovingStars); 
		mpColourListMoving = new ssgColourArray(iNumMovingStars); 
 
		// Build the moving stars sphere 
		sgVec3 p; 
		for (int i = 0; i < iNumFixedStars; i++) 
		{ 
			float fRndA = (float)rand(); 
			float fRndB = (float)rand(); 
			float fRndC = (float)rand(); 
 
			float fA = fRndA/(float)RAND_MAX; 
			float fB = fRndB/(float)RAND_MAX; 
			float fC = (fRndC/(float)RAND_MAX)*mfRadius; 
 
			float theta = fA * 2 * SG_PI; 
			float fF = (2 * fB) - 1; 
			float phi = (float)asin(fF); 
			float x = fC * (float)cos(theta)*(float)cos(phi); 
			float y = fC * (float)sin(theta)*(float)cos(phi); 
			float z = fC * (float)sin(phi); 
 
			// Position the moving stars 
			sgSetVec3(p, x, y, z); 
			mpVertexListMoving->add(p); 
 
			// Colour (magnitude) 
			sgSetVec4(colour, 0.9f, 0.9f, 0.9f, 1.0f); 
			mpColourListMoving->add(colour); 
		} 
 
		ssgLeaf *stars_obj =  
		new ssgVtxTable(GL_POINTS, mpVertexListMoving, NULL, NULL, mpColourListMoving); 
		stars_obj->setState(mpStateMoving); 
		stars_obj->setCallback(SSG_CALLBACK_PREDRAW, sgStarPreDraw); 
		stars_obj->setCallback(SSG_CALLBACK_POSTDRAW, sgStarPostDraw); 
 
		mpStarsMovingTransform = new ssgTransform; 
 
		mpStarsMovingTransform->addKid(stars_obj); 
 
		mpStars->addKid(mpStarsMovingTransform); 
	} 
 
	// Keep a reference 
	mpStars->ref(); 
 
	return mpStars; 
} 
 
 
 
 
bool 
reSpaceDome::Reposition(const sgVec3& StarPos, float fAngle) 
{ 
	sgMat4 T1, GST; 
	sgVec3 Axis; 
	int i; 
 
	// Position fixed & moving stars 
	sgMakeTransMat4(T1, StarPos); 
 
	sgSetVec3(Axis, 0.0f, 0.0f, -1.0f); 
	sgMakeRotMat4(GST, fAngle, Axis); 
 
	sgMat4 TRANSFORM; 
	sgCopyMat4(TRANSFORM, T1); 
	sgPreMultMat4(TRANSFORM, GST); 
 
	sgCoord starpos; 
	sgSetCoord(&starpos, TRANSFORM); 
 
	if (mpStarsFixedTransform) 
		mpStarsFixedTransform->setTransform(&starpos); 
 
	if (mpStarsMovingTransform) 
		mpStarsMovingTransform->setTransform(&starpos); 
 
	// Fixed stars - make them twinkle :-) 
	for (i = 0; i < mpColourListFixed->getNum(); i++) 
	{ 
		float fTwinkle = (float)rand()/(float)RAND_MAX; 
 
		if (fTwinkle > 0.98) 
		{ 
			float* pStarColour = mpColourListFixed->get(i); 
 
			float fRed = (float)rand()/(float)RAND_MAX; 
			float fGreen = (float)rand()/(float)RAND_MAX; 
			float fBlue = (float)rand()/(float)RAND_MAX; 
			float fAlpha = (float)rand()/(float)RAND_MAX; 
			sgSetVec4(pStarColour, fRed, fGreen, fBlue, fAlpha); 
		} 
	} 
 
	// Moving stars - make them move 
	sgVec3 Diff; 
	sgSubVec3(Diff, StarPos, mLastStarPos); 
	for (i = 0; i < mpVertexListMoving->getNum(); i++) 
	{ 
		float* pStarPos = mpVertexListMoving->get(i); 
 
		// Position our moving star 
		sgSetVec3(pStarPos, 
			pStarPos[SG_X] - Diff[SG_X], 
			pStarPos[SG_Y] - Diff[SG_Y], 
			pStarPos[SG_Z] - Diff[SG_Z]); 
 
		// If star moved too far away - randomly reposition it 
		if (sgLengthSquaredVec3(pStarPos) > sgSquare(mfRadius)) 
		{ 
			float fRndA = (float)rand(); 
			float fRndB = (float)rand(); 
 
			float fA = fRndA/(float)RAND_MAX; 
			float fB = fRndB/(float)RAND_MAX; 
 
			float theta = fA * 2 * SG_PI; 
			float fF = (2 * fB) - 1; 
			float phi = (float)asin(fF); 
			float x = mfRadius * (float)cos(theta)*(float)cos(phi); 
			float y = mfRadius * (float)sin(theta)*(float)cos(phi); 
			float z = mfRadius * (float)sin(phi); 
 
			sgSetVec3(pStarPos, x, y, z); 
		} 
	} 
 
	sgCopyVec3(mLastStarPos, StarPos); 
 
	return true; 
}