1 // Description:
2 // Starfield with nebulas.
3 //
4 // Copyright (C) 2001 Frank Becker
5 //
6 // This program is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free Software
8 // Foundation; either version 2 of the License, or (at your option) any later
9 // version.
10 //
11 // This program is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details
14 //
15 #include "Starfield.hpp"
16
17 #include <math.h>
18 #include <string>
19
20 #include <Trace.hpp>
21 #include <GameState.hpp>
22 #include <Random.hpp>
23 #include <Constants.hpp>
24 #include <BitmapManager.hpp>
25
26 using namespace std;
27
Starfield(void)28 Starfield::Starfield( void)
29 {
30 XTRACE();
31
32 _nebula = BitmapManagerS::instance()->getBitmap( "bitmaps/nebula");
33 if( !_nebula)
34 {
35 LOG_ERROR << "Unable to load nebula" << endl;
36 }
37 _nebulaIndex = _nebula->getIndex( "Nebula");
38 _nebulaHalfWidth = (float)(_nebula->getWidth( _nebulaIndex))/2.0f;
39 _nebulaHalfHeight= (float)(_nebula->getHeight( _nebulaIndex))/2.0f;
40 }
41
~Starfield()42 Starfield::~Starfield()
43 {
44 XTRACE();
45 }
46
init(float z)47 void Starfield::init( float z)
48 {
49 XTRACE();
50 for( int i=0; i<NUM_STARS; i++)
51 {
52 _starInfo[i].x = Random::rangef0_1()*200.0f - 100.0f;
53 _starInfo[i].y = Random::rangef0_1()*200.0f - 100.0f;
54 _starInfo[i].z = z;
55 _starInfo[i].d = Random::rangef0_1()*1.0f+0.25f;
56
57 _starInfo[i].r = Random::rangef0_1()*0.5;
58 _starInfo[i].g = Random::rangef0_1()*0.5;
59 _starInfo[i].b = Random::rangef0_1()*0.5;
60 }
61 for( int i=0; i<NUM_NEBULAS; i++)
62 {
63 pickSize( _nebulaInfo[i]);
64 _nebulaInfo[i].rot = Random::rangef0_1() * 360.0f;
65 findMax( _nebulaInfo[i]);
66
67 _nebulaInfo[i].x =(Random::rangef0_1() - 0.5f)*200.0f;
68 _nebulaInfo[i].y =(Random::rangef0_1() - 0.5f)*200.0f;
69 _nebulaInfo[i].d = Random::rangef0_1() * 1.50f+0.25f;
70
71 _nebulaInfo[i].z = z + i;
72 pickColor( _nebulaInfo[i]);
73 }
74
75 updatePrevs();
76 }
77
update(void)78 void Starfield::update( void)
79 {
80 // XTRACE();
81 updatePrevs();
82
83 for( int i=0; i<NUM_STARS; i++)
84 {
85 _starInfo[i].y -= _starInfo[i].d;
86 if( _starInfo[i].y < -100.0)
87 {
88 _starInfo[i].y = 100.0;
89 _prevStarInfoY[ i] = _starInfo[ i].y;
90 }
91 }
92 for( int i=0; i<NUM_NEBULAS; i++)
93 {
94 _nebulaInfo[i].y -= _nebulaInfo[i].d;
95 if( _nebulaInfo[i].y < (-50.0-_nebulaInfo[i].max))
96 {
97 pickSize( _nebulaInfo[i]);
98 _nebulaInfo[i].rot = Random::rangef0_1() * 360.0f;
99 findMax( _nebulaInfo[i]);
100
101 _nebulaInfo[i].x =(Random::rangef0_1() - 0.5f)*200.0f;
102 _nebulaInfo[i].y = 50.0f+_nebulaInfo[i].max;
103 _nebulaInfo[i].d = Random::rangef0_1() * 1.50f+0.25f;
104
105 _prevNebulaInfoY[ i] = _nebulaInfo[ i].y;
106
107 pickColor( _nebulaInfo[i]);
108 }
109 }
110 }
111
updatePrevs(void)112 void Starfield::updatePrevs( void)
113 {
114 // XTRACE();
115 for( int i=0; i<NUM_STARS; i++)
116 {
117 _prevStarInfoY[ i] = _starInfo[ i].y;
118 }
119 for( int i=0; i<NUM_NEBULAS; i++)
120 {
121 _prevNebulaInfoY[ i] = _nebulaInfo[ i].y;
122 }
123 }
124
draw(bool showStars,bool showNebulas)125 void Starfield::draw( bool showStars, bool showNebulas)
126 {
127 // XTRACE();
128 // glDisable(GL_DEPTH_TEST);
129 glDisable(GL_LIGHTING);
130
131 if( showStars)
132 {
133 GLfloat starVertices[NUM_STARS*3];
134 GLfloat starColors[NUM_STARS*4];
135
136 for( int i=0; i<NUM_STARS; i++)
137 {
138 float vy = _prevStarInfoY[i] +
139 (_starInfo[i].y - _prevStarInfoY[i])* GameState::frameFractionOther;
140
141 starVertices[i*3+0] = _starInfo[i].x;
142 starVertices[i*3+1] = vy;
143 starVertices[i*3+2] = _starInfo[i].z;
144
145 starColors[i*4+0] = _starInfo[i].r;
146 starColors[i*4+1] = _starInfo[i].g;
147 starColors[i*4+2] = _starInfo[i].b;
148 starColors[i*4+3] = 0.7;
149 }
150
151 glEnableClientState(GL_VERTEX_ARRAY);
152 glEnableClientState(GL_COLOR_ARRAY);
153
154 glVertexPointer(3, GL_FLOAT, 0, starVertices);
155 glColorPointer(4, GL_FLOAT, 0, starColors);
156
157 glDrawArrays(GL_POINTS, 0, NUM_STARS);
158
159 glDisableClientState(GL_VERTEX_ARRAY);
160 glDisableClientState(GL_COLOR_ARRAY);
161 }
162
163 if( showNebulas)
164 {
165 glEnable(GL_TEXTURE_2D);
166 bindTexture();
167 for( int i=0; i<NUM_NEBULAS; i++)
168 {
169 glPushMatrix();
170
171 float vy = _prevNebulaInfoY[i] +
172 (_nebulaInfo[i].y - _prevNebulaInfoY[i]) * GameState::frameFractionOther;
173
174 glColor4f( _nebulaInfo[i].r, _nebulaInfo[i].g, _nebulaInfo[i].b, 0.3f);
175 glTranslatef( _nebulaInfo[i].x, vy, _nebulaInfo[i].z);
176 glRotatef( _nebulaInfo[i].rot, 0,0,1);
177
178 _nebula->DrawC(
179 _nebulaIndex, 0, 0, _nebulaInfo[i].sizeX, _nebulaInfo[i].sizeY);
180
181 glPopMatrix();
182 }
183 glDisable(GL_TEXTURE_2D);
184 }
185
186 glEnable(GL_LIGHTING);
187 // glEnable(GL_DEPTH_TEST);
188 }
189
pickSize(Nebula & n)190 void Starfield::pickSize( Nebula &n)
191 {
192 n.sizeX = Random::rangef0_1()*1.2f + 0.4f;
193 n.sizeY = Random::rangef0_1()*1.2f + 0.4f;
194 }
195
findMax(Nebula & n)196 void Starfield::findMax( Nebula &n)
197 {
198 float sina = _nebulaHalfWidth *n.sizeX*sin( n.rot * ((float)M_PI/180.0f));
199 float cosa = _nebulaHalfHeight*n.sizeY*cos( n.rot * ((float)M_PI/180.0f));
200 float t1 = fabs(-sina + cosa);
201 float t2 = fabs(+sina + cosa);
202 n.max = max(t1,t2);
203 }
204
pickColor(Nebula & n)205 void Starfield::pickColor( Nebula &n)
206 {
207 //only use 2 color components
208 float r1 = Random::rangef0_1()+0.1f;
209 float r2 = Random::rangef0_1()+0.1f;
210
211 float d = 1.8f/(r1+r2);
212 r1 = r1*d;
213 r2 = r2*d;
214
215 int r = Random::random() % 3;
216 switch( r)
217 {
218 case 0:
219 n.r = r1;
220 n.g = r2;
221 n.b = 0.0;
222 break;
223 case 1:
224 n.r = 0.0;
225 n.g = r1;
226 n.b = r2;
227 break;
228 default:
229 case 2:
230 n.r = r1;
231 n.g = 0.0;
232 n.b = r2;
233 break;
234 }
235 }
236