////////////////////////////////////////////////////////// // // RayTracer implementation // ========= RayTracer::RayTracer(Scene& scene, Camera* camera) : Renderer(scene, camera), maxRecursionLevel(6), minWeight(MIN_WEIGHT) //[]---------------------------------------------------[] //| Constructor | //[]---------------------------------------------------[] { // TODO: UNCOMMENT THE CODE BELOW int n = scene.getNumberOfActors(); printf("Building aggregates for %d actors...\n", n); clock_t t = clock(); Array<ModelPtr> models(n); map<uint, ModelPtr> aggregates; string actorNames; int totalNodes = 0; int i = 1; for (ActorIterator ait(scene.getActorIterator()); ait; i++) { const Actor* a = ait++; printf("Processing actor %d/%d...\n", i, n); if (!a->isVisible()) continue; Primitive* p = dynamic_cast<Primitive*>(a->getModel()); const TriangleMesh* mesh = p->triangleMesh(); // checking if the id already exists in idList if (mesh != 0) { ModelPtr& a = aggregates[mesh->id]; BVH* bvh = new BVH(std::move(p->refine())); totalNodes += bvh->size(); a = bvh; models.add(new ModelInstance(*a, *p)); } } printf("Building scene aggregate...\n"); { BVH* bvh = new BVH(std::move(models)); totalNodes += bvh->size(); aggregate = bvh; } printf("BVH(s) built: %d (%d nodes)\n", aggregates.size() + 1, totalNodes); printElapsedTime("", clock() - t); }
/** * 多面体データから distance field VolumeDataへの変換 * @param w Width * @param h Height * @param d Depth * @retval true 変換成功 * @retval false 変換失敗 */ bool SolidDfToVolume::ToVolume(int w, int h, int d) { m_volume = BufferVolumeData::CreateInstance(); int c = 1; // Store scalar density. m_volume->Create(w, h, d, c); // assert(m_solid); // assert(m_solid->Position()); // assert(m_solid->Position()->GetNum() > 0); float* voxels = m_volume->Buffer()->GetBuffer(); const size_t fnum = w * h * d * c; for (size_t i = 0; i < fnum; i++) { voxels[i] = 0.0f; //-FLT_MAX; // @fixme } std::vector<int> countBuf(w * h * d, 0); // for compute avarage. float *position = m_solid->Position()->GetBuffer(); size_t dim[3] = { w, h, d }; float scale[3] = { (m_bmax[0] - m_bmin[0])/w, (m_bmax[1] - m_bmin[1])/h, (m_bmax[2] - m_bmin[2])/d }; const int solid_n = m_solid->Position()->GetNum()/m_solid->GetType(); const int solid_type = m_solid->GetType(); std::vector<Solid> solids; solids.reserve(solid_n); for (int i = 0; i < solid_n; i++) { solids.push_back( Solid(position + solid_type * 3 * i, solid_type)); } BVH bvh; bvh.generateBvhTree(solids); for (float x = m_bmin[0], y, z; x < m_bmax[0]; x += scale[0]) for (y = m_bmin[1]; y < m_bmax[1]; y += scale[1]) for (z = m_bmin[2]; z < m_bmax[2]; z += scale[2]) { VX::Math::vec3 pt(x, y, z); float d = 1e16; bvh.searchNearestSolid(pt, d, 0); voxels[findLoc(x, y, z, m_bmin, m_bmax, dim)] = d; } printf("ToVolume: %zu, %zu, %zu\n", dim[0], dim[1], dim[2]); return true; }
void build() { /* we reset the allocator when the mesh size changed */ if (mesh && mesh->numPrimitivesChanged) { bvh->alloc.clear(); } /* skip build for empty scene */ const size_t numOriginalPrimitives = mesh ? mesh->size() : scene->getNumPrimitives<Mesh,false>(); if (numOriginalPrimitives == 0) { prims0.clear(); bvh->clear(); return; } double t0 = bvh->preBuild(mesh ? "" : TOSTRING(isa) "::BVH" + toString(N) + "BuilderFastSpatialSAH"); /* create primref array */ const size_t numSplitPrimitives = max(numOriginalPrimitives,size_t(splitFactor*numOriginalPrimitives)); prims0.resize(numSplitPrimitives); PrimInfo pinfo = mesh ? createPrimRefArray(mesh,prims0,bvh->scene->progressInterface) : createPrimRefArray(scene,Mesh::geom_type,false,prims0,bvh->scene->progressInterface); Splitter splitter(scene); /* enable os_malloc for two level build */ if (mesh) bvh->alloc.setOSallocation(true); const size_t node_bytes = pinfo.size()*sizeof(typename BVH::AlignedNode)/(4*N); const size_t leaf_bytes = size_t(1.2*Primitive::blocks(pinfo.size())*sizeof(Primitive)); bvh->alloc.init_estimate(node_bytes+leaf_bytes); settings.singleThreadThreshold = bvh->alloc.fixSingleThreadThreshold(N,DEFAULT_SINGLE_THREAD_THRESHOLD,pinfo.size(),node_bytes+leaf_bytes); settings.branchingFactor = N; settings.maxDepth = BVH::maxBuildDepthLeaf; NodeRef root = BVHBuilderBinnedFastSpatialSAH::build<NodeRef>( typename BVH::CreateAlloc(bvh), typename BVH::AlignedNode::Create2(), typename BVH::AlignedNode::Set2(), CreateLeafSpatial<N,Primitive>(bvh), splitter, bvh->scene->progressInterface, prims0.data(), numSplitPrimitives, pinfo,settings); bvh->set(root,LBBox3fa(pinfo.geomBounds),pinfo.size()); bvh->layoutLargeNodes(size_t(pinfo.size()*0.005f)); /* clear temporary data for static geometry */ if (scene && scene->isStaticAccel()) { prims0.clear(); bvh->shrink(); } bvh->cleanup(); bvh->postBuild(t0); }
bool bvhIsBlocked(RayRecord &originalIntersect, BVH bvh, Light * light, glm::vec2 offset) { glm::vec3 lightP0 = originalIntersect.getP0() + originalIntersect.getP1() * originalIntersect.getT() ; glm::vec3 lightP1 ; //glm::vec3 lightDir ; GLfloat boundT = INF ; if (!light->isPointLight()) { //if directional light lightP1 = light->_position ; } else { //if point light lightP1 = light->_position - lightP0 ; boundT = 1.0f ; } //Material mt ; //RayRecord shadowRay(INF, mt, lightP0 + 0.0005f * lightP1, lightP1) ; RayRecord * shadowRay = light->getRayToLight(lightP0, offset) ; //return bvh.intersectionTest(*shadowRay, boundT) ; bool retval = bvh.intersectionTest(*shadowRay, boundT) ; delete shadowRay ; return retval ; }
int HostRender::run(RaytracingContext& context, PixelFunc const& render_pixel, int kill_timeout_seconds, std::function<void()> const& render_overlay) { auto render_pixel_wrapper = [&](int x, int y, RaytracingContext const &ctx, ThreadLocalData *tld) -> glm::vec3 { RenderData data(context, tld); switch(context.params.render_mode) { case RaytracingParameters::RECURSIVE: if (context.params.stereo) { data.camera_mode = Camera::StereoLeft; auto const left = render_pixel(x, y, ctx, data); data.camera_mode = Camera::StereoRight; auto const right = render_pixel(x, y, ctx, data); return combine_stereo(left, right); } else { return render_pixel(x, y, ctx, data); } case RaytracingParameters::DESATURATE: if (context.params.stereo) { data.camera_mode = Camera::StereoLeft; auto const left = render_pixel(x, y, ctx, data); data.camera_mode = Camera::StereoRight; auto const right = render_pixel(x, y, ctx, data); return combine_stereo(desaturate(left), desaturate(right)); } else { return desaturate(render_pixel(x, y, ctx, data)); } case RaytracingParameters::NUM_RAYS: render_pixel(x, y, ctx, data); return heatmap(float(data.num_cast_rays - 1) / 64.0f); case RaytracingParameters::NORMAL: render_pixel(x, y, ctx, data); if (context.params.normal_mapping) return glm::normalize(data.isect.shading_normal) * 0.5f + glm::vec3(0.5f); else return glm::normalize(data.isect.normal) * 0.5f + glm::vec3(0.5f); case RaytracingParameters::BVH_TIME: case RaytracingParameters::TIME: { Timer timer; timer.start(); if(context.params.render_mode == RaytracingParameters::TIME) { auto const color = render_pixel(x, y, ctx, data); (void) color; } else { Ray ray = createPrimaryRay(data, float(x) + 0.5f, float(y) + 0.5f); for(auto& o: context.scene->objects) { BVH *bvh = dynamic_cast<BVH *>(o.get()); if(bvh) { bvh->intersect(ray, nullptr); } } } timer.stop(); return heatmap(static_cast<float>(timer.getElapsedTimeInMilliSec()) * context.params.scale_render_time); } case RaytracingParameters::DUDV: { auto const color = render_pixel(x, y, ctx, data); (void) color; if(!data.isect.isValid()) return glm::vec3(0.0); return heatmap(std::log(1.0f + 5.0f * glm::length(data.isect.dudv))); } case RaytracingParameters::AABB_INTERSECT_COUNT: { Ray ray = createPrimaryRay(data, float(x) + 0.5f, float(y) + 0.5f); glm::vec3 accum(0.0f); for(auto& o: context.scene->objects) { auto *bvh = dynamic_cast<BVH *>(o.get()); if(bvh) { accum += bvh->intersect_count(ray, 0, 0) * 0.02f; } } return accum; } default: /* should never happen */ return glm::vec3(1, 0, 1); } }; if (context.params.interactive) { return run_interactive(context, render_pixel_wrapper, render_overlay); } else { return run_noninteractive(context, render_pixel_wrapper, kill_timeout_seconds); } }
Geometry* Raytracer::Raytrace(Ray &r, Color &col, int depth, float &dist) { if(depth > TRACEDEPTH) return NULL; dist = MAX_DIST; Vector intersection, L, N, V, R, sampleDir, samplePos; Geometry *geom = NULL; //int result = 0; int res; float dot, diff, spec, shade = 0.0f, ldist, rdist, tempdist, ambient; float step = 1.0f / lrflti(shadowQuality); Color diffuse, specular, reflection, accumulator; Ray shadow, ambientRay; bool inShade; //find the nearest intersection vector<Geometry *> &gv = sc->GetObjects(); for(vector<Geometry *>::iterator git = gv.begin(); git != gv.end(); git++) { if((*git)->GetType() == Geometry::BVHACCEL) { BVH *bvh = static_cast<BVH *>(*git); Geometry *ng = NULL; res = bvh->IntersectRecursive(r, dist, &ng); if(res) { geom = ng; } } else { res = (*git)->Intersect(r, dist); if(res) { geom = *git; //result = res; } } } //if there's no hit, terminate the ray if(!geom) return NULL; if(geom->IsLight()) { col = geom->GetMaterial().GetColor() * geom->GetLightIntensity(); } else { //determine the point of intersection intersection = r.origin + (r.direction * dist); //accumulate the lighting vector<Geometry *> &lov = sc->GetObjects(); for(vector<Geometry *>::iterator lit = lov.begin(); lit != lov.end(); lit++) { if(((*lit)->IsLight()) && ((*lit)->GetType() == Geometry::SPHERE)) { L = ((Sphere *)(*lit))->GetPosition() - intersection; ldist = L.Length(); L /= ldist; if(geom->GetType() == Geometry::SDFUNC) { N = geom->GetNormal(intersection); shadow.origin = intersection + N * (10.0f * EPSILON); } else { shadow.origin = intersection + L * EPSILON; } //shadow if(shadowQuality == 1) { Geometry *lcache = (*lit)->GetLightCacheItem(omp_get_thread_num()); shade = 1.0f; shadow.direction = L; //try shadow cache first bool lightCacheHit = false; if(lcache && (lcache->Intersect(shadow, ldist))) { lightCacheHit = true; shade = 0.0f; } //now iterate through the geometry if(!lightCacheHit) { vector<Geometry *> &sov = sc->GetObjects(); for(vector<Geometry *>::iterator sit = sov.begin(); sit != sov.end(); sit++) { if((*sit != *lit) && (*sit != lcache) && ((*sit)->Intersect(shadow, ldist))) { (*lit)->SetLightCacheItem(*sit, omp_get_thread_num()); shade = 0.0f; break; } } } } else { shade = 0.0f; int i; //apparently parallel shadows slows it down //#pragma omp parallel for default(none) shared(light, intersection, ldist, numItems, step) private(i, inShade, tempdist, shadowObj, s) firstprivate(shadow) reduction(+:shade) schedule(dynamic, 1) for(i = 0; i < shadowQuality; i++) { Geometry *lcache = (*lit)->GetLightCacheItem(omp_get_thread_num()); shadow.direction = (*lit)->GeneratePoint() - intersection; shadow.direction.Normalize(); inShade = false; tempdist = ldist; //try shadow cache first bool lightCacheHit = false; if(lcache && (lcache->Intersect(shadow, tempdist))) { lightCacheHit = true; shade = 0.0f; } //now iterate through the geometry if(!lightCacheHit) { vector<Geometry *> &sov = sc->GetObjects(); for(vector<Geometry *>::iterator sit = sov.begin(); sit != sov.end(); sit++) { if((*sit != *lit) && (*sit != lcache) && ((*sit)->Intersect(shadow, tempdist))) { (*lit)->SetLightCacheItem(*sit, omp_get_thread_num()); inShade = true; break; } } } //update the shading if(!inShade) { shade += step; } } } //make sure the point isn't in a shadow if(shade != 0.0f) { N = geom->GetNormal(intersection); //diffuse if(geom->GetMaterial().GetDiffuse() > 0) { dot = N.Dot(L); if(dot > 0) { diff = dot * geom->GetMaterial().GetDiffuse(); diffuse = geom->GetMaterial().GetColor() * (*lit)->GetMaterial().GetColor() * diff; } } //specular if(geom->GetMaterial().GetSpecular() > 0) { V = r.direction; R = L - N * L.Dot(N) * 2.0f; dot = V.Dot(R); if(dot > 0) { spec = powf(dot, 20.0f) * geom->GetMaterial().GetSpecular(); specular = geom->GetMaterial().GetSpecularColor() * (*lit)->GetMaterial().GetColor() * spec; } } col += (diffuse + specular) * shade; //col += geom->GetMaterial().GetColor(); } } } //end light loop //calculate ambient lighting if(occlusion > 0) { //setup needed for both types of AO ambient = 0.0f; //we can use really fake and fast AO for SDFs if(geom->GetType() == Geometry::SDFUNC) { //this type of AO calculation needs far less "rays" occlusion /= 12; if(occlusion == 0) occlusion = 1; //from Rendering Worlds With Two Triangles paper //ao = 1 - k * sum(1, 5, 1/(2^i) * (pink(i) - yellow(i))); // pink(i) = distance from intersection point to sample point along the normal // = delta * i // yellow(i) = distance from sample point to surface // = distfield(intersection + delta * i * n) N = geom->GetNormal(intersection); SDF *sdf = reinterpret_cast<SDF *>(geom); float sum = 0.0f; float k = 0.3f; // magic number for choosing overall strength of AO float scale = 1.0f; float delta = 0.1f; // magic number for sample distances for(int i = 1; i <= occlusion; i++) { scale *= 0.5f; float pink = delta * static_cast<float>(i); Vector sample = intersection + (N * pink); float yellow = sdf->distance(sample); sum += scale * fmax(pink - yellow, 0.0f); //note that pink >= yellow since the intersection point is the furthest possible you could go } ambient = k * (1.0f - sum); } else { //initialize the ambient light float u, v, sqrtv, angle, ambdist; bool intersected; Vector sampleDir; float invsamples = 1.0f / lrflti(occlusion); //shoot out cosine weighted rays for(int i = 0; i < occlusion; i++) { u = lrflti(rand()) * MAX_RAND_DIVIDER * TWOPI; v = lrflti(rand()) * MAX_RAND_DIVIDER; sqrtv = sqrtf(v); sampleDir = Vector(cosf(u) * sqrtv, sinf(u) * sqrtv, sqrtf(1.0f - v)); N = geom->GetNormal(intersection); angle = N.Dot(sampleDir); if(angle < 0) { sampleDir *= -1.0f; angle = -angle; } intersected = false; if(geom->GetType() == Geometry::SDFUNC) { ambientRay.origin = intersection + N * (10.0f * EPSILON); } else { ambientRay.origin = intersection + sampleDir * EPSILON; } ambientRay.direction = sampleDir; ambdist = MAXDEPTH; vector<Geometry *> &aov = sc->GetObjects(); for(vector<Geometry *>::iterator aoit = aov.begin(); aoit != aov.end(); aoit++) { if((!(*aoit)->IsLight()) && ((*aoit)->Intersect(ambientRay, ambdist))) { intersected = true; break; } } if(!intersected) { ambient += invsamples * angle; } } } col += geom->GetMaterial().GetColor() * geom->GetMaterial().GetDiffuse() * ambient; } //get reflection if(geom->GetMaterial().GetReflectivity() > 0) { if(depth < TRACEDEPTH) { /*N = geom->GetNormal(intersection); R = r.direction - N * (2.0f * N.Dot(r.direction)); Raytrace(Ray(intersection + R * EPSILON, R), reflection, depth + 1, rdist); col += reflection * geom->GetMaterial().GetColor() * geom->GetMaterial().GetReflectivity();*/ N = geom->GetNormal(intersection); R = r.direction - N * (2.0f * N.Dot(r.direction)); samplePos = intersection + R * EPSILON; Ray reflectedRay(samplePos, R); Raytrace(reflectedRay, accumulator, depth + 1, rdist); for(int i = 1; i < reflectionBlur; i++) { float x = ((0.2f * lrflti(rand())) / RAND_MAX) - 0.1f; float y = ((0.2f * lrflti(rand())) / RAND_MAX) - 0.1f; float z = ((0.2f * lrflti(rand())) / RAND_MAX) - 0.1f; sampleDir = R + Vector(x, y, z); sampleDir.Normalize(); Ray sampleRay(samplePos, sampleDir); Raytrace(sampleRay, reflection, depth + 1, rdist); accumulator += reflection; } if(reflectionBlur > 1) accumulator /= lrflti(reflectionBlur); col += accumulator * geom->GetMaterial().GetColor() * geom->GetMaterial().GetReflectivity(); } } } return geom; }
void build(size_t, size_t) { /* progress monitor */ auto progress = [&] (size_t dn) { bvh->scene->progressMonitor(dn); }; auto virtualprogress = BuildProgressMonitorFromClosure(progress); /* fast path for empty BVH */ const size_t numPrimitives = scene->getNumPrimitives<BezierCurves,1>(); if (numPrimitives == 0) { prims.clear(); bvh->set(BVH::emptyNode,empty,0); return; } double t0 = bvh->preBuild(TOSTRING(isa) "::BVH" + toString(N) + "BuilderHairSAH"); //profile(1,5,numPrimitives,[&] (ProfileTimer& timer) { /* create primref array */ bvh->alloc.init_estimate(numPrimitives*sizeof(Primitive)); prims.resize(numPrimitives); const PrimInfo pinfo = createBezierRefArray<1>(scene,prims,virtualprogress); /* build hierarchy */ typename BVH::NodeRef root = bvh_obb_builder_binned_sah<N> ( [&] () { return bvh->alloc.threadLocal2(); }, [&] (const PrimInfo* children, const size_t numChildren, HeuristicArrayBinningSAH<BezierPrim> alignedHeuristic, FastAllocator::ThreadLocal2* alloc) -> Node* { Node* node = (Node*) alloc->alloc0.malloc(sizeof(Node),16); node->clear(); for (size_t i=0; i<numChildren; i++) node->set(i,children[i].geomBounds); return node; }, [&] (const PrimInfo* children, const size_t numChildren, UnalignedHeuristicArrayBinningSAH<BezierPrim> unalignedHeuristic, FastAllocator::ThreadLocal2* alloc) -> UnalignedNode* { UnalignedNode* node = (UnalignedNode*) alloc->alloc0.malloc(sizeof(UnalignedNode),16); node->clear(); for (size_t i=0; i<numChildren; i++) { const LinearSpace3fa space = unalignedHeuristic.computeAlignedSpace(children[i]); const PrimInfo sinfo = unalignedHeuristic.computePrimInfo(children[i],space); node->set(i,OBBox3fa(space,sinfo.geomBounds)); } return node; }, [&] (size_t depth, const PrimInfo& pinfo, FastAllocator::ThreadLocal2* alloc) -> NodeRef { size_t items = pinfo.size(); size_t start = pinfo.begin; Primitive* accel = (Primitive*) alloc->alloc1.malloc(items*sizeof(Primitive)); NodeRef node = bvh->encodeLeaf((char*)accel,items); for (size_t i=0; i<items; i++) { accel[i].fill(prims.data(),start,pinfo.end,bvh->scene,false); } return node; }, progress, prims.data(),pinfo,N,BVH::maxBuildDepthLeaf,1,1,BVH::maxLeafBlocks); bvh->set(root,pinfo.geomBounds,pinfo.size()); //}); /* clear temporary data for static geometry */ if (scene->isStatic()) { prims.clear(); bvh->shrink(); } bvh->cleanup(); bvh->postBuild(t0); }
void BVH::build(std::vector<Bbox*>& bboxes) { num_nodes++; int num = bboxes.size(); if (num == 0) { std::cerr << "(BVH::build) bboxes has size 0" << std::endl; return; } // Make leaf node if only one object if (num <= NUM_TRI_IN_LEAF) { num_leaves++; //m_bbox = bboxes[0]; m_bbox = new Bbox(); for (int i = 0; i < num; i++) { m_bbox->addObject(bboxes[i]->object[0]); } for (int i = 0; i < num; i++) { delete bboxes[i]; } return; } // Get split axis based on objects' center BVHHelper splits[NUM_SPLITS]; /* int best_plane; float minVal, maxVal; int axis = getSplitPlane(bboxes, minVal, maxVal); float splitLength = (maxVal - minVal) / ((float)NUM_SPLITS); */ Vector3 best_minVal, best_maxVal; int best_axis = -1; float best_min_cost = MIRO_TMAX; int best_plane = -1; float best_splitLength; for (int axis = 0; axis < 3; axis++) { Vector3 minVal, maxVal; splitPlaneByAxis(bboxes, axis, minVal, maxVal); float splitLength = (maxVal[axis] - minVal[axis]) / ((float)NUM_SPLITS); int tmp_best_plane = -1; // initialize for (int i = 0; i < NUM_SPLITS; i++) { splits[i] = BVHHelper(); } // Put bbox (objects) in the right box split for (int i = 0; i < num; i++) { if (bboxes[i]->object.size() > 1) { std::cerr << "(BVH::build) bboxes[i]->object has size > 1" << std::endl; return; } float boxSplitVal = bboxes[i]->object[0]->center()[axis]; int index = getSplitIndex(boxSplitVal, minVal[axis], splitLength, axis); if (index >= NUM_SPLITS) { //if (tmp == NUM_SPLITS) { // index--; // Include edges to last box split //} //else { std::cerr << "(BVH::build) index > NUM_SPLITS (1)" << std::endl; //} } splits[index].update(bboxes[i]); } float l = (maxVal[axis] - minVal[axis]) / ((float)NUM_SPLITS); float w = maxVal[(axis + 1) % 3] - minVal[(axis + 1) % 3]; float h = maxVal[(axis + 2) % 3] - minVal[(axis + 2) % 3]; //// Calculate cost for each box split //for (int i = 0; i < NUM_SPLITS; i++) { // // (Not sure if sa is left to 0.0f) // if (splits[i].num_objs == 0) continue; // /* // // Not sure on cost equation // // 2LW + 2(L+W)H // float l = splits[i].max.x - splits[i].min.x; // float w = splits[i].max.y - splits[i].min.y; // float h = splits[i].max.z - splits[i].min.z; // float sa = 2.0f * l * w + (2 * (l + w) * h); // */ // splits[i].sa = sa; //} // Get the plane with minimum cost float min_cost = MIRO_TMAX; for (int i = 1; i < NUM_SPLITS; i++) { float l_sa = 0.0f, r_sa = 0.0f; int l_num = 0, r_num = 0; float left_side = 0.0f, right_side = 0.0f; // left side for (int j = 0; j < i; j++) { //l_sa += splits[j].sa; l_num += splits[j].num_objs; } // right side for (int j = i; j < NUM_SPLITS; j++) { //r_sa += splits[j].sa; r_num += splits[j].num_objs; } //left_side = l_sa * l_num; //right_side = r_sa * r_num; l_sa = l * i; r_sa = l * (NUM_SPLITS - i); left_side = 2.0f * l_sa * w + (2 * (l_sa + w) * h); right_side = 2.0f * r_sa * w + (2 * (r_sa + w) * h); float cost = left_side * l_num + right_side * r_num; if (cost < min_cost) { min_cost = cost; tmp_best_plane = i; } } if (min_cost < best_min_cost) { best_min_cost = min_cost; best_plane = tmp_best_plane; best_axis = axis; best_minVal = minVal; best_maxVal = maxVal; best_splitLength = splitLength; } } // Put bbox (objects) in the left or right split std::vector<Bbox*> leftBoxes; //= new Bbox[best_l_num]; std::vector<Bbox*> rightBoxes; //= new Bbox[best_r_num]; Bbox * lBox = new Bbox(); Bbox * rBox = new Bbox(); int l_index = 0, r_index = 0; for (int i = 0; i < num; i++) { float boxSplitVal = bboxes[i]->object[0]->center()[best_axis]; int index = getSplitIndex(boxSplitVal, best_minVal[best_axis], best_splitLength, best_axis); float boundary = m_bbox->min[best_axis] + (best_plane * best_splitLength); //float boxSplitVal = bboxes[i]->object[0]->center()[axis]; //int index = getSplitIndex(boxSplitVal, minVal, splitLength, axis); //float boundary = m_bbox->min[axis] + (best_plane * splitLength); if (index < best_plane) { //leftBoxes[l_index++] = *bboxes[i]; leftBoxes.push_back(bboxes[i]); lBox->addObject(bboxes[i]->object[0]); } else { //rightBoxes[r_index++] = *bboxes[i]; rightBoxes.push_back(bboxes[i]); rBox->addObject(bboxes[i]->object[0]); } } // delete ptrs //delete splits; BVH *leftChild = new BVH(); BVH *rightChild = new BVH(); leftChild->m_bbox = lBox; rightChild->m_bbox = rBox; leftChild->build(leftBoxes); rightChild->build(rightBoxes); m_children.push_back(leftChild); m_children.push_back(rightChild); }
void mediObjVolumeCreationStrategy::process(std::vector<mediParticle> & particles ) { BVH<BVHBoundingSphere> bvh = BVH<BVHBoundingSphere>(); for(unsigned int i=0; i<obj.f.size(); i++) { bvh.insert( BVHTriangle(0, obj.v[obj.f[i].v[0]-1], obj.v[obj.f[i].v[1]-1], obj.v[obj.f[i].v[2]-1])); } bvh.buildHierarchy(); std::cout << "BVH hierarchy build" << std::endl; Vector3 minV, maxV; obj.boundingBox(minV,maxV); /*for(int x=0; x<resolutions[0]; x++) for( int y=0; y<resolutions[1]; y++) for( int z=0; z<resolutions[2]; z++) { Vector3 v( (1-(float(x)/resolutions[0]))*minV[0]+(float(x)/resolutions[0])*maxV[0], (1-(float(y)/resolutions[1]))*minV[1]+(float(y)/resolutions[1])*maxV[1], (1-(float(z)/resolutions[2]))*minV[2]+(float(z)/resolutions[2])*maxV[2]); particles.push_back(mediParticle(v)); }*/ for(int x=0; x<resolutions[0]; x++) for( int y=0; y<resolutions[1]; y++) { Vector3 orig( (1-(float(x)/resolutions[0]))*minV[0]+(float(x)/resolutions[0])*maxV[0], (1-(float(y)/resolutions[1]))*minV[1]+(float(y)/resolutions[1])*maxV[1], minV[2]); Vector3 dir = Vector3(0,0,1); float EPS=0.01; BVHTriangleHit hit1 = bvh.rayIntersection(BVHRay(orig,dir)); while(hit1.distance!=std::numeric_limits<float>::infinity()) { particles.push_back(mediParticle(orig+ (dir*hit1.distance))); BVHTriangleHit hit2 = bvh.rayIntersection(BVHRay(orig+dir*(hit1.distance+EPS),dir)); if (hit2.distance!=std::numeric_limits<float>::infinity()) { particles.push_back(mediParticle(orig+ dir*(hit1.distance+EPS) + dir*(hit2.distance))); float d =0; while( d<hit2.distance) { d=d + (maxV[2]-minV[2])/resolutions[2]; particles.push_back(mediParticle(orig + dir*(hit1.distance+EPS+d) )); } } else { std::cerr << "Geometry not closed" << std::endl; //exit(0); } orig = orig + dir*(hit1.distance+EPS) + dir*(hit2.distance+EPS); // new orig at end of solid part hit1 = bvh.rayIntersection(BVHRay(orig,dir)); } } }
void generate_geometries(vector<Geometry*>& geometries) { num_triangles = 0; num_object = geometries.size(); for (int i = 0; i < num_object; ++i) num_triangles += geometries[i]->vertex.size() / 3; float* vertex_buffer = new float[num_triangles * 9]; float* normal_buffer = new float[num_triangles * 9]; float* tex_buffer = new float[num_triangles * 6]; float* index_buffer = new float[num_triangles]; float* material = new float[21 * num_object]; float* v_ptr = vertex_buffer, *n_ptr = normal_buffer, *m_ptr = material, *t_ptr = tex_buffer; int s = 0; for (int i = 0; i < num_object; ++i) { if (use_bvh) { geometries[i]->applyTransform(); memcpy(v_ptr, geometries[i]->t_vertex.data(), geometries[i]->t_vertex.size() * 3 * sizeof(float)); v_ptr += geometries[i]->vertex.size() * 3; memcpy(n_ptr, geometries[i]->t_normal.data(), geometries[i]->t_normal.size() * 3 * sizeof(float)); n_ptr += geometries[i]->t_normal.size() * 3; } else { memcpy(v_ptr, geometries[i]->vertex.data(), geometries[i]->vertex.size() * 3 * sizeof(float)); v_ptr += geometries[i]->vertex.size() * 3; memcpy(n_ptr, geometries[i]->normal.data(), geometries[i]->normal.size() * 3 * sizeof(float)); n_ptr += geometries[i]->normal.size() * 3; } memcpy(t_ptr, geometries[i]->uv.data(), geometries[i]->uv.size() * 2 * sizeof(float)); t_ptr += geometries[i]->uv.size() * 2; *m_ptr++ = geometries[i]->kd; *m_ptr++ = geometries[i]->ks; *m_ptr++ = geometries[i]->tex; *m_ptr++ = geometries[i]->offset.x; *m_ptr++ = geometries[i]->offset.y; *m_ptr++ = geometries[i]->offset.z; *m_ptr++ = geometries[i]->x_axis.x; *m_ptr++ = geometries[i]->x_axis.y; *m_ptr++ = geometries[i]->x_axis.z; *m_ptr++ = geometries[i]->y_axis.x; *m_ptr++ = geometries[i]->y_axis.y; *m_ptr++ = geometries[i]->y_axis.z; *m_ptr++ = geometries[i]->s.x; *m_ptr++ = geometries[i]->s.y; *m_ptr++ = geometries[i]->s.z; for (int j = s / 3; j < s / 3 + geometries[i]->vertex.size() / 3; ++j) index_buffer[j] = i; s += geometries[i]->vertex.size(); *m_ptr++ = s; *m_ptr++ = geometries[i]->ka; *m_ptr++ = geometries[i]->kr; *m_ptr++ = geometries[i]->kf; *m_ptr++ = geometries[i]->nr; *m_ptr++ = geometries[i]->alpha; } BVH* bvh = new BVH(vertex_buffer, normal_buffer, tex_buffer, index_buffer, num_triangles); vector<float> bvh_buffer; bvh->genBuffer(bvh_buffer); mesh_texture = create_texture_2D(vertex_buffer, 9, num_triangles, mesh_texture); normal_texture = create_texture_2D(normal_buffer, 9, num_triangles, normal_texture); material_texture = create_texture_2D(material, 21, num_object, material_texture); tex_texture = create_texture_2D(tex_buffer, 6, num_triangles, tex_texture); index_texture = create_texture(index_buffer, num_triangles, index_texture); bvh_texture = create_texture_2D(bvh_buffer.data(), 11, bvh_buffer.size() / 11, bvh_texture); sampler_texture = create_texture(samples, 2 * SAMPLE_SIZE * SAMPLE_SIZE + 2, sampler_texture); num_bvh = bvh_buffer.size() / 11; delete[] vertex_buffer; delete[] normal_buffer; delete[] tex_buffer; delete[] material; }
bool intersect_ray(Ray &ray, Intersection *intersection=nullptr) { return world.intersect_ray(ray, intersection); }
// Finalizes the scene for rendering void finalize() { world.add_primitives(primitives); world.finalize(); }