Gview.H 7.53 KiB
#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 );
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 );
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 );
const Matrix *To2w( int drawerno ) const; /* returns &Tidentity if invalid */
int To2w( int drawerno, const Matrix * ); /* returns zero if invalid */
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_Gview *, int, int, GLuint *, void *arg), void *arg );
void (*picker( void **argp = 0 ))(Fl_Gview *, 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_; }
/* 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:
Point qc2w_;
Matrix Tc2w_, Tw2c_;
int persp_;
enum Gv_Stereo stereo_;
float focallen_, halfyfov_, near_, far_;
float aspect_, stereosep_;
int target_;
int movingtarget_;
void (*pickcb_)( Fl_Gview *, 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 */
/* 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 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;
nav( GV_ORBIT );
reset( GV_ID_CAMERA );
}
};
#endif /* C++ */
#endif /*_GVIEW_H*/