Esempio n. 1
0
BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, int num)
{
	if(num == 0) {
		BoundBox bounds = BoundBox::empty;
		return new LeafNode(bounds, 0, 0, 0);
	}
	else if(num == 1) {
		if(start == prim_index.size()) {
			assert(params.use_spatial_split);

			prim_segment.push_back(ref->prim_segment());
			prim_index.push_back(ref->prim_index());
			prim_object.push_back(ref->prim_object());
		}
		else {
			prim_segment[start] = ref->prim_segment();
			prim_index[start] = ref->prim_index();
			prim_object[start] = ref->prim_object();
		}

		uint visibility = objects[ref->prim_object()]->visibility;
		return new LeafNode(ref->bounds(), visibility, start, start+1);
	}
	else {
		int mid = num/2;
		BVHNode *leaf0 = create_object_leaf_nodes(ref, start, mid); 
		BVHNode *leaf1 = create_object_leaf_nodes(ref+mid, start+mid, num-mid); 

		BoundBox bounds = BoundBox::empty;
		bounds.grow(leaf0->m_bounds);
		bounds.grow(leaf1->m_bounds);

		return new InnerNode(bounds, leaf0, leaf1);
	}
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pRender - 
//-----------------------------------------------------------------------------
void CGizmo::Render(CRender3D *pRender)
{
	Vector XAxis( m_Position[0] + m_fAxisLength, m_Position[1], m_Position[2] );
	Vector YAxis( m_Position[0], m_Position[1] + m_fAxisLength, m_Position[2] );
	Vector ZAxis( m_Position[0], m_Position[1], m_Position[2] + m_fAxisLength );

	static BoundBox UniformScaleBox;
	Vector Mins;
	Vector Maxs;
	Mins[0] = m_Position[0] - m_fAxisLength * 0.1;
	Mins[1] = m_Position[1] - m_fAxisLength * 0.1;
	Mins[2] = m_Position[2] - m_fAxisLength * 0.1;
	Maxs[0] = m_Position[0] + m_fAxisLength * 0.1;
	Maxs[1] = m_Position[1] + m_fAxisLength * 0.1;
	Maxs[2] = m_Position[2] + m_fAxisLength * 0.1;
	UniformScaleBox.ResetBounds();
	UniformScaleBox.UpdateBounds(Mins, Maxs);

	pRender->BeginRenderHitTarget(this, GIZMO_HANDLE_UNIFORM_SCALE);
	//pRender->RenderBox(Mins, Maxs, BoxType_Solid, 200, 200, 200);
	pRender->EndRenderHitTarget();

	pRender->SetRenderMode( RENDER_MODE_TEXTURED );

	DrawGizmoAxis(pRender, m_Position, XAxis, 255, 0, 0, GIZMO_AXIS_X);
	DrawGizmoAxis(pRender, m_Position, YAxis, 0, 255, 0, GIZMO_AXIS_Y);
	DrawGizmoAxis(pRender, m_Position, ZAxis, 0, 0, 255, GIZMO_AXIS_Z);

	pRender->SetRenderMode( RENDER_MODE_DEFAULT );
}
Esempio n. 3
0
void BVHSpatialSplit::split_triangle_primitive(const Mesh *mesh,
                                               const Transform *tfm,
                                               int prim_index,
                                               int dim,
                                               float pos,
                                               BoundBox& left_bounds,
                                               BoundBox& right_bounds)
{
	const int *inds = mesh->triangles[prim_index].v;
	const float3 *verts = &mesh->verts[0];
	float3 v1 = tfm ? transform_point(tfm, verts[inds[2]]) : verts[inds[2]];

	for(int i = 0; i < 3; i++) {
		float3 v0 = v1;
		int vindex = inds[i];
		v1 = tfm ? transform_point(tfm, verts[vindex]) : verts[vindex];
		float v0p = v0[dim];
		float v1p = v1[dim];

		/* insert vertex to the boxes it belongs to. */
		if(v0p <= pos)
			left_bounds.grow(v0);

		if(v0p >= pos)
			right_bounds.grow(v0);

		/* edge intersects the plane => insert intersection to both boxes. */
		if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
			float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
			left_bounds.grow(t);
			right_bounds.grow(t);
		}
	}
}
Esempio n. 4
0
BoundBox BicubicPatch::bound()
{
  BoundBox bbox = BoundBox::empty;

  for (int i = 0; i < 16; i++)
    bbox.grow(hull[i]);

  return bbox;
}
Esempio n. 5
0
BoundBox LinearTrianglePatch::bound()
{
	BoundBox bbox;

	for(int i = 0; i < 3; i++)
		bbox.grow(hull[i]);
	
	return bbox;
}
Esempio n. 6
0
BoundBox BicubicTangentPatch::bound()
{
	BoundBox bbox;

	for(int i = 0; i < 16; i++)
		bbox.grow(hull[i]);
	
	return bbox;
}
Esempio n. 7
0
BoundBox GregoryTrianglePatch::bound()
{
	BoundBox bbox;

	for(int i = 0; i < 20; i++)
		bbox.grow(hull[i]);
	
	return bbox;
}
Esempio n. 8
0
BoundBox LinearQuadPatch::bound()
{
	BoundBox bbox;

	for(int i = 0; i < 4; i++)
		bbox.grow(hull[i]);
	
	return bbox;
}
Esempio n. 9
0
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
{
	vector<int>& p_segment = prim_segment;
	vector<int>& p_index = prim_index;
	vector<int>& p_object = prim_object;
	BoundBox bounds = BoundBox::empty;
	int num = 0, ob_num = 0;
	uint visibility = 0;

	for(int i = 0; i < range.size(); i++) {
		BVHReference& ref = references[range.start() + i];

		if(ref.prim_index() != -1) {
			if(range.start() + num == prim_index.size()) {
				assert(params.use_spatial_split);

				p_segment.push_back(ref.prim_segment());
				p_index.push_back(ref.prim_index());
				p_object.push_back(ref.prim_object());
			}
			else {
				p_segment[range.start() + num] = ref.prim_segment();
				p_index[range.start() + num] = ref.prim_index();
				p_object[range.start() + num] = ref.prim_object();
			}

			bounds.grow(ref.bounds());
			visibility |= objects[ref.prim_object()]->visibility;
			num++;
		}
		else {
			if(ob_num < i)
				references[range.start() + ob_num] = ref;
			ob_num++;
		}
	}

	BVHNode *leaf = NULL;
	
	if(num > 0) {
		leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);

		if(num == range.size())
			return leaf;
	}

	/* while there may be multiple triangles in a leaf, for object primitives
	 * we want there to be the only one, so we keep splitting */
	const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
	BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
	
	if(leaf)
		return new InnerNode(range.bounds(), leaf, oleaf);
	else
		return oleaf;
}
Esempio n. 10
0
void BVHBuild::add_references(BVHRange& root)
{
	/* reserve space for references */
	size_t num_alloc_references = 0;

	foreach(Object *ob, objects) {
		if(params.top_level) {
			if(!ob->mesh->is_instanced()) {
				num_alloc_references += ob->mesh->triangles.size();
				num_alloc_references += count_curve_segments(ob->mesh);
			}
			else
				num_alloc_references++;
		}
		else {
			num_alloc_references += ob->mesh->triangles.size();
			num_alloc_references += count_curve_segments(ob->mesh);
		}
	}

	references.reserve(num_alloc_references);

	/* add references from objects */
	BoundBox bounds = BoundBox::empty, center = BoundBox::empty;
	int i = 0;

	foreach(Object *ob, objects) {
		if(params.top_level) {
			if(!ob->mesh->is_instanced())
				add_reference_mesh(bounds, center, ob->mesh, i);
			else
				add_reference_object(bounds, center, ob, i);
		}
		else
			add_reference_mesh(bounds, center, ob->mesh, i);

		i++;

		if(progress.get_cancel()) return;
	}

	/* happens mostly on empty meshes */
	if(!bounds.valid())
		bounds.grow(make_float3(0.0f, 0.0f, 0.0f));

	root = BVHRange(bounds, center, 0, references.size());
}
Esempio n. 11
0
BoundBox Camera::viewplane_bounds_get()
{
	/* TODO(sergey): This is all rather stupid, but is there a way to perform
	 * checks we need in a more clear and smart fasion?
	 */
	BoundBox bounds = BoundBox::empty;

	if(type == CAMERA_PANORAMA) {
		bounds.grow(make_float3(cameratoworld.w.x,
		                        cameratoworld.w.y,
		                        cameratoworld.w.z));
	}
	else {
		bounds.grow(transform_raster_to_world(0.0f, 0.0f));
		bounds.grow(transform_raster_to_world(0.0f, (float)height));
		bounds.grow(transform_raster_to_world((float)width, (float)height));
		bounds.grow(transform_raster_to_world((float)width, 0.0f));
		if(type == CAMERA_PERSPECTIVE) {
			/* Center point has the most distance in local Z axis,
			 * use it to construct bounding box/
			 */
			bounds.grow(transform_raster_to_world(0.5f*width, 0.5f*height));
		}
	}
	return bounds;
}
Esempio n. 12
0
void FlightPointList::boundBox(BoundBox &bbox)
{
	uint index;

	for(index=0; index<size(); index++)
	{
    bbox.setMinMax(m_flightPointList[index]->pos());
	}
}
Esempio n. 13
0
SPtr<ModelRecord> BoundBox_Loader::loadModel(WorldEntity *we, const std::string &model_id, varconf::Config &model_config) {
  assert (we);
  SPtr<ModelRecord> model_record = ModelLoader::loadModel(we, model_id, model_config);

  BoundBox *model = new BoundBox();

  WFMath::AxisBox<3> bbox = we->hasBBox() ? (we->getBBox()) : (WFMath::AxisBox<3>(WFMath::Point<3>(0.0f,0.0f,0.0f), WFMath::Point<3>(1.0f,1.0f,1.0f)));
 
  std::string texture = we->type();
  bool wrap = false; //default to false

  // Check whether we specify texture wrapping
  if (model_config.findItem(model_id, KEY_texture)) {
    texture = (std::string)model_config.getItem(model_id, KEY_texture);
  }
  // Get texture name
  if (model_config.findItem(model_id, KEY_wrap_texture)) {
    wrap = (bool)model_config.getItem(model_id, KEY_wrap_texture);
  }

  // Initialise model
  if (model->init(bbox, texture, wrap)) {
    std::cerr<< "BoundBoxLoader: Error initialising model" << std::endl;
    delete model;
    return SPtr<ModelRecord>();
  }

  bool use_stencil = RenderSystem::getInstance().getState(RenderSystem::RENDER_STENCIL) && model_record->outline;

  StaticObjectList &sol = model->getStaticObjects();
  StaticObjectList::iterator I = sol.begin();
  while (I != sol.end()) {
    (*I)->setState(model_record->state);
    (*I)->setSelectState(model_record->select_state);
    (*I)->setUseStencil(use_stencil);

    ++I;
  }

  model_record->model = SPtr<Model>(model);

  return model_record;
}
Esempio n. 14
0
  //Determine the global assembly box
  ErrorCode ParallelMergeMesh::GetGlobalBox(double *gbox)
  {
    ErrorCode rval;

    /*Get Bounding Box*/
    BoundBox box;
    if(mySkinEnts[0].size() != 0){
      rval = box.update(*myMB, mySkinEnts[0]);MB_CHK_ERR(rval);
    }

    //Invert the max
    box.bMax *= -1;

    /*Communicate to all processors*/
    MPI_Allreduce(&box, gbox, 6, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);

    /*Assemble Global Bounding Box*/
    //Flip the max back
    for(int i=3; i<6; i++){
      gbox[i] *= -1;
    }
    return MB_SUCCESS;
  }
