void VTKWriter::writeOutput(int xsize, int ysize, OffsetArray<double> *_p, OffsetArray<utils::Vector<double,2> > *_v, const std::string& filename, int iteration) { initializeOutput(xsize*ysize); for(int i=0;i<xsize;i++) for(int j=0;j<ysize;j++) plotCell(_p,_v,i,j,1,0,0,1); writeFile(filename, iteration); }
int svmmRaycast( volume_t* v, const ray_t& r, int steps, bool precise ) { double tmin, tmax; glm::ivec3 size =v->size; fragment_t frag; frag.color =glm::vec4( 0,0,0,1 ); frag.normal =glm::vec3(0); frag.position =glm::vec3(0); frag.position_vs =glm::vec3(0); box_t b = volumeSizeToAABB( size ); if( !rayAABBIntersect( r, b, tmin, tmax ) ) return 0; glm::vec3 rayEntry = r.origin + r.direction * (float)std::max( 0.0, tmin ); glm::vec3 rayExit = r.origin + r.direction * (float)tmax; // Determine the side of the unit cube the ray enters // In order to do this, we need the component with the largest absolute number // These lines are optimized to do so without branching const glm::vec3 box_plane( 0, 1, 2 ); // X, Y and Z dividing planes glm::vec3 r0 = glm::abs( rayEntry / b.max ); float largest =std::max( r0.x, std::max( r0.y, r0.z ) ); // Largest relative component glm::vec3 r1 = glm::floor( r0 / largest ); // Vector with a '1' at the largest component int side = glm::clamp( glm::dot( box_plane, r1 ), 0.f, 2.f ); // Map the ray entry from unit-cube space to voxel space largest =std::max( size.x, std::max( size.y, size.z ) ); glm::vec3 rayEntry_vs =(rayEntry + b.max) * largest; // Calculate the index in the volume by chopping off the decimal part /* glm::ivec3 index = glm::clamp( glm::ivec3( glm::floor( rayEntry_vs ) ) , glm::ivec3( 0 ), glm::ivec3( size.x-1, size.y-1, size.z-1 ) );*/ /*frag.position_vs = glm::clamp( glm::vec3( rayEntry_vs ) , glm::vec3( 0 ), glm::vec3( size.x-1, size.y-1, size.z-1 ) );*/ frag.position_vs =rayEntry_vs; // Determine the sign of the stepping through the volume glm::vec3 step = glm::sign( r.direction ); // EDIT: mitigate the division-by-zero problem glm::bvec3 zeros =glm::equal( r.direction, glm::vec3(0) ); glm::vec3 direction =glm::vec3(glm::not_(zeros)) * r.direction + glm::vec3(zeros) * glm::vec3(.00000001f); // deltaDist gives the distance on the ray path for each following dividing plane glm::vec3 deltaDist =glm::abs( glm::vec3( glm::length( r.direction ) ) / direction ); printf( "deltaDist: (%f,%f,%f)\n", deltaDist.x, deltaDist.y, deltaDist.z ); deltaDist *= ((b.max * 2.f) / glm::vec3(size)); //glm::vec3 deltaDist =((b.max * 2.f) / glm::vec3(size)) / glm::normalize(direction); // Computes the distances to the next voxel for each component glm::vec3 boxDist = ( sign( r.direction ) * (glm::floor(rayEntry_vs) - rayEntry_vs) + (sign( r.direction ) * 0.5f ) + 0.5f ) * deltaDist; /* glm::vec3 ddist; ddist.x =( step.x > 0 ? (glm::floor( rayEntry_vs.x ) + 1.f - rayEntry_vs.x) : (rayEntry_vs.x - glm::floor( rayEntry_vs.x ) ) ); ddist.y =( step.y > 0 ? (glm::floor( rayEntry_vs.y ) + 1.f - rayEntry_vs.y) : (rayEntry_vs.y - glm::floor( rayEntry_vs.y ) ) ); ddist.z =( step.z > 0 ? (glm::floor( rayEntry_vs.z ) + 1.f - rayEntry_vs.z) : (rayEntry_vs.z - glm::floor( rayEntry_vs.z ) ) ); glm::vec3 boxDist( deltaDist / ddist );*/ printf( "deltaDist: (%f,%f,%f) boxDist: (%f,%f,%f)\n", deltaDist.x, deltaDist.y, deltaDist.z, boxDist.x, boxDist.y, boxDist.z ); // PLOT _plot_index =newPlot( voxelPx( glm::floor( frag.position_vs ) ), PLOT_INDEX_COLOR ); // ABOVE IS THE SAME AS voxelmapRaycast() // level_t *cur_level =v->levels; int level =0; char vox; glm::ivec3 abs_index, block_index, block_offset, subblock_index, grid_offset, voxel_index, mipmap_size; // uint64_t block_num =0; // uint32_t vox_raw; glm::ivec3 superblock_bounds; bool first =true; int s; for( s =0; s < steps; s++ ) { glm::ivec3 index =glm::floor( frag.position_vs ); // if( glm::any( glm::lessThan( index, glm::ivec3(0) ) ) || glm::any( glm::greaterThanEqual( index, size ) ) ) // break; cur_level =v->levels; level =0; //block_num =0; // while(1) { mipmap_size =v->size / cur_level->mipmap_factor; // REDUNDANT // Absolute position in the mipmap level abs_index =index / cur_level->mipmap_factor; // Relative position in the block block_index =abs_index; // The block is devided in subblocks: calculate the offset within the subblock block_offset = glm::ivec3( 0 ); // Calculate the index of the first block of the subblock subblock_index =block_index - block_offset; // Blocks are ordered linear on disk but as 3D texture on the GPU, // this is the 'block grid'. We need to calculate the block's // position in the grid. grid_offset =glm::ivec3(0); voxel_index =grid_offset * v->blockwidth + block_index; //printf( "(%d,%d,%d) ", voxel_index.x, voxel_index.y, voxel_index.z ); // Determine the level's format vox =cur_level->data_ptr[voxel_index.z+voxel_index.y*mipmap_size.z+voxel_index.x*mipmap_size.z*mipmap_size.y]; if( level == v->n_levels-1 || vox & TERMINAL ) { break; } level++; cur_level++; } // frag.color =blendF2B( vox, frag.color ); if( vox & FILLED ) { // We calculate the position in unit-cube space.. frag.position =frag.position_vs / (float)largest - b.max; // ..and the normal of the current 'face' of the voxel frag.normal[side] = -step[side]; first =false; break; } /* if( frag.color.a < 0.1f ) { break; }*/ // plot( &_plot_index, voxelPx( index ) ); // PLOT //plotCell( index, HIGHLIGHT, 1 ); plotCell( abs_index*cur_level->mipmap_factor, HIGHLIGHT, cur_level->mipmap_factor ); // plotCell( superblock_bounds, HIGHLIGHT2, /*cur_level->mipmap_factor*/ 1 ); glm::vec3 stepToParentBoundary( .5f * glm::vec3( cur_level->mipmap_factor-1 ) + .5f * step * glm::vec3( cur_level->mipmap_factor-1 ) - step * glm::vec3( index & (cur_level->mipmap_factor-1 ) ) ); /* glm::vec3 minStep( index & (cur_level->mipmap_factor-1) ); glm::vec3 maxStep( glm::vec3( cur_level->mipmap_factor-1) - minStep ); glm::vec3 stepToParentBoundary( step.x == 1 ? maxStep.x : minStep.x, step.y == 1 ? maxStep.y : minStep.y, step.z == 1 ? maxStep.z : minStep.z );*/ glm::vec3 distToParentBoundary( stepToParentBoundary * deltaDist ); glm::vec3 dist( boxDist + distToParentBoundary ); glm::bvec3 b0= glm::lessThan( dist, dist.yzx() ); glm::bvec3 b1= glm::lessThanEqual( dist, dist.zxy() ); glm::vec3 mask =glm::ivec3( b0.x && b1.x, b0.y && b1.y, b0.z && b1.z ); glm::vec3 mask2 =glm::abs( glm::vec3(1) - mask ); glm::vec3 sec_dist =glm::vec3( glm::dot( mask, distToParentBoundary ) ) / deltaDist; glm::vec3 multi_step =(sec_dist * mask2) + stepToParentBoundary * mask; printf( "step %d: index: (%d,%d,%d) stepToBoundary: (%f, %f, %f) distToBoundary: (%f, %f, %f) multi_step: (%f %f %f)\n", s, index.x, index.y, index.z, stepToParentBoundary.x, stepToParentBoundary.y, stepToParentBoundary.z, distToParentBoundary.x,distToParentBoundary.y,distToParentBoundary.z, multi_step.x, multi_step.y, multi_step.z ); // if( cur_level->mipmap_factor != 1 ) { boxDist += deltaDist * multi_step; // index += step * glm::ivec3(mask); frag.position_vs += step * glm::floor( multi_step ); // plotCell( glm::floor( frag.position_vs ) , HIGHLIGHT2, 1 ); // } // Branchless equivalent for /* for( int i =0; i < 3; i++ ) if( boxDist[side] > boxDist[i] ) side =i;*/ //while( glm::all( glm::equal( abs_index, index / cur_level->mipmap_factor ) ) ) { if( 1 ) { glm::vec3 mask; if( precise ) { glm::bvec3 b0= glm::lessThan( boxDist, boxDist.yzx() ); glm::bvec3 b1= glm::lessThanEqual( boxDist, boxDist.zxy() ); mask =glm::ivec3( b0.x && b1.x, b0.y && b1.y, b0.z && b1.z ); } else { glm::vec3 boxDist2 =glm::floor( boxDist ); glm::bvec3 b0= glm::lessThanEqual( boxDist2, boxDist2.yzx() ); glm::bvec3 b1= glm::lessThanEqual( boxDist2, boxDist2.zxy() ); mask =glm::ivec3( b0.x && b1.x, b0.y && b1.y, b0.z && b1.z ); } //side = glm::dot( box_plane, mask ); // mask[side]=1; //printf ( "boxdist: %f %f %f mask %f %f %f side %d\n", // boxDist.x, boxDist.y, boxDist.z, mask.x, mask.y, mask.z, side ); boxDist += deltaDist * mask; frag.position_vs += step * mask; //plotCell( index, HIGHLIGHT2, 1 ); } // plot( &_plot_index, voxelPx( index ) ); // PLOT plotCell( glm::floor( frag.position_vs ) , HIGHLIGHT2, 1 ); } return s; }