Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://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 //-----------------------------------------------------------------------------