~ubuntu-branches/debian/jessie/stellarium/jessie

« back to all changes in this revision

Viewing changes to src/projector.cpp

Tags: upstream-0.9.0
Import upstream version 0.9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Stellarium
3
 
 * Copyright (C) 2003 Fabien Chereau
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
 
#include <iostream>
21
 
#include <cstdio>
22
 
#include "projector.h"
23
 
#include "fisheye_projector.h"
24
 
#include "cylinder_projector.h"
25
 
#include "stereographic_projector.h"
26
 
#include "spheric_mirror_projector.h"
27
 
 
28
 
 
29
 
const char *Projector::typeToString(PROJECTOR_TYPE type) {
30
 
  switch (type) {
31
 
    case PERSPECTIVE_PROJECTOR:    return "perspective";
32
 
    case FISHEYE_PROJECTOR:        return "fisheye";
33
 
    case CYLINDER_PROJECTOR:       return "cylinder";
34
 
    case STEREOGRAPHIC_PROJECTOR:  return "stereographic";
35
 
    case SPHERIC_MIRROR_PROJECTOR: return "spheric_mirror";
36
 
  }
37
 
  cerr << "fatal: Projector::typeToString(" << type << ") failed" << endl;
38
 
  assert(0);
39
 
    // just shutup the compiler, this point will never be reached
40
 
  return 0;
41
 
}
42
 
 
43
 
Projector::PROJECTOR_TYPE Projector::stringToType(const string &s) {
44
 
  if (s=="perspective")    return PERSPECTIVE_PROJECTOR;
45
 
  if (s=="fisheye")        return FISHEYE_PROJECTOR;
46
 
  if (s=="cylinder")       return CYLINDER_PROJECTOR;
47
 
  if (s=="stereographic")  return STEREOGRAPHIC_PROJECTOR;
48
 
  if (s=="spheric_mirror") return SPHERIC_MIRROR_PROJECTOR;
49
 
  cerr << "fatal: Projector::stringToType(" << s << ") failed" << endl;
50
 
  assert(0);
51
 
    // just shutup the compiler, this point will never be reached
52
 
  return PERSPECTIVE_PROJECTOR;
53
 
}
54
 
 
55
 
const char *Projector::maskTypeToString(PROJECTOR_MASK_TYPE type) {
56
 
  if(type == DISK ) return "disk";
57
 
  else return "none";
58
 
}
59
 
 
60
 
Projector::PROJECTOR_MASK_TYPE Projector::stringToMaskType(const string &s) {
61
 
  if (s=="disk")    return DISK;
62
 
  return NONE;
63
 
}
64
 
 
65
 
 
66
 
Projector *Projector::create(PROJECTOR_TYPE type,
67
 
                             const Vec4i& viewport,
68
 
                             double _fov) {
69
 
  Projector *rval = 0;
70
 
  switch (type) {
71
 
    case PERSPECTIVE_PROJECTOR:
72
 
      rval = new Projector(viewport,_fov);
73
 
      break;
74
 
    case FISHEYE_PROJECTOR:
75
 
      rval = new FisheyeProjector(viewport,_fov);
76
 
      break;
77
 
    case CYLINDER_PROJECTOR:
78
 
      rval = new CylinderProjector(viewport,_fov);
79
 
      break;
80
 
    case STEREOGRAPHIC_PROJECTOR:
81
 
      rval = new StereographicProjector(viewport,_fov);
82
 
      break;
83
 
    case SPHERIC_MIRROR_PROJECTOR:
84
 
      rval = new SphericMirrorProjector(viewport,_fov);
85
 
      break;
86
 
  }
87
 
  if (rval == 0) {
88
 
    cerr << "fatal: Projector::create(" << type << ") failed" << endl;
89
 
    exit(1);
90
 
  }
91
 
    // just shutup the compiler, this point will never be reached
92
 
  return rval;
93
 
}
94
 
 
95
 
Projector::Projector(const Vec4i& viewport, double _fov)
96
 
          :maskType(NONE), fov(1.0), min_fov(0.0001), max_fov(100),
97
 
           zNear(0.1), zFar(10000),
98
 
           vec_viewport(viewport),
99
 
           flag_auto_zoom(0), gravityLabels(0)
100
 
{
101
 
        flip_horz = 1.0;
102
 
        flip_vert = 1.0;
103
 
        setViewport(viewport);
104
 
        set_fov(_fov);
105
 
}
106
 
 
107
 