Esempio n. 15
0
void BVHSpatialSplit::split_curve_primitive(const Mesh *mesh,
                                            const Transform *tfm,
                                            int prim_index,
                                            int segment_index,
                                            int dim,
                                            float pos,
                                            BoundBox& left_bounds,
                                            BoundBox& right_bounds)
{
	/* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/
	const int k0 = mesh->curves[prim_index].first_key + segment_index;
	const int k1 = k0 + 1;
	const float4& key0 = mesh->curve_keys[k0];
	const float4& key1 = mesh->curve_keys[k1];
	float3 v0 = float4_to_float3(key0);
	float3 v1 = float4_to_float3(key1);

	if(tfm != NULL) {
		v0 = transform_point(tfm, v0);
		v1 = transform_point(tfm, v1);
	}

	float v0p = v0[dim];
	float v1p = v1[dim];

	/* insert vertex to the boxes it belongs to. */
	if(v0p <= pos)
		left_bounds.grow(v0);

	if(v0p >= pos)
		right_bounds.grow(v0);

	if(v1p <= pos)
		left_bounds.grow(v1);

	if(v1p >= pos)
		right_bounds.grow(v1);

	/* edge intersects the plane => insert intersection to both boxes. */
	if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) {
		float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f));
		left_bounds.grow(t);
		right_bounds.grow(t);
	}
}
Esempio n. 16
0
void BVH4::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility)
{
	if(leaf) {
		int4 *data = &pack.leaf_nodes[idx];
		int4 c = data[0];
		/* Refit leaf node. */
		for(int prim = c.x; prim < c.y; prim++) {
			int pidx = pack.prim_index[prim];
			int tob = pack.prim_object[prim];
			Object *ob = objects[tob];

			if(pidx == -1) {
				/* Object instance. */
				bbox.grow(ob->bounds);
			}
			else {
				/* Primitives. */
				const Mesh *mesh = ob->mesh;

				if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
					/* Curves. */
					int str_offset = (params.top_level)? mesh->curve_offset: 0;
					Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
					int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);

					curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);

					visibility |= PATH_RAY_CURVE;

					/* Motion curves. */
					if(mesh->use_motion_blur) {
						Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

						if(attr) {
							size_t mesh_size = mesh->curve_keys.size();
							size_t steps = mesh->motion_steps - 1;
							float3 *key_steps = attr->data_float3();

							for(size_t i = 0; i < steps; i++)
								curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
						}
					}
				}
				else {
					/* Triangles. */
					int tri_offset = (params.top_level)? mesh->tri_offset: 0;
					Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
					const float3 *vpos = &mesh->verts[0];

					triangle.bounds_grow(vpos, bbox);

					/* Motion triangles. */
					if(mesh->use_motion_blur) {
						Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

						if(attr) {
							size_t mesh_size = mesh->verts.size();
							size_t steps = mesh->motion_steps - 1;
							float3 *vert_steps = attr->data_float3();

							for(size_t i = 0; i < steps; i++)
								triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
						}
					}
				}
			}
			visibility |= ob->visibility_for_tracing();
		}
		/* TODO(sergey): This is actually a copy of pack_leaf(),
		 * but this chunk of code only knows actual data and has
		 * no idea about BVHNode.
		 *
		 * Would be nice to de-duplicate code, but trying to make
		 * making code more general ends up in much nastier code
		 * in my opinion so far.
		 *
		 * Same applies to the inner nodes case below.
		 */
		float4 leaf_data[BVH_QNODE_LEAF_SIZE];
		leaf_data[0].x = __int_as_float(c.x);
		leaf_data[0].y = __int_as_float(c.y);
		leaf_data[0].z = __uint_as_float(visibility);
		leaf_data[0].w = __uint_as_float(c.w);
		memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4)*BVH_QNODE_LEAF_SIZE);
	}
	else {
		int4 *data = &pack.nodes[idx];
		bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0;
		int4 c;
		if(is_unaligned) {
			c = data[13];
		}
		else {
			c = data[7];
		}
		/* Refit inner node, set bbox from children. */
		BoundBox child_bbox[4] = {BoundBox::empty,
		                          BoundBox::empty,
		                          BoundBox::empty,
		                          BoundBox::empty};
		uint child_visibility[4] = {0};
		int num_nodes = 0;

		for(int i = 0; i < 4; ++i) {
			if(c[i] != 0) {
				refit_node((c[i] < 0)? -c[i]-1: c[i], (c[i] < 0),
				           child_bbox[i], child_visibility[i]);
				++num_nodes;
				bbox.grow(child_bbox[i]);
				visibility |= child_visibility[i];
			}
		}

		if(is_unaligned) {
			Transform aligned_space[4] = {transform_identity(),
			                              transform_identity(),
			                              transform_identity(),
			                              transform_identity()};
			pack_unaligned_node(idx,
			                    aligned_space,
			                    child_bbox,
			                    &c[0],
			                    visibility,
			                    0.0f,
			                    1.0f,
			                    4);
		}
		else {
			pack_aligned_node(idx,
			                  child_bbox,
			                  &c[0],
			                  visibility,
			                  0.0f,
			                  1.0f,
			                  4);
		}
	}
}
Esempio n. 17
0
 inline bool isBounded( iXY &test )
 {
     return( capture_area.bounds( location, test ) );
 }
