Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ref_image.H

Go to the documentation of this file.
00001 /*****************************************************************
00002  * ref_image.H
00003  *****************************************************************/
00004 #ifndef REF_IMAGE_H_IS_INCLUDED
00005 #define REF_IMAGE_H_IS_INCLUDED
00006 
00007 #include "std/support.H"
00008 #include "glew/glew.H"
00009 
00010 #include "disp/ref_img_client.H" // RefImageClient::ref_img_t
00011 #include "disp/colors.H"         // Color namespace and utility functions
00012 #include "geom/image.H"          // Image
00013 #include "geom/rgba.H"           // RGBA conversions
00014 #include "geom/texturegl.H"      // tex mem ref img
00015 #include "geom/winsys.H"         // bits per component
00016 #include "mlib/point2i.H"
00017 #include "mesh/patch.H"
00018 #include "mesh/simplex_filter.H"
00019 #include "mesh/base_ref_image.H"
00020 
00021 #include "gtex/util.H"
00022 
00023 /**********************************************************************
00024  * CoordSystem2d
00025  **********************************************************************/
00026 class CoordSystem2d {
00027  protected:
00028    uint           _width;
00029    uint           _height;
00030    uint           _max;
00031    double         _half_width;
00032    double         _half_height;
00033    double         _half_min_dim;
00034 
00035    NDCvec         _ndc_offset;
00036 
00037  public:
00038    CoordSystem2d() :
00039       _width(0), _height(0), _max(0),
00040       _half_width(0), _half_height(0),
00041       _half_min_dim(0) {}
00042 
00043    virtual ~CoordSystem2d() {}
00044   
00045    // accessors
00046    uint  width()        const   { return _width; }
00047    uint height()        const   { return _height;}
00048    uint    max()        const   { return _max;}
00049 
00050    virtual bool resize(uint new_w, uint new_h) {
00051       _width        = new_w;
00052       _height       = new_h;
00053       _max          = _width * _height;
00054       _half_width   = _width/2.0;
00055       _half_height  = _height/2.0;
00056       _half_min_dim = min(_half_width,_half_height);
00057       return true;
00058    }
00059 
00060    CNDCvec& ndc_offset()                { return _ndc_offset; }
00061    void     set_ndc_offset(CNDCvec& v)  { _ndc_offset = v; }
00062   
00063    //**** RANGE FUNCTIONS ***
00064    bool uint_in_range(uint id) const { return (id<_max); }
00065    bool pix_in_range(Cpoint2i &pix) const {
00066       return (pix[0]>=0 && pix[1]>=0 &&
00067               (uint)pix[0]<_width && (uint)pix[1]<_height);
00068    }
00069   
00070    //**** CONVERSION FUNCTIONS ****
00071 
00072    // *** PIX <--> UINT ***
00073    uint pix_to_uint(Cpoint2i& pix) const {
00074       return clamp(pix[1],0,(int)_height-1)*_width +
00075          clamp(pix[0],0,(int)_width-1);
00076    }
00077    Point2i uint_to_pix(uint id) const {
00078       return Point2i(id % _width, id / _width);
00079    }
00080 
00081    // *** PIX <--> NDC ***
00082    NDCpt pix_to_ndc(Cpoint2i &pix) const {
00083       return NDCpt((pix[0]-_half_width)/_half_min_dim,
00084                    (pix[1]-_half_height)/_half_min_dim);
00085    }
00086    Point2i ndc_to_pix(CNDCpt &ndc) const {
00087       return Point2i(int(ndc[0]*_half_min_dim + _half_width),
00088                      int(ndc[1]*_half_min_dim + _half_height));
00089    }
00090 
00091    // *** NDC <--> UINT ***
00092    NDCpt uint_to_ndc(uint id) const {
00093       return NDCpt((id%_width - _half_width)/_half_min_dim,
00094                    (id/_width - _half_height)/_half_min_dim) + _ndc_offset;
00095    }
00096    uint ndc_to_uint(CNDCpt& ndc) const {
00097       const int x = (int) (ndc[0]*_half_min_dim + _half_width);
00098       const int y = (int) (ndc[1]*_half_min_dim + _half_height);
00099       return clamp(y,0,(int)_height-1)*_width + clamp(x,0,(int)_width-1);
00100    }
00101 };
00102 
00103 /**********************************************************************
00104  * Array2d:
00105  **********************************************************************/
00106 template <class T>
00107 class Array2d : public CoordSystem2d {
00108  public:
00109    //******** MANAGERS ********
00110    Array2d() : CoordSystem2d(), _values(0) {}
00111    Array2d(const Array2d<T>& arr) : _values(0) {
00112       resize(arr._width, arr._height);
00113       for (uint i=0; i<_max; i++)
00114          _values[i] = arr._values[i];
00115    }
00116 
00117    //******** SETTING UP ********
00118    virtual ~Array2d() { delete[] _values; }
00119 
00120    void clear(int clear_val=0) {
00121       memset(_values, clear_val, _max*sizeof(T));
00122    }
00123 
00124    virtual bool resize(uint new_w, uint new_h) {
00125       if (new_w == _width && new_h == _height)
00126          return false;
00127       CoordSystem2d::resize(new_w, new_h);
00128       allocate();
00129       return true;
00130    }
00131 
00132    //******** ACCESSORS ********
00133    T& val(uint id)              const   { return _values[id];}
00134    T& val(CNDCpt& ndc)    const   { return val(ndc_to_uint(ndc));  }
00135    T& val(Cpoint2i& pix)  const   { return val(pix_to_uint(pix));  }
00136    T& val(int x, int y)         const   { return val(Point2i(x,y)); } 
00137 
00138  protected: 
00139    T*   _values;        // 1D array representing 2D grid of values
00140   
00141    void allocate() {
00142       delete [] _values;
00143       _values = 0;
00144       if (_max>0) {
00145          _values = new T[_max];
00146          assert(_values);
00147       }
00148    }
00149 };
00150 
00151 /**********************************************************************
00152  * RefImage: 
00153  **********************************************************************/
00154 #define CRefImage const RefImage
00155 class RefImage : public Array2d<GLuint> {
00156  protected:
00157    VIEWptr      _view;                  // associated VIEW
00158    str_ptr      _rend_str;              // e.g. RSMOOTH_SHADE
00159 
00160    // XXX - might be trouble-matic:
00161    //   since pixel data is stored in a GLuint,
00162    //   the only format really supported is GL_RGBA
00163    //   (or other 4-byte formats):
00164    GLenum                       _format;        // e.g. GL_RGBA
00165    GLenum                       _type;          // e.g. GL_UNSIGNED_BYTE
00166    RefImageClient::ref_img_t    _ref_img_type;  // REF_IMG_COLOR
00167 
00168    static  HASH _hash;  // for looking up a RefImage given a VIEW
00169 
00170    virtual void draw_objects(CGELlist&) const;
00171 
00172  public:
00173    //******** MANAGERS ********
00174    // use this to get (create or lookup) a RefImage 
00175    // associated with a given VIEW:
00176    static RefImage* lookup(CVIEWptr& v = VIEW::peek());
00177 
00178    // public constructor for those rare instances when you just want
00179    // to get your own, not tied to a view
00180    RefImage(CVIEWptr& v,
00181             Cstr_ptr &rend_str = RSMOOTH_SHADE,
00182             GLenum format=GL_RGBA,
00183             GLenum type=GL_UNSIGNED_BYTE) :
00184       _view(v),
00185       _rend_str(rend_str),
00186       _format(format),
00187       _type(type),
00188       _ref_img_type(RefImageClient::REF_IMG_COLOR) {}
00189 
00190    CVIEWptr& view() const { return _view; }
00191 
00192    // return an Image with same dimensions
00193    // as this, but formatted for RGB:
00194    int copy_rgb(Image& img) const;
00195 
00196    // read from / write to the frame buffer:
00197    void read_FB() { glReadPixels(0,0,_width,_height,_format,_type,_values); }
00198    void draw_FB() const;
00199 
00200    // ensure image is up-to-date:
00201    virtual void update();
00202 
00203    // set every pixel to the given rgba color:
00204    void fill(uchar r, uchar g, uchar b, uchar a=255U) {
00205       fill(build_rgba(r,g,b,a));
00206    }
00207    void fill(uint fill_color);
00208 
00209    // set the given pixel to the given color:
00210    void set(Cpoint2i& pix, uint rgba_color) { val(pix) = rgba_color; }
00211    void set(Cpoint2i& pix, uchar r, uchar g, uchar b, uchar a=255U) {
00212       set(pix, build_rgba(r,g,b,a));
00213    }
00214    void set(int x, int y, uint rgba_color) {
00215       set(Cpoint2i(x,y), rgba_color);
00216    }
00217    void set(int x, int y, uchar r, uchar g, uchar b, uchar a=255U) {
00218       set(Cpoint2i(x,y), build_rgba(r, g, b, a));
00219    }
00220 
00221    // set the color at location x,y to the given color/alpha rgba value:
00222    void set(int x, int y, CCOLOR& c, double alpha = 1) {
00223       set(x, y, Color::color_to_rgba(c, alpha));
00224    }
00225    // blend the given color into the image using opacity alpha:
00226    void blend(int x, int y, CCOLOR& c, double alpha) {
00227       set(x, y, interp(color(x, y), c, alpha), 1);
00228    }
00229 
00230    //******** CONVENIENT COLOR ACCESSORS ********
00231 
00232    // return the color at image location x,y (ignoring alpha):
00233    COLOR color(int x, int y) const {
00234       return Color::rgba_to_color(val(x,y));
00235    }
00236    // return the color (ignoring alpha) at given NDC location:
00237    COLOR color(CNDCpt& ndc) const {
00238       return Color::rgba_to_color(val(ndc));
00239    }
00240 
00241    // return the given component as a uint in range [0,255]:
00242    uint red(uint id)            const      { return rgba_to_r(val(id));  }
00243    uint red(CNDCpt& ndc)        const      { return rgba_to_r(val(ndc)); }
00244    uint red(Cpoint2i& pix)      const      { return rgba_to_r(val(pix)); }
00245    uint red(int x, int y)       const      { return rgba_to_r(val(x,y)); }
00246 
00247    uint green(uint id)          const      { return rgba_to_g(val(id));  }
00248    uint green(CNDCpt& ndc)      const      { return rgba_to_g(val(ndc)); }
00249    uint green(Cpoint2i& pix)    const      { return rgba_to_g(val(pix)); }
00250    uint green(int x, int y)     const      { return rgba_to_g(val(x,y)); }
00251 
00252    uint blue(uint id)           const      { return rgba_to_b(val(id));  }
00253    uint blue(CNDCpt& ndc)       const      { return rgba_to_b(val(ndc)); }
00254    uint blue(Cpoint2i& pix)     const      { return rgba_to_b(val(pix)); }
00255    uint blue(int x, int y)      const      { return rgba_to_b(val(x,y)); }
00256 
00257    uint alpha(uint id)          const      { return rgba_to_a(val(id));  }
00258    uint alpha(CNDCpt& ndc)      const      { return rgba_to_a(val(ndc)); }
00259    uint alpha(Cpoint2i& pix)    const      { return rgba_to_a(val(pix)); }
00260    uint alpha(int x, int y)     const      { return rgba_to_a(val(x,y)); }
00261 
00262    // return the luminance (ignoring alpha) as a uint in range
00263    // [0,255], where 0 is black and 255 is white:
00264    uint grey(uint id)       const       { return rgba_to_grey(val(id));  }
00265    uint grey(CNDCpt& ndc)   const       { return rgba_to_grey(val(ndc)); }
00266    uint grey(Cpoint2i& pix) const       { return rgba_to_grey(val(pix)); }
00267    uint grey(int x, int y)  const       { return rgba_to_grey(val(x,y)); }
00268 
00269    // return the luminance (ignoring alpha) as a double in range
00270    // [0,1], where 0 is black and 1 is white:
00271    double grey_d(uint id)       const   { return rgba_to_grey_d(val(id));  }
00272    double grey_d(CNDCpt& ndc)   const   { return rgba_to_grey_d(val(ndc)); }
00273    double grey_d(Cpoint2i& pix) const   { return rgba_to_grey_d(val(pix)); }
00274    double grey_d(int x, int y)  const   { return rgba_to_grey_d(val(x,y)); }
00275 
00276    //******** FILE I/O ********
00277    int read_file (char* file);
00278    int write_file(char* file);
00279 
00280    //******** SEARCH FUNCTIONS ********
00281 
00282    // Return true if the given value v is found in an (n x n) square
00283    // region around the given center location, where n = 2*rad + 1.
00284    // E.g., if rad == 1 the search is within a 3 x 3 region:
00285    bool find_val_in_box(uint v, Cpoint2i& center, uint rad=1) const;
00286    bool find_val_in_box(uint v, CNDCpt&   center, uint rad=1) const {
00287       return find_val_in_box(v, ndc_to_pix(center), rad);
00288    }
00289 
00290    bool find_val_in_box(uint v, uint mask, Cpoint2i& center, uint rad=1, int nbr=256) const;
00291    bool find_val_in_box(uint v, uint mask, CNDCpt&   center, uint rad=1, int nbr=256) const {
00292       return find_val_in_box(v, mask, ndc_to_pix(center), rad, nbr);
00293    }
00294 };
00295 
00296 /**********************************************************************
00297  * RefImage2:
00298  **********************************************************************/
00299 #define CRefImage2 const RefImage2
00300 class RefImage2 : public RefImage {
00301  protected:
00302 
00303    static  HASH  _hash;
00304 
00305    RefImage2(CVIEWptr& v, Cstr_ptr &rend_str = RSMOOTH_SHADE,
00306              GLenum format=GL_RGBA,
00307              GLenum type=GL_UNSIGNED_BYTE) : 
00308       RefImage(v, rend_str, format, type) {
00309       _ref_img_type = RefImageClient::REF_IMG_COLOR_2;
00310    }
00311 
00312  public:
00313 
00314    static RefImage2* lookup(CVIEWptr& v = VIEW::peek());
00315 };
00316 
00317 
00318 /**********************************************************************
00319  * IDRefImage:
00320  *
00321  *      Also known as the "ID reference image."
00322  *
00323  *      Implements an "item buffer," where each pixel encodes an
00324  *      object ID. Specifically, "objects" in this case are mesh
00325  *      faces, edges, or vertices (usually just faces). Given a pixel
00326  *      location, the item buffer can be used to perform O(1) picking
00327  *      (not counting the cost of preparing the item buffer). This
00328  *      technique has been described in various papers; e.g.:
00329  *
00330  *        Rodney J. Recker, David W. George, Donald P. Greenberg.
00331  *        Acceleration Techniques for Progressive Refinement
00332  *        Radiosity, 1990 Symposium on Interactive 3D Graphics, 24
00333  *        (2), pp. 59-66 (March 1990). Edited by Rich Riesenfeld and
00334  *        Carlo Séquin. ISBN 0-89791-351-5.
00335  *
00336  *      This is also described in Lee Markosian's Ph.D. thesis,
00337  *      "Art-based Modeling and Rendering for Computer Graphics."
00338  *      Brown University, May 2000.
00339  **********************************************************************/
00340 #define CIDRefImage const IDRefImage
00341 class IDRefImage : public RefImage {
00342  public:
00343    //******** MANAGERS ********
00344    // no public constructor -- get your hands on one this way:
00345    static IDRefImage* lookup(CVIEWptr& v = VIEW::peek());
00346 
00347    // make sure the reference image is current:
00348    virtual void update(); 
00349 
00350    //******** RGBA <---> KEY CONVERSIONS ********
00351    // Convert Bsimplex key value to 32-bit RGBA that can be given to
00352    // OpenGL, then read back from the frame buffer to reliably yield
00353    // the original key value:
00354 
00355    // At compilation time you can define REF_IMG_32_BIT if you know
00356    // you will run your application on a machine (and with a visual)
00357    // that supports 32-bit RGBA. In that case these are no-ops and we
00358    // can save a function call if the following are inlined. To define
00359    // REF_IMG_32_BIT add a line saying REF_IMG_32_BIT=yes in your
00360    // Makefile.local. 
00361 
00362    static uint key_to_rgba(uint key)    { 
00363       return key; 
00364 #ifdef REF_IMG_32_BIT
00365       return key; 
00366 #else
00367       return key_to_rgba2(key);      
00368 #endif
00369    }
00370    static uint rgba_to_key(uint rgba)   { 
00371       return rgba;
00372 #ifdef REF_IMG_32_BIT
00373       return rgba;
00374 #else      
00375       return rgba_to_key2(rgba);
00376 #endif
00377    }
00378    static uint key_to_rgba2(uint key);      
00379    static uint rgba_to_key2(uint rgba);
00380 
00381 
00382    //******** LOOKUP -- CONVENIENCE METHODS ********
00383    Bsimplex* simplex(uint id)       const {
00384       return Bsimplex::lookup(rgba_to_key(val(id)));
00385    }
00386    Bsimplex* simplex(CNDCpt& ndc)   const { return simplex(ndc_to_uint(ndc)); }
00387    Bsimplex* simplex(Cpoint2i& pix) const { return simplex(pix_to_uint(pix)); }
00388 
00389    Bvert* vert(uint id) const {
00390       Bsimplex* sim = simplex(id);
00391       return is_vert(sim) ? (Bvert*)sim : 0;
00392    }
00393    Bedge* edge(uint id) const {
00394       Bsimplex* sim = simplex(id);
00395       return is_edge(sim) ? (Bedge*)sim : 0;
00396    }
00397    Bface* face(uint id) const {
00398       Bsimplex* sim = simplex(id);
00399       return is_face(sim) ? (Bface*)sim : 0;
00400    }
00401    Bvert* vert(CNDCpt& ndc)         const { return vert(ndc_to_uint(ndc)); }
00402    Bedge* edge(CNDCpt& ndc)         const { return edge(ndc_to_uint(ndc)); }
00403    Bface* face(CNDCpt& ndc)         const { return face(ndc_to_uint(ndc)); }
00404    Patch* patch(CNDCpt& ndc)        const { return patch(simplex(ndc)); }
00405    Patch* face_patch(CNDCpt& ndc)   const { return face_patch(simplex(ndc));}
00406 
00407    Bvert* vert(Cpoint2i& pix)       const { return vert(pix_to_uint(pix)); }
00408    Bedge* edge(Cpoint2i& pix)       const { return edge(pix_to_uint(pix)); }
00409    Bface* face(Cpoint2i& pix)       const { return face(pix_to_uint(pix)); }
00410 
00411    //******** INTERSECTION ********
00412 
00413    // Do exact intersection. If a vert or an edge is hit exactly,
00414    // return it as the simplex.
00415    Bsimplex* intersect_sim(CNDCpt& ndc, Wpt& obj_pt) const {
00416       Bsimplex* sim = simplex(ndc);
00417       if (sim && sim->get_face())
00418          return sim->get_face()->find_intersect_sim(ndc, obj_pt);
00419       else return 0;
00420    }
00421 
00422    // Find the simplex that is intersected exactly (if any), but
00423    // return a face (either the sim itself or one that contains it):
00424    Bface* intersect(CNDCpt& ndc, Wpt& obj_pt) const {
00425       Bsimplex* sim = intersect_sim(ndc, obj_pt);
00426       return sim ? sim->get_face() : 0;
00427    }
00428 
00429    // Exact intersection -- return a face:
00430    Bface* intersect(CNDCpt& ndc) const {
00431       static Wpt foo;
00432       return intersect(ndc, foo);
00433    }
00434 
00435    // Search in a region defined by a screen point and radius.
00436    // Return true if some pixel corresponds to a simplex that
00437    // matches the search criterion. Also return (in 'hit' parameter)
00438    // the closest matching pixel of the reference image. This is
00439    // similar to find_near_simplex (below), but can also be used
00440    // when the search criterion accepts a null simplex:
00441    bool search(
00442       CNDCpt&           center,         // search center
00443       double            screen_pix_rad, // search radius in screen pixels
00444       CSimplexFilter&   filt,           // filter giving search criterion
00445       Point2i&          hit             // return value - hit point
00446       );
00447 
00448    // Similar to search() above, but returns the matching simplex
00449    // itself, if any. Returns 0 on failure.
00450    Bsimplex* find_near_simplex(
00451       CNDCpt& center,
00452       double screen_pix_rad = 1.0,
00453       CSimplexFilter& filt = SimplexFilter());
00454 
00455    // return true if the given pixel location records the ID of an
00456    // edge, and the edge is in the given patch, and it's a silhouette
00457    // edge.
00458    bool is_patch_sil_edge(Cpoint2i& pix, const Patch* patch) const {
00459       static Bedge* temp = 0;
00460       if (pix_in_range(pix) && (temp = edge(pix)) 
00461           && (temp->patch() == patch) && (temp->is_sil())) 
00462          return true;
00463       else return false;
00464    }
00465    bool is_patch_sil_edge(CNDCpt& pix, const Patch* patch) const {
00466       return is_patch_sil_edge(ndc_to_pix(pix), patch);
00467    }
00468 
00469    Bedge* find_neighbor(CNDCpt& p, Bedge* current, int radius = 1) const;
00470    ARRAY<Bedge*> find_all_neighbors(CNDCpt& p, Patch* patch, int radius = 1) const;
00471    ARRAY<Bedge*> find_all_neighbors(Cpoint2i& p, Patch* patch, int radius = 1) const;
00472    bool is_simplex_near(CNDCpt& p, const Bsimplex* simp, int radius = 1) const;
00473    bool is_patch_sil_edge_near(CNDCpt& ndc, const Patch* patch, int radius = 1) const;
00474 
00475    bool is_face_visible( CNDCpt& ndc, const Bface* bf ) const {
00476       Bface* f = face(ndc);
00477       if (!f) return false;
00478 
00479       if (f==bf) return true;
00480 
00481       static Wpt obj_pt;
00482       
00483       Bsimplex* sim = f->find_intersect_sim(ndc, obj_pt);
00484       return sim ? sim->on_face(bf) : false;
00485    }
00486    bool near_pix(Cpoint2i& pix, Point2i& ret, Patch* patch) {
00487       Point2i p;
00488       if (pix_in_range(pix) && face_patch(simplex(pix)) == patch)
00489          ret = pix;
00490       else if (pix_in_range(p = pix + Vec2i(-1, 0)) &&
00491                face_patch(simplex(p)) == patch)
00492          ret = p;
00493       else if (pix_in_range(p = pix + Vec2i( 1, 0)) &&
00494                face_patch(simplex(p)) == patch)
00495          ret = p;
00496       else if (pix_in_range(p = pix + Vec2i(-1,-1)) &&
00497                face_patch(simplex(p)) == patch)
00498          ret = p;
00499       else if (pix_in_range(p = pix + Vec2i(-1, 0)) &&
00500                face_patch(simplex(p)) == patch)
00501          ret = p;
00502       else if (pix_in_range(p = pix + Vec2i(-1, 1)) &&
00503                face_patch(simplex(p)) == patch)
00504          ret = p;
00505       else if (pix_in_range(p = pix + Vec2i( 1,-1)) &&
00506                face_patch(simplex(p)) == patch)
00507          ret = p;
00508       else if (pix_in_range(p = pix + Vec2i( 1, 0)) &&
00509                face_patch(simplex(p)) == patch)
00510          ret = p;
00511       else if (pix_in_range(p = pix + Vec2i( 1, 1)) &&
00512                face_patch(simplex(p)) == patch)
00513          ret = p;
00514       else
00515          return 0;
00516       return 1;
00517    }
00518 
00519    // global access to the one true ID ref image
00520    static void set_instance(IDRefImage * id_ref) { _instance = id_ref;      }
00521    static void set_instance(CVIEWptr & v)        { set_instance(lookup(v)); }
00522    static IDRefImage* instance()                 { return _instance;        }
00523 
00524    static void setup_bits(CVIEWptr&);
00525 
00526    //*******************************************************
00527    // PROTECTED
00528    //*******************************************************
00529  protected:
00530    IDRefImage(CVIEWptr& v);
00531 
00532    virtual void draw_objects(CGELlist&) const;
00533 
00534    Patch* patch(Bsimplex* sim) const {
00535       return (is_face(sim) ? ((Bface*)sim)->patch() :
00536               is_edge(sim) ? ((Bedge*)sim)->patch() :
00537               0);
00538    }
00539 
00540    Patch* face_patch(Bsimplex* sim) const {
00541       return (is_face(sim) ? ((Bface*)sim)->patch() : 0); 
00542    }
00543 
00544 
00545    static  HASH  _hash; // associates an IDRefImage with a VIEW
00546 
00547    static uint _red_bits;
00548    static uint _green_bits;
00549    static uint _blue_bits;
00550    static uint _alpha_bits;
00551    static bool _nonstandard_bits;
00552 
00553    // global instance 
00554    static IDRefImage* _instance;
00555 };
00556 
00557 #define CVisRefImage const VisRefImage
00558 class VisRefImageFactory;
00559 /**********************************************************************
00560  * VisRefImage:
00561  *
00562  *   Visibility reference image
00563  **********************************************************************/
00564 MAKE_PTR_SUBC(VisRefImage, FRAMEobs);
00565 class VisRefImage : public    IDRefImage,
00566                     protected BMESHobs,
00567                     protected CAMobs,
00568                     protected DISPobs,
00569                     protected EXISTobs,
00570                     public    FRAMEobs,
00571                     protected XFORMobs,
00572                     public    BaseVisRefImage {
00573  public:
00574    //******** MANAGERS ********
00575    virtual ~VisRefImage() { unobserve(); }
00576 
00577    //******** UPDATING ********
00578    bool need_update();
00579    virtual void update() {
00580       if (need_update())
00581          IDRefImage::update();
00582       _dirty = 0;
00583    }
00584    void force_dirty() { _dirty = 1; }
00585 
00586    //******** STATICS ********
00587    static void init();
00588    static VisRefImage* lookup(CVIEWptr& view = VIEW::peek()) {
00589       if (!view)
00590          return 0;
00591       if (!BaseVisRefImage::_factory)
00592          init();
00593       return (VisRefImage*)BaseVisRefImage::lookup(view);
00594    }
00595 
00596    //******** PICKING METHODS ********
00597    static NDCpt get_cursor() {
00598       if (!DEVice_2d::last) {
00599          err_msg( "VisRefImage::get_cursor: error: Device_2d::last is nil");
00600          return NDCpt();
00601       }
00602       return NDCpt(DEVice_2d::last->cur());
00603    }
00604 
00605    static Bsimplex* get_simplex(CNDCpt& cur = get_cursor(),
00606                                 double screen_rad=1,
00607                                 CSimplexFilter& filt = SimplexFilter()) {
00608       VisRefImage* vis = lookup(VIEW::peek());
00609       if (vis) {
00610          vis->update();
00611          return vis->find_near_simplex(cur, screen_rad, filt);
00612       }
00613       return (Bsimplex*)0;
00614    }
00615 
00616    // Return the nearest Bface within the given screen region,
00617    // with a preference for front-facing Bfaces:
00618    static Bface* get_face(CNDCpt& cur = get_cursor(), double screen_rad=1);
00619 
00620    // Call get_face() on each screen point in sequence:
00621    static Bface_list get_faces(const PIXEL_list& pix, double screen_rad=1);
00622 
00623    // Convenience:
00624    static Bface* Intersect(CNDCpt& ndc, Wpt& obj_pt) {
00625       VisRefImage* vis = lookup(VIEW::peek());
00626       if (vis) {
00627          vis->update();
00628          return vis->intersect(ndc, obj_pt);
00629       }
00630       return (Bface*)0;
00631    }
00632    static Bface* Intersect(CNDCpt& ndc) {
00633       Wpt foo;
00634       return Intersect(ndc, foo);
00635    }
00636 
00637    // 1. Search the ID image to find the nearest Bface
00638    //    within a radius of the given NDC screen location.
00639    // 2. Convert the screen location to a barycentric
00640    //    coordinate on the Bface.
00641    // 3. Return the Bface and barycentric coordinate.
00642    //    (Returns NULL on failure.)
00643    static Bface* get_face_bc(
00644       Wvec& bc, CNDCpt& ndc = get_cursor(), double rad=1
00645       );
00646    
00647    // Same as above, but also convert the Bface / barycentric
00648    // coordinate to an equivalent pair at the given mesh subdivision
00649    // level.
00650    static Bface* get_sub_face(
00651       int level, Wvec& bc, CNDCpt& ndc = get_cursor(), double rad=1
00652       );
00653 
00654    // Same as above, but also convert the Bface / barycentric
00655    // coordinate to an equivalent pair at the mesh edit level.
00656    static Bface* get_edit_face(
00657       Wvec& bc, CNDCpt& ndc = get_cursor(), double rad=1
00658       );
00659 
00660    static Bface* get_edit_face(CNDCpt& ndc = get_cursor(), double rad=1) {
00661       Wvec bc; return get_edit_face(bc, ndc, rad);
00662    }
00663 
00664    static Bface* get_ctrl_face(CNDCpt& cur = get_cursor(),
00665                                double screen_rad=1) {
00666       return ::get_ctrl_face(get_face(cur, screen_rad));
00667    }
00668 
00669    static Bedge* get_edge(CNDCpt& cur = get_cursor(),
00670                           double screen_rad=1) {
00671       return (Bedge*)get_simplex(cur, screen_rad, BedgeFilter());
00672    }
00673 
00674    static Bvert* get_vert(CNDCpt& cur = get_cursor(),
00675                           double screen_rad=1) {
00676       return (Bvert*)get_simplex(cur, screen_rad, BvertFilter());
00677    }
00678 
00679    static Patch* get_patch(CNDCpt& cur = get_cursor(),
00680                            double screen_rad=1) {
00681       // see mesh/patch.H:
00682       return ::get_patch(get_simplex(cur, screen_rad));
00683    }
00684 
00685    static Patch* get_ctrl_patch(CNDCpt& cur = get_cursor(),
00686                                 double screen_rad=1) {
00687       // see mesh/patch.H:
00688       return ::get_ctrl_patch(get_simplex(cur, screen_rad));
00689    }
00690 
00691    static BMESH* get_mesh(CNDCpt& cur = get_cursor(),
00692                           double screen_rad=1) {
00693       // see mesh/bsimplex.H:
00694       return ::get_mesh(get_simplex(cur, screen_rad));
00695    }
00696 
00697    static BMESH* get_ctrl_mesh(CNDCpt& cur = get_cursor(),
00698                                double screen_rad=1) {
00699       // see mesh/lmesh.H
00700       return ::get_ctrl_mesh(get_mesh(cur, screen_rad));
00701    }
00702 
00703    //******** BaseVisRefImage METHODS ********
00704 
00705    virtual void      vis_update() { update(); }
00706    virtual Bsimplex* vis_simplex(CNDCpt& ndc) const { return simplex(ndc); }
00707    virtual Bface*    vis_intersect(CNDCpt& ndc, Wpt& obj_pt) const {
00708       return intersect(ndc, obj_pt);
00709    }
00710    virtual void debug(CNDCpt& p) const;
00711 
00712    //******** OBSERVER METHODS ********
00713 
00714    void observe  ();
00715    void unobserve();
00716 
00717    // FRAMEobs:
00718    virtual int  tick();
00719 
00720    //*******************************************************
00721    // PROTECTED
00722    //*******************************************************
00723  protected:
00724    friend class VisRefImageFactory;
00725 
00726    //******** DATA ********
00727    int          _dirty;             // flag set when change occurred
00728    int          _countup;
00729 
00730    //******** MANAGERS ********
00731    VisRefImage(CVIEWptr& v);
00732 
00733    //******** UPDATING ********
00734    void reset() { _dirty = 1; _countup = 0; }
00735 
00736    //******** IDRefImage METHODS ********
00737    virtual void draw_objects(CGELlist&) const;
00738 
00739    virtual bool resize(uint new_w, uint new_h) {
00740       if (!IDRefImage::resize(new_w, new_h))
00741          return false;
00742       reset();
00743       return true;
00744    }
00745 
00746    //******** OBSERVER METHODS ********:
00747    // BMESHobs:
00748    virtual void notify_change(BMESH*, BMESH::change_t)  { reset(); }
00749    virtual void notify_xform (BMESH*, CWtransf&, CMOD&) { reset(); }
00750 
00751    // CAMobs:
00752    virtual void notify(CCAMdataptr&)    { reset(); }
00753 
00754    // DISPobs:
00755    virtual void notify(CGELptr&, int)   { reset(); }
00756 
00757    // EXISTobs:
00758    virtual void notify_exist(CGELptr&, int) { reset(); }
00759 
00760    // XFORMobs
00761    virtual void notify_xform(CGEOMptr&, STATE) { reset(); }
00762 };
00763 
00764 /**********************************************************************
00765  * TexMemRefImage: 
00766  *
00767  *   A "reference image" that saves the rendered image in a texture
00768  *   on the graphics card instead of in main memory.
00769  *
00770  **********************************************************************/
00771 class TexMemRefImage {
00772  public:
00773    // ******** MANAGERS ********
00774    
00775    // Use this to get (create or lookup) a TexMemRefImage 
00776    // associated with a given VIEW:
00777    static TexMemRefImage* lookup(CVIEWptr& v = VIEW::peek());
00778 
00779    // public constructor for those rare instances when you just want
00780    // to get your own, not tied to a view
00781    TexMemRefImage(
00782       CVIEWptr& v,
00783       RefImageClient::ref_img_t img_type=RefImageClient::REF_IMG_TEX_MEM
00784       );
00785 
00786    virtual ~TexMemRefImage() {}
00787    
00788    //******** ACCESSORS ********
00789    CVIEWptr& view() const { return _view; }
00790 
00791    // ******** UTILITIES ********
00792 
00793    // resize to new dimensions:
00794    bool resize(const Point2i& dims);
00795 
00796    // Ensure that the texture stored in GPU texture-memory is updated.
00797    void update();
00798 
00799    // Read from the frame buffer into a texture in GPU memory.
00800    void read_FB();
00801 
00802    // Draws the stored texture to the screen (for debugging):
00803    void draw_FB();
00804 
00805    // Return pointer to the texture
00806    TEXTUREglptr get_texture() const { return _texture; }
00807 
00808    //******** STATICS ********
00809 
00810    // lookup the TexMemRefImage and return a pointer to its internal texture:
00811    static TEXTUREglptr lookup_texture(CVIEWptr& v = VIEW::peek()) {
00812       TexMemRefImage* tex_mem = lookup(v);
00813       return tex_mem ? tex_mem->get_texture() : 0;
00814    }
00815    
00816    // Lookup the texture unit used by the current TexMemRefImage:
00817    static GLenum lookup_tex_unit(CVIEWptr& v = VIEW::peek()) {
00818       TEXTUREglptr tex = lookup_texture(v);
00819       return tex ? tex->get_tex_unit() : TexUnit::REF_IMG + GL_TEXTURE0;
00820    }
00821       
00822 
00823    static void activate_tex_unit(CVIEWptr& v = VIEW::peek()) {
00824       TEXTUREglptr tex = lookup_texture(v);
00825       assert(tex);
00826       tex->apply_texture();     // GL_ENABLE
00827    }
00828 
00829  protected:
00830    VIEWptr                      _view;          // associated VIEW
00831    RefImageClient::ref_img_t    _ref_img_type;  // REF_IMG_TEX_REF
00832    TEXTUREglptr                 _texture;
00833 
00834    static  HASH _hash;  // for looking up a TexMemRefImage given a VIEW
00835 
00836    virtual void draw_objects(CGELlist&) const;
00837 };
00838 
00839 #endif // REF_IMAGE_H_IS_INCLUDED
00840 
00841 // end of file ref_image.H

Generated on Mon Sep 18 11:39:33 2006 for jot by  doxygen 1.4.4