Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlVolume/RaycastVolume.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
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/RaycastVolume.hpp>
00033 #include <vlGraphics/GLSL.hpp>
00034 #include <vlGraphics/Light.hpp>
00035 #include <vlGraphics/Camera.hpp>
00036 
00037 using namespace vl;
00038 
00065 RaycastVolume::RaycastVolume()
00066 {
00067   VL_DEBUG_SET_OBJECT_NAME()
00068   // box geometry
00069   mGeometry = new Geometry;
00070 
00071   // install vertex coords array
00072   mVertCoord = new ArrayFloat3;
00073   mVertCoord->resize( 8 );
00074   mGeometry->setVertexArray( mVertCoord.get() );
00075 
00076   // install texture coords array
00077   mTexCoord = new ArrayFloat3;
00078   mTexCoord->resize( 8 );
00079   mGeometry->setTexCoordArray( 0, mTexCoord.get() );
00080 
00081   // install index array
00082   ref<DrawElementsUInt> de = new DrawElementsUInt( PT_QUADS );
00083   mGeometry->drawCalls()->push_back( de.get() );
00084   unsigned int de_indices[] = 
00085   {
00086     0,1,2,3, 1,5,6,2, 5,4,7,6, 4,0,3,7, 3,2,6,7, 4,5,1,0
00087   };
00088   de->indexBuffer()->resize( 4*6 );
00089   memcpy( de->indexBuffer()->ptr(), de_indices, sizeof( de_indices ) );
00090 
00091   // generate default texture coordinates
00092   fvec3 texc[] = 
00093   {
00094     fvec3( 0,0,0 ), fvec3( 1,0,0 ), fvec3( 1,1,0 ), fvec3( 0,1,0 ),
00095     fvec3( 0,0,1 ), fvec3( 1,0,1 ), fvec3( 1,1,1 ), fvec3( 0,1,1 )
00096   };
00097   memcpy( mTexCoord->ptr(), texc, sizeof( texc ) );
00098 
00099   // default box dimensions and geometry
00100   setBox( AABB( vec3( 0,0,0 ), vec3( 1,1,1 ) ) );
00101 }
00102 //-----------------------------------------------------------------------------
00111 void RaycastVolume::updateUniforms( vl::Actor*actor, vl::real, const vl::Camera* camera, vl::Renderable*, const vl::Shader* shader )
00112 {
00113   const GLSLProgram* glsl = shader->getGLSLProgram();
00114   VL_CHECK( glsl );
00115 
00116   // used later
00117   fmat4 inv_mat;
00118   if (actor->transform())
00119     inv_mat = ( fmat4 )actor->transform()->worldMatrix().getInverse();
00120 
00121   if ( glsl->getUniformLocation( "light_position" ) != -1 && glsl->getUniformLocation( "light_enable" ) != -1 )
00122   {
00123     // computes up to 4 light positions ( in object space ) and enables
00124 
00125     int light_enable[4] = { 0,0,0,0 };
00126     fvec3 light_position[4];
00127 
00128     for( int i=0; i<4; ++i )
00129     {
00130       const vl::Light* light = shader->getLight( i );
00131       light_enable[i] = light != NULL;
00132       if ( light )
00133       {
00134         // light position following transform
00135         if ( light->boundTransform() )
00136           light_position[i] = ( fmat4 )light->boundTransform()->worldMatrix() * light->position().xyz();
00137         // light position following camera
00138         else
00139           light_position[i] = ( ( fmat4 )camera->modelingMatrix() * light->position() ).xyz();
00140 
00141         // light position in object space
00142         if ( actor->transform() )
00143           light_position[i] = inv_mat * light_position[i];
00144       }
00145     }
00146 
00147     actor->gocUniform( "light_position" )->setUniform( 4, light_position );
00148     actor->gocUniform( "light_enable" )->setUniform1i( 4, light_enable );
00149   }
00150 
00151   if ( glsl->getUniformLocation( "eye_position" ) != -1 )
00152   {
00153     // pass the eye position in object space
00154 
00155     // eye postion
00156     fvec3 eye = ( fvec3 )camera->modelingMatrix().getT();
00157     // world to object space
00158     if ( actor->transform() )
00159       eye = inv_mat * eye;
00160     actor->gocUniform( "eye_position" )->setUniform( eye );
00161   }
00162 
00163   if ( glsl->getUniformLocation( "eye_look" ) != -1 )
00164   {
00165     // pass the eye look direction in object space
00166 
00167     // eye postion
00168     fvec3 look = -( fvec3 )camera->modelingMatrix().getZ();
00169     // world to object space
00170     if ( actor->transform() )
00171     {
00172       // look = inv_mat * look;
00173       look = ( fmat4 )actor->transform()->worldMatrix().getInverse().getTransposed() * look;
00174     }
00175     actor->gocUniform( "eye_look" )->setUniform( look );
00176   }
00177 }
00178 //-----------------------------------------------------------------------------
00179 void RaycastVolume::bindActor( Actor* actor )
00180 {
00181   actor->actorEventCallbacks()->erase( this );
00182   actor->actorEventCallbacks()->push_back( this );
00183   actor->setLod( 0, mGeometry.get() );
00184 }
00185 //-----------------------------------------------------------------------------
00186 void RaycastVolume::onActorRenderStarted( Actor* actor, real clock, const Camera* camera, Renderable* rend, const Shader* shader, int pass )
00187 {
00188   if ( pass>0 )
00189     return;
00190 
00191   // setup uniform variables
00192 
00193   if ( shader->getGLSLProgram() )
00194     updateUniforms( actor, clock, camera, rend, shader );
00195 }
00196 //-----------------------------------------------------------------------------
00197 void RaycastVolume::generateTextureCoordinates( const ivec3& size )
00198 {
00199   if ( !size.x() || !size.y() || !size.z() )
00200   {
00201     Log::error( "RaycastVolume::generateTextureCoordinates(): failed! The size passed does not represent a 3D image.\n" );
00202     return;
00203   }
00204 
00205   float dx = 0.5f/size.x();
00206   float dy = 0.5f/size.y();
00207   float dz = 0.5f/size.z();
00208 
00209   float x0 = 0.0f + dx;
00210   float x1 = 1.0f - dx;
00211   float y0 = 0.0f + dy;
00212   float y1 = 1.0f - dy;
00213   float z0 = 0.0f + dz;
00214   float z1 = 1.0f - dz;
00215 
00216   fvec3 texc[] = 
00217   {
00218     fvec3( x0,y0,z1 ), fvec3( x1,y0,z1 ), fvec3( x1,y1,z1 ), fvec3( x0,y1,z1 ), // mic fixme: i don't remember why we need z1 here and z0 below...
00219     fvec3( x0,y0,z0 ), fvec3( x1,y0,z0 ), fvec3( x1,y1,z0 ), fvec3( x0,y1,z0 ), 
00220   };
00221   memcpy( mTexCoord->ptr(), texc, sizeof( texc ) );
00222 }
00223 //-----------------------------------------------------------------------------
00224 void RaycastVolume::generateTextureCoordinates(const ivec3& img_size, const ivec3& min_corner, const ivec3& max_corner)
00225 {
00226     if (!img_size.x() || !img_size.y() || !img_size.z())
00227     {
00228         Log::error("RaycastVolume::setDisplayRegion(): failed! The size passed does not represent a 3D image.\n");
00229         return;
00230     }
00231 
00232     float dx = 0.5f/img_size.x();
00233     float dy = 0.5f/img_size.y();
00234     float dz = 0.5f/img_size.z();
00235 
00236     float x0 = min_corner.x()/(float)img_size.x() + dx;
00237     float x1 = max_corner.x()/(float)img_size.x() - dx;
00238     float y0 = min_corner.y()/(float)img_size.y() + dy;
00239     float y1 = max_corner.y()/(float)img_size.y() - dy;
00240     float z0 = min_corner.z()/(float)img_size.z() + dz;
00241     float z1 = max_corner.z()/(float)img_size.z() - dz;
00242 
00243     fvec3 texc[] = 
00244     {
00245       fvec3( x0,y0,z1 ), fvec3( x1,y0,z1 ), fvec3( x1,y1,z1 ), fvec3( x0,y1,z1 ), 
00246       fvec3( x0,y0,z0 ), fvec3( x1,y0,z0 ), fvec3( x1,y1,z0 ), fvec3( x0,y1,z0 ), 
00247     };
00248     memcpy( mTexCoord->ptr(), texc, sizeof(texc) );
00249 }
00250 //-----------------------------------------------------------------------------
00251 void RaycastVolume::setBox( const AABB& box ) 
00252 {
00253   mBox = box;
00254   // generate the box geometry
00255   float x0 = box.minCorner().x();
00256   float y0 = box.minCorner().y();
00257   float z0 = box.minCorner().z();
00258   float x1 = box.maxCorner().x();
00259   float y1 = box.maxCorner().y();
00260   float z1 = box.maxCorner().z();
00261   fvec3 box_verts[] = 
00262   {
00263     fvec3( x0,y0,z1 ), fvec3( x1,y0,z1 ), fvec3( x1,y1,z1 ), fvec3( x0,y1,z1 ), 
00264     fvec3( x0,y0,z0 ), fvec3( x1,y0,z0 ), fvec3( x1,y1,z0 ), fvec3( x0,y1,z0 ), 
00265   };
00266   memcpy( mVertCoord->ptr(), box_verts, sizeof( box_verts ) );
00267   mGeometry->setBoundsDirty( true );
00268 }
00269 //-----------------------------------------------------------------------------

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:44.
Permission is granted to use this page to write and publish articles regarding Visualization Library.