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

uv_data.H

Go to the documentation of this file.
00001 /*****************************************************************
00002  * uv_data.H
00003  *****************************************************************/
00004 #ifndef UV_DATA_H_IS_INCLUDED
00005 #define UV_DATA_H_IS_INCLUDED
00006 
00007 #include "lface.H"
00008 
00009 class UVMapping;
00010 
00011 /*****************************************************************
00012  * UVdata:
00013  *
00014  *    UV coordinates associated with a Bvert on a Bface.
00015  *
00016  *    Can store uv-coords explicitly for a vertex, which is an
00017  *    option when all the faces around the vertex agree on what
00018  *    the uv-coordinate should be.
00019  *
00020  *    If they don't all agree, then each face stores its own
00021  *    uv-coordinate for that vertex.
00022  *
00023  *    XXX - TODO: add specialized sub-classes for handling the
00024  *          distinct cases that the data is stored on a Bface,
00025  *          Bedge, or Bvert. Currently, the UVdata class is used
00026  *          for storing data on all 3 of those cases, which is a
00027  *          little clunky.
00028  *****************************************************************/
00029 #define CUVdata const UVdata
00030 class UVdata : public SimplexData {
00031  public:
00032    //******** MANAGERS ********
00033    // No public constructor -- use UVdata::set(...) below
00034 
00035    //******** RUN TIME TYPE ID ********
00036    DEFINE_RTTI_METHODS2("UVdata", SimplexData, CSimplexData*);
00037 
00038    /*******************************************************
00039     * Static methods
00040     *******************************************************/
00041 
00042    //******** CHECKING FOR UV-COORDS ********
00043 
00044    // Determine if the face has uv-coords:
00045    static bool has_uv(CBface* f) { return lookup(f) != NULL; }
00046 
00047    // Determine if it's a quad with continuous UV-coordinates:
00048    static bool quad_has_uv(CBface* quad);
00049 
00050    //******** GETTING UV-COORDS ********
00051 
00052    // In case the vertex has continuous uv-coords,
00053    // assign them to 'uv' and return true:
00054    static bool get_uv(CBvert* v, UVpt& uv);
00055 
00056    // Extract uv-coords for a Bvert on a Bface, w/ error checking.
00057    // An error occurs if v or f are nil, or f does not contain
00058    // v, or there are no uv-coords assigned to v or f:
00059    static bool get_uv(CBvert* v, CBface* f, UVpt& uv);
00060 
00061    // Same as above, with assertion of success, for confident types:
00062    static UVpt get_uv(CBvert* v, CBface* f);
00063 
00064    static bool get_uvs(CBface* f, UVpt& uv1, mlib::UVpt& uv2, mlib::UVpt& uv3) {
00065       if (!f)
00066          return false;
00067       return get_uv(f->v1(), f, uv1) &&
00068          get_uv(f->v2(), f, uv2) && get_uv(f->v3(), f, uv3);
00069    }
00070 
00071    static bool get_uvs(CBvert* v1, CBvert* v2, CBvert* v3,
00072                        UVpt& uv1, mlib::UVpt& uv2, mlib::UVpt& uv3) {
00073       Bface* f = lookup_face(v1,v2,v3);
00074       if (!f)
00075          return false;
00076       return get_uv(v1, f, uv1) && get_uv(v2, f, uv2) && get_uv(v3, f, uv3);
00077    }
00078 
00079    // XXX - Here for backwards compatibility. Will be removed.
00080    static UVpt get_uv(CBvert* v, CBface* f, bool& success) {
00081       UVpt ret;
00082       if (get_uv(v, f, ret)) {
00083          success = 1;
00084          return ret;
00085       }
00086       success = false;
00087       return ret;
00088    }
00089 
00090    // Return the 4 UV-coordinates at the quad corners:
00091    static bool get_quad_uvs(CBface* quad,
00092                             UVpt& uva, mlib::UVpt& uvb, mlib::UVpt& uvc, mlib::UVpt& uvd);
00093 
00094    // Return the 4 UV-coordinates of the given vertices that form a quad:
00095    static bool get_quad_uvs(CBvert* a, CBvert* b, CBvert* c, CBvert* d, 
00096                             UVpt& uva, mlib::UVpt& uvb, mlib::UVpt& uvc, mlib::UVpt& uvd);
00097 
00098    // For the given quad, do bilinear interpolation on the UV
00099    // coordinates at its 4 corners. The input parameter 'uv' can
00100    // vary from (0,0) at the lower left to (1,1) at the upper
00101    // right. The computed UV coordinate is returned in
00102    // 'texcoord', and the boolean return value indicates success
00103    // (true) or failure.
00104    static bool quad_interp_texcoord(
00105       CBface* quad, CUVpt& uv, mlib::UVpt& texcoord);
00106 
00107    //******** SETTING UV-COORDS ********
00108 
00109    // If uv-coords around v are continuous, then assign a new
00110    // value at v and return true. Otherwise return false.
00111    static bool set(Bvert* v, CUVpt& uv);
00112 
00113    // Set uv-coords for a single vertex WRT a face
00114    static bool set(Bvert* v, Bface* f, CUVpt& uv);
00115 
00116    // Set uv-coords on a face for 3 vertices all at once:
00117    static bool set(Bface* f,
00118                    Bvert* v1, Bvert* v2, Bvert* v3,
00119                    CUVpt&  a, mlib::CUVpt&  b, mlib::CUVpt&  c) {
00120       return (set(v1,f,a) && set(v2,f,b) && set(v3,f,c)); 
00121    }
00122 
00123    // Set uv-coords on a face, with given coords corresponding to
00124    // the face's v1, v2, v3 in that order:
00125    static bool set(Bface* f, CUVpt& a, mlib::CUVpt& b, mlib::CUVpt& c) {
00126       return set(f, f->v1(), f->v2(), f->v3(), a, b, c);
00127    }
00128 
00129    // Set uv-coords on a face (provided the 3 CCW verts define one):
00130    static bool set(Bvert*  v1, Bvert*  v2, Bvert*  v3,
00131                    CUVpt& uv1, mlib::CUVpt& uv2, mlib::CUVpt& uv3);
00132 
00133    // Set uv-coords on a quad (provided the 4 CCW verts define one):
00134    static bool set(Bvert*  v1, Bvert*  v2, Bvert*  v3, Bvert*  v4,
00135                    CUVpt& uv1, mlib::CUVpt& uv2, mlib::CUVpt& uv3, mlib::CUVpt& uv4);
00136 
00137    // Displace the currently assigned uv-coord by the given
00138    // delta.  Both methods require uv-coords to exist
00139    // already at the given vertex. First version also
00140    // requires uv-coords to be continuous:
00141    static bool offset_uv(Bvert* v, CUVvec& delt);
00142    static bool offset_uv(Bvert* v, Bface* f, CUVvec& delt);
00143 
00144    // change from per-vert uv-representation to per-face
00145    // at original subdiv level and all finer ones too
00146    static void split(CEdgeStrip& stip);
00147 
00148    //******** UV-CONTINUITY ********
00149 
00150    // Returns true if UV-coords are continuous across the edge:
00151    static bool is_continuous(CBedge* e);
00152 
00153    // Gives the number of UV-discontinous edges adjacent to v:
00154    static int discontinuity_degree(CBvert* v);
00155 
00156    // Returns true if there are no UV-discontinuous edges around v:
00157    static bool is_continuous(CBvert* v) {
00158       return (discontinuity_degree(v) == 0);
00159    }
00160 
00161    //******** LOOKUP ********
00162    // Lookup a UVdata* from a Bsimplex:
00163    static UVdata* lookup(CBsimplex* s) {
00164       return s ? (UVdata*)s->find_data(key()) : 0;
00165    }
00166 
00167    // Similar to above, but creates a UVdata if it wasn't found
00168    static UVdata* get_data(Bsimplex* s) {
00169       UVdata* ret = lookup(s);
00170       return ret ? ret : s ? new UVdata(s) : 0;
00171    }
00172 
00173    /*******************************************************
00174     * Non-static methods
00175     *******************************************************/
00176 
00177    //******** ACCESSORS ********
00178    UVMapping*   mapping()                 const { return _mapping; }
00179    void         set_mapping(UVMapping *m)       { _mapping = m; }
00180 
00181    // XXX - Temporary, for backward compatibility.
00182    //       For looking up uv-coords, callers should
00183    //       switch over to UVdata::get_uv(v,f) as above.
00184    Bface* face() const { assert(is_face(_simplex)); return (Bface*)_simplex; }
00185 
00186    // These are only safe to call on a UVdata associated w/ a face:
00187    // (otherwise an assertion fails):
00188    CUVpt& uv(CBvert* v) const;
00189    CUVpt& uv(int i)     const   { return uv(face()->v(i)); }
00190    CUVpt& uv1()         const   { return uv(1); }
00191    CUVpt& uv2()         const   { return uv(2); }
00192    CUVpt& uv3()         const   { return uv(3); }
00193 
00194    //******** SETTING SUBDIVISION CALC SCHEME ********
00195 
00196    // XXX - These don't invalidate previously computed subdivision
00197    //       values (if any), as they should:
00198    void set_do_simple() { _calc_type = SIMPLE_CALC; }
00199    void set_do_loop()   { _calc_type = LOOP_CALC; }
00200    void set_do_hybrid() { _calc_type = HYBRID_CALC; }
00201 
00202    //******** COORDINATE CONVERSIONS ********
00203    // Convert barycentric coords to UV:
00204    void bc2uv(CWvec& bc, mlib::UVpt& ret) {
00205       ret =  (uv1()*bc[0]) + (uv2()*bc[1]) + (uv3()*bc[2]);
00206    }
00207 
00208    //******** SimplexData VIRTUAL METHODS ********
00209    // These are here to prevent warnings:
00210    // store it on the given simplex:
00211    void set(uint id, Bsimplex* s)       { SimplexData::set(id,s); }
00212    void set(Cstr_ptr& str, Bsimplex* s) { SimplexData::set(str,s); }
00213    
00214    virtual void notify_split(Bsimplex*) {
00215       // Q: Need to do something?
00216       // A: Yes. (Not implemented.)
00217       err_msg("UVdata::notify_split: Warning: not implemented");
00218    }
00219 
00220    // Called when subdiv elements are generated:
00221    virtual void notify_subdiv_gen();
00222 
00223    // Callback for when the simplex is deleted:
00224    virtual void notify_simplex_deleted() {
00225       // New mapping dies when the hatch groups using it die
00226       // off.  That should happen before we get here...
00227       assert(!_mapping);
00228 
00229       // The base class does the right thing (deletes this!):
00230       SimplexData::notify_simplex_deleted();
00231    } 
00232 
00233    // Callback for when subdivision values need to be recomputed:
00234    virtual bool  handle_subdiv_calc();
00235 
00236    //*****************************************************************
00237  protected:
00238 
00239    // Enum for different schemes for computing UV-subdivision values:
00240    enum calc_type {
00241       SIMPLE_CALC = 0,          // The default choice
00242       LOOP_CALC,                // Use scheme of Charles Loop
00243       HYBRID_CALC               // Use mixed Catmull-Clark / Loop
00244    };
00245       
00246    UVpt         _uv;            // Just used when the simplex is a Bvert
00247    bool         _uv_valid;      // Tells whether above is valid
00248    calc_type    _calc_type;     // Which scheme to use
00249    bool         _did_subdiv;    // if true, subdiv calc was done once
00250 
00251    UVMapping*   _mapping;       // XXX - need a comment here...
00252 
00253    // The unique ID used to lookup UVdata:
00254    static uint key() {
00255       uint ret = (uint)**static_name();
00256       return ret;
00257    }
00258 
00259    //******** PROTECTED CONSTRUCTOR ********
00260    // The constructor is called (internally) only when the given
00261    // simplex does not already have a UVdata associated with it.
00262    //
00263    // UVdata gets looked-up by its classname.
00264    UVdata(Bsimplex* s);
00265 
00266    // For vertices only -- record a uv-coord for that vertex, to
00267    // be used regardless of which face containing the vertex is
00268    // considered.
00269    void set_uv(CUVpt& uv) {
00270       assert(is_vert(simplex()));
00271       _uv = uv;
00272       _uv_valid = true;
00273    }
00274 
00275    // Set uv-coords on a vertex, taking precendence over any
00276    // per-face uv-coords around the vertex.
00277    //
00278    // The public method set(v, uv) calls this method after
00279    // screening to ensure uv-coords are continuous at v:
00280    static void _set(Bvert* v, CUVpt& uv) {
00281       UVdata* uvd = get_data(v);
00282       assert(uvd);
00283       uvd->set_uv(uv);
00284    }
00285 
00286    //******** SPLITTING ********
00287 
00288    // Change from continuous uv at a vertex to per-face uv:
00289    static void split(Bvert* v);
00290 
00291    // split the verts
00292    static void split(CBvert_list& verts);
00293 
00294    // split a chain of verts, continuing at each finer subdiv level
00295    static void split_chain(Bvert_list chain);
00296 
00297    //******** SUBDIVISION HELPERS ********
00298 
00299    UVpt subdiv_uv(CBvert* v, CBface* f) const;
00300    UVpt subdiv_uv(CBedge* e, CBface* f) const;
00301 
00302    void set_subdiv_uv(Ledge* e, Lface* f);
00303    void set_subdiv_uv(Lvert* v, Lface* f);
00304 };
00305 
00306 #endif // UV_DATA_H_IS_INCLUDED
00307 
00308 /* end of file uv_data.H */

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