~ubuntu-branches/debian/squeeze/stellarium/squeeze

« back to all changes in this revision

Viewing changes to src/meteor.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cédric Delfosse
  • Date: 2008-05-19 21:28:23 UTC
  • mfrom: (3.1.5 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080519212823-m5nfiuntxstxzxj7
Tags: 0.9.1-4
Add libxcursor-dev, libxfixes-dev, libxinerama-dev, libqt4-opengl-dev to
build-deps (Closes: #479906)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Stellarium
3
 
 * This file Copyright (C) 2004 Robert Spearman
4
 
 * 
5
 
 * This program is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU General Public License
7
 
 * as published by the Free Software Foundation; either version 2
8
 
 * of the License, or (at your option) any later version.
9
 
 * 
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 * 
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 
 */
19
 
 
20
 
// This is an ad hoc meteor model
21
 
// Could use a simple ablation physics model in the future
22
 
 
23
 
/*
24
 
NOTE: Here the radiant is always along the ecliptic at the apex of the Earth's way.
25
 
In reality, individual meteor streams have varying velocity vectors and therefore radiants
26
 
which are generally not at the apex of the Earth's way, such as the Perseids shower.
27
 
*/
28
 
 
29
 
// Improved realism and efficiency 2004-12
30
 
 
31
 
#include <cstdlib>
32
 
#include "meteor.h"
33
 
 
34
 
Meteor::Meteor(Projector *proj, Navigator* nav, ToneReproductor* eye, double v)
35
 
{
36
 
  //  velocity = 11+(double)rand()/((double)RAND_MAX+1)*v;  // abs range 11-72 km/s
37
 
  velocity=v;
38
 
 
39
 
  max_mag = 1;
40
 
 
41
 
  // determine meteor model view matrix (want z in dir of travel of earth, z=0 at center of earth)
42
 
  // meteor life is so short, no need to recalculate
43
 
  double equ_rotation; // rotation needed to align with path of earth
44
 
  Vec3d sun_dir = nav->helio_to_earth_equ( Vec3d(0,0,0) );
45
 
 
46
 
  Mat4d tmat = Mat4d::xrotation(-23.45f*M_PI/180.f);  // ecliptical tilt
47
 
  sun_dir.transfo4d(tmat);  // convert to ecliptical coordinates
48
 
  sun_dir.normalize();
49
 
  equ_rotation = acos( sun_dir.dot( Vec3d(1,0,0) ) );
50
 
  if( sun_dir[1] < 0 ) equ_rotation = 2*M_PI - equ_rotation;
51
 
 
52
 
  equ_rotation -= M_PI_2;
53
 
 
54
 
  mmat = Mat4d::xrotation(23.45f*M_PI/180.f) * Mat4d::zrotation(equ_rotation) * Mat4d::yrotation(M_PI_2);
55
 
 
56
 
 
57
 
  // select random trajectory using polar coordinates in XY plane, centered on observer
58
 
  xydistance = (double)rand()/((double)RAND_MAX+1)*(VISIBLE_RADIUS);
59
 
  double angle = (double)rand()/((double)RAND_MAX+1)*2*M_PI;
60
 
 
61
 
  // find observer position in meteor coordinate system
62
 
  obs = nav->local_to_earth_equ(Vec3d(0,0,EARTH_RADIUS));
63
 
  obs.transfo4d(mmat.transpose());
64
 
 
65
 
  // set meteor start x,y
66
 
  pos_internal[0] = pos_train[0] = position[0] = xydistance*cos(angle) +obs[0];
67
 
  pos_internal[1] = pos_train[1] = position[1] = xydistance*sin(angle) +obs[1];
68
 
 
69
 
  // determine life of meteor (start and end z value based on atmosphere burn altitudes)
70
 
 
71
 
  // D is distance from center of earth
72
 
  double D = sqrt( position[0]*position[0] + position[1]*position[1] );
73
 
 
74
 
  if( D > EARTH_RADIUS+HIGH_ALTITUDE ) {
75
 
    // won't be visible
76
 
    alive = 0;
77
 
    return;
78
 
  }
79
 
 
80
 
  start_h = sqrt( pow(EARTH_RADIUS+HIGH_ALTITUDE,2) - D*D);
81
 
 
82
 
  // determine end of burn point, and nearest point to observer for distance mag calculation
83
 
  // mag should be max at nearest point still burning
84
 
  if( D > EARTH_RADIUS+LOW_ALTITUDE ) {
85
 
    end_h = -start_h;  // earth grazing
86
 
    min_dist = xydistance;
87
 
  } else {
88
 
    end_h = sqrt( pow(EARTH_RADIUS+LOW_ALTITUDE,2) - D*D);
89
 
    min_dist = sqrt( xydistance*xydistance + pow( end_h - obs[2], 2) );
90
 
  }
91
 
 
92
 
  if(min_dist > VISIBLE_RADIUS ) {
93
 
    // on average, not visible (although if were zoomed ...)
94
 
    alive = 0;
95
 
    return;
96
 
  }
97
 
    
98
 
  /* experiment
99
 
  // limit lifetime to 0.5-3.0 sec
100
 
  double tmp_h = start_h - velocity * (0.5 + (double)rand()/((double)RAND_MAX+1) * 2.5);
101
 
  if( tmp_h > end_h ) {
102
 
    end_h = tmp_h;
103
 
  }
104
 
  */
105
 
 
106
 
  pos_train[2] = position[2] = start_h;
107
 
 
108
 
  //  printf("New meteor: %f %f s:%f e:%f v:%f\n", position[0], position[1], start_h, end_h, velocity);
109
 
 
110
 
  alive = 1;
111
 
  train=0;
112
 
 
113
 
  // Determine drawing color given magnitude and eye 
114
 
  // (won't be visible during daylight)
115
 
 
116
 
  // *** color varies somewhat based on velocity, plus atmosphere reddening
117
 
 
118
 
  // determine intensity
119
 
  float Mag1 = (double)rand()/((double)RAND_MAX+1)*6.75f - 3;
120
 
  float Mag2 = (double)rand()/((double)RAND_MAX+1)*6.75f - 3;
121
 
  float Mag = (Mag1 + Mag2)/2.0f;
122
 
 
123
 
  mag = (5. + Mag) / 256.0;
124
 
  if (mag>250) mag = mag - 256;
125
 
 
126
 
  float term1 = expf(-0.92103f*(mag + 12.12331f)) * 108064.73f;
127
 
 
128
 
  float cmag=1.f;
129
 
  float rmag;
130
 
 
131
 
  // Compute the equivalent star luminance for a 5 arc min circle and convert it
132
 
  // in function of the eye adaptation
133
 
  rmag = eye->adapt_luminance(term1);
134
 
  rmag = rmag/powf(proj->get_fov(),0.85f)*50.f;
135
 
 
136
 
  // if size of star is too small (blink) we put its size to 1.2 --> no more blink
137
 
  // And we compensate the difference of brighteness with cmag
138
 
  if (rmag<1.2f) {
139
 
    cmag=rmag*rmag/1.44f;
140
 
  }
141
 
 
142
 
  mag = cmag;  // assumes white
143
 
 
144
 
  // most visible meteors are under about 180km distant
145
 
  // scale max mag down if outside this range 
146
 
  float scale = 1;
147
 
  if(min_dist!=0) scale = 180*180/(min_dist*min_dist);
148
 
  if( scale < 1 ) mag *= scale;
149
 
 
150
 
}
151
 
 
152
 
Meteor::~Meteor()
153
 
{   
154
 
}
155
 
 
156
 
// returns true if alive
157
 
bool Meteor::update(int delta_time)
158
 
{
159
 
 
160
 
  if(!alive) return(0);
161
 
 
162
 
  if( position[2] < end_h ) {
163
 
    // burning has stopped so magnitude fades out
164
 
    // assume linear fade out
165
 
 
166
 
    mag -= max_mag * (double)delta_time/500.0f;
167
 
    if( mag < 0 ) alive=0;  // no longer visible
168
 
 
169
 
  }
170
 
 
171
 
  // *** would need time direction multiplier to allow reverse time replay
172
 
  position[2] = position[2] - velocity/1000.0f*(double)delta_time;
173
 
 
174
 
  // train doesn't extend beyond start of burn
175
 
  if( position[2] + velocity*0.5f > start_h ) {
176
 
    pos_train[2] = start_h ;
177
 
  } else {
178
 
    pos_train[2] -= velocity*(double)delta_time/1000.0f;
179
 
  }
180
 
 
181
 
  //printf("meteor position: %f delta_t %d\n", position[2], delta_time);
182
 
 
183
 
  // determine visual magnitude based on distance to observer
184
 
  double dist = sqrt( xydistance*xydistance + pow( position[2]-obs[2], 2) );
185
 
 
186
 
  if( dist == 0 ) dist = .01;  // just to be cautious (meteor hits observer!)
187
 
 
188
 
  dist_multiplier = min_dist*min_dist / (dist*dist);
189
 
 
190
 
  return(alive);
191
 
}
192
 
 
193
 
 
194
 
// returns true if visible
195
 
bool Meteor::draw(Projector *proj, Navigator* nav)
196
 
{
197
 
 
198
 
        if(!alive) return(0);
199
 
 
200
 
        Vec3d start, end;
201
 
 
202
 
        Vec3d spos = position;
203
 
        Vec3d epos = pos_train;
204
 
 
205
 
        // convert to equ
206
 
        spos.transfo4d(mmat);
207
 
        epos.transfo4d(mmat);
208
 
 
209
 
        // convert to local and correct for earth radius [since equ and local coordinates in stellarium use same 0 point!] 
210
 
        spos = nav->earth_equ_to_local( spos );
211
 
        epos = nav->earth_equ_to_local( epos );
212
 
        spos[2] -= EARTH_RADIUS;
213
 
        epos[2] -= EARTH_RADIUS;
214
 
 
215
 
        int t1 = proj->project_local_check(spos/1216, start);  // 1216 is to scale down under 1 for desktop version
216
 
        int t2 = proj->project_local_check(epos/1216, end);
217
 
 
218
 
        // don't draw if not visible (but may come into view)
219
 
        if( t1 + t2 == 0 ) return 1;
220
 
 
221
 
        //  printf("[%f %f %f] (%d, %d) (%d, %d)\n", position[0], position[1], position[2], (int)start[0], (int)start[1], (int)end[0], (int)end[1]);
222
 
 
223
 
        if( train ) {
224
 
                // connect this point with last drawn point
225
 
 
226
 
                double tmag = mag*dist_multiplier;
227
 
 
228
 
                // compute an intermediate point so can curve slightly along projection distortions
229
 
                Vec3d intpos;
230
 
                Vec3d posi = pos_internal; 
231
 
                posi[2] = position[2] + (pos_train[2] - position[2])/2;
232
 
                posi.transfo4d(mmat);
233
 
                posi = nav->earth_equ_to_local( posi );
234
 
                posi[2] -= EARTH_RADIUS;
235
 
                proj->project_local(posi/1216, intpos);
236
 
 
237
 
                // draw dark to light
238
 
                glBegin(GL_LINE_STRIP);
239
 
                glColor4f(0,0,0,0);
240
 
                glVertex3f(end[0],end[1],0);
241
 
                glColor4f(1,1,1,tmag/2);
242
 
                glVertex3f(intpos[0],intpos[1],0);
243
 
                glColor4f(1,1,1,tmag);
244
 
                glVertex3f(start[0],start[1],0);
245
 
                glEnd();
246
 
        } else {
247
 
                //glPointSize(1); // glpoint is not portable...
248
 
                glBegin(GL_POINTS);
249
 
                glVertex3f(start[0],start[1],0);
250
 
                glEnd();
251
 
        }
252
 
 
253
 
        /*  
254
 
        // TEMP - show radiant
255
 
        Vec3d radiant = Vec3d(0,0,0.5f);
256
 
        radiant.transfo4d(mmat);
257
 
        if( projection->project_earth_equ(radiant, start) ) {
258
 
    glColor3f(1,0,1);
259
 
    glBegin(GL_LINES);
260
 
    glVertex3f(start[0]-10,start[1],0);
261
 
    glVertex3f(start[0]+10,start[1],0);
262
 
    glEnd();
263
 
 
264
 
    glBegin(GL_LINES);
265
 
    glVertex3f(start[0],start[1]-10,0);
266
 
    glVertex3f(start[0],start[1]+10,0);
267
 
    glEnd();
268
 
        }
269
 
        */
270
 
 
271
 
        train = 1;
272
 
 
273
 
        return(1);
274
 
}
275
 
 
276
 
bool Meteor::is_alive(void)
277
 
{
278
 
  return(alive);
279
 
}