Esempio n. 18
0
	BoundBox(const BoundBox<THEIR_PRECISION>& src)
		: minpoint(src.min_point())
		, maxpoint(src.max_point())
	{ }
Esempio n. 19
0
	/**
	 * These add the given point to this bbox - they
	 * offset each corner by this point. Usful for calculating
	 * the location of a box in a higher scope, or for moving
	 * it around as part of a calculation
	 *
	 * Naturally, the {+,-} don't modify and the {+,-}= do.
	 */
	BoundBox operator+ (const point_type& rhs) const {
		BoundBox result = *this;
		result.offset(rhs);
		return result;
	}
Esempio n. 20
0
	BoundBox operator- (const point_type& rhs) const {
		BoundBox result = *this;
		result.offset(point_type(-rhs.x, -rhs.y));
		return result;
	}
Esempio n. 21
0
void BVH::refit_primitives(int start, int end, BoundBox& bbox, uint& visibility)
{
	/* Refit range of primitives. */
	for(int prim = start; prim < end; prim++) {
		int pidx = pack.prim_index[prim];
		int tob = pack.prim_object[prim];
		Object *ob = objects[tob];

		if(pidx == -1) {
			/* Object instance. */
			bbox.grow(ob->bounds);
		}
		else {
			/* Primitives. */
			const Mesh *mesh = ob->mesh;

			if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
				/* Curves. */
				int str_offset = (params.top_level)? mesh->curve_offset: 0;
				Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
				int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);

				curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);

				visibility |= PATH_RAY_CURVE;

				/* Motion curves. */
				if(mesh->use_motion_blur) {
					Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

					if(attr) {
						size_t mesh_size = mesh->curve_keys.size();
						size_t steps = mesh->motion_steps - 1;
						float3 *key_steps = attr->data_float3();

						for(size_t i = 0; i < steps; i++)
							curve.bounds_grow(k, key_steps + i*mesh_size, &mesh->curve_radius[0], bbox);
					}
				}
			}
			else {
				/* Triangles. */
				int tri_offset = (params.top_level)? mesh->tri_offset: 0;
				Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
				const float3 *vpos = &mesh->verts[0];

				triangle.bounds_grow(vpos, bbox);

				/* Motion triangles. */
				if(mesh->use_motion_blur) {
					Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

					if(attr) {
						size_t mesh_size = mesh->verts.size();
						size_t steps = mesh->motion_steps - 1;
						float3 *vert_steps = attr->data_float3();

						for(size_t i = 0; i < steps; i++)
							triangle.bounds_grow(vert_steps + i*mesh_size, bbox);
					}
				}
			}
		}
		visibility |= ob->visibility_for_tracing();
	}
}
Esempio n. 22
0
void BVHSpatialSplit::split(BVHBuild *builder,
                            BVHRange& left,
                            BVHRange& right,
                            const BVHRange& range)
{
	/* Categorize references and compute bounds.
	 *
	 * Left-hand side:			[left_start, left_end[
	 * Uncategorized/split:		[left_end, right_start[
	 * Right-hand side:			[right_start, refs.size()[ */

	vector<BVHReference>& refs = *references_;
	int left_start = range.start();
	int left_end = left_start;
	int right_start = range.end();
	int right_end = range.end();
	BoundBox left_bounds = BoundBox::empty;
	BoundBox right_bounds = BoundBox::empty;

	for(int i = left_end; i < right_start; i++) {
		if(refs[i].bounds().max[this->dim] <= this->pos) {
			/* entirely on the left-hand side */
			left_bounds.grow(refs[i].bounds());
			swap(refs[i], refs[left_end++]);
		}
		else if(refs[i].bounds().min[this->dim] >= this->pos) {
			/* entirely on the right-hand side */
			right_bounds.grow(refs[i].bounds());
			swap(refs[i--], refs[--right_start]);
		}
	}

	/* Duplicate or unsplit references intersecting both sides.
	 *
	 * Duplication happens into a temporary pre-allocated vector in order to
	 * reduce number of memmove() calls happening in vector.insert().
	 */
	vector<BVHReference>& new_refs = storage_->new_references;
	new_refs.clear();
	new_refs.reserve(right_start - left_end);
	while(left_end < right_start) {
		/* split reference. */
		BVHReference lref, rref;
		split_reference(*builder, lref, rref, refs[left_end], this->dim, this->pos);

		/* compute SAH for duplicate/unsplit candidates. */
		BoundBox lub = left_bounds;		// Unsplit to left:		new left-hand bounds.
		BoundBox rub = right_bounds;	// Unsplit to right:	new right-hand bounds.
		BoundBox ldb = left_bounds;		// Duplicate:			new left-hand bounds.
		BoundBox rdb = right_bounds;	// Duplicate:			new right-hand bounds.

		lub.grow(refs[left_end].bounds());
		rub.grow(refs[left_end].bounds());
		ldb.grow(lref.bounds());
		rdb.grow(rref.bounds());

		float lac = builder->params.primitive_cost(left_end - left_start);
		float rac = builder->params.primitive_cost(right_end - right_start);
		float lbc = builder->params.primitive_cost(left_end - left_start + 1);
		float rbc = builder->params.primitive_cost(right_end - right_start + 1);

		float unsplitLeftSAH = lub.safe_area() * lbc + right_bounds.safe_area() * rac;
		float unsplitRightSAH = left_bounds.safe_area() * lac + rub.safe_area() * rbc;
		float duplicateSAH = ldb.safe_area() * lbc + rdb.safe_area() * rbc;
		float minSAH = min(min(unsplitLeftSAH, unsplitRightSAH), duplicateSAH);

		if(minSAH == unsplitLeftSAH) {
			/* unsplit to left */
			left_bounds = lub;
			left_end++;
		}
		else if(minSAH == unsplitRightSAH) {
			/* unsplit to right */
			right_bounds = rub;
			swap(refs[left_end], refs[--right_start]);
		}
		else {
			/* duplicate */
			left_bounds = ldb;
			right_bounds = rdb;
			refs[left_end++] = lref;
			new_refs.push_back(rref);
			right_end++;
		}
	}
	/* Insert duplicated references into actual array in one go. */
	if(new_refs.size() != 0) {
		refs.insert(refs.begin() + (right_end - new_refs.size()),
		            new_refs.begin(),
		            new_refs.end());
	}
	left = BVHRange(left_bounds, left_start, left_end - left_start);
	right = BVHRange(right_bounds, right_start, right_end - right_start);
}
Esempio n. 23
0
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
{
	for(uint j = 0; j < mesh->triangles.size(); j++) {
		Mesh::Triangle t = mesh->triangles[j];
		BoundBox bounds = BoundBox::empty;

		for(int k = 0; k < 3; k++) {
			float3 co = mesh->verts[t.v[k]];
			bounds.grow(co);
		}

		if(bounds.valid()) {
			references.push_back(BVHReference(bounds, j, i, ~0));
			root.grow(bounds);
			center.grow(bounds.center2());
		}
	}

	for(uint j = 0; j < mesh->curves.size(); j++) {
		Mesh::Curve curve = mesh->curves[j];

		for(int k = 0; k < curve.num_keys - 1; k++) {
			BoundBox bounds = BoundBox::empty;

			float3 co[4];
			co[0] = mesh->curve_keys[max(curve.first_key + k - 1,curve.first_key)].co;
			co[1] = mesh->curve_keys[curve.first_key + k].co;
			co[2] = mesh->curve_keys[curve.first_key + k + 1].co;
			co[3] = mesh->curve_keys[min(curve.first_key + k + 2, curve.first_key + curve.num_keys - 1)].co;

			float3 lower;
			float3 upper;
			curvebounds(&lower.x, &upper.x, co, 0);
			curvebounds(&lower.y, &upper.y, co, 1);
			curvebounds(&lower.z, &upper.z, co, 2);
			float mr = max(mesh->curve_keys[curve.first_key + k].radius, mesh->curve_keys[curve.first_key + k + 1].radius);
			bounds.grow(lower, mr);
			bounds.grow(upper, mr);

			if(bounds.valid()) {
				references.push_back(BVHReference(bounds, j, i, k));
				root.grow(bounds);
				center.grow(bounds.center2());
			}
		}
	}
}
Esempio n. 24
0
void Shadows::update(Settings *settings, FRMMATRIX4X4& projIn, FRMMATRIX4X4& ModelviewIn,    float* fv3SunDirIn) {
    
    direction = FRMVECTOR3(fv3SunDirIn[0], fv3SunDirIn[1], fv3SunDirIn[2]);
    
    // update pssm matrices
    float znear = 1.0f;
    float zfar = 250.0f;
    float shadowRange = 200.0f;
    float shadow_distribute = 0.1f;//25f;

    FRMMATRIX4X4 invProj;
    inverse( (float *)&invProj, (float *)&projIn );

    //hack in a fast inverse
    FRMMATRIX4X4 imodelview;
    inverse((float *)& imodelview, (float *)& ModelviewIn);//inverse(mat4(fMat4ModelviewIn));//inverse(camera->getModelview());

    // ortho basis (incorrect solution for vertical direction)
    FRMVECTOR3 side = FrmVector3Normalize (FrmVector3Cross ( FRMVECTOR3(0.0f,0.0f,1.0f), direction));
    FRMVECTOR3 up = FrmVector3Normalize (FrmVector3Cross (direction, side));
    //vec3 side = normalize(cross(direction, vec3(0.0f,0.0f,1.0f)));
    //vec3 up = normalize(cross(direction, side));
    
    // bound frustum points
    FRMVECTOR3 points[8] = {
        FRMVECTOR3(-1.0f,-1.0f,-1.0f), FRMVECTOR3(1.0f,-1.0f,-1.0f), FRMVECTOR3(-1.0f,1.0f,-1.0f), FRMVECTOR3(1.0f,1.0f,-1.0f),
        FRMVECTOR3(-1.0f,-1.0f, 1.0f), FRMVECTOR3(1.0f,-1.0f, 1.0f), FRMVECTOR3(-1.0f,1.0f, 1.0f), FRMVECTOR3(1.0f,1.0f, 1.0f),
    };
    
    // world space bound frustum points
    for(int i = 0; i < 8; i++) {
        FRMVECTOR4 point = FrmVector4Transform( FRMVECTOR4( points[i].x, points[i].y, points[i].z, 1.0f), invProj );// mat4((float *)& invProj ) * vec4(points[i]);
        points[i] = FRMVECTOR3( point.x, point.y, point.z ) / point.w;
    }
    
    // world space bound frustum directions
    FRMVECTOR3 directions[4];
    for(int i = 0; i < 4; i++) {
        directions[i] = FrmVector3Normalize( points[i + 4] - points[i]);
    }
    
    // split bound frustum
    for(int i = 0; i < 4; i++) {
        
        float k0 = (float)(i + 0) / 4;
        float k1 = (float)(i + 1) / 4;
        float fmin = FrmLerp(shadow_distribute, znear * powf(zfar / znear,k0),znear + (zfar - znear) * k0);
        float fmax = FrmLerp(shadow_distribute, znear * powf(zfar / znear,k1),znear + (zfar - znear) * k1);
        
        // none flickering removal
        if( settings->getFlickering() == Settings::FLICKERING_NONE) 
        {
            
            BoundBox bb;
            for(int j = 0; j < 4; j++) {
                bb.expand(points[j] + (directions[j] * fmin));
                bb.expand(points[j] + (directions[j] * fmax));
            }
            BoundSphere bs(bb);
            

            //save out radius squared
            spheres[i] = FRMVECTOR4( FrmVector3TransformCoord( bs.getCenter(), imodelview), bs.getRadius() * bs.getRadius());

            FRMVECTOR3 target = FrmVector3TransformCoord( bs.getCenter(), imodelview );
            
            // This offset is applied to prevent far-plane clipping
            float zFarOffset = 10.0f;
            ortho( (float*)&projections[i], bs.getRadius(),-bs.getRadius(),bs.getRadius(),-bs.getRadius(), 0.1f, shadowRange - zFarOffset);
            modelviews[i] = FrmMatrixLookAtRH(target + (direction * shadowRange / 2.0f),target - (direction * shadowRange / 2.0f),up);
            
        }
        // exact flickering removal
        else
        {
            BoundBox bb;
            for(int j = 0; j < 4; j++) {
                bb.expand(points[j] + (directions[j] * fmin));
                bb.expand(points[j] + (directions[j] * fmax));
            }
            BoundSphere bs(bb);

            //save out radius squared
            spheres[i] = FRMVECTOR4( FrmVector3TransformCoord( bs.getCenter(), imodelview ), bs.getRadius() * bs.getRadius());
            
            float half_size = size / 2.0f;

            FRMVECTOR3 target = FrmVector3TransformCoord( bs.getCenter(), imodelview );

            float x = ceilf( FrmVector3Dot(target,up) * half_size / bs.getRadius()) * bs.getRadius() / half_size;
            float y = ceilf( FrmVector3Dot(target,side) * half_size / bs.getRadius()) * bs.getRadius() / half_size;
            target = up * x + side * y + (direction * FrmVector3Dot(target,direction));

            // This offset is applied to prevent far-plane clipping
            float zFarOffset = 10.0f;
            ortho( (float*)&projections[i],bs.getRadius(),-bs.getRadius(),bs.getRadius(),-bs.getRadius(), 0.1f, shadowRange - zFarOffset);
            modelviews[i] = FrmMatrixLookAtRH(target + (direction * shadowRange / 2.0f), target - (direction * shadowRange / 2.0f),up);
        }

        // Flip the texture coordinates for D3D
        int flipped = 1;

        modelviewprojections[i] = FrmMatrixMultiply( modelviews[i], projections[i]);

        if(settings->getTechnique() == Settings::TECHNIQUE_ATLAS) 
        {
            modelviewprojections[i] = FrmMatrixMultiply( FrmMatrixMultiply( FrmMatrixMultiply( modelviewprojections[i], FrmMatrixScale(0.25f,(flipped) ? -0.25f : 0.25f,0.5f) ),  FrmMatrixTranslate(0.25f,0.25f,0.5f)), FrmMatrixTranslate(0.5f * (i % 2),0.5f * (i / 2),0.0f));
        }
        else 
        {
            modelviewprojections[i] = FrmMatrixMultiply( FrmMatrixMultiply( modelviewprojections[i], FrmMatrixScale(0.5f,(flipped) ? -0.5f : 0.5f,0.5f)), FrmMatrixTranslate(0.5f,0.5f,0.5f));

        }

        FRMMATRIX4X4 invModel;

        inverse((float *)& invModel, (float *)& modelviews[i]);
        offsets[i] = FRMVECTOR3( invModel.M(3, 0), invModel.M(3, 1), invModel.M(3, 2));

    }
}
Esempio n. 25
0
 bool bounds(const iXY& loc) const
 {
     return( bbox.bounds( location, loc ) );
 }