Projector::~Projector()
108
 
{
109
 
}
110
 
 
111
 
// Init the viewing matrix, setting the field of view, the clipping planes, and screen ratio
112
 
// The function is a reimplementation of gluPerspective
113
 
void Projector::init_project_matrix(void)
114
 
{
115
 
        double f = 1./tan(fov*M_PI/360.);
116
 
        double ratio = (double)getViewportHeight()/getViewportWidth();
117
 
        mat_projection.set(     flip_horz*f*ratio, 0., 0., 0.,
118
 
                                                        0., flip_vert*f, 0., 0.,
119
 
                                                        0., 0., (zFar + zNear)/(zNear - zFar), -1.,
120
 
                                                        0., 0., (2.*zFar*zNear)/(zNear - zFar), 0.);
121
 
        glMatrixMode(GL_PROJECTION);
122
 
        glLoadMatrixd(mat_projection);
123
 
    glMatrixMode(GL_MODELVIEW);
124
 
}
125
 
 
126
 
void Projector::setViewport(int x, int y, int w, int h)
127
 
{
128
 
        vec_viewport[0] = x;
129
 
        vec_viewport[1] = y;
130
 
        vec_viewport[2] = w;
131
 
        vec_viewport[3] = h;
132
 
        center.set(vec_viewport[0]+vec_viewport[2]/2,vec_viewport[1]+vec_viewport[3]/2,0);
133
 
        view_scaling_factor = 1.0/fov*180./M_PI*MY_MIN(getViewportWidth(),getViewportHeight());
134
 
        glViewport(x, y, w, h);
135
 
        init_project_matrix();
136
 
}
137
 
 
138
 
void Projector::set_fov(double f)
139
 
{
140
 
        fov = f;
141
 
        if (f>max_fov) fov = max_fov;
142
 
        if (f<min_fov) fov = min_fov;
143
 
        view_scaling_factor = 1.0/fov*180./M_PI*MY_MIN(getViewportWidth(),getViewportHeight());
144
 
        init_project_matrix();
145
 
}
146
 
 
147
 
void Projector::setMaxFov(double max) {
148
 
  if (fov > max) set_fov(max);
149
 
  max_fov = max;
150
 
}
151
 
 
152
 
// Fill with black around the circle
153
 
void Projector::draw_viewport_shape(void)
154
 
{
155
 
        if (maskType != DISK) return;
156
 
 
157
 
        glDisable(GL_BLEND);
158
 
        glColor3f(0.f,0.f,0.f);
159
 
        set_orthographic_projection();
160
 
        glTranslatef(getViewportPosX()+getViewportWidth()/2,getViewportPosY()+getViewportHeight()/2,0.f);
161
 
        GLUquadricObj * p = gluNewQuadric();
162
 
        gluDisk(p, MY_MIN(getViewportWidth(),getViewportHeight())/2, getViewportWidth()+getViewportHeight(), 256, 1);  // should always cover whole screen
163
 
        gluDeleteQuadric(p);
164
 
        reset_perspective_projection();
165
 
}
166
 
 
167
 
void Projector::set_clipping_planes(double znear, double zfar)
168
 
{
169
 
        zNear = znear;
170
 
        zFar = zfar;
171
 
        init_project_matrix();
172
 
}
173
 
 
174
 
void Projector::change_fov(double deltaFov)
175
 
{
176
 
  // if we are zooming in or out
177
 
  if (deltaFov) set_fov(fov+deltaFov);
178
 
}
179
 
 
180
 
 
181
 
// Set the standard modelview matrices used for projection
182
 
void Projector::set_modelview_matrices( const Mat4d& _mat_earth_equ_to_eye,
183
 
                                        const Mat4d& _mat_helio_to_eye,
184
 
                                        const Mat4d& _mat_local_to_eye,
185
 
                                        const Mat4d& _mat_j2000_to_eye)
186
 
