00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
00069 mGeometry = new Geometry;
00070
00071
00072 mVertCoord = new ArrayFloat3;
00073 mVertCoord->resize( 8 );
00074 mGeometry->setVertexArray( mVertCoord.get() );
00075
00076
00077 mTexCoord = new ArrayFloat3;
00078 mTexCoord->resize( 8 );
00079 mGeometry->setTexCoordArray( 0, mTexCoord.get() );
00080
00081
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->indices()->resize( 4*6 );
00089 memcpy( de->indices()->ptr(), de_indices, sizeof( de_indices ) );
00090
00091
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
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
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
00124
00125 int light_enable[4] = { 0,0,0,0 };
00126 fvec3 light_position[4];
00127 bool has_lights = false;
00128
00129 for( int i=0; i<4; ++i )
00130 {
00131 const vl::Light* light = shader->getLight( i );
00132 light_enable[i] = light != NULL;
00133 if ( light )
00134 {
00135 has_lights = true;
00136
00137 if ( light->followedTransform() )
00138 light_position[i] = ( fmat4 )light->followedTransform()->worldMatrix() * light->position().xyz();
00139
00140 else
00141 light_position[i] = ( ( fmat4 )camera->inverseViewMatrix() * light->position() ).xyz();
00142
00143
00144 if ( actor->transform() )
00145 light_position[i] = inv_mat * light_position[i];
00146 }
00147 }
00148
00149 actor->gocUniform( "light_position" )->setUniform( 4, light_position );
00150 actor->gocUniform( "light_enable" )->setUniform1i( 4, light_enable );
00151 }
00152
00153 if ( glsl->getUniformLocation( "eye_position" ) != -1 )
00154 {
00155
00156
00157
00158 fvec3 eye = ( fvec3 )camera->inverseViewMatrix().getT();
00159
00160 if ( actor->transform() )
00161 eye = inv_mat * eye;
00162 actor->gocUniform( "eye_position" )->setUniform( eye );
00163 }
00164
00165 if ( glsl->getUniformLocation( "eye_look" ) != -1 )
00166 {
00167
00168
00169
00170 fvec3 look = -( fvec3 )camera->inverseViewMatrix().getZ();
00171
00172 if ( actor->transform() )
00173 {
00174
00175 look = ( fmat4 )actor->transform()->worldMatrix().getInverse().getTransposed() * look;
00176 }
00177 actor->gocUniform( "eye_look" )->setUniform( look );
00178 }
00179 }
00180
00181 void RaycastVolume::bindActor( Actor* actor )
00182 {
00183 actor->actorEventCallbacks()->erase( this );
00184 actor->actorEventCallbacks()->push_back( this );
00185 actor->setLod( 0, mGeometry.get() );
00186 }
00187
00188 void RaycastVolume::onActorRenderStarted( Actor* actor, Real clock, const Camera* camera, Renderable* rend, const Shader* shader, int pass )
00189 {
00190 if ( pass>0 )
00191 return;
00192
00193
00194
00195 if ( shader->getGLSLProgram() )
00196 updateUniforms( actor, clock, camera, rend, shader );
00197 }
00198
00199 void RaycastVolume::generateTextureCoordinates( const ivec3& size )
00200 {
00201 if ( !size.x() || !size.y() || !size.z() )
00202 {
00203 Log::error( "RaycastVolume::generateTextureCoordinates(): failed! The size passed does not represent a 3D image.\n" );
00204 return;
00205 }
00206
00207 float dx = 0.5f/size.x();
00208 float dy = 0.5f/size.y();
00209 float dz = 0.5f/size.z();
00210
00211 float x0 = 0.0f + dx;
00212 float x1 = 1.0f - dx;
00213 float y0 = 0.0f + dy;
00214 float y1 = 1.0f - dy;
00215 float z0 = 0.0f + dz;
00216 float z1 = 1.0f - dz;
00217
00218 fvec3 texc[] =
00219 {
00220 fvec3( x0,y0,z1 ), fvec3( x1,y0,z1 ), fvec3( x1,y1,z1 ), fvec3( x0,y1,z1 ),
00221 fvec3( x0,y0,z0 ), fvec3( x1,y0,z0 ), fvec3( x1,y1,z0 ), fvec3( x0,y1,z0 ),
00222 };
00223 memcpy( mTexCoord->ptr(), texc, sizeof( texc ) );
00224 }
00225
00226 void RaycastVolume::generateTextureCoordinates(const ivec3& img_size, const ivec3& min_corner, const ivec3& max_corner)
00227 {
00228 if (!img_size.x() || !img_size.y() || !img_size.z())
00229 {
00230 Log::error("RaycastVolume::setDisplayRegion(): failed! The size passed does not represent a 3D image.\n");
00231 return;
00232 }
00233
00234 float dx = 0.5f/img_size.x();
00235 float dy = 0.5f/img_size.y();
00236 float dz = 0.5f/img_size.z();
00237
00238 float x0 = min_corner.x()/(float)img_size.x() + dx;
00239 float x1 = max_corner.x()/(float)img_size.x() - dx;
00240 float y0 = min_corner.y()/(float)img_size.y() + dy;
00241 float y1 = max_corner.y()/(float)img_size.y() - dy;
00242 float z0 = min_corner.z()/(float)img_size.z() + dz;
00243 float z1 = max_corner.z()/(float)img_size.z() - dz;
00244
00245 fvec3 texc[] =
00246 {
00247 fvec3(x0,y0,z0), fvec3(x1,y0,z0), fvec3(x1,y1,z0), fvec3(x0,y1,z0),
00248 fvec3(x0,y0,z1), fvec3(x1,y0,z1), fvec3(x1,y1,z1), fvec3(x0,y1,z1)
00249 };
00250 memcpy( mTexCoord->ptr(), texc, sizeof(texc) );
00251 }
00252
00253 void RaycastVolume::setBox( const AABB& box )
00254 {
00255 mBox = box;
00256
00257 float x0 = box.minCorner().x();
00258 float y0 = box.minCorner().y();
00259 float z0 = box.minCorner().z();
00260 float x1 = box.maxCorner().x();
00261 float y1 = box.maxCorner().y();
00262 float z1 = box.maxCorner().z();
00263 fvec3 box_verts[] =
00264 {
00265 fvec3( x0,y0,z1 ), fvec3( x1,y0,z1 ), fvec3( x1,y1,z1 ), fvec3( x0,y1,z1 ),
00266 fvec3( x0,y0,z0 ), fvec3( x1,y0,z0 ), fvec3( x1,y1,z0 ), fvec3( x0,y1,z0 ),
00267 };
00268 memcpy( mVertCoord->ptr(), box_verts, sizeof( box_verts ) );
00269 mGeometry->setBoundsDirty( true );
00270 }
00271