Esempio n. 26
0
void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility)
{
  if (leaf) {
    int4 *data = &pack.leaf_nodes[idx];
    int4 c = data[0];
    /* Refit leaf node. */
    for (int prim = c.x; prim < c.y; prim++) {
      int pidx = pack.prim_index[prim];
      int tob = pack.prim_object[prim];
      Object *ob = objects[tob];

      if (pidx == -1) {
        /* Object instance. */
        bbox.grow(ob->bounds);
      }
      else {
        /* Primitives. */
        const Mesh *mesh = ob->mesh;

        if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) {
          /* Curves. */
          int str_offset = (params.top_level) ? mesh->curve_offset : 0;
          Mesh::Curve curve = mesh->get_curve(pidx - str_offset);
          int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]);

          curve.bounds_grow(k, &mesh->curve_keys[0], &mesh->curve_radius[0], bbox);

          visibility |= PATH_RAY_CURVE;

          /* Motion curves. */
          if (mesh->use_motion_blur) {
            Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

            if (attr) {
              size_t mesh_size = mesh->curve_keys.size();
              size_t steps = mesh->motion_steps - 1;
              float3 *key_steps = attr->data_float3();

              for (size_t i = 0; i < steps; i++) {
                curve.bounds_grow(k, key_steps + i * mesh_size, &mesh->curve_radius[0], bbox);
              }
            }
          }
        }
        else {
          /* Triangles. */
          int tri_offset = (params.top_level) ? mesh->tri_offset : 0;
          Mesh::Triangle triangle = mesh->get_triangle(pidx - tri_offset);
          const float3 *vpos = &mesh->verts[0];

          triangle.bounds_grow(vpos, bbox);

          /* Motion triangles. */
          if (mesh->use_motion_blur) {
            Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

            if (attr) {
              size_t mesh_size = mesh->verts.size();
              size_t steps = mesh->motion_steps - 1;
              float3 *vert_steps = attr->data_float3();

              for (size_t i = 0; i < steps; i++) {
                triangle.bounds_grow(vert_steps + i * mesh_size, bbox);
              }
            }
          }
        }
      }

      visibility |= ob->visibility;
    }

    float4 leaf_data[BVH_ONODE_LEAF_SIZE];
    leaf_data[0].x = __int_as_float(c.x);
    leaf_data[0].y = __int_as_float(c.y);
    leaf_data[0].z = __uint_as_float(visibility);
    leaf_data[0].w = __uint_as_float(c.w);
    memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_ONODE_LEAF_SIZE);
  }
  else {
    float8 *data = (float8 *)&pack.nodes[idx];
    bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0;
    /* Refit inner node, set bbox from children. */
    BoundBox child_bbox[8] = {BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty,
                              BoundBox::empty};
    int child[8];
    uint child_visibility[8] = {0};
    int num_nodes = 0;

    for (int i = 0; i < 8; ++i) {
      child[i] = __float_as_int(data[(is_unaligned) ? 13 : 7][i]);

      if (child[i] != 0) {
        refit_node((child[i] < 0) ? -child[i] - 1 : child[i],
                   (child[i] < 0),
                   child_bbox[i],
                   child_visibility[i]);
        ++num_nodes;
        bbox.grow(child_bbox[i]);
        visibility |= child_visibility[i];
      }
    }

    if (is_unaligned) {
      Transform aligned_space[8] = {transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity(),
                                    transform_identity()};
      pack_unaligned_node(
          idx, aligned_space, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes);
    }
    else {
      pack_aligned_node(idx, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes);
    }
  }
}
Esempio n. 27
0
    ErrorCode BoundBox::update(Interface &iface, const Range& elems)
    {
      ErrorCode rval;
      bMin = CartVect(HUGE_VAL);
      bMax = CartVect(-HUGE_VAL);
      
      CartVect coords;
      EntityHandle const *conn, *conn2;
      int len, len2;
      Range::const_iterator i;
  
        // vertices
      const Range::const_iterator elem_begin = elems.lower_bound( MBEDGE );
      for (i = elems.begin(); i != elem_begin; ++i) {
        rval = iface.get_coords( &*i, 1, coords.array() );
        if (MB_SUCCESS != rval)
          return rval;
        update_min(coords.array());
        update_max(coords.array());
      }

        // elements with vertex-handle connectivity list
      const Range::const_iterator poly_begin = elems.lower_bound( MBPOLYHEDRON, elem_begin );
      std::vector<EntityHandle> dum_vector;
      for (i = elem_begin; i != poly_begin; ++i) {
        rval = iface.get_connectivity( *i, conn, len, true, &dum_vector);
        if (MB_SUCCESS != rval)
          return rval;

        for (int j = 0; j < len; ++j) {
          rval = iface.get_coords( conn+j, 1, coords.array() );
          if (MB_SUCCESS != rval)
            return rval;
          update_min(coords.array());
          update_max(coords.array());
        }
      }
  
        // polyhedra
      const Range::const_iterator set_begin  = elems.lower_bound( MBENTITYSET, poly_begin );
      for (i = poly_begin; i != set_begin; ++i) {
        rval = iface.get_connectivity( *i, conn, len, true );
        if (MB_SUCCESS != rval)
          return rval;

        for (int j = 0; j < len; ++j) {
          rval = iface.get_connectivity( conn[j], conn2, len2 );
          for (int k = 0; k < len2; ++k) {
            rval = iface.get_coords( conn2+k, 1, coords.array() );
            if (MB_SUCCESS != rval)
              return rval;
            update_min(coords.array());
            update_max(coords.array());
          }
        }
      }
  
        // sets
      BoundBox box;
      for (i = set_begin; i != elems.end(); ++i) {
        Range tmp_elems;
        rval = iface.get_entities_by_handle(*i, tmp_elems);
        if (MB_SUCCESS != rval) return rval;
        rval = box.update(iface, tmp_elems);
        if (MB_SUCCESS != rval) return rval;

        update(box);
      }
  
      return MB_SUCCESS;
    }