{
187
 
        mat_earth_equ_to_eye = _mat_earth_equ_to_eye;
188
 
        mat_j2000_to_eye = _mat_j2000_to_eye;
189
 
        mat_helio_to_eye = _mat_helio_to_eye;
190
 
        mat_local_to_eye = _mat_local_to_eye;
191
 
 
192
 
        inv_mat_earth_equ_to_eye = (mat_projection*mat_earth_equ_to_eye).inverse();
193
 
        inv_mat_j2000_to_eye = (mat_projection*mat_j2000_to_eye).inverse();
194
 
        inv_mat_helio_to_eye = (mat_projection*mat_helio_to_eye).inverse();
195
 
        inv_mat_local_to_eye = (mat_projection*mat_local_to_eye).inverse();     
196
 
}
197
 
 
198
 
// Update auto_zoom if activated
199
 
void Projector::update_auto_zoom(int delta_time)
200
 
{
201
 
        if (flag_auto_zoom)
202
 
        {
203
 
                // Use a smooth function
204
 
                double c;
205
 
 
206
 
                if( zoom_move.start > zoom_move.aim )
207
 
                {
208
 
                        // slow down as approach final view
209
 
                        c = 1 - (1-zoom_move.coef)*(1-zoom_move.coef)*(1-zoom_move.coef);
210
 
                }
211
 
                else
212
 
                {
213
 
                        // speed up as leave zoom target
214
 
                        c = (zoom_move.coef)*(zoom_move.coef)*(zoom_move.coef);
215
 
                }
216
 
 
217
 
                set_fov(zoom_move.start + (zoom_move.aim - zoom_move.start) * c);
218
 
                zoom_move.coef+=zoom_move.speed*delta_time;
219
 
                if (zoom_move.coef>=1.)
220
 
                {
221
 
                        flag_auto_zoom = 0;
222
 
                        set_fov(zoom_move.aim);
223
 
                }
224
 
        }
225
 
        /*
226
 
    if (flag_auto_zoom)
227
 
    {
228
 
                // Use a smooth function
229
 
                float smooth = 3.f;
230
 
                double c = atanf(smooth * 2.*zoom_move.coef-smooth)/atanf(smooth)/2+0.5;
231
 
                set_fov(zoom_move.start + (zoom_move.aim - zoom_move.start) * c);
232
 
        zoom_move.coef+=zoom_move.speed*delta_time;
233
 
        if (zoom_move.coef>=1.)
234
 
        {
235
 
                        flag_auto_zoom = 0;
236
 
            set_fov(zoom_move.aim);
237
 
        }
238
 
    }*/
239
 
}
240
 
 
241
 
// Zoom to the given field of view
242
 
void Projector::zoom_to(double aim_fov, float move_duration)
243
 
{
244
 
        zoom_move.aim=aim_fov;
245
 
    zoom_move.start=fov;
246
 
    zoom_move.speed=1.f/(move_duration*1000);
247
 
    zoom_move.coef=0.;
248
 
    flag_auto_zoom = true;
249
 
}
250
 
 
251
 
 
252
 
// Set the drawing mode in 2D. Use reset_perspective_projection() to reset
253
 
// previous projection mode
254
 
void Projector::set_orthographic_projection(void) const
255
 
{
256
 
        glMatrixMode(GL_PROJECTION);            // projection matrix mode
257
 
    glPushMatrix();                                             // store previous matrix
258
 
    glLoadIdentity();
259
 
    gluOrtho2D( vec_viewport[0], vec_viewport[0] + vec_viewport[2],
260
 
                                vec_viewport[1], vec_viewport[1] + vec_viewport[3]);    // set a 2D orthographic projection
261
 
        glMatrixMode(GL_MODELVIEW);                     // modelview matrix mode
262
 
    glPushMatrix();
263
 
    glLoadIdentity();
264
 
}
265
 
 
266
 
// Reset the previous projection mode after a call to set_orthographic_projection()
267
 
void Projector::reset_perspective_projection(void) const
268
 
{
269
 
    glMatrixMode(GL_PROJECTION);                // Restore previous matrix
270
 
    glPopMatrix();
271
 
    glMatrixMode(GL_MODELVIEW);
272
 
    glPopMatrix();
273
 
}
274
 
 
275
 
 
276
 
 
277
 
// Reimplementation of gluSphere : glu is overrided for non standard projection
278
 
 
279
 
