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->indexBuffer()->resize( 4*6 );
00089 memcpy( de->indexBuffer()->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
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
00135 if ( light->boundTransform() )
00136 light_position[i] = ( fmat4 )light->boundTransform()->worldMatrix() * light->position().xyz();
00137
00138 else
00139 light_position[i] = ( ( fmat4 )camera->modelingMatrix() * light->position() ).xyz();
00140
00141
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
00154
00155
00156 fvec3 eye = ( fvec3 )camera->modelingMatrix().getT();
00157
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
00166
00167
00168 fvec3 look = -( fvec3 )camera->modelingMatrix().getZ();
00169
00170 if ( actor->transform() )
00171 {
00172
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
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 ),
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
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