Newer
Older
#ifndef _GVIEW_H
#define _GVIEW_H
/*
* Somewhat geomview-style OpenGL viewer for FLTK
* Analogous to vtk's RenderWindowInteractor.
* Stuart Levy, slevy@ncsa.uiuc.edu
* National Center for Supercomputing Applications,
* University of Illinois 2001.
*/
#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 */
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,
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
};
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;
}
};
struct MausSample {
float x, y;
float t;
};
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 *, int again );
int (*postdraw)( Fl_Gview *, int again );
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) */
float pixelaspect() const { return pixelaspect_; }
void pixelaspect( float newasp );
int stereooffset() const { return stereooff_; }
void stereooffset( int pixels );
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);
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_; }
float fps() const; /* frames per second (smoothed) */
int framecount;
/* 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(); }
int inertia() const { return inertia_; }
void inertia( int on );
void driftoff( );
void drifton( );
void drifton( MausSample *rate );
int drifting() const { return drifting_; }
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
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_; }
void initfrom( Fl_Gview * );
virtual void draw();
virtual int handle(int ev);
static void idlepick( void *me );
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_, pixelaspect_, stereosep_;
int stereooff_;
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 );
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 */
MausSample driftrate_;
float drifttime_; /* wall-clock time at previous drift cycle */
int inertia_;
int drifting_;
#define NMAUSAMP 4
MausSample ms_[NMAUSAMP];
int nms_;
/* Nav status -- where current mouse drag started */
int evx_, evy_, evslow_, evzaxis_, evconstrain_;
Matrix evTobj2w_, evTc2w_, evTw2c_;
/* smoothed frame rate */
float sumwdt_, sumw_;
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 takeMausSample( int ev, float timescale );
int pastMaus( MausSample *rate, float ago );
void rateaccum( float dt );
ndrawers_ = maxdrawers_ = 0;
drawers_ = NULL;
owncoords_ = 0;
persp_ = 1;
stereo_ = GV_MONO;
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;
inertia_ = 0;
drifting_ = 0;
driftrate_.x = driftrate_.y = driftrate_.t = 0;
sumwdt_ = sumw_ = 0;
framecount = 0;