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

CellProjector.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           CellProjector.cpp  -  description
00003                              -------------------
00004     begin                : Thu May 1 2003
00005     copyright            : (C) 2003 by tmeng
00006     email                : tmeng@sfu.ca
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include <string.h> //for strcmp
00019 
00020 #include "CellProjector.h"
00021 
00022 //----------------------------------------------------------------------------
00023 //------------------------- Class Variables Declaration ----------------------
00024 //----------------------------------------------------------------------------
00025 
00026 const int vu111211a::TETS_DEF_5_FOLD[10][4] = //checked by inspection
00027   {{4,0,1,2}, {7,1,3,2}, {4,2,1,7}, {4,7,6,2}, {4,5,7,1}, //first scheme
00028    {6,0,3,2}, {5,0,1,3}, {5,6,0,3}, {4,5,6,0}, {5,7,6,3}}; //second scheme
00029 
00030 const int vu111211a::TETS_DEF_6_FOLD[6][4] = //checked by inspection
00031     {{5,1,7,6}, {5,1,6,4}, {4,1,6,0}, {0,1,6,2}, {6,1,3,2}, {6,1,7,3}};
00032 
00033 //The voxel at origin has 8 vertices, each with x,y,z component
00034 const int vu111211a::VOXEL_VERTEX_LOCATIONS[8][3] = 
00035   {{0,0,0}, {1,0,0}, {0,1,0}, {1,1,0},
00036    {0,0,1}, {1,0,1}, {0,1,1}, {1,1,1}};
00037 
00038 const int vu111211a::TRIANGLE_DEF[4][3] = //checked by inspecting code
00039   {{0,1,2}, {1,3,2}, {0,2,3}, {0,3,1}};
00040 
00041 //----------------------------------------------------------------------------
00042 //------------------------- The default constructor --------------------------
00043 //----------------------------------------------------------------------------
00044 
00045 vu111211a::vu111211a()
00046   : m_state(NORMAL), m_subdivScheme(SIX_FOLD), m_isSort(false),
00047     m_isRender(false), m_tetIndex(0), m_grid()
00048   //m_View is set elsewhere, m_ImgBuffer set later.
00049 {
00050 }
00051 
00052 //----------------------------------------------------------------------------
00053 //------------------------- The copy constructor -----------------------------
00054 //----------------------------------------------------------------------------
00055 
00056 vu111211a::vu111211a(const vu111211a& inst) 
00057 {
00058   *this = inst; //invokes operator=, avoids redundent code
00059 }
00060 
00061 //----------------------------------------------------------------------------
00062 //------------------------- The destructor -----------------------------------
00063 //----------------------------------------------------------------------------
00064 
00065 vu111211a::~vu111211a()
00066 {
00067 }
00068 
00069 //----------------------------------------------------------------------------
00070 //------------------------- The assignment operator --------------------------
00071 //----------------------------------------------------------------------------
00072 
00073 vu111211a& vu111211a::operator=(const vu111211a& rhs)
00074 {
00075   if (this != &rhs)
00076     {
00077       vu111211::operator=(rhs); //chain to parent.
00078       m_View = rhs.m_View;
00079       m_ImgBuffer = rhs.m_ImgBuffer;
00080       m_state = rhs.m_state;
00081       m_subdivScheme = rhs.m_subdivScheme;
00082       m_isSort = rhs.m_isSort;
00083       m_isRender = rhs.m_isRender;
00084       m_tetIndex = rhs.m_tetIndex;
00085       m_grid = rhs.m_grid;
00086     }
00087     return *this;
00088 }
00089 
00090 //----------------------------------------------------------------------------
00091 //------------------------- public setViewVectors() --------------------------
00092 //----------------------------------------------------------------------------
00093 
00094 void vu111211a::setViewVectors(const vuVector& view,const vuVector& up,const vuVector& right)
00095 {
00096   m_View = view; 
00097   //m_View is the offset between the camera and the origin
00098   //so it is the opposite of the viewRay.
00099 }
00100 
00101 //----------------------------------------------------------------------------
00102 //------------------------- public initOpenGL() ------------------------------
00103 //----------------------------------------------------------------------------
00104 
00105 void vu111211a::initOpenGL() const
00106   //I've looked in CellProjector's initGlut function, everything that's
00107   //there seems to be here, plus some more. Will need to clean up later.
00108 {
00109   GLfloat shininess = 50.0f; //very shiny material.
00110   GLfloat specular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
00111 
00112   glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, shininess);
00113   glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular);
00114   glEnable(GL_COLOR_MATERIAL);
00115   glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
00116   //after this line, OpenGL pays attention to glColor
00117   //and not glMaterial. Without this line, it would
00118   //be the other way around.
00119 
00120   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00121   //GL_FRONT only should NOT work, coz lots of tets will need to have their backfaces
00122   //toward the viewer and they are needed for compositing.
00123 
00124   glShadeModel(GL_SMOOTH);
00125   glDisable(GL_DEPTH_TEST);
00126   glDisable(GL_ALPHA_TEST);
00127   glDisable(GL_CULL_FACE);
00128 
00129   //For blending and compositing calculations.
00130   glEnable(GL_BLEND);
00131   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00132 
00133   //scaling scales normals, this normalizes them. KEEP.
00134   glEnable(GL_NORMALIZE); //does not have to normalize gradients later on.
00135   //the gradients are just like normals and are passed into glNormal()
00136   //should compare to see how slow this is. If software normalization is
00137   //faster, then should use that.
00138 
00139   glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //background color;
00140   glClearDepth(1.0f); //default depth
00141   //value clamps to between 0 and 1. If an incoming pixel has a depth value
00142   //less than 1, that pixel will replace the current one. Else, it will be 
00143   //discarded.
00144 }
00145 
00146 //----------------------------------------------------------------------------
00147 //------------------------- public render() ----------------------------------
00148 //----------------------------------------------------------------------------
00149 
00150 void vu111211a::render() 
00151 {
00152   if(IsReRendering()) //only if redraw is desired do we render.
00153   {
00154     glClear(GL_COLOR_BUFFER_BIT); //erase color buffer
00155 
00156     //Be careful about the following values. Off by 1 -> very distorted images.
00157     //So if image looks correct, couldn't have made a mistake here.
00158 
00159     //quick hack to center data set, should be removed later
00160     //don't understand why the offset is needed, but it has
00161     //been working for every data set that I've been reading in.
00162     glMatrixMode(GL_MODELVIEW);
00163     glPushMatrix();
00164     glTranslatef(0.5f, 0.5f, 0.0f);
00165 
00166     //Set the OpenGL light info. Replaces the 0th light that
00167     //may already be shining from somewhere. Let the light be 
00168     //fixed to the camera so the data set is always visible.
00169     glLightfv(GL_LIGHT0, GL_POSITION, m_View.getData());
00170 
00171     //Drawing the grid without lighting so it shows up properly.
00172     glDisable(GL_LIGHTING);
00173     m_grid.drawInOpenGL();
00174     glEnable(GL_LIGHTING);
00175     
00176     if ((m_DataSize <= 4096) || (m_isRender)) //16 cubed
00177       { //draw in real time only if data set is small.
00178         m_isRender = false; //only draw once for large data sets.
00179         if (m_isSort)
00180           drawVoxelsSorted();
00181         else
00182           drawVoxelsUnsorted();
00183       }
00184     glPopMatrix();
00185   }
00186 
00187   this->writeImgBuffer(); //writes current frame into m_ImgBuffer.
00188   //this line hardly takes up any time (about 6 ms) to execute. 
00189   //So leave it in, even if there is no need to access the image 
00190   //buffer from the outside.
00191 }
00192 
00193 //----------------------------------------------------------------------------
00194 //------------------------- public drawPic() ---------------------------------
00195 //----------------------------------------------------------------------------
00196 
00197 void vu111211a::drawPic() const
00200   //called by vuCellProjector::DrawFromImage().
00201 {
00202   glDrawBuffer (GL_FRONT);
00203   glFinish ();
00204   
00205   glDisable (GL_BLEND);
00206 
00207   glDrawPixels (m_ImgBuffer.getWidth () - 1, m_ImgBuffer.getHeight () - 1, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *) (m_ImgBuffer.get_rgb ()));
00208   glDrawBuffer (GL_BACK);
00209   glDrawPixels (m_ImgBuffer.getWidth () - 1, m_ImgBuffer.getHeight () - 1, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *) (m_ImgBuffer.get_rgb ()));
00210 
00211   glFinish ();
00212 
00213   glDrawBuffer (GL_BACK);
00214 
00215   glEnable (GL_BLEND);
00216 }
00217 
00218 //----------------------------------------------------------------------------
00219 //------------------------- public getBuffer() -------------------------------
00220 //----------------------------------------------------------------------------
00221 
00222 vuImage* vu111211a::getBuffer ()
00223 {
00224   return &m_ImgBuffer;
00225 }
00226 
00227 //----------------------------------------------------------------------------
00228 //------------------------- public read() ------------------------------------
00229 //----------------------------------------------------------------------------
00230 
00231 bool vu111211a::read()
00232 {
00233   bool success = vu111211::read();
00234   if (!success) return false;
00235 
00236   //don't preprocess the gradients, cause quantized normals
00237   //are not entirely accurate, and float* normals take 12 times
00238   //as much space as the data set and will slow computations
00239   //down or even halt the program.
00240 
00241   this->initGrid();
00242 
00243   return true;
00244 }
00245 
00246 //----------------------------------------------------------------------------
00247 //------------------------- public readRaw() ---------------------------------
00248 //----------------------------------------------------------------------------
00249 
00250 bool vu111211a::readRaw(void)
00251 {
00252   dword len;
00253   ifstream in;
00254 
00255 #ifdef IS_NOCREATE_NEEDED
00256   in.open(m_FileName, ios::in|ios::binary|ios::nocreate);
00257 #else
00258   // The nocreate is not available on the IRIX boxes that we were compiling
00259   // this code on, so we had to remove this part from
00260   in.open(m_FileName, ios::in|ios::binary);
00261 #endif
00262   if (!in.is_open()) return false;
00263 
00264   in.seekg(0, ios::end);
00265   len = in.tellg();
00266   in.seekg(0, ios::beg);
00267 
00268   in >> m_Dim1Size >> m_Dim2Size >> m_Dim3Size;
00269   if (in.fail()) return false;
00270   m_DataSize = m_Dim1Size*m_Dim2Size*m_Dim3Size; //volume::m_DataSize
00271 
00272   m_Data = new byte[m_DataSize]; //volume::m_Data
00273   in.read((char *) (m_Data), int (m_DataSize));
00274   if (in.fail()) return false;
00275 
00276   in.close();
00277 
00278   //see read() above as to why not preprocess the gradients.
00279 
00280   return true;
00281 }
00282 
00283 //----------------------------------------------------------------------------
00284 //------------------------- private drawVoxelsSorted() -----------------------
00285 //----------------------------------------------------------------------------
00286 
00287 void vu111211a::drawVoxelsSorted() const
00288 {
00289 }
00290 
00291 //----------------------------------------------------------------------------
00292 //------------------------- private drawVoxelsUnSorted() ---------------------
00293 //----------------------------------------------------------------------------
00294 
00295 void vu111211a::drawVoxelsUnsorted() const
00296 {
00297   //CanNOT use the static keyword, else when opening a data set with
00298   //different dimentions, incorrect dimensions will be used.
00299   const int NUM_X_VOXELS = m_Dim1Size - 1; //one less than num of intensities.
00300   const int NUM_Y_VOXELS = m_Dim2Size - 1;
00301   const int NUM_Z_VOXELS = m_Dim3Size - 1;
00302 
00303   int x, y, z; //indices for the three respective axes.
00304   for (x = 0; x < NUM_X_VOXELS; x++)
00305       for (y = 0; y < NUM_Y_VOXELS; y++)
00306           for(z = 0; z < NUM_Z_VOXELS; z++)
00307               drawVoxel(x, y, z);
00308 }
00309 
00310 //----------------------------------------------------------------------------
00311 //------------------------- private drawVoxel() ------------------------------
00312 //----------------------------------------------------------------------------
00313 
00314 void vu111211a::drawVoxel(int x, int y, int z) const
00315 {  
00316   int i;
00317   const int VOXEL_ORIGIN[3] = {x,y,z};
00318   if (m_state == MANUAL_TET)
00319     {
00320       //Need to clear canvas for redrawing.
00321       glClear(GL_DEPTH_BUFFER_BIT); 
00322       //can only draw one tet at once with above clearing call.
00323 
00324       glDisable(GL_LIGHTING);
00325       glDisable(GL_BLEND);
00326       glEnable(GL_DEPTH_TEST);
00327       
00328       switch (m_subdivScheme)
00329         {
00330         case FIVE_FOLD:
00331           drawTet(TETS_DEF_5_FOLD[m_tetIndex], VOXEL_ORIGIN);
00332           break;
00333         case SIX_FOLD:
00334           drawTet(TETS_DEF_6_FOLD[m_tetIndex], VOXEL_ORIGIN);
00335           break;
00336         }
00337 
00338       glEnable(GL_LIGHTING);
00339       glEnable(GL_BLEND);
00340       glDisable(GL_DEPTH_TEST);
00341     }
00342   else if (m_state == NORMAL)
00343     {
00344       switch (m_subdivScheme)
00345         {
00346         case FIVE_FOLD:
00347           if((x+y+z)%2) //scheme 1
00348             { //could merge this with else by being smart with for statement.
00349               //int* tetOrder = getTetOrder();
00350               for (i = 0; i < 5; i++)
00351                 drawTet(TETS_DEF_5_FOLD[i], VOXEL_ORIGIN);
00352             }
00353           else //scheme 2, alternate with scheme 1 in all 3 axes
00354             {
00355               //int* tetOrder = getTetOrder();
00356               for (i = 5; i < 10; i++)
00357                 drawTet(TETS_DEF_5_FOLD[i], VOXEL_ORIGIN);
00358             }
00359           break;
00360         case SIX_FOLD:
00361           for (i = 0; i < 6; i++)
00362             drawTet(TETS_DEF_6_FOLD[i], VOXEL_ORIGIN);
00363         };
00364     }
00365 }
00366 
00367 //----------------------------------------------------------------------------
00368 //------------------------- private drawTet() --------------------------------
00369 //----------------------------------------------------------------------------
00370 
00371 void vu111211a::drawTet(const int TET_RELATIVE_INDICES[4], const int VOXEL_ORIGIN[3]) const
00372 {
00373   int tet[4][3]; //each tet has 4 vertices of 3 components each.
00374   int i, j;
00375   int vertexIndex;
00376   for (i = 0; i < 4; i++) //for each vertex of tet
00377     //compute the ith vertex of tet.
00378     {
00379       //find the vertex index on the voxel.
00380       vertexIndex = TET_RELATIVE_INDICES[i];
00381       for (j = 0; j < 3; j++) //for each of x,y,z component
00382         {
00383           //add the xyz offset to the voxel at the origin.
00384           tet[i][j] = VOXEL_VERTEX_LOCATIONS[vertexIndex][j] + VOXEL_ORIGIN[j];
00385         }
00386     }
00387   //seems right so far by inspecting cout statements
00388   drawTet(tet);
00389 }
00390 
00391 //----------------------------------------------------------------------------
00392 //------------------------- private drawTet() --------------------------------
00393 //----------------------------------------------------------------------------
00394 
00395 void vu111211a::drawTet(int tetVertexLocations[4][3]) const
00396 {
00397 
00398   int i, j; //loop indices
00399   int vertexIndex;
00400   byte intensity;
00401 
00402   if (m_state == MANUAL_TET)
00403     {
00404       drawTetNormals(tetVertexLocations); //draw normals for debugging
00405       char orientation[5];
00406       orientation[4] = '\0'; //nul terminated
00407       getTetOrientation(tetVertexLocations, orientation);
00408     }
00409    
00410   glBegin(GL_TRIANGLES); //each triple is a triangle.
00411 
00412   for (i = 0; i < 4; i++) //for each triangle
00413     {
00414       for (j = 0; j < 3; j++) //for each of its vertices
00415         {
00416           vertexIndex = TRIANGLE_DEF[i][j]; //draw this vertex in this iteration.
00417           if (m_state == NORMAL)
00418             {
00419               //compute the intensity at the vertex
00420               intensity = this->getIntensity(tetVertexLocations[vertexIndex]);
00421 
00422               glColor4f(m_TFunc[intensity][0], 
00423                         //first [] returns RGBA color array, second [] returns float
00424                         //in the range of 0 to 1.
00425                         m_TFunc[intensity][1], 
00426                         m_TFunc[intensity][2],
00427                         m_TFunc[intensity][3]);
00428             }
00429           else if (m_state == MANUAL_TET)
00430             {
00431               glColor4f(((i+j)/7.0f+0.5f)/1.5f,
00432                         (i/7.0f+0.5f)/1.5f,
00433                         (j/7.0f+0.5f)/1.5f,
00434                         1.0f);
00435             }
00436           glVertex3iv(tetVertexLocations[vertexIndex]);   
00437         }
00438     }
00439   glEnd();
00440 }
00441 
00442 //----------------------------------------------------------------------------
00443 //------------------------- private drawTetNormals() -------------------------
00444 //----------------------------------------------------------------------------
00445 
00446 void vu111211a::drawTetNormals(int tetVertexLocations[4][3]) const
00447 {
00448   int i, j; //loop indices.
00449   vuVector v[4]; //vertex locations in float instead of int
00450 
00451   //compute the four triangle faces of the tet.
00452   for (i = 0; i < 4; i++) //for each triangle.
00453     {
00454       for (j = 0; j < 3; j++) //for each vertex of the triangle.
00455         {
00456           v[i][j] = (float)(tetVertexLocations[i][j]);
00457         }
00458     }
00459 
00460   //Calculating a point inside the tetrahedron
00461   float m = 0.5f;
00462   vuVector p = v[0] + m*(v[1] - v[0]);
00463   p = p + m*(v[2] - p);
00464   p = p + m*(v[3] - p);
00465 
00466   //drawing the normals centered at p.
00467   glBegin(GL_LINES); //each new pair is a new line.
00468   vuVector normals[4]; //one for each triangle
00469   this->getTetNormals(tetVertexLocations, normals);
00470   for (i = 0; i < 4; i++)
00471     {
00472       glColor4f(i/6.0f, (i+4)/ 7.0f, i/ 4.0f, 1.0f);
00473       glVertex3fv(p.getData());
00474       glColor4f(i/4.0f, (i+3)/ 6.0f, i/ 7.0f, 1.0f);
00475       glVertex3fv((p+normals[i]).getData());
00476     }
00477   glEnd(); //make sure the glBegin and glEnd are not nested
00478 }
00479 
00480 //----------------------------------------------------------------------------
00481 //------------------------- private getTetOrientation() ----------------------
00482 //----------------------------------------------------------------------------
00483 
00484 void vu111211a::getTetOrientation(int tetVertexLocations[4][3], 
00485                                   char orientation[4] /* out */) const
00486 {
00487   vuVector normals[4];
00488   this->getTetNormals(tetVertexLocations, normals);
00489   
00490   int i;
00491   for (i = 0; i < 4; i++) //for each triangle
00492     {
00493       if (normals[i].dot(m_View) > 0.0f)
00494         //m_View is the offset between the camera and the origin
00495         //so it is the opposite of the viewRay.
00496         { //triangle is pointing TOWARD the viewer (opp dir as view ray)
00497           orientation[i] = '+';
00498         }
00499       else orientation[i] = '-'; //pointing AWAY from viewer
00500       //note the if else is different from old code, since m_View
00501       //is the view ray negated.
00502     }
00503 }
00504 
00505 //----------------------------------------------------------------------------
00506 //------------------------- private getTetNormals() --------------------------
00507 //----------------------------------------------------------------------------
00508 
00509 void vu111211a::getTetNormals(int tetVertexLocations[4][3], 
00510                               vuVector normals[4] /* out */) const
00511 {
00512   /*static*/ const int TRIANGLE_DEF[4][3] = //checked by inspecting code
00513     {{0,1,2}, {1,3,2}, {0,2,3}, {0,3,1}};
00514 
00515   int i, j, k; //loop indices.
00516   int vertexIndex;
00517   vuVector v[4]; //vertex locations in float instead of int
00518   vuVector* triangles[4][3]; //4 triangles, 3 vertices each
00519 
00520   //compute the four triangle faces of the tet.
00521   for (i = 0; i < 4; i++) //for each triangle.
00522     {
00523       for (j = 0; j < 3; j++) //for each vertex of the triangle.
00524         {
00525           v[i][j] = (float)(tetVertexLocations[i][j]); //update ith vertex
00526           for (k = 0; k < 3; k++) //for each xyz component of vertex.
00527             {
00528               vertexIndex = TRIANGLE_DEF[i][j];
00529               triangles[i][j] = &(v[vertexIndex]); //update ith triangle
00530             }
00531         } //ith vertex and ith triangle computed, ok since triangle 
00532       //is composed of pointers and other vertices will be changed
00533       //in subsequence iteration of loop.
00534     }
00535   for (i = 0; i < 4; i++)  //calculate normal for each triangle.
00536     normals[i] = getNormal(triangles[i]);
00537 }
00538 
00539 //----------------------------------------------------------------------------
00540 //------------------------- private getNormal() ------------------------------
00541 //----------------------------------------------------------------------------
00542 
00543 vuVector vu111211a::getNormal(vuVector* v[3]) const
00544 {
00545   vuVector normal;
00546   normal = (*v[2] - *v[1]).cross(*v[0] - *v[1]);
00547   return normal;
00548 }
00549 
00550 //----------------------------------------------------------------------------
00551 //------------------------- private getTetIntensity() -------------------------
00552 //----------------------------------------------------------------------------
00553 
00554 byte vu111211a::getIntensity(int vertex[3]) const
00555 {
00556   //Cannot use "static" because data sets may be of different sizes
00557   //as the user opens and closes data set files.
00558   const int NUM_X_SAMPLES = m_Dim1Size;
00559   const int NUM_Y_SAMPLES = m_Dim2Size;
00560 
00561   int x = vertex[0];
00562   int y = vertex[1];
00563   int z = vertex[2];
00564   int intensityIndex = z * (NUM_X_SAMPLES * NUM_Y_SAMPLES) + y * NUM_X_SAMPLES + x; 
00565 
00566   byte intensity = this->m_Data[intensityIndex];  
00567 
00568   return intensity;
00569 }
00570 
00571 //----------------------------------------------------------------------------
00572 //------------------------- private initGrid() -------------------------------
00573 //----------------------------------------------------------------------------
00574 
00575 void vu111211a::initGrid()
00576 {
00577   float scale = 1.25f;
00578   float width = scale * (m_Dim1Size-1); //x
00579   float height = scale * (m_Dim2Size-1); //y
00580   float depth = scale * (m_Dim3Size-1); //z
00581 
00582   m_grid = vuGrid(width, height, depth);
00583 }
00584 
00585 //----------------------------------------------------------------------------
00586 //------------------------- private writeImgBuffer() -------------------------
00587 //----------------------------------------------------------------------------
00588 
00589 void vu111211a::writeImgBuffer()
00593   //To be used by i.e. a parallel coordinates interface that displays
00594   //renderings from different renderers side by side.
00595 
00596   //This function needs to be re-examined to make sure it works.
00597 {
00598   int retval [4];
00599   glGetIntegerv (GL_VIEWPORT, retval);
00600   m_ImgBuffer.init (retval [2] + 1, retval [3] + 1);
00601   glReadBuffer (GL_FRONT);
00602   glReadPixels (0, 0, m_ImgBuffer.getWidth () - 1, m_ImgBuffer.getHeight () - 1, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char *) (m_ImgBuffer.get_rgb ()));
00603 
00604   //testing to see if the dimensions are updating with window resizing.
00605   //cout << "dim1:" << retval [2] << "dim2:" << retval [3] << endl;
00606 }

Generated on Wed Dec 15 21:20:28 2004 for vuVolume by  doxygen 1.3.9.1