Skip to content
Snippets Groups Projects
Gview.H 10.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • teuben's avatar
    teuben committed
    #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.
    
     * This file is part of partiview, released under the
     * Illinois Open Source License; see the file LICENSE.partiview for details.
    
    teuben's avatar
    teuben committed
     */
    
    
    #ifdef __APPLE__
    #include <OpenGL/gl.h>
    #include <OpenGL/glu.h>
    #else
    #include <GL/gl.h>    /* for GLuint */
    
    teuben's avatar
    teuben committed
    #include <GL/glu.h>
    
    teuben's avatar
    teuben committed
    #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 */
    
    teuben's avatar
    teuben committed
    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>
    
    
    #ifdef FLHACK
    # include "flhack.H"
    #else
    # include <FL/Fl.H>
    # include <FL/Fl_Gl_Window.H>
    #endif
    
    
    teuben's avatar
    teuben committed
    #include "geometry.h"
    
    enum Gv_Nav {
      GV_FLY,
      GV_ORBIT,
      GV_ROTATE,
      GV_TRANSLATE,
      GV_LASTENUM
    };
    
    enum Gv_Stereo {
      GV_MONO,
      GV_REDCYAN,
    
    slevy's avatar
    slevy committed
      GV_CROSSEYED,
    
    teuben's avatar
    teuben committed
      GV_QUADBUFFERED,
    
      GV_LEFTEYE,
      GV_RIGHTEYE
    
    teuben's avatar
    teuben committed
    };
    
    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;
      }
    };
     
    
    slevy's avatar
    slevy committed
    struct MausSample {
      float x, y;
      float t;
    };
    
    teuben's avatar
    teuben committed
    
    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 );
    
    teuben's avatar
    teuben committed
    
    
      void glmode( int modebits );			/* wrapper for Fl_Gl_Window::mode( ... ) */
    
    
    teuben's avatar
    teuben committed
      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_; }
    
    teuben's avatar
    teuben committed
      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 );		
    
    teuben's avatar
    teuben committed
    
      int perspective() { return persp_; }
      void perspective(int persp);
      float focallen() const { return focallen_; }
      void focallen( float dist );
    
      int focalpoint( Point *fpt, float *minfocallen ) const {
          if(fpt) *fpt = focalpoint_;
          if(minfocallen) *minfocallen = minfocallen_;
          return focalpointing_;
      }
      void focalpoint( Point *fpt, float minfocallen, int on ) {
          focalpoint_ = *fpt;
          minfocallen_ = minfocallen;
          focalpointing_ = on;
      }
      void focalpoint( int on ) {
          focalpointing_ = on;
      }
    
    teuben's avatar
    teuben committed
      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) */
    
    slevy's avatar
    slevy committed
      float pixelaspect() const { return pixelaspect_; }
      void pixelaspect( float newasp );
      int stereooffset() const { return stereooff_; }
      void stereooffset( int pixels );
    
    teuben's avatar
    teuben committed
    
      enum Gv_Stereo stereo() const { return stereo_; }
      void stereo( enum Gv_Stereo setting ) { stereo_ = setting; redraw(); }
    
    teuben's avatar
    teuben committed
      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);
    
    teuben's avatar
    teuben committed
      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_; }
    
    
    slevy's avatar
    slevy committed
      float fps() const;	/* frames per second (smoothed) */
      int framecount;
    
    
    teuben's avatar
    teuben committed
    	/* 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(); }
    
    
    slevy's avatar
    slevy committed
      int inertia() const { return inertia_; }
      void inertia( int on );
      void driftoff( );
      void drifton( );
      void drifton( MausSample *rate );
      int drifting() const { return drifting_; }
    
    
    teuben's avatar
    teuben committed
      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 * );
    
    
      int dspcontext() const { return dspcontext_; }
      void dspcontext( int dspctx );
    
    
    
    teuben's avatar
    teuben committed
      virtual void draw();
      virtual int  handle(int ev);
    
      static void idlepick( void *me );
    
    slevy's avatar
    slevy committed
      static void idledrift( void *me );
    
      static int next_dspcontext();
    
    teuben's avatar
    teuben committed
    
     protected:
    
      static int next_dspcontext_;
    
    
      void glprojection( float nearclip, float farclip, const Matrix *postproj );
    
    
    teuben's avatar
    teuben committed
      Point qc2w_;
      Matrix Tc2w_, Tw2c_; 
    
      int persp_;
      enum Gv_Stereo stereo_;
      float focallen_, halfyfov_, near_, far_;
    
    slevy's avatar
    slevy committed
      float aspect_, pixelaspect_, stereosep_;
      int stereooff_;
    
    teuben's avatar
    teuben committed
    
    
      float minfocallen_;
      Point focalpoint_;
      int focalpointing_;
    
    
      Matrix Tc2subc_;
      float subclrbt_[4];  // subcam frustum tan(left),tan(right),tan(bot),tan(top)
    
    teuben's avatar
    teuben committed
      int target_;
      int movingtarget_;
    
    
      void (*pickcb_)( Fl_Gl_Window *, int hits, int nents, GLuint *buf, void *arg );
    
    teuben's avatar
    teuben committed
      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 */
    
    slevy's avatar
    slevy committed
      MausSample driftrate_;
      float drifttime_;		/* wall-clock time at previous drift cycle */
      int inertia_;
      int drifting_;
    
    #define NMAUSAMP 4
      MausSample ms_[NMAUSAMP];
      int nms_;
    
    teuben's avatar
    teuben committed
    
      /* Nav status -- where current mouse drag started */
      int evx_, evy_, evslow_, evzaxis_, evconstrain_;
      Matrix evTobj2w_, evTc2w_, evTw2c_;
    
    
    slevy's avatar
    slevy committed
      /* smoothed frame rate */
      float sumwdt_, sumw_;
    
    
    teuben's avatar
    teuben committed
      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;
    
    teuben's avatar
    teuben committed
      };
      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 */
    
    
    slevy's avatar
    slevy committed
      void takeMausSample( int ev, float timescale );
      int  pastMaus( MausSample *rate, float ago );
      void rateaccum( float dt );
    
    
    teuben's avatar
    teuben committed
      void init() {
        msg = printf;
        eventhook = NULL;
    
        predraw = NULL;
        postdraw = NULL;
    
    slevy's avatar
    slevy committed
        num.has = 0;
    
    teuben's avatar
    teuben committed
        ndrawers_ = maxdrawers_ = 0;
        drawers_ = NULL;
    
    teuben's avatar
    teuben committed
        owncoords_ = 0;
        persp_ = 1;
        stereo_ = GV_MONO;
    
    slevy's avatar
    slevy committed
        pixelaspect_ = 1.0;
    
    teuben's avatar
    teuben committed
        stereosep_ = .05;
    
    slevy's avatar
    slevy committed
        stereooff_ = 0;
    
    teuben's avatar
    teuben committed
        target_ = GV_ID_CAMERA;
        movingtarget_ = 0;
        focallen_ = 3;  halfyfov_ = .5;	/* 60-degree default FOV */
        near_ = .1;    far_ = 100;
    
    
        minfocallen_ = 0.1;
        focalpoint_.x[0] = focalpoint_.x[1] = focalpoint_.x[2] = 0;
        focalpointing_ = 0;
    
    
    teuben's avatar
    teuben committed
        zspeed = 1;
        inpick_ = 0;
    
    slevy's avatar
    slevy committed
        nms_ = 0;
    
    teuben's avatar
    teuben committed
        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;
    
    slevy's avatar
    slevy committed
        inertia_ = 0;
        drifting_ = 0;
        driftrate_.x = driftrate_.y = driftrate_.t = 0;
        sumwdt_ = sumw_ = 0;
        framecount = 0;
    
    teuben's avatar
    teuben committed
        nav( GV_ORBIT );
        reset( GV_ID_CAMERA );
      }
    };
    #endif /* C++ */
    #endif /*_GVIEW_H*/