3
* Copyright (C) 2003 Fabien Chereau
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.
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.
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.
30
#include "Mapping.hpp"
31
#include "SphereGeometry.hpp"
36
//! Provides functions for drawing operations which are performed with some sort of
37
//! "projection" according to the current projection mode. This projection
38
//! distorts the shape of the objects to be drawn and make the necessary calls
39
//! to OpenGL to draw the required object. This class overrides a number of openGL
40
//! functions to enable non-linear projection, such as fisheye or stereographic
41
//! projections. This class also provide drawing primitives that are optimized
42
//! according to the projection mode.
46
//! Supported reference frame types
55
///////////////////////////////////////////////////////////////////////////
57
Projector(const Vector4<GLint>& viewport, double _fov = 60.);
60
//! Initialise the Projector.
61
//! - Sets the viewport size according to the window/screen size and settings
62
//! in the ini parser object.
63
//! - Sets the maximum field of view for each projection type.
64
//! - Register each projection type.
65
//! - Sets the flag to use gravity labels or not according to the ini parser
67
//! - Sets the default projection mode and field of view.
68
//! - Sets whether to use GL points or a spite, according to the ini parser
69
//! object and the detected hardware capabilities.
71
//! @param conf The ini parser object.
72
void init(const InitParser& conf);
74
//! Set the standard modelview matrices used for projection.
75
// TODO: more complete description of what they are used for.
76
//! @param _mat_earth_equ_to_eye ???
77
//! @param _mat_helio_to_eye
78
//! @param _mat_local_to_eye
79
//! @param _mat_j2000_to_eye
81
void set_modelview_matrices(const Mat4d& _mat_earth_equ_to_eye,
82
const Mat4d& _mat_helio_to_eye,
83
const Mat4d& _mat_local_to_eye,
84
const Mat4d& _mat_j2000_to_eye);
86
//! Set the flag with decides whether to arrage labels so that
87
//! they are aligned with the bottom of a 2d screen, or a 3d dome.
88
void setFlagGravityLabels(bool gravity) { gravityLabels = gravity; }
89
//! Get the current state of the flag which decides whether to
90
//! arrage labels so that they are aligned with the bottom of a 2d
91
//! screen, or a 3d dome.
92
bool getFlagGravityLabels() const { return gravityLabels; }
94
//! Register a new projection mapping.
95
void registerProjectionMapping(Mapping *c);
97
///////////////////////////////////////////////////////////////////////////
98
//! @enum PROJECTOR_MASK_TYPE Methods for controlling viewport and mask.
99
enum PROJECTOR_MASK_TYPE
101
DISK, //!< For disk viewport mode (circular mask to seem like bins/telescope)
102
NONE //!< Regular - no mask.
105
//! Get a string description of a PROJECTOR_MASK_TYPE.
106
static const char *maskTypeToString(PROJECTOR_MASK_TYPE type);
108
//! Get a PROJECTOR_MASK_TYPE from a string description.
109
static PROJECTOR_MASK_TYPE stringToMaskType(const string &s);
111
//! Get the current type of the mask if any.
112
PROJECTOR_MASK_TYPE getMaskType(void) const {return maskType;}
114
//! Set the mask type.
115
void setMaskType(PROJECTOR_MASK_TYPE m) {maskType = m; }
117
//! Set up the view port dimensions and position.
118
//! Define viewport size, center(relative to lower left corner)
119
//! and diameter of FOV disk.
120
//! @param x The x-position of the viewport.
121
//! @param y The y-position of the viewport.
122
//! @param w The width of the viewport.
123
//! @param h The height of the viewport.
124
//! @param cx The center of the viewport in the x axis (relative to left edge).
125
//! @param cy The center of the viewport in the y axis (relative to bottom edge).
126
//! @param fov_diam The field of view diameter.
127
void setViewport(int x, int y, int w, int h,
128
double cx, double cy, double fov_diam);
130
//! Get the lower left corner of the viewport and the width, height.
131
const Vector4<GLint>& getViewport(void) const {return viewport_xywh;}
133
//! Get the center of the viewport relative to the lower left corner.
134
Vec2d getViewportCenter(void) const
136
return Vec2d(viewport_center[0]-viewport_xywh[0],
137
viewport_center[1]-viewport_xywh[1]);
140
//! Get the diameter of the FOV disk.
141
double getViewportFovDiameter(void) const {return viewport_fov_diameter;}
143
//! Get the horizontal viewport offset in pixels.
144
int getViewportPosX(void) const {return viewport_xywh[0];}
146
//! Get the vertical viewport offset in pixels.
147
int getViewportPosY(void) const {return viewport_xywh[1];}
149
//! Get the viewport size in pixels.
150
int getViewportWidth(void) const {return viewport_xywh[2];}
151
int getViewportHeight(void) const {return viewport_xywh[3];}
153
//! Handle the resizing of the window.
154
void windowHasBeenResized(int width,int height);
156
//! Return a polygon matching precisely the real viewport defined by
157
//! the area on the screen where projection is valid.
158
//! Normally, nothing should be drawn outside this area. This viewport
159
//! is usually the rectangle defined by the screen, but in case of
160
//! non-linear projection, it can also be a more complex shape.
161
std::vector<Vec2d> getViewportVertices2d() const;
163
//! Return a convex polygon on the sphere which includes the viewport
164
//! in the current frame.
165
//! @param margin an extra margin in pixel which extends the polygon size
166
StelGeom::ConvexPolygon getViewportConvexPolygon(double marginX=0., double marginY=0.) const;
168
//! Un-project the entire viewport depending on mapping, maskType,
169
//! viewport_fov_diameter, viewport_center, and viewport dimensions.
170
StelGeom::ConvexS unprojectViewport(void) const;
172
//! Set whether a disk mask must be drawn over the viewport.
173
void setViewportMaskDisk(void) {setMaskType(Projector::DISK);}
174
//! Get whether a disk mask must be drawn over the viewport.
175
bool getViewportMaskDisk(void) const {return getMaskType()==Projector::DISK;}
176
//! Set whether no mask must be drawn over the viewport.
177
void setViewportMaskNone(void) {setMaskType(Projector::NONE);}
179
//! Set the current OpenGL viewport to projector's viewport.
180
void applyViewport(void) const {
181
glViewport(viewport_xywh[0], viewport_xywh[1], viewport_xywh[2], viewport_xywh[3]);
184
//! Set the clipping planes.
185
// TODO: A better explanation.
186
void set_clipping_planes(double znear, double zfar);
187
//! Get the clipping planes.
188
// TODO: A better explanation.
189
void get_clipping_planes(double* zn, double* zf) const {*zn = zNear; *zf = zFar;}
191
///////////////////////////////////////////////////////////////////////////
192
// Methods for controlling the PROJECTION matrix
193
//! Get the state of the horizontal flip.
194
//! @return True if flipped horizontally, else false.
195
bool getFlipHorz(void) const {return (flip_horz < 0.0);}
196
//! Get the state of the vertical flip.
197
//! @return True if flipped vertically, else false.
198
bool getFlipVert(void) const {return (flip_vert < 0.0);}
199
//! Set the horizontal flip status.
200
//! @param flip The new value (true = flipped, false = unflipped).
201
void setFlipHorz(bool flip) {
202
flip_horz = flip ? -1.0 : 1.0;
203
glFrontFace(needGlFrontFaceCW()?GL_CW:GL_CCW);
205
//! Set the vertical flip status.
206
//! @param flip The new value (true = flipped, false = unflipped).
207
void setFlipVert(bool flip) {
208
flip_vert = flip ? -1.0 : 1.0;
209
glFrontFace(needGlFrontFaceCW()?GL_CW:GL_CCW);
212
// TODO Doxygen docs: What is this for?
213
bool needGlFrontFaceCW(void) const
214
{return (flip_horz*flip_vert < 0.0);}
216
//! Get whether the GL_POINT_SPRITE extension is available now.
217
bool getflagGlPointSprite() const {return flagGlPointSprite;}
219
//! Set the Field of View in degrees.
220
void setFov(double f);
221
//! Get the Field of View in degrees.
222
double getFov(void) const {return fov;}
224
//! Get size of a radian in pixels at the center of the viewport disk
225
double getPixelPerRadAtCenter(void) const {return pixel_per_rad;}
227
//! Set the maximum field of View in degrees.
228
void setMaxFov(double max);
229
//! Get the maximum field of View in degrees.
230
double getMaxFov(void) const {return max_fov;}
231
//! Return the initial default FOV in degree.
232
double getInitFov() const {return initFov;}
235
///////////////////////////////////////////////////////////////////////////
236
// Full projection methods
237
//! Check to see if a 2d position is inside the viewport.
238
bool check_in_viewport(const Vec3d& pos) const
239
{return (pos[1]>=viewport_xywh[1] && pos[0]>=viewport_xywh[0] &&
240
pos[1]<=(viewport_xywh[1] + viewport_xywh[3]) && pos[0]<=(viewport_xywh[0] + viewport_xywh[2]));}
242
//! Project the vector v from the current frame into the viewport.
243
//! @param v the vector in the current frame.
244
//! @param win the projected vector in the viewport 2D frame.
245
//! @return true if the projected coordinate is valid.
246
bool project(const Vec3d& v, Vec3d& win) const
248
// really important speedup:
249
win[0] = modelViewMatrix.r[0]*v[0] + modelViewMatrix.r[4]*v[1]
250
+ modelViewMatrix.r[8]*v[2] + modelViewMatrix.r[12];
251
win[1] = modelViewMatrix.r[1]*v[0] + modelViewMatrix.r[5]*v[1]
252
+ modelViewMatrix.r[9]*v[2] + modelViewMatrix.r[13];
253
win[2] = modelViewMatrix.r[2]*v[0] + modelViewMatrix.r[6]*v[1]
254
+ modelViewMatrix.r[10]*v[2] + modelViewMatrix.r[14];
255
const bool rval = mapping->forward(win);
256
// very important: even when the projected point comes from an
257
// invisible region of the sky (rval=false), we must finish
258
// reprojecting, so that OpenGl can successfully eliminate
259
// polygons by culling.
260
win[0] = viewport_center[0] + flip_horz * pixel_per_rad * win[0];
261
win[1] = viewport_center[1] + flip_vert * pixel_per_rad * win[1];
262
win[2] = (win[2] - zNear) / (zNear - zFar);
266
//! Project the vector v from the current frame into the viewport.
267
//! @param v the vector in the current frame.
268
//! @param win the projected vector in the viewport 2D frame.
269
//! @return true if the projected point is inside the viewport.
270
bool projectCheck(const Vec3d& v, Vec3d& win) const {return (project(v, win) && check_in_viewport(win));}
272
//! Project the vector v from the viewport frame into the current frame.
273
//! @param win the vector in the viewport 2D frame.
274
//! @param v the projected vector in the current frame.
275
//! @return true if the projected coordinate is valid.
276
bool unProject(const Vec3d& win, Vec3d& v) const {return unProject(win[0], win[1], v);}
277
bool unProject(double x, double y, Vec3d& v) const;
279
const Mapping &getMapping(void) const {return *mapping;}
281
//! Project the vectors v1 and v2 from the current frame into the viewport.
282
//! @param v1 the first vector in the current frame.
283
//! @param v2 the second vector in the current frame.
284
//! @param win1 the first projected vector in the viewport 2D frame.
285
//! @param win2 the second projected vector in the viewport 2D frame.
286
//! @return true if at least one of the projected vector is within the viewport.
287
bool projectLineCheck(const Vec3d& v1, Vec3d& win1, const Vec3d& v2, Vec3d& win2) const
288
{return project(v1, win1) && project(v2, win2) && (check_in_viewport(win1) || check_in_viewport(win2));}
290
//! Set the frame in which we want to draw from now on.
291
//! The frame will be the current one until this method or setCustomFrame is called again.
292
//! @param frameType the type.
293
void setCurrentFrame(FRAME_TYPE frameType) const;
295
//! Set a custom model view matrix.
296
//! The new setting remains active until the next call to setCurrentFrame
297
//! or setCustomFrame.
298
//! @param the openGL MODELVIEW matrix to use.
299
void setCustomFrame(const Mat4d&) const;
301
//! Set the current projection mapping to use.
302
//! The mapping must have been registered before being used.
303
//! @param projectionName a string which can be e.g. "perspective", "stereographic", "fisheye", "cylinder".
304
void setCurrentProjection(const std::string& projectionName);
306
//! Get the current projection mapping name.
307
std::string getCurrentProjection() {return currentProjectionType;}
310
///////////////////////////////////////////////////////////////////////////
311
// Standard methods for drawing primitives in general (non-linear) mode
312
///////////////////////////////////////////////////////////////////////////
314
//! Fill with black around the viewport.
315
void draw_viewport_shape(void);
317
//! Generalisation of glVertex3v for non-linear projections.
318
//! This method does not manage the lighting operations properly.
319
void drawVertex3v(const Vec3d& v) const;
320
void drawVertex3(double x, double y, double z) const {drawVertex3v(Vec3d(x, y, z));}
322
//! Draw the string at the given position and angle with the given font.
323
//! @param x horizontal position of the lower left corner of the first character of the text in pixel.
324
//! @param y horizontal position of the lower left corner of the first character of the text in pixel.
325
//! @param str the text to print.
326
//! @param angleDeg rotation angle in degree. Rotation is around x,y.
327
//! @param xshift shift in pixel in the rotated x direction.
328
//! @param yshift shift in pixel in the rotated y direction.
329
//! @param noGravity don't take into account the fact that the text should be written with gravity.
330
void drawText(const SFont* font, float x, float y, const string& str, float angleDeg=0.f,
331
float xshift=0.f, float yshift=0.f, bool noGravity=true) const
333
drawText(font, x, y, StelUtils::stringToWstring(str), angleDeg, xshift, yshift);
336
//! Draw the (multi-byte) string at the given position and angle with the given font.
337
//! If the gravity label flag is set, uses drawTextGravity180.
338
//! @param x horizontal position of the lower left corner of the first character of the text in pixel.
339
//! @param y horizontal position of the lower left corner of the first character of the text in pixel.
340
//! @param str the text to print.
341
//! @param angleDeg rotation angle in degree. Rotation is around x,y.
342
//! @param xshift shift in pixel in the rotated x direction.
343
//! @param yshift shift in pixel in the rotated y direction.
344
//! @param noGravity don't take into account the fact that the text should be written with gravity.
345
void drawText(const SFont* font, float x, float y, const wstring& str, float angleDeg=0.f,
346
float xshift=0.f, float yshift=0.f, bool noGravity=true) const;
348
//! Draw the given polygon
349
//! @param poly The polygon to draw
350
void drawPolygon(const StelGeom::Polygon& poly) const;
352
//! Draw a parallel arc in the current frame. The arc start from point start
353
//! going in the positive longitude direction and with the given length in radian.
354
//! @param start the starting position of the parallel in the current frame.
355
//! @param length the angular length in radian (or distance on the unit sphere).
356
//! @param labelAxis if true display a label indicating the latitude at begining and at the end of the arc.
357
//! @param textColor color to use for rendering text. If NULL use the current openGL painting color.
358
//! @param nbSeg if not==-1,indicate how many line segments should be used for drawing the arc, if==-1
359
//! this value is automatically adjusted to prevent seeing the curve as a polygon.
360
void drawParallel(const Vec3d& start, double length, bool labelAxis=false,
361
const SFont* font=NULL, const Vec4f* textColor=NULL, int nbSeg=-1) const;
363
//! Draw a meridian arc in the current frame. The arc starts from point start
364
//! going in the positive latitude direction if longitude is in [0;180], in the negative direction
365
//! otherwise, and with the given length in radian. The length can be up to 2 pi.
366
//! @param start the starting position of the meridian in the current frame.
367
//! @param length the angular length in radian (or distance on the unit sphere).
368
//! @param labelAxis if true display a label indicating the longitude at begining and at the end of the arc.
369
//! @param textColor color to use for rendering text. If NULL use the current openGL painting color.
370
//! @param nbSeg if not==-1,indicate how many line segments should be used for drawing the arc, if==-1
371
//! this value is automatically adjusted to prevent seeing the curve as a polygon.
372
void drawMeridian(const Vec3d& start, double length, bool labelAxis=false,
373
const SFont* font=NULL, const Vec4f* textColor=NULL, int nbSeg=-1) const;
375
//! draw a simple circle, 2d viewport coordinates in pixel
376
void drawCircle(double x,double y,double r) const;
378
//! Draw a square using the current texture at the given projected 2d position.
379
//! @param x x position in the viewport in pixel.
380
//! @param y y position in the viewport in pixel.
381
//! @param size the size of a square side in pixel.
382
void drawSprite2dMode(double x, double y, double size) const;
384
//! Draw a rotated square using the current texture at the given projected 2d position.
385
//! @param x x position in the viewport in pixel.
386
//! @param y y position in the viewport in pixel.
387
//! @param size the size of a square side in pixel.
388
//! @param rotation rotation angle in degree.
389
void drawSprite2dMode(double x, double y, double size, double rotation) const;
391
//! Draw a rotated rectangle using the current texture at the given projected 2d position.
392
//! @param x x position in the viewport in pixel.
393
//! @param y y position in the viewport in pixel.
394
//! @param sizex the size of the rectangle x side in pixel.
395
//! @param sizey the size of the rectangle y side in pixel.
396
//! @param rotation rotation angle in degree.
397
void drawRectSprite2dMode(double x, double y, double sizex, double sizey, double rotation) const;
399
//! Draw a GL_POINT at the given position.
400
//! @param x x position in the viewport in pixels.
401
//! @param y y position in the viewport in pixels.
402
void drawPoint2d(double x, double y) const;
404
//! Re-implementation of gluSphere : glu is overridden for non-standard projection.
405
void sSphere(GLdouble radius, GLdouble one_minus_oblateness,
406
GLint slices, GLint stacks, int orient_inside = 0) const;
408
//! Re-implementation of gluCylinder : glu is overridden for non-standard projection.
409
void sCylinder(GLdouble radius, GLdouble height, GLint slices, GLint stacks, int orient_inside = 0) const;
411
//! Draw a disk with a special texturing mode having texture center at center of disk.
412
//! The disk is made up of concentric circles with increasing refinement.
413
//! The number of slices of the outmost circle is (inner_fan_slices<<level).
414
//! @param radius the radius of the disk.
415
//! @param inner_fan_slices the number of slices.
416
//! @param level the numbe of concentric circles.
417
void sFanDisk(double radius,int inner_fan_slices,int level) const;
419
//! Draw a disk with a special texturing mode having texture center at center.
420
//! @param radius the radius of the disk.
421
//! @param slices the number of slices.
422
//! @param stacks ???
423
//! @param orient_inside ???
424
void sDisk(GLdouble radius, GLint slices, GLint stacks, int orient_inside = 0) const;
426
//! Draw a ring with a radial texturing.
427
void sRing(GLdouble r_min, GLdouble r_max, GLint slices, GLint stacks, int orient_inside) const;
429
//! Draw a fisheye texture in a sphere.
430
void sSphere_map(GLdouble radius, GLint slices, GLint stacks,
431
double texture_fov = 2.*M_PI, int orient_inside = 0) const;
433
///////////////////////////////////////////////////////////////////////////
434
// Methods for linear mode
435
///////////////////////////////////////////////////////////////////////////
437
//! Reimplementation of gluCylinder for use in linear mode.
438
void sCylinderLinear(GLdouble radius, GLdouble height, GLint slices, GLint stacks,
439
int orient_inside = 0) const;
441
//! Reimplementation of gluSphere for use in linear mode.
442
void sSphereLinear(GLdouble radius, GLdouble one_minus_oblateness, GLint slices,
443
GLint stacks, int orient_inside = 0) const;
447
void drawTextGravity180(const SFont* font, float x, float y, const wstring& str,
448
bool speed_optimize = 1, float xshift = 0, float yshift = 0) const;
450
//! Init the real openGL Matrices to a 2d orthographic projection
451
void initGlMatrixOrtho2d(void) const;
453
//! The current projector mask
454
PROJECTOR_MASK_TYPE maskType;
456
double initFov; // initial default FOV in degree
457
double fov; // Field of view in degree
458
double min_fov; // Minimum fov in degree
459
double max_fov; // Maximum fov in degree
460
double zNear, zFar; // Near and far clipping planes
462
Vector4<GLint> viewport_xywh; // Viewport parameters
463
Vec2d viewport_center; // Viewport center in screen pixel
464
double viewport_fov_diameter; // diameter of a circle with 180 degrees diameter in screen pixel
466
Mat4d projectionMatrix; // Projection matrix
468
double pixel_per_rad; // pixel per rad at the center of the viewport disk
469
double flip_horz,flip_vert; // Whether to flip in horizontal or vertical directions
471
Mat4d mat_earth_equ_to_eye; // Modelview Matrix for earth equatorial projection
472
Mat4d mat_j2000_to_eye; // for precessed equ coords
473
Mat4d mat_helio_to_eye; // Modelview Matrix for earth equatorial projection
474
Mat4d mat_local_to_eye; // Modelview Matrix for earth equatorial projection
476
bool gravityLabels; // should label text align with the horizon?
478
bool flagGlPointSprite; // Define whether glPointSprite is activated
480
mutable Mat4d modelViewMatrix; // openGL MODELVIEW Matrix
482
const Mapping *mapping;
483
std::map<std::string,const Mapping*> projectionMapping;
485
std::string currentProjectionType; // Type of the projection currently used
489
#endif // _PROJECTOR_H_