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; }