# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlVolume/SlicedVolume.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlVolume/SlicedVolume.hpp>
    00033 #include <vlGraphics/GLSL.hpp>
    00034 #include <vlGraphics/Camera.hpp>
    00035 #include <vlCore/Time.hpp>
    00036
    00037 using namespace vl;
    00038
    00077 //-----------------------------------------------------------------------------
    00079 SlicedVolume::SlicedVolume()
    00080 {
    00081   VL_DEBUG_SET_OBJECT_NAME()
    00082   mSliceCount = 1024;
    00083   mGeometry = new Geometry;
    00084
    00085   fvec3 texc[] =
    00086   {
    00087     fvec3(0,0,0), fvec3(1,0,0), fvec3(1,1,0), fvec3(0,1,0),
    00088     fvec3(0,0,1), fvec3(1,0,1), fvec3(1,1,1), fvec3(0,1,1)
    00089   };
    00090   memcpy(mTexCoord, texc, sizeof(texc));
    00091 }
    00092 //-----------------------------------------------------------------------------
    00101 void SlicedVolume::updateUniforms(Actor*actor, Real, const Camera* camera, Renderable*, const Shader* shader)
    00102 {
    00103   const GLSLProgram* glsl = shader->getGLSLProgram();
    00104
    00105   if (glsl->getUniformLocation("light_position") != -1 && glsl->getUniformLocation("light_enable") != -1)
    00106   {
    00107     // computes up to 4 light positions (in object space) and enables
    00108
    00109     int light_enable[4] = { 0,0,0,0 };
    00110     fvec3 light_position[4];
    00111
    00112     for(int i=0; i<4; ++i)
    00113     {
    00114       const Light* light = shader->getLight(i);
    00115       light_enable[i] = light != NULL;
    00116       if (light)
    00117       {
    00118         // light position following transform
    00119         if (light->followedTransform())
    00120           light_position[i] = (fmat4)light->followedTransform()->worldMatrix() * light->position().xyz();
    00121         // light position following camera
    00122         else
    00123           light_position[i] = ((fmat4)camera->inverseViewMatrix() * light->position()).xyz();
    00124
    00125         // light position in object space
    00126         if (actor->transform())
    00127           light_position[i] = (fmat4)actor->transform()->worldMatrix().getInverse() * light_position[i];
    00128       }
    00129     }
    00130
    00131     actor->gocUniform("light_position")->setUniform(4, light_position);
    00132     actor->gocUniform("light_enable")->setUniform1i(4, light_enable);
    00133   }
    00134
    00135   if (glsl->getUniformLocation("eye_position") != -1)
    00136   {
    00137     // pass the eye position in object space
    00138
    00139     // eye postion
    00140     fvec3 eye = (fvec3)camera->inverseViewMatrix().getT();
    00141     // world to object space
    00142     if (actor->transform())
    00143       eye = (fmat4)actor->transform()->worldMatrix().getInverse() * eye;
    00144     actor->gocUniform("eye_position")->setUniform(eye);
    00145   }
    00146 }
    00147 //-----------------------------------------------------------------------------
    00148 namespace
    00149 {
    00150   class Edge
    00151   {
    00152   public:
    00153     int v0, v1, intersection, flags;
    00154     bool operator<(const Edge& other) const
    00155     {
    00156       return intersection > other.intersection;
    00157     }
    00158   };
    00159 }
    00160 //-----------------------------------------------------------------------------
    00161 void SlicedVolume::bindActor(Actor* actor)
    00162 {
    00163   actor->actorEventCallbacks()->push_back( this );
    00164   actor->setLod(0, mGeometry.get());
    00165 }
    00166 //-----------------------------------------------------------------------------
    00167 void SlicedVolume::onActorRenderStarted(Actor* actor, Real clock, const Camera* camera, Renderable* rend, const Shader* shader, int pass)
    00168 {
    00169   if (pass>0)
    00170     return;
    00171
    00172   // setup uniform variables
    00173
    00174   if (shader->getGLSLProgram())
    00175     updateUniforms(actor, clock, camera, rend, shader);
    00176
    00177   // setup geometry: generate viewport aligned slices
    00178
    00179   // skip generation is actor and camera did not move
    00180   fmat4 mat;
    00181   if (actor->transform())
    00182     mat = (fmat4)(camera->viewMatrix() * actor->transform()->worldMatrix());
    00183   else
    00184     mat = (fmat4)camera->viewMatrix();
    00185
    00186   if (mCache == mat)
    00187     return;
    00188   else
    00189     mCache = mat;
    00190
    00191   fmat4 imat = mat.getInverse();
    00192
    00193   fvec3 cube_verts[] =
    00194   {
    00195     fvec3((float)box().minCorner().x(), (float)box().minCorner().y(), (float)box().minCorner().z()),
    00196     fvec3((float)box().maxCorner().x(), (float)box().minCorner().y(), (float)box().minCorner().z()),
    00197     fvec3((float)box().maxCorner().x(), (float)box().maxCorner().y(), (float)box().minCorner().z()),
    00198     fvec3((float)box().minCorner().x(), (float)box().maxCorner().y(), (float)box().minCorner().z()),
    00199     fvec3((float)box().minCorner().x(), (float)box().minCorner().y(), (float)box().maxCorner().z()),
    00200     fvec3((float)box().maxCorner().x(), (float)box().minCorner().y(), (float)box().maxCorner().z()),
    00201     fvec3((float)box().maxCorner().x(), (float)box().maxCorner().y(), (float)box().maxCorner().z()),
    00202     fvec3((float)box().minCorner().x(), (float)box().maxCorner().y(), (float)box().maxCorner().z())
    00203   };
    00204
    00205   int min_idx = 0;
    00206   int max_idx = 0;
    00207   for(int i=0; i<8; ++i)
    00208   {
    00209     cube_verts[i] = mat * cube_verts[i];
    00210     if (fabs(cube_verts[i].z()) < fabs(cube_verts[min_idx].z())) min_idx = i;
    00211     if (fabs(cube_verts[i].z()) > fabs(cube_verts[max_idx].z())) max_idx = i;
    00212   }
    00213
    00214   if (cube_verts[min_idx].z() > 0)
    00215   {
    00216     // fixme?
    00217     // the actor is not visible: remove the geometry or disable the actor?
    00218     // return;
    00219   }
    00220
    00221   const int TOP    = 1;
    00222   const int BOTTOM = 2;
    00223   const int LEFT   = 4;
    00224   const int RIGHT  = 8;
    00225   const int FRONT  = 16;
    00226   const int BACK   = 32;
    00227
    00228   Edge edges[] =
    00229   {
    00230     {0,1,-1,FRONT |BOTTOM}, {1,2,-1,FRONT|RIGHT}, {2,3,-1,FRONT|TOP},  {3,0,-1,FRONT |LEFT},
    00231     {4,5,-1,BACK  |BOTTOM}, {5,6,-1,BACK |RIGHT}, {6,7,-1,BACK |TOP},  {7,4,-1,BACK  |LEFT},
    00232     {1,5,-1,BOTTOM|RIGHT},  {2,6,-1,TOP  |RIGHT}, {3,7,-1,TOP  |LEFT}, {0,4,-1,BOTTOM|LEFT}
    00233   };
    00234
    00235   std::vector<fvec3> points;
    00236   std::vector<fvec3> points_t;
    00237   std::vector<fvec3> polygons;
    00238   std::vector<fvec3> polygons_t;
    00239
    00240   polygons.reserve(sliceCount()*5);
    00241   polygons_t.reserve(sliceCount()*5);
    00242   float zrange = cube_verts[max_idx].z() - cube_verts[min_idx].z();
    00243   float zstep  = zrange/(sliceCount()+1);
    00244   int vert_idx[12];
    00245   for(int islice=0; islice<sliceCount(); ++islice)
    00246   {
    00247     float z = cube_verts[max_idx].z() - zstep*(islice+1);
    00248     fvec3 plane_o(0,0,z);
    00249     fvec3 plane_n(0,0,1.0f);
    00250     points.clear();
    00251     points_t.clear();
    00252     for(int iedge=0; iedge<12; ++iedge)
    00253     {
    00254       edges[iedge].intersection = -1;
    00255       fvec3 vi  = cube_verts[ edges[iedge].v0 ];
    00256       fvec3 eij = cube_verts[ edges[iedge].v1 ] - cube_verts[ edges[iedge].v0 ];
    00257       float denom = dot(plane_n,eij);
    00258       if (denom == 0)
    00259         continue;
    00260       float lambda = (z - dot(plane_n,vi))/denom;
    00261       if (lambda<0 || lambda>1)
    00262         continue;
    00263       fvec3 v = vi + eij*lambda;
    00264       edges[iedge].intersection = (int)points.size();
    00265       points.push_back(v);
    00266       fvec3 a = texCoords()[ edges[iedge].v0 ];
    00267       fvec3 b = texCoords()[ edges[iedge].v1 ] - texCoords()[ edges[iedge].v0 ];
    00268       fvec3 vt = a + b*lambda;
    00269       points_t.push_back(vt);
    00270     }
    00271     std::sort(edges, edges+12);
    00272     int vert_idx_c = 0;
    00273     for(int ie0=0; ie0<12-1; ++ie0)
    00274     {
    00275       if (edges[ie0].intersection == -1)
    00276         break;
    00277       vert_idx[vert_idx_c++] = edges[ie0].intersection;
    00278       for(int ie1=ie0+1; ie1<12; ++ie1)
    00279       {
    00280         if (edges[ie1].intersection == -1)
    00281           continue;
    00282         if( (edges[ie0].flags & edges[ie1].flags) )
    00283         {
    00284           Edge t       = edges[ie0+1];
    00285           edges[ie0+1] = edges[ie1];
    00286           edges[ie1]   = t;
    00287           break;
    00288         }
    00289       }
    00290     }
    00291     for(int vc=0; vc<vert_idx_c-2; ++vc)
    00292     {
    00293       polygons.push_back(imat*points  [vert_idx[0]]);
    00294       polygons.push_back(imat*points  [vert_idx[vc+1]]);
    00295       polygons.push_back(imat*points  [vert_idx[vc+2]]);
    00296       polygons_t.push_back(points_t[vert_idx[0]]);
    00297       polygons_t.push_back(points_t[vert_idx[vc+1]]);
    00298       polygons_t.push_back(points_t[vert_idx[vc+2]]);
    00299     }
    00300     #ifndef NDEBUG
    00301       for(int ie0=0; ie0<12-1; ++ie0)
    00302       {
    00303         if (edges[ie0].intersection == -1)
    00304           break;
    00305         if (edges[ie0+1].intersection == -1)
    00306           break;
    00307         VL_CHECK(edges[ie0].flags & edges[ie0+1].flags)
    00308       }
    00309     #endif
    00310   }
    00311
    00312   mGeometry->drawCalls()->clear();
    00313   ref<DrawArrays> da = new DrawArrays(PT_TRIANGLES, 0, (int)polygons.size());
    00314   mGeometry->drawCalls()->push_back( da.get() );
    00315   ref<ArrayFloat3> vertex_array = new ArrayFloat3;
    00316   ref<ArrayFloat3> texcoo_array = new ArrayFloat3;
    00317   vertex_array->resize(polygons.size());
    00318   texcoo_array->resize(polygons_t.size());
    00319   VL_CHECK((size_t)vertex_array->gpuBuffer()->bytesUsed() == sizeof(polygons  [0])*polygons.  size());
    00320   VL_CHECK((size_t)texcoo_array->gpuBuffer()->bytesUsed() == sizeof(polygons_t[0])*polygons_t.size());
    00321   memcpy(vertex_array->ptr(), &polygons  [0], vertex_array->gpuBuffer()->bytesUsed());
    00322   memcpy(texcoo_array->ptr(), &polygons_t[0], texcoo_array->gpuBuffer()->bytesUsed());
    00323   mGeometry->setVertexArray(vertex_array.get());
    00324   mGeometry->setTexCoordArray(0,texcoo_array.get());
    00325
    00326   mGeometry->setDisplayListDirty(true);
    00327   mGeometry->setVBODirty(true);
    00328
    00329   // fixme:
    00330   // it seems we have some problems with camera clipping/culling when the camera is close to the volume: the slices disappear or degenerate.
    00331   // it does not seem to depend from camera clipping plane optimization.
    00332 }
    00333 //-----------------------------------------------------------------------------
    00334 void SlicedVolume::generateTextureCoordinates(const ivec3& img_size)
    00335 {
    00336   if (!img_size.x() || !img_size.y() || !img_size.z())
    00337   {
    00338     Log::error("SlicedVolume::generateTextureCoordinates(): failed! The img_size passed does not represent a 3D image.\n");
    00339     return;
    00340   }
    00341
    00342   float dx = 0.5f/img_size.x();
    00343   float dy = 0.5f/img_size.y();
    00344   float dz = 0.5f/img_size.z();
    00345
    00346   float x0 = 0.0f + dx;
    00347   float x1 = 1.0f - dx;
    00348   float y0 = 0.0f + dy;
    00349   float y1 = 1.0f - dy;
    00350   float z0 = 0.0f + dz;
    00351   float z1 = 1.0f - dz;
    00352
    00353   fvec3 texc[] =
    00354   {
    00355     fvec3(x0,y0,z1), fvec3(x1,y0,z1), fvec3(x1,y1,z1), fvec3(x0,y1,z1),
    00356     fvec3(x0,y0,z0), fvec3(x1,y0,z0), fvec3(x1,y1,z0), fvec3(x0,y1,z0),
    00357   };
    00358   memcpy(mTexCoord, texc, sizeof(texc));
    00359 }
    00360 //-----------------------------------------------------------------------------
    00361 void SlicedVolume::generateTextureCoordinates(const ivec3& img_size, const ivec3& min_corner, const ivec3& max_corner)
    00362 {
    00363     if (!img_size.x() || !img_size.y() || !img_size.z())
    00364     {
    00365         Log::error("SlicedVolume::setDisplayRegion(): failed! The size passed does not represent a 3D image.\n");
    00366         return;
    00367     }
    00368
    00369     float dx = 0.5f/img_size.x();
    00370     float dy = 0.5f/img_size.y();
    00371     float dz = 0.5f/img_size.z();
    00372
    00373     float x0 = min_corner.x()/(float)img_size.x() + dx;
    00374     float x1 = max_corner.x()/(float)img_size.x() - dx;
    00375     float y0 = min_corner.y()/(float)img_size.y() + dy;
    00376     float y1 = max_corner.y()/(float)img_size.y() - dy;
    00377     float z0 = min_corner.z()/(float)img_size.z() + dz;
    00378     float z1 = max_corner.z()/(float)img_size.z() - dz;
    00379
    00380     fvec3 texc[] =
    00381     {
    00382         fvec3(x0,y0,z0), fvec3(x1,y0,z0), fvec3(x1,y1,z0), fvec3(x0,y1,z0),
    00383         fvec3(x0,y0,z1), fvec3(x1,y0,z1), fvec3(x1,y1,z1), fvec3(x0,y1,z1)
    00384     };
    00385     memcpy(mTexCoord, texc, sizeof(texc));
    00386 }
    00387 //-----------------------------------------------------------------------------
    00388 void SlicedVolume::setBox(const AABB& box)
    00389 {
    00390   mBox = box;
    00391   mCache.fill(0);
    00392   mGeometry->setBoundingBox( box );
    00393   mGeometry->setBoundingSphere( box );
    00394   mGeometry->setBoundsDirty(true);
    00395 }
    00396 //-----------------------------------------------------------------------------

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:26.
Permission is granted to use this page to write and publish articles regarding Visualization Library.