Newer
Older
#ifndef _GVIEW_H
#define _GVIEW_H
/*
* Somewhat geomview-style OpenGL viewer for FLTK
* This is analogous to vtk's RenderWindowInteractor
*/
#include <GL/gl.h> /* for GLuint */
#include <GL/glu.h>
#include <stdio.h>
#define GV_ID_CAMERA (-1)
#ifndef __cplusplus
typedef struct _Fl_Gview Fl_Gview;
int Gview_add_drawer( Fl_Gview *gview,
void (*func)( Fl_Gview *, void *obj, void *arg ),
void *obj, void *arg, int id );
void Gview_get_o2w( Fl_Gview *gview, Matrix *pos, int drawer ); /* returns parent */
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
void Gview_set_o2w( Fl_Gview *gview, CONST Matrix *pos, int drawer );
int Gview_inpick( Fl_Gview *gview ); /* for plain-C drawers */
void Gview_setpick( Fl_Gview *gview, void (*pickcb)(Fl_Gview *, int hits, int ents, GLuint *buf) );
#else /* C++ */
#include <stdlib.h>
#include <FL/Fl.H>
#include <FL/Fl_Gl_Window.H>
#include "geometry.h"
enum Gv_Nav {
GV_FLY,
GV_ORBIT,
GV_ROTATE,
GV_TRANSLATE,
GV_LASTENUM
};
enum Gv_Stereo {
GV_MONO,
GV_REDCYAN,
GV_CROSSEYED, /* not implemented yet 4/00 */
GV_QUADBUFFERED,
};
struct GNumber {
int has; /* 0 if not, -1 or +1 (sign) if present */
int val;
int expon; /* digits after decimal point */
int prefix; /* prefix character (e.g. 'c' or 'g') */
void clear() { has = val = expon = prefix = 0; }
int addchar(int c) {
switch(c) {
case '.': expon = 1; if(!has) has = 1, val = 0; return 1;
case '-': has = -1; val = expon = 0; return 1;
case 'c':
case 'g': prefix = c; has = 1; val = expon = 0; return 1;
}
if(c >= '0' && c <= '9') {
if(!has) { has = 1; val = expon = 0; }
if(expon) expon++;
val = 10*val + c - '0';
return 1;
}
return 0;
}
int tvalue( int defval = 0 ) {
return has && prefix=='c' ? ~value(defval)
: value(defval);
}
int value( int defval = 0 ) { return has ? has*val : defval; }
float fvalue( float defval = 0 ) {
if(!has) return defval;
float v = has * val;
while(--expon > 0) v *= 0.1;
return v;
}
};
class Fl_Gview : public Fl_Gl_Window {
public:
Fl_Gview(int x, int y, int h, int w, const char *label = 0);
int add_drawer( void (*func)( Fl_Gview *, void *obj, void *arg ), void *obj, void *arg, char *name = NULL, int id = -1 );
int next_id() const;
void notifier( void (*func)( Fl_Gview *, void * ), void * );
int (*msg)( const char *fmt, ... );
int (*eventhook)( Fl_Gview *, int ev );
void (*predraw)( Fl_Gview * );
void (*postdraw)( Fl_Gview * );
const Matrix *Tc2w() const;
const Matrix *Tw2c() const;
void Tc2w( const Matrix * );
void Tw2c( const Matrix * );
void lookvec( int row, const Point *vec );
void reset( int obj = GV_ID_CAMERA );
void usesubcam( int on ) { use_subc_ = on; }
int usesubcam() const { return use_subc_; };
void Tc2subc( Matrix *newT ) { Tc2subc_ = *newT; }
const Matrix *Tc2subc() const { return &Tc2subc_; }
void subc_lrbt( float lrbt[4] );
const float *subc_lrbt() const { return subclrbt_; }
const Matrix *To2w( int drawerno ) const; /* returns &Tidentity if invalid */
int To2w( int drawerno, const Matrix * ); /* returns zero if invalid */
int objparent( int drawerno ) const; /* parent object id (0=world, -1=camera) */
void objparent( int drawerno, int id );
int perspective() { return persp_; }
void perspective(int persp);
float focallen() const { return focallen_; }
void focallen( float dist );
float halfyfov() const { return halfyfov_; } ;
void halfyfov( float half_dist_at_focallen );
float angyfov() const;
void angyfov( float degrees );
float nearclip() const { return near_; };
void nearclip(float newnear);
float farclip() const { return far_; };
void farclip(float newfar);
float aspect() const { return aspect_; }
void aspect( float newasp ); /* sets window aspect ratio (xsize/ysize) */
enum Gv_Stereo stereo() const { return stereo_; }
void stereo( enum Gv_Stereo setting ) { stereo_ = setting; redraw(); }
float stereosep() const { return stereosep_; }
void stereosep( float tanhalfangle ) { stereosep_ = tanhalfangle; redraw(); }
int inpick() const { return inpick_; } // draw()ers: am I in GL_SELECT mode?
void picksize( float width, float height );
void pickbuffer( int words, GLuint *buf );
void picker( void (*pickcb)(Fl_Gl_Window *, int, int, GLuint *, void *arg), void *arg );
void (*picker( void **argp = 0 ))(Fl_Gl_Window *, int, int, GLuint *, void *arg);
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
int pickresults( int *wordsp, GLuint **bufp ); /* returns num hits, too */
int do_pick( float pickx, float picky ); /* Calls back function given by picker() */
int snapshot( int x, int y, int w, int h, void *packedrgb );
// Take snapshot into caller-supplied buffer, w*h*3 bytes long
const Point *center() const { return &pcenw_; }
void center( const Point *pcenw );
int owncoords() { return owncoords_; }
void owncoords(int useown);
void nav( enum Gv_Nav navmode );
enum Gv_Nav nav() const { return nav_; }
/* Do nav ops apply to the target? !movingtarget() means
* that all nav applies to the camera, even r and t.
*/
int movingtarget() const { return movingtarget_; }
void movingtarget(int v) { movingtarget_ = v; notify(); }
void target( int drawerno ) {
if(drawerno >= GV_ID_CAMERA && drawerno < ndrawers_
&& drawerno != target_) {
target_ = drawerno;
notify();
}
}
int target() const { return target_; }
int ndrawers() const { return ndrawers_; }
float zspeed; /* for fly, translate modes */
GNumber num; /* accumulates numeric keyboard input */
int retarget() {
if(num.has) target( num.tvalue() );
return target();
}
char *dname( int drawerno );
void bgcolor( Point *rgb ) { bgcolor_ = *rgb; redraw(); }
const Point *bgcolor() const { return &bgcolor_; }
virtual void draw();
virtual int handle(int ev);
static void idlepick( void *me );
protected:
void glprojection( float nearclip, float farclip, const Matrix *postproj );
Point qc2w_;
Matrix Tc2w_, Tw2c_;
int persp_;
enum Gv_Stereo stereo_;
float focallen_, halfyfov_, near_, far_;
float aspect_, stereosep_;
Matrix Tc2subc_;
float subclrbt_[4]; // subcam frustum tan(left),tan(right),tan(bot),tan(top)
void (*pickcb_)( Fl_Gl_Window *, int hits, int nents, GLuint *buf, void *arg );
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
int inpick_;
float pickx_, picky_, pickwidth_, pickheight_;
int picknents_, pickhits_;
GLuint *pickbuf_;
GLuint tpickbuf[1024];
void *pickarg_;
/* We handle mouse-driven picking in an idle-callback, to avoid
* getting behind if there are many events.
*/
float dpickx_, dpicky_;
int pickneeded_;
int hasfocus_;
void (*notify_)( Fl_Gview *, void *);
void *notifyarg_;
void notify();
/* navigation settings */
enum Gv_Nav nav_; /* nav mode */
int owncoords_; /* own coordinates */
Point pcenw_; /* center pt (world coords) for orbit/rotate */
int nullthresh_; /* null-motion threshold in pixels */
/* Nav status -- where current mouse drag started */
int evx_, evy_, evslow_, evzaxis_, evconstrain_;
Matrix evTobj2w_, evTc2w_, evTw2c_;
struct drawer {
void (*func)(Fl_Gview *, void *obj, void *arg);
void *obj, *arg;
Matrix To2w;
char *name;
int id;
int parent; /* 0=world, GV_ID_CAMERA=attach-to-camera */
int objclip; /* object has custom clip planes? */
float objnear, objfar;
};
int ndrawers_, maxdrawers_;
struct drawer *drawers_;
int withid( int id ) const;
void draw_scene( int needproj, const Matrix *postproj );
Point bgcolor_; /* OK, it's not a Point, we just want 3 components */
void do_nav(int ev, int slow, int zaxis, int constrained);
void start_nav( int navtarget ); /* Save event-position, camera, target-position */
void init() {
msg = printf;
eventhook = NULL;
ndrawers_ = maxdrawers_ = 0;
drawers_ = NULL;
owncoords_ = 0;
persp_ = 1;
stereo_ = GV_MONO;
stereosep_ = .05;
target_ = GV_ID_CAMERA;
movingtarget_ = 0;
focallen_ = 3; halfyfov_ = .5; /* 60-degree default FOV */
near_ = .1; far_ = 100;
zspeed = 1;
inpick_ = 0;
pickwidth_ = 2, pickheight_ = 2;
picknents_ = sizeof(tpickbuf) / sizeof(tpickbuf[0]);
pickbuf_ = tpickbuf;
pickarg_ = NULL;
notify_ = NULL;
notifyarg_ = NULL;
pcenw_.x[0] = pcenw_.x[1] = pcenw_.x[2] = 0;
bgcolor_.x[0] = bgcolor_.x[1] = bgcolor_.x[2] = .2;
nullthresh_ = 2;
hasfocus_ = 0;
use_subc_ = 0;
Tc2subc_ = Tidentity;
subclrbt_[0] = subclrbt_[2] = -1;
subclrbt_[1] = subclrbt_[3] = 1;