void Projector::sSphere(GLdouble radius, GLdouble one_minus_oblateness,
280
 
                        GLint slices, GLint stacks,
281
 
                        const Mat4d& mat, int orient_inside) const {
282
 
  glPushMatrix();
283
 
  glLoadMatrixd(mat);
284
 
 
285
 
  if (one_minus_oblateness == 1.0) { // gluSphere seems to have hardware acceleration
286
 
    GLUquadricObj * p = gluNewQuadric();
287
 
    gluQuadricTexture(p,GL_TRUE);
288
 
    if (orient_inside) gluQuadricOrientation(p, GLU_INSIDE);
289
 
    gluSphere(p, radius, slices, stacks);
290
 
    gluDeleteQuadric(p);
291
 
  } else {
292
 
    //GLfloat rho, theta;
293
 
    GLfloat x, y, z;
294
 
    GLfloat s, t, ds, dt;
295
 
    GLint i, j;
296
 
    GLfloat nsign;
297
 
 
298
 
    if (orient_inside) nsign = -1.0;
299
 
    else nsign = 1.0;
300
 
 
301
 
    const GLfloat drho = M_PI / (GLfloat) stacks;
302
 
 
303
 
#if defined(__sun) || defined(__sun__)
304
 
        // in Sun C/C++ on Solaris 8 VLAs are not allowed, so let's use new double[]
305
 
    double* cos_sin_rho = new double[2 * (stacks + 1)];
306
 
#else
307
 
    double cos_sin_rho[2*(stacks+1)];
308
 
#endif
309
 
    double *cos_sin_rho_p = cos_sin_rho;
310
 
    for (i = 0; i <= stacks; i++) {
311
 
      double rho = i * drho;
312
 
      *cos_sin_rho_p++ = cos(rho);
313
 
      *cos_sin_rho_p++ = sin(rho);
314
 
    }
315
 
 
316
 
    const GLfloat dtheta = 2.0 * M_PI / (GLfloat) slices;
317
 
    double cos_sin_theta[2*(slices+1)];
318
 
    double *cos_sin_theta_p = cos_sin_theta;
319
 
    for (i = 0; i <= slices; i++) {
320
 
      double theta = (i == slices) ? 0.0 : i * dtheta;
321
 
      *cos_sin_theta_p++ = cos(theta);
322
 
      *cos_sin_theta_p++ = sin(theta);
323
 
    }
324
 
    // texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis
325
 
    // t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes)
326
 
    // cannot use triangle fan on texturing (s coord. at top/bottom tip varies)
327
 
    ds = 1.0 / slices;
328
 
    dt = 1.0 / stacks;
329
 
    t = 1.0;            // because loop now runs from 0
330
 
 
331
 
    // draw intermediate stacks as quad strips
332
 
    for (i = 0,cos_sin_rho_p = cos_sin_rho; i < stacks;
333
 
         i++,cos_sin_rho_p+=2)
334
 
    {
335
 
        glBegin(GL_QUAD_STRIP);
336
 
        s = 0.0;
337
 
        for (j = 0,cos_sin_theta_p = cos_sin_theta; j <= slices;
338
 
             j++,cos_sin_theta_p+=2)
339
 
        {
340
 
            x = -cos_sin_theta_p[1] * cos_sin_rho_p[1];
341
 
            y = cos_sin_theta_p[0] * cos_sin_rho_p[1];
342
 
            z = nsign * cos_sin_rho_p[0];
343
 
            glNormal3f(x * one_minus_oblateness * nsign,
344
 
                       y * one_minus_oblateness * nsign,
345
 
                       z * nsign);
346
 
            glTexCoord2f(s, t);
347
 
            sVertex3(x * radius,
348
 
                     y * radius,
349
 
                     one_minus_oblateness * z * radius, mat);
350
 
            x = -cos_sin_theta_p[1] * cos_sin_rho_p[3];
351
 
            y = cos_sin_theta_p[0] * cos_sin_rho_p[3];
352
 
            z = nsign * cos_sin_rho_p[2];
353
 
            glNormal3f(x * one_minus_oblateness * nsign,
354
 
                       y * one_minus_oblateness * nsign,
355
 
                       z * nsign);
356
 
            glTexCoord2f(s, t - dt);
357
 
            s += ds;
358
 
            sVertex3(x * radius,
359
 
                     y * radius,
360
 
                     one_minus_oblateness * z * radius, mat);
361
 
        }
362
 
        glEnd();
363
 
        t -= dt;
364
 
    }
365
 
#if defined(__sun) || defined(__sun__)
366
 
    delete[] cos_sin_rho;
367
 
#endif
368
 
  }
369
 
 
370
 
  glPopMatrix();
371
 
}
372
 
 
373
 
 
374
 
