// We create packets and directly fill each zBuffer tile. Note that we // really store t values void TaskRayTraceHiZ::run(size_t taskID) { const uint32 taskX = taskID % this->taskXNum; const uint32 taskY = taskID / this->taskXNum; const uint32 startX = taskX * this->width; const uint32 startY = taskY * this->height; const uint32 endX = startX + this->width; const uint32 endY = startY + this->height; uint32 tileY = startY / HiZ::Tile::height; for (uint32 y = startY; y < endY; y += RayPacket::height, ++tileY) { uint32 tileX = startX / HiZ::Tile::width; for (uint32 x = startX; x < endX; x += RayPacket::width, ++tileX) { RayPacket pckt; PacketHit hit; gen.generate(pckt, x, y); intersector->traverse(pckt, hit); ssef zmin(inf), zmax(neg_inf); const uint32 tileID = tileX + tileY * zBuffer->tileXNum; PF_ASSERT(tileID < zBuffer->tileNum); HiZ::Tile &tile = zBuffer->tiles[tileID]; for (uint32 chunkID = 0; chunkID < HiZ::Tile::chunkNum; ++chunkID) { //const ssef t = hit.t[chunkID]; const ssef t = hit.t[chunkID] *dot(sse3f(view.x,view.y,view.z), pckt.dir[chunkID]); tile.z[chunkID] = t; zmin = min(zmin, t); zmax = max(zmax, t); } tile.zmin = reduce_min(zmin)[0]; tile.zmax = reduce_max(zmax)[0]; } } }
void GhostBlockBrickedVolume::createEquivalentISPC() { // Get the voxel type. voxelType = getParamString("voxelType", "unspecified"); exitOnCondition(getVoxelType() == OSP_UNKNOWN, "unrecognized voxel type (must be set before calling " "ospSetRegion())"); // Get the volume dimensions. this->dimensions = getParam3i("dimensions", vec3i(0)); exitOnCondition(reduce_min(this->dimensions) <= 0, "invalid volume dimensions (must be set before calling " "ospSetRegion())"); // Create an ISPC GhostBlockBrickedVolume object and assign type-specific // function pointers. ispcEquivalent = ispc::GBBV_createInstance(this, (int)getVoxelType(), (const ispc::vec3i &)this->dimensions); }
void BlockBrickedVolume::createEquivalentISPC() { //! Get the voxel type. voxelType = getParamString("voxelType", "unspecified"); exitOnCondition(getVoxelType() == OSP_UNKNOWN, "unrecognized voxel type"); //! Create an ISPC BlockBrickedVolume object and assign type-specific function pointers. ispcEquivalent = ispc::BlockBrickedVolume_createInstance((int) getVoxelType()); //! Get the volume dimensions. volumeDimensions = getParam3i("dimensions", vec3i(0)); exitOnCondition(reduce_min(volumeDimensions) <= 0, "invalid volume dimensions"); //! Get the transfer function. transferFunction = (TransferFunction *) getParamObject("transferFunction", NULL); exitOnCondition(transferFunction == NULL, "no transfer function specified"); //! Get the value range. //! Voxel range not used for now. // vec2f voxelRange = getParam2f("voxelRange", vec2f(0.0f)); exitOnCondition(voxelRange == vec2f(0.0f), "no voxel range specified"); //! Get the gamma correction coefficient and exponent. vec2f gammaCorrection = getParam2f("gammaCorrection", vec2f(1.0f)); //! Set the volume dimensions. ispc::BlockBrickedVolume_setVolumeDimensions(ispcEquivalent, (const ispc::vec3i &) volumeDimensions); //! Set the value range (must occur before setting the transfer function). //ispc::BlockBrickedVolume_setValueRange(ispcEquivalent, (const ispc::vec2f &) voxelRange); //! Set the transfer function. ispc::BlockBrickedVolume_setTransferFunction(ispcEquivalent, transferFunction->getEquivalentISPC()); //! Set the recommended sampling rate for ray casting based renderers. ispc::BlockBrickedVolume_setSamplingRate(ispcEquivalent, getParam1f("samplingRate", 1.0f)); //! Set the gamma correction coefficient and exponent. ispc::BlockBrickedVolume_setGammaCorrection(ispcEquivalent, (const ispc::vec2f &) gammaCorrection); //! Allocate memory for the voxel data in the ISPC object. ispc::BlockBrickedVolume_allocateMemory(ispcEquivalent); }
size_t BVH4MB::rotate(Base* nodeID, size_t depth) { /*! nothing to rotate if we reached a leaf node. */ if (nodeID->isLeaf()) return 0; Node* parent = nodeID->node(); /*! rotate all children first */ ssei cdepth; for (size_t c=0; c<4; c++) cdepth[c] = (int)rotate(parent->child[c],depth+1); /* compute current area of all children */ ssef sizeX = parent->upper_x-parent->lower_x; ssef sizeY = parent->upper_y-parent->lower_y; ssef sizeZ = parent->upper_z-parent->lower_z; ssef childArea = sizeX*(sizeY + sizeZ) + sizeY*sizeZ; /*! transpose node bounds */ ssef plower0,plower1,plower2,plower3; transpose(parent->lower_x,parent->lower_y,parent->lower_z,ssef(zero),plower0,plower1,plower2,plower3); ssef pupper0,pupper1,pupper2,pupper3; transpose(parent->upper_x,parent->upper_y,parent->upper_z,ssef(zero),pupper0,pupper1,pupper2,pupper3); BBox<ssef> other0(plower0,pupper0), other1(plower1,pupper1), other2(plower2,pupper2), other3(plower3,pupper3); /*! Find best rotation. We pick a target child of a first child, and swap this with an other child. We perform the best such swap. */ float bestCost = pos_inf; int bestChild = -1, bestTarget = -1, bestOther = -1; for (size_t c=0; c<4; c++) { /*! ignore leaf nodes as we cannot descent into */ if (parent->child[c]->isLeaf()) continue; Node* child = parent->child[c]->node(); /*! transpose child bounds */ ssef clower0,clower1,clower2,clower3; transpose(child->lower_x,child->lower_y,child->lower_z,ssef(zero),clower0,clower1,clower2,clower3); ssef cupper0,cupper1,cupper2,cupper3; transpose(child->upper_x,child->upper_y,child->upper_z,ssef(zero),cupper0,cupper1,cupper2,cupper3); BBox<ssef> target0(clower0,cupper0), target1(clower1,cupper1), target2(clower2,cupper2), target3(clower3,cupper3); /*! put other0 at each target position */ float cost00 = halfArea3f(merge(other0 ,target1,target2,target3)); float cost01 = halfArea3f(merge(target0,other0 ,target2,target3)); float cost02 = halfArea3f(merge(target0,target1,other0 ,target3)); float cost03 = halfArea3f(merge(target0,target1,target2,other0 )); ssef cost0 = ssef(cost00,cost01,cost02,cost03); ssef min0 = vreduce_min(cost0); int pos0 = (int)__bsf(movemask(min0 == cost0)); /*! put other1 at each target position */ float cost10 = halfArea3f(merge(other1 ,target1,target2,target3)); float cost11 = halfArea3f(merge(target0,other1 ,target2,target3)); float cost12 = halfArea3f(merge(target0,target1,other1 ,target3)); float cost13 = halfArea3f(merge(target0,target1,target2,other1 )); ssef cost1 = ssef(cost10,cost11,cost12,cost13); ssef min1 = vreduce_min(cost1); int pos1 = (int)__bsf(movemask(min1 == cost1)); /*! put other2 at each target position */ float cost20 = halfArea3f(merge(other2 ,target1,target2,target3)); float cost21 = halfArea3f(merge(target0,other2 ,target2,target3)); float cost22 = halfArea3f(merge(target0,target1,other2 ,target3)); float cost23 = halfArea3f(merge(target0,target1,target2,other2 )); ssef cost2 = ssef(cost20,cost21,cost22,cost23); ssef min2 = vreduce_min(cost2); int pos2 = (int)__bsf(movemask(min2 == cost2)); /*! put other3 at each target position */ float cost30 = halfArea3f(merge(other3 ,target1,target2,target3)); float cost31 = halfArea3f(merge(target0,other3 ,target2,target3)); float cost32 = halfArea3f(merge(target0,target1,other3 ,target3)); float cost33 = halfArea3f(merge(target0,target1,target2,other3 )); ssef cost3 = ssef(cost30,cost31,cost32,cost33); ssef min3 = vreduce_min(cost3); int pos3 = (int)__bsf(movemask(min3 == cost3)); /*! find best other child */ ssef otherCost = ssef(extract<0>(min0),extract<0>(min1),extract<0>(min2),extract<0>(min3)); int pos[4] = { pos0,pos1,pos2,pos3 }; sseb valid = ssei(int(depth+1))+cdepth <= ssei(maxDepth); // only select swaps that fulfill depth constraints if (none(valid)) continue; size_t n = select_min(valid,otherCost); float cost = otherCost[n]-childArea[c]; //< increasing the original child bound is bad, decreasing good /*! accept a swap when it reduces cost and is not swapping a node with itself */ if (cost < bestCost && n != c) { bestCost = cost; bestChild = (int)c; bestOther = (int)n; bestTarget = pos[n]; } } /*! if we did not find a swap that improves the SAH then do nothing */ if (bestCost >= 0) return 1+reduce_max(cdepth); /*! perform the best found tree rotation */ Node* child = parent->child[bestChild]->node(); swap(parent,bestOther,child,bestTarget); parent->lower_x[bestChild] = reduce_min(child->lower_x); parent->lower_y[bestChild] = reduce_min(child->lower_y); parent->lower_z[bestChild] = reduce_min(child->lower_z); parent->upper_x[bestChild] = reduce_max(child->upper_x); parent->upper_y[bestChild] = reduce_max(child->upper_y); parent->upper_z[bestChild] = reduce_max(child->upper_z); parent->lower_dx[bestChild] = reduce_min(child->lower_dx); parent->lower_dy[bestChild] = reduce_min(child->lower_dy); parent->lower_dz[bestChild] = reduce_min(child->lower_dz); parent->upper_dx[bestChild] = reduce_max(child->upper_dx); parent->upper_dy[bestChild] = reduce_max(child->upper_dy); parent->upper_dz[bestChild] = reduce_max(child->upper_dz); /*! This returned depth is conservative as the child that was * pulled up in the tree could have been on the critical path. */ cdepth[bestOther]++; // bestOther was pushed down one level return 1+reduce_max(cdepth); }