コード例 #1
0
ファイル: Intersections.cpp プロジェクト: pxf/pxf-tech2
bool ray_aabb(ray_t* ray,aabb* box,intersection_response_t* resp)
{
	float t_min = -100000.0f;	// MIN VAL
	float t_max = 100000.0f;	// MAX VAL
	float t1,t2;

	Vec3f Ac = box->pos + box->size*0.5;
	Vec3f p = Ac - ray->o;
	Vec3f d = ray->d;
	float f,e;

	Vec3f min = (box->pos - ray->o) / d;
	Vec3f max = (box->pos + box->size - ray->o) / d;

	for(size_t i=0;i<3;i++)
	{
		e = p.GetAxis(i);
		f = d.GetAxis(i);

		if(fabs(f) > 1.0E-9f)
		{
			float t1 = min.GetAxis(i);
			float t2 = max.GetAxis(i);

			if(t1 > t2) 
				std::swap(t1,t2);
			if(t1 > t_min)
				t_min = t1;
			if(t2 < t_max) 
				t_max = t2;
			if(t_min > t_max) 
				return false;
			if(t_max < 0)
				return false;
		}
		else if( (-e -p.GetAxis(i) > 0) || (-e+p.GetAxis(i) < 0))
		{
			return false;
		}
	}

	aabb_intersection_response_t* r = (aabb_intersection_response_t*) resp;
	r->t_min = t_min;
	r->t_max = t_max;

	return true;
}
コード例 #2
0
ファイル: BVH.cpp プロジェクト: pxf/pxf-tech2
triangle_t* ray_tree_find_occluder(tree_t* tree, ray_t* ray, intersection_response_t &resp, float dist)
{
	Vec3f o = ray->o;
	Vec3f d = ray->d;
	Vec3f inv_d = Inverse(d);

	ca_node_t* nodes = tree->nodes;
	ca_node_t* node = nodes;

	triangle_t* ret_p = 0;
	triangle_t* triangle_data = tree->triangle_data;
	int* index_list = tree->index_list;

	float t_min=0.0f,t_max=dist;

	// init stack
	stack_entry_t* stack = tree->stack;
	int entry_ptr=0,exit_ptr=1;
	
	Vec3f entry_v = o + d*t_min;
	Vec3f exit_v = o + d*t_max;

	stack[entry_ptr].node = node;
	stack[entry_ptr].p = entry_v;

	stack[exit_ptr].node = 0;
	stack[exit_ptr].p = exit_v;

	ca_node_t* near_node;
	ca_node_t* far_node;

	int i;

	// build stack
	while(node)
	{
		while(!node->is_leaf())
		{
			unsigned axis = node->axis;
			float split_pos = node->split_pos;
			
			// determine near and far nodes 
			if(stack[entry_ptr].p.GetAxis(axis) <= split_pos)
			{
				// enter point is on left side of split_position
				if(stack[exit_ptr].p.GetAxis(axis) <= split_pos)
				{
					// ray hit left child
					node = &nodes[node->data.inner_node.left_node];
					continue;
				}

				// parallel
				//if(stack[exit_ptr].p.GetAxis(axis) >= split_pos && stack[exit_ptr].p.GetAxis(axis) <= (split_pos + KD_EPSILON))
				if(stack[exit_ptr].p.GetAxis(axis) == split_pos)
				{
					// continue with right child
					node = &nodes[node->data.inner_node.right_node];
					continue;
				}

				// ray hits both children
				far_node = &nodes[node->data.inner_node.right_node];
				node = &nodes[node->data.inner_node.left_node];
			}
			// ray origin is on right child
			else 
			{
				// ray hits right only
				if(stack[exit_ptr].p.GetAxis(axis) > split_pos)
				{
					node = &nodes[node->data.inner_node.right_node];
					continue;
				}

				// ray hits both, in opposite directions
				far_node = &nodes[node->data.inner_node.left_node];
				node = &nodes[node->data.inner_node.right_node];
			}
			
			// get distance to split position
			float t_split = (split_pos - o.GetAxis(axis)) * inv_d.GetAxis(axis); //4 d.GetAxis(axis);

			// set stack pointers
			int ptr = exit_ptr++;
			if(exit_ptr == entry_ptr)
				exit_ptr++;

			stack[exit_ptr].node = far_node;
			stack[exit_ptr].p = o + d * t_split;
			stack[exit_ptr].prev = ptr;
		}

		int start_index = node->data.leaf_node.list_index;
		int count = node->data.leaf_node.tri_count;

		float closest_depth = dist;
		ray_t r = *ray;
		bool retval = false;

		intersection_response_t _resp;

		for(int i=0; i < count; i++) {
			unsigned index = index_list[start_index + i];
			triangle_t t = triangle_data[index];

			if(ray_triangle(t.vertices,&r,&_resp)) {
				retval = true;

				if(_resp.depth < closest_depth) {
					ret_p = &triangle_data[index];
					closest_depth = _resp.depth;
					resp = _resp;
				}
			}
		}

		if(retval) {
			return ret_p;
		}

		entry_ptr = exit_ptr;
		node = stack[exit_ptr].node;
		exit_ptr = stack[entry_ptr].prev;
	}

	return 0;
}
コード例 #3
0
ファイル: BVH.cpp プロジェクト: pxf/pxf-tech2
triangle_t* ray_tree_intersection(tree_t* tree, ray_t* ray, intersection_response_t &resp)
{
	Vec3f minpos = tree->min;
	Vec3f maxpos = tree->max;

	aabb box;
	box.pos = minpos;
	box.size = maxpos - minpos;

	if(!ray_aabb(ray,&box,&resp))
		return 0;

	Vec3f o = ray->o;
	Vec3f d = ray->d;
	Vec3f inv_d = Inverse(d);

	ca_node_t* nodes = tree->nodes;
	ca_node_t* node = nodes;

	triangle_t* ret_p = 0;
	triangle_t* triangle_data = tree->triangle_data;
	int* index_list = tree->index_list;

	// get box extents
	float t_min=-FLT_MAX,t_max=FLT_MAX;

	Vec3f _min = (minpos - o) * inv_d;
	Vec3f _max = (maxpos - o) * inv_d;

	for(size_t i=0; i<3; i++)
	{
		float t1 = _min.GetAxis(i);
		float t2 = _max.GetAxis(i);

		if(t1 > t2) 
			std::swap(t1,t2);
		if(t1 > t_min)
			t_min = t1;
		if(t2 < t_max) 
			t_max = t2;
	}

	Vec3f enter = o + d*t_min;
	Vec3f exit = o + d*t_max;

	/*

	stack<stack_node_t,vector<stack_node_t>> candidates;
	int far_node;
	while(node) {

		while(!node->is_leaf()) {
			unsigned char axis = node->axis;
			float split_pos = node->split_pos;

			if(enter.GetAxis(axis) <= split_pos) {
				// left voxel
				if(exit.GetAxis(axis) <= split_pos) {
					// ray hits only left cell
					node = &nodes[node->data.inner_node.left_node];
					continue;
				}

				//if(interval(exit.GetAxis(axis),split_pos)) {
				if(exit.GetAxis(axis) >= split_pos + KD_EPSILON) {
					// ray parallel to split plane, traverse right cell?
					node = &nodes[node->data.inner_node.right_node];
					continue;
				}

				// ray hits both cells
				node = &nodes[node->data.inner_node.left_node];
				far_node = node->data.inner_node.right_node;

			} else {
				// right voxel
				if(exit.GetAxis(axis) > split_pos) {
					// ray hits right cell only
					node = &nodes[node->data.inner_node.right_node];
					continue;
				}

				// ray hits both cells
				node = &nodes[node->data.inner_node.right_node];
				far_node = node->data.inner_node.left_node;
			}
			// distance to split position:
			float t = (split_pos - o.GetAxis(axis)) / d.GetAxis(axis);

			stack_node_t n;
			n.node = far_node;
			n.p = o + d*t;

			candidates.push(n);
		}

		int start_index = node->data.leaf_node.list_index;
		int count = node->data.leaf_node.tri_count;

		float closest_depth = 10000.0f;
		ray_t r = *ray;
		bool retval = false;

		intersection_response_t _resp;

		for(int i=0; i < count; i++) {
			unsigned index = index_list[start_index + i];
			triangle_t t = triangle_data[index];

			if(ray_triangle(t.vertices,&r,&_resp)) {
				retval = true;

				if(resp.depth < closest_depth) {
					ret_p = &triangle_data[index];
					closest_depth = resp.depth;
				}
			}

			if(retval) return ret_p;
		}
		
		if(candidates.empty()) return 0;

		stack_node_t n = candidates.top();
		candidates.pop();

		enter = exit;
		exit = n.p;
		node = &nodes[n.node];
	}


	return 0;
	*/

	// init stack
	stack_entry_t* stack = tree->stack;
	int entry_ptr=0,exit_ptr=1;
	
	Vec3f entry_v = o + d*t_min;
	Vec3f exit_v = o + d*t_max;

	if (t_min > 0.0f) stack[entry_ptr].p = o + d * t_min;
	else stack[entry_ptr].p = o;

	stack[entry_ptr].node = node;
	//stack[entry_ptr].p = entry_v;

	stack[exit_ptr].node = 0;
	stack[exit_ptr].p = exit_v;

	ca_node_t* near_node;
	ca_node_t* far_node;

	int i;

	// build stack
	while(node)
	{
		while(!node->is_leaf())
		{
			unsigned axis = node->axis;
			float split_pos = node->split_pos;
			
			// determine near and far nodes 
			if(stack[entry_ptr].p.GetAxis(axis) <= split_pos)
			{
				// enter point is on left side of split_position
				if(stack[exit_ptr].p.GetAxis(axis) <= split_pos)
				{
					// ray hit left child
					node = &nodes[node->data.inner_node.left_node];
					continue;
				}

				// parallel
				//if(stack[exit_ptr].p.GetAxis(axis) >= split_pos && stack[exit_ptr].p.GetAxis(axis) <= (split_pos + KD_EPSILON))
				if(stack[exit_ptr].p.GetAxis(axis) == split_pos)
				{
					// continue with right child
					node = &nodes[node->data.inner_node.right_node];
					continue;
				}

				// ray hits both children
				far_node = &nodes[node->data.inner_node.right_node];
				node = &nodes[node->data.inner_node.left_node];
			}
			// ray origin is on right child
			else 
			{
				// ray hits right only
				if(stack[exit_ptr].p.GetAxis(axis) > split_pos)
				{
					node = &nodes[node->data.inner_node.right_node];
					continue;
				}

				// ray hits both, in opposite directions
				far_node = &nodes[node->data.inner_node.left_node];
				node = &nodes[node->data.inner_node.right_node];
			}
			
			// get distance to split position
			float t_split = (split_pos - o.GetAxis(axis)) * inv_d.GetAxis(axis); //4 d.GetAxis(axis);

			// set stack pointers
			int ptr = exit_ptr++;
			if(exit_ptr == entry_ptr)
				exit_ptr++;

			stack[exit_ptr].node = far_node;
			stack[exit_ptr].p = o + d * t_split;
			stack[exit_ptr].prev = ptr;
		}

		int start_index = node->data.leaf_node.list_index;
		int count = node->data.leaf_node.tri_count;

		float closest_depth = FLT_MAX;
		ray_t r = *ray;
		bool retval = false;

		intersection_response_t _resp;

		for(int i=0; i < count; i++) {
			unsigned index = index_list[start_index + i];
			triangle_t t = triangle_data[index];

			if(ray_triangle(t.vertices,&r,&_resp)) {
				retval = true;

				if(_resp.depth < closest_depth) {
					ret_p = &triangle_data[index];
					closest_depth = _resp.depth;
					resp = _resp;
				}
			}
		}

		if(retval) {
			return ret_p;
		}

		entry_ptr = exit_ptr;
		node = stack[exit_ptr].node;
		exit_ptr = stack[entry_ptr].prev;
	}

	return 0;
}