Esempio n. 1
0
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;
}
Esempio n. 2
0
bool DepthBuffer::testAABB(vec3f min,vec3f max){
	vec4f vertices[8];
	gatherBoxVertices(vertices,min,max);
	transformBoxVertices(vertices,viewProjection_);
	boxVerticesToScreenVertices(vertices,clipSpaceToScreenSpaceMultiplier,center_);
	ScreenSpaceQuad faces[6];
	auto faceCount = extractBoxQuads(faces,vertices,aabbFrontFaceMask);
	for(uint32 i = 0;i<faceCount;++i){
		if(testTriangle2x2(faces[i].v[0],faces[i].v[1],faces[i].v[2])) return true;
		if(testTriangle2x2(faces[i].v[2],faces[i].v[3],faces[i].v[0])) return true;
	}
	return false;

	//Transform the AABB vertices to Homogenous clip space
	//vec4f vertices[8];
	vertices[0] = vec4f(min.x,min.y,min.z,1);
	vertices[1] = vec4f(max.x,min.y,min.z,1);
	vertices[2] = vec4f(max.x,max.y,min.z,1);
	vertices[3] = vec4f(min.x,max.y,min.z,1);
	vertices[4] = vec4f(min.x,min.y,max.z,1);
	vertices[5] = vec4f(max.x,min.y,max.z,1);
	vertices[6] = vec4f(max.x,max.y,max.z,1);
	vertices[7] = vec4f(min.x,max.y,max.z,1);
	vec4f clipMin,clipMax;
	for(uint32 i =0;i<8;++i){
		vertices[i] = viewProjection_ * vertices[i]; 
		vertices[i] = vertices[i] * (1.0f/vertices[i].w);
		//Homogenous coordinates => non-homogenous coordinates
		//Determine the min/max for the screen aabb
		clipMin = vec4f::min(vertices[i],clipMin);
		clipMax = vec4f::max(vertices[i],clipMax);
	}
	//Determine the screen aabb which covers the box
	//Clip space coordinates => screen coordinates [-1,1] -> [-320,320] -> [0,640]
	clipMin = vec4f::max(clipMin,vec4f(-1.0f,-1.0f,-1.0f,-1.0f))*clipSpaceToScreenSpaceMultiplier;
	clipMax = vec4f::min(clipMax,vec4f(1.0f,1.0f,1.0f,1.0f))*clipSpaceToScreenSpaceMultiplier;
	vec2i screenMin = vec2i(int32(clipMin.x),int32(clipMin.y))+center_;
	screenMin.x &= (~1);screenMin.y &= (~1);
	vec2i screenMax = vec2i(int32(clipMax.x),int32(clipMax.y))+center_;
	
	auto rowIdx = screenMin.y*size_.x + 2 * screenMin.x;

	float minZ = vertices[0].z;
	for(uint32 i = 1;i< 8;i++){
		minZ = std::min(minZ,vertices[i].z);
	}
	VecF32 flatDepth(minZ);

	//Iterate over the pixels
	for(;screenMin.y < screenMax.y;screenMin.y+=2,rowIdx += 2 * size_.x){
		auto idx = rowIdx;
	for(int32 x = screenMin.x;x<screenMax.x;x+=2,idx+=4){
		//Fetch the distance value for the current pixel.
		auto depth = VecF32::load(data_ + idx);
		vec3f rayo,rayd;
		getRay(rayo,rayd,x,screenMin.y);
		float dist;
		if(!rayAABBIntersect(min,max,rayo,rayd,dist)) continue;
		dist = ((dist-znear_)/zfar_ ) * 2.0f - 1.0f;
		VecF32 flatDepth(dist);
		flatDepth.store(data_+idx);
		auto mask = _mm_movemask_ps(cmple(flatDepth,depth).simd);
		//if(mask != 0)//{
			//return true; //Visible
		//}
			
		//
		//

		//Compute the distance to the aabb (raytrace)
		//vec3f rayo,rayd;
		//getRay(rayo,rayd,x,screenMin.y);
		//float dist;
		
		//Convert the distance from view space to depth space [-1,1]
		//dist = ((dist-znear_)/zfar_ ) * 2.0f - 1.0f;
		//Compare the values.
		//if(dist <= depth){
			//return true;
		//	data_[idx] = dist;
		//}
	} }
	return false;
}