Esempio n. 28
0
void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, int i)
{
	Attribute *attr_mP = NULL;
	
	if(mesh->has_motion_blur())
		attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

	for(uint j = 0; j < mesh->triangles.size(); j++) {
		Mesh::Triangle t = mesh->triangles[j];
		BoundBox bounds = BoundBox::empty;
		PrimitiveType type = PRIMITIVE_TRIANGLE;

		t.bounds_grow(&mesh->verts[0], bounds);

		/* motion triangles */
		if(attr_mP) {
			size_t mesh_size = mesh->verts.size();
			size_t steps = mesh->motion_steps - 1;
			float3 *vert_steps = attr_mP->data_float3();

			for(size_t i = 0; i < steps; i++)
				t.bounds_grow(vert_steps + i*mesh_size, bounds);

			type = PRIMITIVE_MOTION_TRIANGLE;
		}

		if(bounds.valid()) {
			references.push_back(BVHReference(bounds, j, i, type));
			root.grow(bounds);
			center.grow(bounds.center2());
		}
	}

	Attribute *curve_attr_mP = NULL;

	if(mesh->has_motion_blur())
		curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);

	for(uint j = 0; j < mesh->curves.size(); j++) {
		Mesh::Curve curve = mesh->curves[j];
		PrimitiveType type = PRIMITIVE_CURVE;

		for(int k = 0; k < curve.num_keys - 1; k++) {
			BoundBox bounds = BoundBox::empty;
			curve.bounds_grow(k, &mesh->curve_keys[0], bounds);

			/* motion curve */
			if(curve_attr_mP) {
				size_t mesh_size = mesh->curve_keys.size();
				size_t steps = mesh->motion_steps - 1;
				float4 *key_steps = curve_attr_mP->data_float4();

				for(size_t i = 0; i < steps; i++)
					curve.bounds_grow(k, key_steps + i*mesh_size, bounds);

				type = PRIMITIVE_MOTION_CURVE;
			}

			if(bounds.valid()) {
				int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
				
				references.push_back(BVHReference(bounds, j, i, packed_type));
				root.grow(bounds);
				center.grow(bounds.center2());
			}
		}
	}
}
Esempio n. 29
0
bool Object::loadFile(const std::string &path) {
    using namespace std;
    using namespace std::chrono;

    const time_point loadStartTime = high_resolution_clock::now();

    ifstream ifs(path.c_str(), ifstream::in);
    if (!ifs.is_open()) {
        std::cerr << "File \"" << path << "\" could not be loaded." << std::endl;
        return false;
    }

    BoundBox boundBox;
    string line;
    vector<string> tokens;
    string mtlPath;
    string mtlName;
    while (ifs.good()) {
        tokens.clear();
        getline(ifs, line);
        istringstream iss(line);
        copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter(tokens));
        if (tokens.size() == 0 || tokens[0].size() == 0 || tokens[0][0] == '#')
            continue;

        if (tokens[0] == "v") {
            if (tokens.size() != 4) {
                cerr << path << ": Vertex command does not have correct number of components\n";
                continue;
            }
            const Vector3f vertex(FromString<float>(tokens[1]),
                    FromString<float>(tokens[2]),
                    FromString<float>(tokens[3]));
            boundBox.extend(vertex);
            vertices.push_back(vertex);
        } else if (tokens[0] == "vt") {
            if (tokens.size() != 3) {
                cerr << path << ": Texture coordinate command does not have correct number of components\n";
                continue;
            }
            const Vector2f texcoord(FromString<float>(tokens[1]), FromString<float>(tokens[2]));
            texcoords.push_back(texcoord);
        } else if (tokens[0] == "vn") {
            if (tokens.size() != 4) {
                cerr << path << ": Normal command does not have correct number of components\n";
                continue;
            }
            const Vector3f normal(FromString<float>(tokens[1]),
                    FromString<float>(tokens[2]),
                    FromString<float>(tokens[3]));
            normals.push_back(normal);
        } else if (tokens[0] == "f") {
            Face face = { };
            if (tokens.size() != 4 && tokens.size() != 5) {
                cerr << path << ": Face command does not have correct number of arguments\n";
                continue;
            }
            face.isQuad = tokens.size() == 5;
            face.mat = MaterialLib::load(mtlPath, mtlName);

            const size_t slashesCount = count(tokens[1].begin(), tokens[1].end(), '/');
            switch (slashesCount) {
            case 0: {
                for (size_t i = 0; i < 3U + face.isQuad; i++) {
                    face.vertexIdxs[i] = indexFromStr(tokens[i + 1], vertices.size()) - 1;
                }
                faces.push_back(face);
                break;
            }

            case 1: {
                for (size_t i = 0; i < 3U + face.isQuad; i++) {
                    const std::string &token = tokens[i + 1];
                    const size_t slashPos = token.find('/');
                    face.vertexIdxs[i] = indexFromStr(token.substr(0, slashPos), vertices.size()) - 1;
                    if (token.size() - slashPos > 1)
                        face.texcoordIdxs[i] = indexFromStr(token.substr(slashPos + 1), texcoords.size()) - 1;
                }
                faces.push_back(face);
                break;
            }

            case 2: {
                for (size_t i = 0; i < 3U + face.isQuad; i++) {
                    const std::string &token = tokens[i + 1];
                    const size_t slash0Pos = token.find('/');
                    const size_t slash1Pos = token.find('/', slash0Pos + 1);
                    face.vertexIdxs[i] = indexFromStr(token.substr(0, slash0Pos), vertices.size()) - 1;
                    if (slash1Pos - slash0Pos > 1)
                        face.texcoordIdxs[i] = indexFromStr(token.substr(slash0Pos + 1, slash1Pos - slash0Pos),
                                texcoords.size()) - 1;
                    if (token.size() - slash0Pos > 1)
                        face.normalIdxs[i] = indexFromStr(token.substr(slash1Pos + 1), normals.size()) - 1;
                }
                faces.push_back(face);
                break;
            }

            default:
                cerr << path << ": Invalid face command in \"" << line << "\"\n";
                break;
            }
        } else if (tokens[0] == "usemtl") {
            if (tokens.size() != 2) {
                cerr << path << ": Use material command does not have correct number of arguments\n";
                continue;
            }
            mtlName = tokens[1];
        } else if (tokens[0] == "mtllib") {
            if (tokens.size() != 2) {
                cerr << path << ": Material library command does not have correct number of arguments\n";
                continue;
            }
            mtlPath = tokens[1];
        } else {
            cerr << path << ": Unrecognized token \"" << tokens[0] << "\"\n";
        }
    }
    ifs.close();

    const time_point loadEndTime = high_resolution_clock::now();
    cout
            << "File \""
            << path
            << "\" loaded in "
            << DurationStr(loadStartTime, loadEndTime)
            << " with "
            << faces.size()
            << " face(s), "
            << normals.size()
            << " normal(s), and "
            << texcoords.size()
            << " texture coordinate(s).\n"
            << "\tBounding box: {"
            << boundBox.min().transpose()
            << ", "
            << boundBox.max().transpose()
            << "}\n";

    return true;
}
Esempio n. 30
0
void BVHBuild::add_reference_object(BoundBox& root, BoundBox& center, Object *ob, int i)
{
	references.push_back(BVHReference(ob->bounds, -1, i, 0));
	root.grow(ob->bounds);
	center.grow(ob->bounds.center2());
}