// Draw a half sphere
375
 
void Projector::sHalfSphere(GLdouble radius, GLint slices, GLint stacks,
376
 
        const Mat4d& mat, int orient_inside) const
377
 
{
378
 
        glPushMatrix();
379
 
        glLoadMatrixd(mat);
380
 
 
381
 
        GLfloat rho, drho, theta, dtheta;
382
 
        GLfloat x, y, z;
383
 
        GLfloat s, t, ds, dt;
384
 
        GLint i, j, imin, imax;
385
 
        GLfloat nsign;
386
 
 
387
 
        if (orient_inside) nsign = -1.0;
388
 
        else nsign = 1.0;
389
 
 
390
 
        drho = M_PI / (GLfloat) stacks;
391
 
        dtheta = 2.0 * M_PI / (GLfloat) slices;
392
 
 
393
 
        // texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis
394
 
        // t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes)
395
 
        // cannot use triangle fan on texturing (s coord. at top/bottom tip varies)
396
 
        ds = 1.0 / slices;
397
 
        dt = 1.0 / stacks;
398
 
        t = 1.0;                        // because loop now runs from 0
399
 
        imin = 0;
400
 
        imax = stacks;
401
 
 
402
 
        // draw intermediate stacks as quad strips
403
 
        for (i = imin; i < imax/2; i++)
404
 
        {
405
 
                rho = i * drho;
406
 
                glBegin(GL_QUAD_STRIP);
407
 
                s = 0.0;
408
 
                for (j = 0; j <= slices; j++)
409
 
                {
410
 
                        theta = (j == slices) ? 0.0 : j * dtheta;
411
 
                        x = -sin(theta) * sin(rho);
412
 
                        y = cos(theta) * sin(rho);
413
 
                        z = nsign * cos(rho);
414
 
                        glNormal3f(x * nsign, y * nsign, z * nsign);
415
 
                        glTexCoord2f(s, t);
416
 
                        sVertex3(x * radius, y * radius, z * radius, mat);
417
 
                        x = -sin(theta) * sin(rho + drho);
418
 
                        y = cos(theta) * sin(rho + drho);
419
 
                        z = nsign * cos(rho + drho);
420
 
                        glNormal3f(x * nsign, y * nsign, z * nsign);
421
 
                        glTexCoord2f(s, t - dt);
422
 
                        s += ds;
423
 
                        sVertex3(x * radius, y * radius, z * radius, mat);
424
 
                }
425
 
                glEnd();
426
 
                t -= dt;
427
 
        }
428
 
        glPopMatrix();
429
 
}
430
 
 
431
 
// Draw a disk with a special texturing mode having texture center at disk center
432
 
void Projector::sDisk(GLdouble radius, GLint slices, GLint stacks,
433
 
        const Mat4d& mat, int orient_inside) const
434
 
{
435
 
        glPushMatrix();
436
 
        glLoadMatrixd(mat);
437
 
 
438
 
        GLfloat r, dr, theta, dtheta;
439
 
        GLfloat x, y;
440
 
        GLint j;
441
 
        GLfloat nsign;
442
 
 
443
 
        if (orient_inside) nsign = -1.0;
444
 
        else nsign = 1.0;
445
 
 
446
 
        dr = radius / (GLfloat) stacks;
447
 
        dtheta = 2.0 * M_PI / (GLfloat) slices;
448
 
        if (slices < 0) slices = -slices;
449
 
 
450
 
        // draw intermediate stacks as quad strips
451
 
        for (r = 0; r < radius; r+=dr)
452
 
        {
453
 
                glBegin(GL_TRIANGLE_STRIP);
454
 
                for (j = 0; j <= slices; j++)
455
 
                {
456
 
                        theta = (j == slices) ? 0.0 : j * dtheta;
457
 
                        x = r*cos(theta);
458
 
                        y = r*sin(theta);
459
 
                        glNormal3f(0, 0, nsign);
460
 
                        glTexCoord2f(0.5+x/2/radius, 0.5+y/2/radius);
461
 
                        sVertex3(x, y, 0, mat);
462
 
                        x = (r+dr)*cos(theta);
463
 
                        y = (r+dr)*sin(theta);
464
 
                        glNormal3f(0, 0, nsign);
465
 
                        glTexCoord2f(0.5+x/2/radius, 0.5+y/2/radius);
466
 
                        sVertex3(x, y, 0, mat);
467
 
                }
468
 
                glEnd();
469
 
        }
470
 
        glPopMatrix();
471
 
}
472
 
 
473
 
