arbeit
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

subdivPlanarQuadS.cpp

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////
00002 // 6/6/02       Aaron Lefohn    Scientific Computing and Imaging Institute
00003 // School of Computing          University of Utah
00004 //
00005 //  This library is free software; you can redistribute it and/or
00006 //  modify it under the terms of the GNU Lesser General Public
00007 //  License as published by the Free Software Foundation; either
00008 //  version 2.1 of the License, or (at your option) any later version.
00009 //
00010 //  This library is distributed in the hope that it will be useful,
00011 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 //  Lesser General Public License for more details.
00014 //
00015 //  You should have received a copy of the GNU Lesser General Public
00016 //  License along with this library; if not, write to the Free Software
00017 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 ////////////////////////////////////////////////////////////////////////
00019 //
00020 // SubdivPlanarQuadS.cpp: implementation of the SubdivPlanarQuadS class.
00021 //
00022 /////////////////////////////////////////////////////////////////////
00023 
00024 #include <drawable/subdivPlanarQuadS.h>
00025 #include <drawable/primsGL.h>
00026 
00027 #include <iostream>
00028 #include <math.h>
00029 
00030 using namespace std;
00031 using namespace gutz;
00032 
00033 using namespace glift;
00034 
00035 SubdivPlanarQuadS::SubdivPlanarQuadS( GLenum primType, const vec2i& subDiv, const vec2f& lowerLeft, 
00036                                      const vec2f& upperRight, bool genTexCoords, bool genNorms,
00037                                      bool sharedVerts, TexCoordGen* texGen )
00038 {
00039    m_useShared = sharedVerts;
00040 
00041    init( primType, subDiv, lowerLeft, upperRight, 0.0f, 
00042       genTexCoords, genNorms, texGen ); 
00043 }
00044 
00045 SubdivPlanarQuadS::SubdivPlanarQuadS( GLenum primType, const vec2i& subDiv, const vec2f& lowerLeft, 
00046                                      const vec2f& upperRight, float z, bool genTexCoords, bool genNorms,
00047                                      bool sharedVerts, TexCoordGen* texGen )
00048 {
00049    m_useShared = sharedVerts;
00050 
00051    init( primType, subDiv, lowerLeft, upperRight, z, 
00052       genTexCoords, genNorms, texGen ); 
00053 }
00054 
00055 SubdivPlanarQuadS::~SubdivPlanarQuadS()
00056 {
00057    /*   for(int i=0; i < m_tiles.dim(0); i++) {
00058    for(int j=0; j < m_tiles.dim(1); j++) {
00059    delete m_tiles[i][j];
00060    }
00061    }
00062    */
00063 }
00064 
00065 /// Create subDivQuad with shared vertices (minimum number of possible verts)
00066 void SubdivPlanarQuadS::init( GLenum primType, const vec2i& subDiv,
00067                              const vec2f& lowerLeft, const vec2f& upperRight, 
00068                              float z, bool genTexCoords, bool genNorms,
00069                              TexCoordGen* texGen )
00070 {
00071    m_lowerLeft = lowerLeft;
00072    m_upperRight = upperRight;
00073    m_subDiv = subDiv;
00074    m_z = z;
00075    m_numActivePatches = subDiv.x * subDiv.y;
00076 
00077    if( isPowOfTwo(m_subDiv.x) && isPowOfTwo(m_subDiv.y) ) {
00078       m_lgSubDiv = vec2i( int(log(float(m_subDiv.x))/log(2.0f)), int(log(float(m_subDiv.y))/log(2.0f)) );
00079    }
00080 
00081    int numPatches = subDiv.x * subDiv.y;
00082    m_indices = arrayo1ui( numPatches*4, (unsigned int)0 );/// Possibility of 4 vertices per patch
00083 
00084    if( primType != GL_QUADS ) {//&&
00085       //        primType != GL_TRIANGLES ) {
00086       err() << "initMembers Error:\n"
00087          << "\tprimType must be GL_QUADS.\n";/// or GL_TRIANGLES.\n";
00088       exit(1);
00089    }
00090 
00091    /// Setup the texture coordinate generation functor
00092    bool createdTexGen = false;
00093    if( genTexCoords && texGen==NULL )  {
00094       texGen = new ScaleTexGen2D();
00095       createdTexGen = true;
00096    }
00097    else if( genTexCoords==false && texGen ) {
00098       err() << "createStrips(...) Error:\n"
00099          << "\tIllegal to disable texCoordGeneration and pass\n"
00100          << "\tin alternate texCoordGenerator.\n";
00101       exit(1);
00102    }
00103 
00104    vec3f normVec(0.0f, 0.0f, 1.0f);     //Constant for this primitive since always orthog to z-axis.
00105    vec3f quadScale( (float)fabs(upperRight.x - lowerLeft.x),  /// Scale factor for entire quad
00106       (float)fabs(upperRight.y - lowerLeft.y),
00107       1.0f );
00108 
00109    /// Generate vertices, norms, and indices
00110    arrayo2f vert, norm;
00111    arrayo1ui indices;
00112 
00113    if( m_useShared ) {
00114       initShared( subDiv, quadScale, z, normVec, vert, norm, indices );
00115    }
00116    else {
00117       initRedundant( subDiv, quadScale, z, normVec, vert, norm, indices );
00118    }
00119 
00120    norm = genNorms ? norm : arrayo2f();
00121 
00122    /// Generate texture coordinates based on vertices and dimen of quad
00123    arrayo2f texCoord = genTexCoords ? texGen->genTexCoords( vert, quadScale ) : arrayo2f();
00124 
00125    /// Generate the PixelTiles
00126    //initTiles( vert, texCoord, indices );
00127 
00128    /// Generate the primitive
00129    PrimGL* prim=NULL;
00130    switch(primType) {
00131    case GL_QUADS:       
00132       prim = new QuadsGL( vert, texCoord, quadScale, norm, indices, 
00133          arrayo2f(), arrayo1ub(), GLIFT_DRAW_IMM );
00134       break;
00135       /*        case GL_TRIANGLES: 
00136       prim = new TrianglesGL( vert, texCoord, quadScale, norm, indices, 
00137       gutz::arrayo2f(), gutz::arrayo1ub(), GLIFT_DRAW_ARR );
00138       break;
00139       */
00140    default: err() << "init(...):\n\tUnsupported primitive.\n\n";
00141       exit(1);
00142    }
00143 
00144    if( createdTexGen ) {
00145       delete texGen;
00146    }
00147 
00148    WrappedPrim::init( prim );
00149    m_prim = prim;
00150 }
00151 
00152 // Create the tiles 
00153 /*void SubdivPlanarQuadS::initTiles( const arrayo2f& vert, const arrayo2f& texCoord, arrayo1ui& indices )
00154 {
00155 const int NUM_TILES = m_subDiv.y * m_subDiv.x;
00156 const int NUM_INDICES = NUM_TILES * 4;
00157 assert( indices.dim(0) == NUM_INDICES );
00158 
00159 m_tiles = arrayOwn2<PixelTile*>(m_subDiv.y, m_subDiv.x, (PixelTile*)NULL);
00160 
00161 int startIndex=0;
00162 int tileIndex =0;
00163 for(int r=0; r < m_subDiv.y; r++ ) {            /// Row
00164 for(int c=0; c < m_subDiv.x; c++) {     /// Column
00165 arrayw1ui tileIndices(4, &(indices[startIndex]));
00166 startIndex += 4;
00167 
00168 m_tiles[r][c] = new PixelTile( vert, texCoord, tileIndices, tileIndex );
00169 tileIndex++;
00170 }
00171 }
00172 }*/
00173 
00174 void SubdivPlanarQuadS::initShared( const vec2i& subDiv, const vec3f& quadScale, float z, const vec3f& normVec, 
00175                                    arrayo2f& vert, arrayo2f& norm, arrayo1ui& indices )
00176 {
00177    const int NUM_VERTS_SHARE = (subDiv.x + 1) * (subDiv.y + 1);
00178    const int NUM_VERTS_ALL   = (subDiv.x + subDiv.y) * (subDiv.x + subDiv.y);
00179    vec2f     patchDimen( quadScale.x/subDiv.x,             /// Dimension of each subdivision patch
00180       quadScale.y/subDiv.y );
00181 
00182    /// Allocate memory for the data.
00183    /// TODO: Joe hacked these, I don't know what the intent of the original was!!!!
00184    //vert = arrayo2f( NUM_VERTS_SHARE, 3, (int)0 );
00185    vert = arrayo2f( NUM_VERTS_SHARE, 3, (float)0.0f );
00186    //norm = arrayo2f( NUM_VERTS_SHARE, 3, (int)0 );
00187    norm = arrayo2f( NUM_VERTS_SHARE, 3, (float)0.0f );
00188    //indices = arrayo1ui( NUM_VERTS_ALL,  (int)0);
00189    indices = arrayo1ui( NUM_VERTS_ALL,  (unsigned int)0);
00190 
00191    /// Create all vertices, norms, and indices
00192    int v=0; //Vertex  number
00193    int i=0; //Indices number
00194 
00195    for(int r=0; r <= subDiv.y; r++ ) {          /// Row
00196       for(int c=0; c <= subDiv.x; c++) {        /// Column
00197 
00198          vec3f curPos( patchDimen.x*c, patchDimen.y*r, z );/// Start at bottom-left corner
00199 
00200          vert[v][0] = curPos.x;
00201          vert[v][1] = curPos.y;
00202          vert[v][2] = curPos.z;
00203 
00204          norm[v][0] = normVec[0];
00205          norm[v][1] = normVec[1];
00206          norm[v][2] = normVec[2];
00207 
00208          if( r < subDiv.y ) {/// Set Indices
00209             if( c == 0 ) {  /// Left edge
00210                indices[i] = v;
00211                i++;
00212             }
00213             else {
00214                /// Finish out this quad
00215                indices[i+0] = v; 
00216                indices[i+1] = v + subDiv.x + 1; 
00217                indices[i+2] = v + subDiv.x;
00218                i+=3;
00219 
00220                if( c != subDiv.x ) { /// Not on right edge...TODO: Should this be c < subDiv.w?
00221                   /// First vertex of the next quad
00222                   indices[i] = v;
00223                   i++;
00224                }
00225             }
00226          }
00227 
00228          v++; //Increment vertex number
00229       }
00230    }
00231 }
00232 
00233 void SubdivPlanarQuadS::initRedundant( const vec2i& subDiv, const vec3f& quadScale, float z, const vec3f& normVec,
00234                                       gutz::arrayo2f& vert, gutz::arrayo2f& norm, arrayo1ui& indices )
00235 {       
00236    const int NUM_VERTS = (subDiv.x + subDiv.y) * (subDiv.x + subDiv.y);//All vertices are repeated!!
00237    vec2f     patchDimen( quadScale.x/subDiv.x,             /// Dimension of each subdivision patch
00238       quadScale.y/subDiv.y );
00239    vec2f          dim = patchDimen;
00240 
00241    /// Allocate memory for the data.
00242    vert = gutz::arrayo2f( NUM_VERTS, 3, (float)0 );
00243    norm = gutz::arrayo2f( NUM_VERTS, 3, (float)0 );
00244    indices = arrayo1ui( NUM_VERTS, (unsigned int)0 );
00245 
00246    /// Create all vertices, norms, and indices
00247    int v = 0;                                                           /// Vertex index
00248    for(int r=0; r < subDiv.y; r++ ) {           /// Row
00249       for(int c=0; c < subDiv.x; c++) { /// Column
00250 
00251          Vecvec3f pos(4);
00252          pos[0] = vec3f(dim.x*c,                dim.y*r,         z );/// Start at bottom-left corner
00253          pos[1] = vec3f(dim.x*(c+1), dim.y*r,    z );
00254          pos[2] = vec3f(dim.x*(c+1), dim.y*(r+1), z );
00255          pos[3] = vec3f(dim.x*c,                dim.y*(r+1), z );
00256 
00257          /// Compute all vertices, norms, and indices for this patch
00258          for(int i=0; i < 4; i++) { 
00259             vert[v][0] = pos[i].x;
00260             vert[v][1] = pos[i].y;
00261             vert[v][2] = pos[i].z;
00262 
00263             norm[v][0] = normVec[0];
00264             norm[v][1] = normVec[1];
00265             norm[v][2] = normVec[2];
00266 
00267             indices[v] = v;
00268 
00269             v++;
00270          }
00271       }
00272    }
00273 }
00274 
00275 void SubdivPlanarQuadS::bindQuads( const arrayw1ui& patchIndices )
00276 {
00277    /// Optimization Note: The Conditionals in the loop are loop-invariant
00278    //                                     so they should be optimized out by any decent compiler.
00279 
00280    int i=0; //Indices counter
00281    m_indices.reshape( m_subDiv.x * m_subDiv.y * 4 );//Reset to original size
00282    vec2i numVerts( m_subDiv.x + 1, m_subDiv.y + 1 );
00283    bool wIsPowOfTwo = isPowOfTwo( m_subDiv.x );
00284 
00285    m_numActivePatches = patchIndices.dim(0);
00286    for(int p=0; p < patchIndices.dim(0); p++) { /// Loop over all enabled indices
00287       int index = patchIndices[p];
00288 
00289       /// Get (row, col) coords for this index
00290       int r,c;
00291       if( wIsPowOfTwo ) {       
00292          r = index >> m_lgSubDiv.x;
00293          c = mod_fast(index, m_subDiv.x);
00294       }
00295       else {
00296          r = index / m_subDiv.x;
00297          c = index % m_subDiv.x;
00298       }
00299 
00300       if( m_useShared ) {
00301          m_indices[i+0] = numVerts.x * r + c;
00302          m_indices[i+1] = numVerts.x * r + (c + 1);
00303          m_indices[i+2] = numVerts.x * (r + 1) + (c + 1);
00304          m_indices[i+3] = numVerts.x * (r + 1) + c;
00305          i+=4;
00306       }
00307       else {
00308          int start = (m_subDiv.x * r + c) * 4;
00309 
00310          for(int v=0; v < 4; v++) {
00311             m_indices[i] = start + v;
00312             i++;
00313          }
00314       }
00315    }
00316 
00317    if( m_useShared ) {
00318       m_indices.reshape( i-3 );
00319    }
00320    else {
00321       m_indices.reshape( i );
00322    }
00323 
00324    bindIndices( &m_indices );
00325 }
00326 
00327 /// Specify which patches are to be drawn by their subdiv coords
00328 void SubdivPlanarQuadS::bindQuads( const Vecvec2i& patches )
00329 {
00330    int i=0; //Indices counter
00331    m_indices.reshape( m_subDiv.x * m_subDiv.y * 4 );//Reset to original size
00332    m_numActivePatches = patches.size();
00333 
00334    if( m_useShared ) {
00335       vec2i numVerts( m_subDiv.x + 1, m_subDiv.y + 1 );
00336 
00337       for(int p=0; p < (int)patches.size(); p++) {
00338          vec2i patch = patches[p];
00339 
00340          if( patch >= m_subDiv ) {
00341             err() << "bindQuads(...):\n\tPatch coordinate out of bounds.\n";
00342             exit(1);
00343          }
00344 
00345          m_indices[i+0] = numVerts.x * patch.y + patch.x;
00346          m_indices[i+1] = numVerts.x * patch.y + patch.x + 1;
00347          m_indices[i+2] = numVerts.x * (patch.y + 1) + patch.x + 1;
00348          m_indices[i+3] = numVerts.x * (patch.y + 1) + patch.x;
00349          i+=4;
00350       }
00351 
00352       m_indices.reshape(i-3); //Shrink current size, but do NOT delallocate memory
00353    }
00354    else { /// Redundant vertices
00355       for(int p=0; p < (int)patches.size(); p++){
00356          if( patches[p] >= m_subDiv ) {
00357             err() << "bindQuads(...):\n\tPatch coordinate out of bounds.\n";
00358             exit(1);
00359          }
00360 
00361          int start = (m_subDiv.x * patches[p].y + patches[p].x) * 4;
00362 
00363          for(int v=0; v < 4; v++) {
00364             m_indices[i] = start + v;
00365             i++;
00366          }
00367       }
00368 
00369       m_indices.reshape(i); //Shrink current size, but do NOT delallocate memory
00370    }
00371 
00372    bindIndices( &m_indices );
00373 }
00374 
00375 
00376 

Send questions, comments, and bug reports to:
jmk