示例#1
0
void BVHSpatialSplit::split_curve_reference(const BVHReference& ref,
                                            const Mesh *mesh,
                                            int dim,
                                            float pos,
                                            BoundBox& left_bounds,
                                            BoundBox& right_bounds)
{
	split_curve_primitive(mesh,
	                      NULL,
	                      ref.prim_index(),
	                      PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()),
	                      dim,
	                      pos,
	                      left_bounds,
	                      right_bounds);
}
示例#2
0
	bool operator()(const BVHReference& ra, const BVHReference& rb)
	{
		NO_EXTENDED_PRECISION float ca = ra.bounds().min[dim] + ra.bounds().max[dim];
		NO_EXTENDED_PRECISION float cb = rb.bounds().min[dim] + rb.bounds().max[dim];

		if(ca < cb) return true;
		else if(ca > cb) return false;
		else if(ra.prim_object() < rb.prim_object()) return true;
		else if(ra.prim_object() > rb.prim_object()) return false;
		else if(ra.prim_index() < rb.prim_index()) return true;
		else if(ra.prim_index() > rb.prim_index()) return false;
		else if(ra.prim_segment() < rb.prim_segment()) return true;
		else if(ra.prim_segment() > rb.prim_segment()) return false;

		return false;
	}
示例#3
0
void BVHSpatialSplit::split_triangle_reference(const BVHReference& ref,
                                               const Mesh *mesh,
                                               int dim,
                                               float pos,
                                               BoundBox& left_bounds,
                                               BoundBox& right_bounds)
{
	split_triangle_primitive(mesh,
	                         NULL,
	                         ref.prim_index(),
	                         dim,
	                         pos,
	                         left_bounds,
	                         right_bounds);
}
示例#4
0
void BVHSpatialSplit::split_reference(const BVHBuild& builder,
                                      BVHReference& left,
                                      BVHReference& right,
                                      const BVHReference& ref,
                                      int dim,
                                      float pos)
{
	/* initialize boundboxes */
	BoundBox left_bounds = BoundBox::empty;
	BoundBox right_bounds = BoundBox::empty;

	/* loop over vertices/edges. */
	const Object *ob = builder.objects[ref.prim_object()];
	const Mesh *mesh = ob->mesh;

	if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) {
		split_triangle_reference(ref,
		                         mesh,
		                         dim,
		                         pos,
		                         left_bounds,
		                         right_bounds);
	}
	else if(ref.prim_type() & PRIMITIVE_ALL_CURVE) {
		split_curve_reference(ref,
		                      mesh,
		                      dim,
		                      pos,
		                      left_bounds,
		                      right_bounds);
	}
	else {
		split_object_reference(ob,
		                       dim,
		                       pos,
		                       left_bounds,
		                       right_bounds);
	}

	/* intersect with original bounds. */
	left_bounds.max[dim] = pos;
	right_bounds.min[dim] = pos;
	left_bounds.intersect(ref.bounds());
	right_bounds.intersect(ref.bounds());

	/* set references */
	left = BVHReference(left_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
	right = BVHReference(right_bounds, ref.prim_index(), ref.prim_object(), ref.prim_type());
}
示例#5
0
BVHSpatialSplit::BVHSpatialSplit(const BVHBuild& builder,
                                 BVHSpatialStorage *storage,
                                 const BVHRange& range,
                                 vector<BVHReference> *references,
                                 float nodeSAH)
: sah(FLT_MAX),
  dim(0),
  pos(0.0f),
  storage_(storage),
  references_(references)
{
	/* initialize bins. */
	float3 origin = range.bounds().min;
	float3 binSize = (range.bounds().max - origin) * (1.0f / (float)BVHParams::NUM_SPATIAL_BINS);
	float3 invBinSize = 1.0f / binSize;

	for(int dim = 0; dim < 3; dim++) {
		for(int i = 0; i < BVHParams::NUM_SPATIAL_BINS; i++) {
			BVHSpatialBin& bin = storage_->bins[dim][i];

			bin.bounds = BoundBox::empty;
			bin.enter = 0;
			bin.exit = 0;
		}
	}

	/* chop references into bins. */
	for(unsigned int refIdx = range.start(); refIdx < range.end(); refIdx++) {
		const BVHReference& ref = references_->at(refIdx);
		float3 firstBinf = (ref.bounds().min - origin) * invBinSize;
		float3 lastBinf = (ref.bounds().max - origin) * invBinSize;
		int3 firstBin = make_int3((int)firstBinf.x, (int)firstBinf.y, (int)firstBinf.z);
		int3 lastBin = make_int3((int)lastBinf.x, (int)lastBinf.y, (int)lastBinf.z);

		firstBin = clamp(firstBin, 0, BVHParams::NUM_SPATIAL_BINS - 1);
		lastBin = clamp(lastBin, firstBin, BVHParams::NUM_SPATIAL_BINS - 1);

		for(int dim = 0; dim < 3; dim++) {
			BVHReference currRef = ref;

			for(int i = firstBin[dim]; i < lastBin[dim]; i++) {
				BVHReference leftRef, rightRef;

				split_reference(builder, leftRef, rightRef, currRef, dim, origin[dim] + binSize[dim] * (float)(i + 1));
				storage_->bins[dim][i].bounds.grow(leftRef.bounds());
				currRef = rightRef;
			}

			storage_->bins[dim][lastBin[dim]].bounds.grow(currRef.bounds());
			storage_->bins[dim][firstBin[dim]].enter++;
			storage_->bins[dim][lastBin[dim]].exit++;
		}
	}

	/* select best split plane. */
	for(int dim = 0; dim < 3; dim++) {
		/* sweep right to left and determine bounds. */
		BoundBox right_bounds = BoundBox::empty;

		storage_->right_bounds.resize(BVHParams::NUM_SPATIAL_BINS);
		for(int i = BVHParams::NUM_SPATIAL_BINS - 1; i > 0; i--) {
			right_bounds.grow(storage_->bins[dim][i].bounds);
			storage_->right_bounds[i - 1] = right_bounds;
		}

		/* sweep left to right and select lowest SAH. */
		BoundBox left_bounds = BoundBox::empty;
		int leftNum = 0;
		int rightNum = range.size();

		for(int i = 1; i < BVHParams::NUM_SPATIAL_BINS; i++) {
			left_bounds.grow(storage_->bins[dim][i - 1].bounds);
			leftNum += storage_->bins[dim][i - 1].enter;
			rightNum -= storage_->bins[dim][i - 1].exit;

			float sah = nodeSAH +
				left_bounds.safe_area() * builder.params.primitive_cost(leftNum) +
				storage_->right_bounds[i - 1].safe_area() * builder.params.primitive_cost(rightNum);

			if(sah < this->sah) {
				this->sah = sah;
				this->dim = dim;
				this->pos = origin[dim] + binSize[dim] * (float)i;
			}
		}
	}
}