void Projector::sRing(GLdouble r_min, GLdouble r_max,
474
 
                      GLint slices, GLint stacks,
475
 
                      const Mat4d& mat, int orient_inside) const {
476
 
  glPushMatrix();
477
 
  glLoadMatrixd(mat);
478
 
 
479
 
  double theta;
480
 
  double x,y;
481
 
  int j;
482
 
 
483
 
  const double nsign = (orient_inside)?-1.0:1.0;
484
 
 
485
 
  const double dr = (r_max-r_min) / stacks;
486
 
  const double dtheta = 2.0 * M_PI / slices;
487
 
  if (slices < 0) slices = -slices;
488
 
 
489
 
#if defined(__sun) || defined(__sun__)
490
 
  //in Sun C/C++ on Solaris 8 VLAs are not allowed, so let's use new double[]
491
 
  double *cos_sin_theta = new double[2*(slices+1)];
492
 
#else
493
 
  double cos_sin_theta[2*(slices+1)];
494
 
#endif
495
 
  double *cos_sin_theta_p = cos_sin_theta;
496
 
  for (j = 0; j <= slices; j++) {
497
 
    const double theta = (j == slices) ? 0.0 : j * dtheta;
498
 
    *cos_sin_theta_p++ = cos(theta);
499
 
    *cos_sin_theta_p++ = sin(theta);
500
 
  }
501
 
 
502
 
 
503
 
  // draw intermediate stacks as quad strips
504
 
  for (double r = r_min; r < r_max; r+=dr) {
505
 
    const double tex_r0 = (r-r_min)/(r_max-r_min);
506
 
    const double tex_r1 = (r+dr-r_min)/(r_max-r_min);
507
 
    glBegin(GL_QUAD_STRIP /*GL_TRIANGLE_STRIP*/);
508
 
    for (j=0,cos_sin_theta_p=cos_sin_theta;
509
 
         j<=slices;
510
 
         j++,cos_sin_theta_p+=2) {
511
 
      theta = (j == slices) ? 0.0 : j * dtheta;
512
 
      x = r*cos_sin_theta_p[0];
513
 
      y = r*cos_sin_theta_p[1];
514
 
      glNormal3d(0, 0, nsign);
515
 
      glTexCoord2d(tex_r0, 0.5);
516
 
      sVertex3(x, y, 0, mat);
517
 
      x = (r+dr)*cos_sin_theta_p[0];
518
 
      y = (r+dr)*cos_sin_theta_p[1];
519
 
      glNormal3d(0, 0, nsign);
520
 
      glTexCoord2d(tex_r1, 0.5);
521
 
      sVertex3(x, y, 0, mat);
522
 
    }
523
 
    glEnd();
524
 
  }
525
 
#if defined(__sun) || defined(__sun__)
526
 
    delete[] cos_sin_theta;
527
 
#endif  
528
 
  
529
 
  glPopMatrix();
530
 
}
531
 
 
532
 
static
533
 
inline void sSphereMapTexCoordFast(double rho_div_fov,
534
 
                                   double costheta, double sintheta)
535
 
{
536
 
        if (rho_div_fov>0.5) rho_div_fov=0.5;
537
 
        glTexCoord2d(0.5 + rho_div_fov * costheta,
538
 
                 0.5 + rho_div_fov * sintheta);
539
 
}
540
 
 
541
 
void Projector::sSphere_map(GLdouble radius, GLint slices, GLint stacks,
542
 
                            const Mat4d& mat, double texture_fov,
543
 
                            int orient_inside) const
544
 
