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/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 mGeometry->setObjectName("vl::SlicedVolume");
00085
00086 fvec3 texc[] =
00087 {
00088 fvec3(0,0,0), fvec3(1,0,0), fvec3(1,1,0), fvec3(0,1,0),
00089 fvec3(0,0,1), fvec3(1,0,1), fvec3(1,1,1), fvec3(0,1,1)
00090 };
00091 memcpy(mTexCoord, texc, sizeof(texc));
00092 }
00093
00102 void SlicedVolume::updateUniforms(Actor*actor, real, const Camera* camera, Renderable*, const Shader* shader)
00103 {
00104 const GLSLProgram* glsl = shader->getGLSLProgram();
00105
00106 if (glsl->getUniformLocation("light_position") != -1 && glsl->getUniformLocation("light_enable") != -1)
00107 {
00108
00109
00110 int light_enable[4] = { 0,0,0,0 };
00111 fvec3 light_position[4];
00112
00113 for(int i=0; i<4; ++i)
00114 {
00115 const Light* light = shader->getLight(i);
00116 light_enable[i] = light != NULL;
00117 if (light)
00118 {
00119
00120 if (light->boundTransform())
00121 light_position[i] = (fmat4)light->boundTransform()->worldMatrix() * light->position().xyz();
00122
00123 else
00124 light_position[i] = ((fmat4)camera->modelingMatrix() * light->position()).xyz();
00125
00126
00127 if (actor->transform())
00128 light_position[i] = (fmat4)actor->transform()->worldMatrix().getInverse() * light_position[i];
00129 }
00130 }
00131
00132 actor->gocUniform("light_position")->setUniform(4, light_position);
00133 actor->gocUniform("light_enable")->setUniform1i(4, light_enable);
00134 }
00135
00136 if (glsl->getUniformLocation("eye_position") != -1)
00137 {
00138
00139
00140
00141 fvec3 eye = (fvec3)camera->modelingMatrix().getT();
00142
00143 if (actor->transform())
00144 eye = (fmat4)actor->transform()->worldMatrix().getInverse() * eye;
00145 actor->gocUniform("eye_position")->setUniform(eye);
00146 }
00147 }
00148
00149 namespace
00150 {
00151 class Edge
00152 {
00153 public:
00154 int v0, v1, intersection, flags;
00155 bool operator<(const Edge& other) const
00156 {
00157 return intersection > other.intersection;
00158 }
00159 };
00160 }
00161
00162 void SlicedVolume::bindActor(Actor* actor)
00163 {
00164 actor->actorEventCallbacks()->push_back( this );
00165 actor->setLod(0, mGeometry.get());
00166 }
00167
00168 void SlicedVolume::onActorRenderStarted(Actor* actor, real clock, const Camera* camera, Renderable* rend, const Shader* shader, int pass)
00169 {
00170 if (pass>0)
00171 return;
00172
00173
00174
00175 if (shader->getGLSLProgram())
00176 updateUniforms(actor, clock, camera, rend, shader);
00177
00178
00179
00180
00181 fmat4 mat;
00182 if (actor->transform())
00183 mat = (fmat4)(camera->viewMatrix() * actor->transform()->worldMatrix());
00184 else
00185 mat = (fmat4)camera->viewMatrix();
00186
00187 if (mCache == mat)
00188 return;
00189 else
00190 mCache = mat;
00191
00192 fmat4 imat = mat.getInverse();
00193
00194 fvec3 cube_verts[] =
00195 {
00196 fvec3((float)box().minCorner().x(), (float)box().minCorner().y(), (float)box().minCorner().z()),
00197 fvec3((float)box().maxCorner().x(), (float)box().minCorner().y(), (float)box().minCorner().z()),
00198 fvec3((float)box().maxCorner().x(), (float)box().maxCorner().y(), (float)box().minCorner().z()),
00199 fvec3((float)box().minCorner().x(), (float)box().maxCorner().y(), (float)box().minCorner().z()),
00200 fvec3((float)box().minCorner().x(), (float)box().minCorner().y(), (float)box().maxCorner().z()),
00201 fvec3((float)box().maxCorner().x(), (float)box().minCorner().y(), (float)box().maxCorner().z()),
00202 fvec3((float)box().maxCorner().x(), (float)box().maxCorner().y(), (float)box().maxCorner().z()),
00203 fvec3((float)box().minCorner().x(), (float)box().maxCorner().y(), (float)box().maxCorner().z())
00204 };
00205
00206 int min_idx = 0;
00207 int max_idx = 0;
00208 for(int i=0; i<8; ++i)
00209 {
00210 cube_verts[i] = mat * cube_verts[i];
00211 if (fabs(cube_verts[i].z()) < fabs(cube_verts[min_idx].z())) min_idx = i;
00212 if (fabs(cube_verts[i].z()) > fabs(cube_verts[max_idx].z())) max_idx = i;
00213 }
00214
00215 if (cube_verts[min_idx].z() > 0)
00216 {
00217
00218
00219
00220 }
00221
00222 const int TOP = 1;
00223 const int BOTTOM = 2;
00224 const int LEFT = 4;
00225 const int RIGHT = 8;
00226 const int FRONT = 16;
00227 const int BACK = 32;
00228
00229 Edge edges[] =
00230 {
00231 {0,1,-1,FRONT |BOTTOM}, {1,2,-1,FRONT|RIGHT}, {2,3,-1,FRONT|TOP}, {3,0,-1,FRONT |LEFT},
00232 {4,5,-1,BACK |BOTTOM}, {5,6,-1,BACK |RIGHT}, {6,7,-1,BACK |TOP}, {7,4,-1,BACK |LEFT},
00233 {1,5,-1,BOTTOM|RIGHT}, {2,6,-1,TOP |RIGHT}, {3,7,-1,TOP |LEFT}, {0,4,-1,BOTTOM|LEFT}
00234 };
00235
00236 std::vector<fvec3> points;
00237 std::vector<fvec3> points_t;
00238 std::vector<fvec3> polygons;
00239 std::vector<fvec3> polygons_t;
00240
00241 polygons.reserve(sliceCount()*5);
00242 polygons_t.reserve(sliceCount()*5);
00243 float zrange = cube_verts[max_idx].z() - cube_verts[min_idx].z();
00244 float zstep = zrange/(sliceCount()+1);
00245 int vert_idx[12];
00246 for(int islice=0; islice<sliceCount(); ++islice)
00247 {
00248 float z = cube_verts[max_idx].z() - zstep*(islice+1);
00249 fvec3 plane_o(0,0,z);
00250 fvec3 plane_n(0,0,1.0f);
00251 points.clear();
00252 points_t.clear();
00253 for(int iedge=0; iedge<12; ++iedge)
00254 {
00255 edges[iedge].intersection = -1;
00256 fvec3 vi = cube_verts[ edges[iedge].v0 ];
00257 fvec3 eij = cube_verts[ edges[iedge].v1 ] - cube_verts[ edges[iedge].v0 ];
00258 float denom = dot(plane_n,eij);
00259 if (denom == 0)
00260 continue;
00261 float lambda = (z - dot(plane_n,vi))/denom;
00262 if (lambda<0 || lambda>1)
00263 continue;
00264 fvec3 v = vi + eij*lambda;
00265 edges[iedge].intersection = (int)points.size();
00266 points.push_back(v);
00267 fvec3 a = texCoords()[ edges[iedge].v0 ];
00268 fvec3 b = texCoords()[ edges[iedge].v1 ] - texCoords()[ edges[iedge].v0 ];
00269 fvec3 vt = a + b*lambda;
00270 points_t.push_back(vt);
00271 }
00272 std::sort(edges, edges+12);
00273 int vert_idx_c = 0;
00274 for(int ie0=0; ie0<12-1; ++ie0)
00275 {
00276 if (edges[ie0].intersection == -1)
00277 break;
00278 vert_idx[vert_idx_c++] = edges[ie0].intersection;
00279 for(int ie1=ie0+1; ie1<12; ++ie1)
00280 {
00281 if (edges[ie1].intersection == -1)
00282 continue;
00283 if( (edges[ie0].flags & edges[ie1].flags) )
00284 {
00285 Edge t = edges[ie0+1];
00286 edges[ie0+1] = edges[ie1];
00287 edges[ie1] = t;
00288 break;
00289 }
00290 }
00291 }
00292 for(int vc=0; vc<vert_idx_c-2; ++vc)
00293 {
00294 polygons.push_back(imat*points [vert_idx[0]]);
00295 polygons.push_back(imat*points [vert_idx[vc+1]]);
00296 polygons.push_back(imat*points [vert_idx[vc+2]]);
00297 polygons_t.push_back(points_t[vert_idx[0]]);
00298 polygons_t.push_back(points_t[vert_idx[vc+1]]);
00299 polygons_t.push_back(points_t[vert_idx[vc+2]]);
00300 }
00301 #ifndef NDEBUG
00302 for(int ie0=0; ie0<12-1; ++ie0)
00303 {
00304 if (edges[ie0].intersection == -1)
00305 break;
00306 if (edges[ie0+1].intersection == -1)
00307 break;
00308 VL_CHECK(edges[ie0].flags & edges[ie0+1].flags)
00309 }
00310 #endif
00311 }
00312
00313 mGeometry->drawCalls()->clear();
00314 ref<DrawArrays> da = new DrawArrays(PT_TRIANGLES, 0, (int)polygons.size());
00315 mGeometry->drawCalls()->push_back( da.get() );
00316 ref<ArrayFloat3> vertex_array = new ArrayFloat3;
00317 ref<ArrayFloat3> texcoo_array = new ArrayFloat3;
00318 vertex_array->resize(polygons.size());
00319 texcoo_array->resize(polygons_t.size());
00320 VL_CHECK((size_t)vertex_array->bufferObject()->bytesUsed() == sizeof(polygons [0])*polygons. size());
00321 VL_CHECK((size_t)texcoo_array->bufferObject()->bytesUsed() == sizeof(polygons_t[0])*polygons_t.size());
00322 memcpy(vertex_array->ptr(), &polygons [0], vertex_array->bufferObject()->bytesUsed());
00323 memcpy(texcoo_array->ptr(), &polygons_t[0], texcoo_array->bufferObject()->bytesUsed());
00324 mGeometry->setVertexArray(vertex_array.get());
00325 mGeometry->setTexCoordArray(0,texcoo_array.get());
00326
00327 mGeometry->setDisplayListDirty(true);
00328 mGeometry->setBufferObjectDirty(true);
00329
00330
00331
00332
00333 }
00334
00335 void SlicedVolume::generateTextureCoordinates(const ivec3& img_size)
00336 {
00337 if (!img_size.x() || !img_size.y() || !img_size.z())
00338 {
00339 Log::error("SlicedVolume::generateTextureCoordinates(): failed! The img_size passed does not represent a 3D image.\n");
00340 return;
00341 }
00342
00343 float dx = 0.5f/img_size.x();
00344 float dy = 0.5f/img_size.y();
00345 float dz = 0.5f/img_size.z();
00346
00347 float x0 = 0.0f + dx;
00348 float x1 = 1.0f - dx;
00349 float y0 = 0.0f + dy;
00350 float y1 = 1.0f - dy;
00351 float z0 = 0.0f + dz;
00352 float z1 = 1.0f - dz;
00353
00354 fvec3 texc[] =
00355 {
00356 fvec3(x0,y0,z0), fvec3(x1,y0,z0), fvec3(x1,y1,z0), fvec3(x0,y1,z0),
00357 fvec3(x0,y0,z1), fvec3(x1,y0,z1), fvec3(x1,y1,z1), fvec3(x0,y1,z1),
00358 };
00359 memcpy(mTexCoord, texc, sizeof(texc));
00360 }
00361
00362 void SlicedVolume::generateTextureCoordinates(const ivec3& img_size, const ivec3& min_corner, const ivec3& max_corner)
00363 {
00364 if (!img_size.x() || !img_size.y() || !img_size.z())
00365 {
00366 Log::error("SlicedVolume::setDisplayRegion(): failed! The size passed does not represent a 3D image.\n");
00367 return;
00368 }
00369
00370 float dx = 0.5f/img_size.x();
00371 float dy = 0.5f/img_size.y();
00372 float dz = 0.5f/img_size.z();
00373
00374 float x0 = min_corner.x()/(float)img_size.x() + dx;
00375 float x1 = max_corner.x()/(float)img_size.x() - dx;
00376 float y0 = min_corner.y()/(float)img_size.y() + dy;
00377 float y1 = max_corner.y()/(float)img_size.y() - dy;
00378 float z0 = min_corner.z()/(float)img_size.z() + dz;
00379 float z1 = max_corner.z()/(float)img_size.z() - dz;
00380
00381 fvec3 texc[] =
00382 {
00383 fvec3(x0,y0,z0), fvec3(x1,y0,z0), fvec3(x1,y1,z0), fvec3(x0,y1,z0),
00384 fvec3(x0,y0,z1), fvec3(x1,y0,z1), fvec3(x1,y1,z1), fvec3(x0,y1,z1)
00385 };
00386 memcpy(mTexCoord, texc, sizeof(texc));
00387 }
00388
00389 void SlicedVolume::setBox(const AABB& box)
00390 {
00391 mBox = box;
00392 mCache.fill(0);
00393 mGeometry->setBoundingBox( box );
00394 mGeometry->setBoundingSphere( box );
00395 mGeometry->setBoundsDirty(true);
00396 }
00397