Esempio n. 1
0
//////////////////////////////////////////////////////////
//
// 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);

}
Esempio n. 2
0
/**
 * 多面体データから 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);
      }
Esempio n. 4
0
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 ;
}
Esempio n. 5
0
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);
	}
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
      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);
      }
Esempio n. 8
0
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));
			}

		}

}
Esempio n. 10
0
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;
}
Esempio n. 11
0
	bool intersect_ray(Ray &ray, Intersection *intersection=nullptr) {
		return world.intersect_ray(ray, intersection);
	}
Esempio n. 12
0
	// Finalizes the scene for rendering
	void finalize() {
		world.add_primitives(primitives);
		world.finalize();
	}