{
545
 
    glPushMatrix();
546
 
    glLoadMatrixd(mat);
547
 
 
548
 
    double rho,x,y,z;
549
 
    int i, j;
550
 
    const double nsign = orient_inside?-1:1;
551
 
 
552
 
    const double drho = M_PI / stacks;
553
 
 
554
 
#if defined(__sun) || defined(__sun__)
555
 
        // in Sun C/C++ on Solaris 8 VLAs are not allowed, so let's use new double[]    
556
 
        double *cos_sin_rho = new double[2*(stacks+1)];
557
 
#else
558
 
    double cos_sin_rho[2*(stacks+1)];
559
 
#endif  
560
 
    double *cos_sin_rho_p = cos_sin_rho;
561
 
    for (i = 0; i <= stacks; i++) {
562
 
      const double rho = i * drho;
563
 
      *cos_sin_rho_p++ = cos(rho);
564
 
      *cos_sin_rho_p++ = sin(rho);
565
 
    }
566
 
 
567
 
    const double dtheta = 2.0 * M_PI / slices;
568
 
    double cos_sin_theta[2*(slices+1)];
569
 
    double *cos_sin_theta_p = cos_sin_theta;
570
 
    for (i = 0; i <= slices; i++) {
571
 
      const double theta = (i == slices) ? 0.0 : i * dtheta;
572
 
      *cos_sin_theta_p++ = cos(theta);
573
 
      *cos_sin_theta_p++ = sin(theta);
574
 
    }
575
 
 
576
 
 
577
 
    // texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis
578
 
    // t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes)
579
 
    // cannot use triangle fan on texturing (s coord. at top/bottom tip varies)
580
 
 
581
 
    const int imax = stacks;
582
 
 
583
 
    // draw intermediate stacks as quad strips
584
 
    if (!orient_inside) // nsign==1
585
 
    {
586
 
        for (i = 0,cos_sin_rho_p=cos_sin_rho,rho=0.0;
587
 
             i < imax; ++i,cos_sin_rho_p+=2,rho+=drho)
588
 
        {
589
 
            glBegin(GL_QUAD_STRIP);
590
 
            for (j=0,cos_sin_theta_p=cos_sin_theta;
591
 
                 j<=slices;++j,cos_sin_theta_p+=2)
592
 
            {
593
 
                x = -cos_sin_theta_p[1] * cos_sin_rho_p[1];
594
 
                y = cos_sin_theta_p[0] * cos_sin_rho_p[1];
595
 
                z = cos_sin_rho_p[0];
596
 
                glNormal3d(x * nsign, y * nsign, z * nsign);
597
 
                sSphereMapTexCoordFast(rho/texture_fov,
598
 
                                       cos_sin_theta_p[0],
599
 
                                       cos_sin_theta_p[1]);
600
 
                sVertex3(x * radius, y * radius, z * radius, mat);
601
 
 
602
 
                x = -cos_sin_theta_p[1] * cos_sin_rho_p[3];
603
 
                y = cos_sin_theta_p[0] * cos_sin_rho_p[3];
604
 
                z = cos_sin_rho_p[2];
605
 
                glNormal3d(x * nsign, y * nsign, z * nsign);
606
 
                sSphereMapTexCoordFast((rho + drho)/texture_fov,
607
 
                                       cos_sin_theta_p[0],
608
 
                                       cos_sin_theta_p[1]);
609
 
                sVertex3(x * radius, y * radius, z * radius, mat);
610
 
            }
611
 
            glEnd();
612
 
        }
613
 
    }
614
 
    else
615
 
    {
616
 
        for (i = 0,cos_sin_rho_p=cos_sin_rho,rho=0.0;
617
 
             i < imax; ++i,cos_sin_rho_p+=2,rho+=drho)
618
 
        {
619
 
            glBegin(GL_QUAD_STRIP);
620
 
            for (j=0,cos_sin_theta_p=cos_sin_theta;
621
 
                 j<=slices;++j,cos_sin_theta_p+=2)
622
 
            {
623
 
                x = -cos_sin_theta_p[1] * cos_sin_rho_p[3];
624
 
                y = cos_sin_theta_p[0] * cos_sin_rho_p[3];
625
 
                z = cos_sin_rho_p[2];
626
 
                glNormal3d(x * nsign, y * nsign, z * nsign);
627
 
                sSphereMapTexCoordFast((rho + drho)/texture_fov,
628
 
                                       cos_sin_theta_p[0],
629
 
                                       -cos_sin_theta_p[1]);
630
 
                sVertex3(x * radius, y * radius, z * radius, mat);
631
 
 
632
 
                x = -cos_sin_theta_p[1] * cos_sin_rho_p[1];
633
 
                y = cos_sin_theta_p[0] * cos_sin_rho_p[1];
634
 
                z = cos_sin_rho_p[0];
635
 
                glNormal3d(x * nsign, y * nsign, z * nsign);
636
 
                sSphereMapTexCoordFast(rho/texture_fov,
637
 
                                       cos_sin_theta_p[0],
638
 
                                       -cos_sin_theta_p[1]);
639
 
                sVertex3(x * radius, y * radius, z * radius, mat);
640
 
            }
641
 
            glEnd();
642
 
        }
643
 
    }
644
 
#if defined(__sun) || defined(__sun__)
645
 
    delete[] cos_sin_rho;
646
 
#endif  
647
 
        
648
 
    glPopMatrix();
649
 
}
650
 
 
651
 
 
652
 
// Reimplementation of gluCylinder : glu is overrided for non standard projection
653
 
void Projector::sCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks, const Mat4d& mat, int orient_inside) const
654
 
{
655
 
        glPushMatrix();
656
 
        glLoadMatrixd(mat);
657
 
        GLUquadricObj * p = gluNewQuadric();
658
 
        gluQuadricTexture(p,GL_TRUE);
659
 
        if (orient_inside)
660
 
        {
661
 
                glCullFace(GL_FRONT);
662
 
        }
663
 
        gluCylinder(p, radius, radius, height, slices, stacks);
664
 
        gluDeleteQuadric(p);
665
 
        glPopMatrix();
666
 
        if (orient_inside)
667
 
        {
668
 
                glCullFace(GL_BACK);
669
 
        }
670
 
}
671
 
 
672
 
 
673
 
void Projector::print_gravity180(s_font* font, float x, float y, const wstring& ws,
674
 
                                 bool speed_optimize, float xshift, float yshift) const
675
 
{
676
 
        static float dx, dy, d, theta, psi;
677
 
        dx = x - (vec_viewport[0] + vec_viewport[2]/2);
678
 
        dy = y - (vec_viewport[1] + vec_viewport[3]/2);
679
 
        d = sqrt(dx*dx + dy*dy);
680
 
        
681
 
        // If the text is too far away to be visible in the screen return
682
 
        if (d>MY_MAX(vec_viewport[3], vec_viewport[2])*2) return;
683
 
 
684
 
 
685
 
        theta = M_PI + atan2f(dx, dy - 1);
686
 
        psi = atan2f((float)font->getStrLen(ws)/ws.length(),d + 1) * 180./M_PI;
687
 
 
688
 
        if (psi>5) psi = 5;
689
 
        set_orthographic_projection();
690
 
        glTranslatef(x,y,0);
691
 
        if(gravityLabels) glRotatef(theta*180./M_PI,0,0,-1);
692
 
        glTranslatef(xshift, -yshift, 0);
693
 
        glScalef(1, -1, 1);
694
 
        
695
 
    glEnable(GL_BLEND);
696
 
        glEnable(GL_TEXTURE_2D);
697
 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Normal transparency mode
698
 
        for (unsigned int i=0;i<ws.length();++i)
699
 
        {
700
 
 
701
 
                if (ws[i]>=16 && ws[i]<=18) {
702
 
                        // handle hilight colors (TUI)
703
 
 
704
 
                        // Note: this is hard coded - not generalized
705
 
 
706
 
                        if( ws[i]==17 ) glColor3f(0.5,1,0.5);  // normal
707
 
                        if( ws[i]==18 ) glColor3f(1,1,1);    // hilight
708
 
 
709
 
                } else {
710
 
 
711
 
                        if( !speed_optimize ) {
712
 
                                font->print_char_outlined(ws[i]);
713
 
                        } else {
714
 
                                font->print_char(ws[i]);
715
 
                        }
716
 
 
717
 
                        // with typeface need to manually advance
718
 
                        // TODO, absolute rotation would be better than relative
719
 
                        // TODO: would look better with kerning information...
720
 
                        glTranslatef(font->getStrLen(ws.substr(i,1)) * 1.05, 0, 0);
721
 
 
722
 
                        if( !speed_optimize ) {
723
 
                                psi = atan2f((float)font->getStrLen(ws.substr(i,1))*1.05,d) * 180./M_PI;
724
 
                                if (psi>5) psi = 5;
725
 
                        }
726
 
 
727
 
                        // keep text horizontal if gravity labels off
728
 
                        if(gravityLabels) glRotatef(psi,0,0,-1);        
729
 
                }
730
 
 
731
 
        }
732
 
        reset_perspective_projection();
733
 
}
734