Example #1
0
// return all occluders in all cells that intersect the triangle (p1,p2,p3)
// these occluders do not necessarily intersect (p1,p2,p3), but all possible intersections are included in this set
void Grid::triangleIntersections(Vec3r p0,Vec3r p1,Vec3r p2, set<Polygon3r*> & possibleIntersections)
{
  Vec3r triverts[3] = {p0,p1,p2};

  // find the bbox of the triangle
  vector<Vec3r> vertices;
  vertices.push_back(triverts[0]);  
  vertices.push_back(triverts[1]);  
  vertices.push_back(triverts[2]);
  Vec3r dummy;

  Polygon3r triangle(vertices,dummy);

  Vec3r min, max;
  triangle.getBBox(min, max);

  // Compute the cell coordinates for the bbox
  Vec3u imax, imin;
  getCellCoordinates(max, imax);
  getCellCoordinates(min, imin);
  
  // We are now going to iterate over the cells overlapping with the
  // polygon bbox.

  for (unsigned z = imin[2]; z <= imax[2]; z++)
    for (unsigned y = imin[1]; y <= imax[1]; y++)
      for (unsigned x = imin[0]; x <= imax[0]; x++) 
	{
	  Vec3u coord;
	  Vec3r boxmin, boxmax;
	  
	  coord[0] = x;
	  coord[1] = y;
	  coord[2] = z;

	  // We retrieve the box coordinates of the current cell
	  getCellBox(coord, boxmin, boxmax);

	  // We check whether the triangle and the box ovewrlap:
	  Vec3r boxcenter((boxmin + boxmax) / 2.0);
	  Vec3r boxhalfsize(_cell_size / 2.0);

	  Cell * cell = getCell(coord);

	  if (cell != NULL && GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts))
	    for(OccludersSet::iterator it = cell->getOccluders().begin(); it != cell->getOccluders().end(); ++it)
	      possibleIntersections.insert(*it);
	}
}
Example #2
0
/* by Tomas Akenine-Möller                              */
bool BoundingBox::containsTriangle( const Vec& tv0, const Vec& tv1, const Vec& tv2 ) const
{
	Vec boxcenter(center);
	Vec boxhalfsize(xExtent, yExtent, zExtent);

	int X = 0, Y = 1, Z = 2;

	/*    use separating axis theorem to test overlap between triangle and box */
	/*    need to test for overlap in these directions: */
	/*    1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
	/*       we do not even need to test these) */
	/*    2) normal of the triangle */
	/*    3) crossproduct(edge from tri, {x,y,z}-directin) */
	/*       this gives 3x3=9 more tests */
	Vec v0,v1,v2;
	double min,max,p0,p1,p2,rad,fex,fey,fez;
	Vec normal,e0,e1,e2;

	/* This is the fastest branch on Sun */
	/* move everything so that the box center is in (0,0,0) */
	v0=tv0-boxcenter;
	v1=tv1-boxcenter;
	v2=tv2-boxcenter;
	
	/* compute triangle edges */
	e0=v1-v0;      /* tri edge 0 */
	e1=v2-v1;      /* tri edge 1 */
	e2=v0-v2;      /* tri edge 2 */
	
	/* Bullet 3:  */
	/*  test the 9 tests first (this was faster) */
	fex = fabsf(e0[X]);
	fey = fabsf(e0[Y]);
	fez = fabsf(e0[Z]);
	AXISTEST_X01(e0[Z], e0[Y], fez, fey);
	AXISTEST_Y02(e0[Z], e0[X], fez, fex);
	AXISTEST_Z12(e0[Y], e0[X], fey, fex);
	fex = fabsf(e1[X]);
	fey = fabsf(e1[Y]);
	fez = fabsf(e1[Z]);
	AXISTEST_X01(e1[Z], e1[Y], fez, fey);
	AXISTEST_Y02(e1[Z], e1[X], fez, fex);
	AXISTEST_Z0(e1[Y], e1[X], fey, fex);
	fex = fabsf(e2[X]);
	fey = fabsf(e2[Y]);
	fez = fabsf(e2[Z]);
	AXISTEST_X2(e2[Z], e2[Y], fez, fey);
	AXISTEST_Y1(e2[Z], e2[X], fez, fex);
	AXISTEST_Z12(e2[Y], e2[X], fey, fex);
	
	/* Bullet 1: */
	/*  first test overlap in the {x,y,z}-directions */
	/*  find min, max of the triangle each direction, and test for overlap in */
	/*  that direction -- this is equivalent to testing a minimal AABB around */
	/*  the triangle against the AABB */
	/* test in X-direction */
	FINDMINMAX(v0[X],v1[X],v2[X],min,max);
	if(min>boxhalfsize[X] || max<-boxhalfsize[X]) return 0;
	/* test in Y-direction */
	FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max);
	if(min>boxhalfsize[Y] || max<-boxhalfsize[Y]) return 0;
	/* test in Z-direction */
	FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max);
	if(min>boxhalfsize[Z] || max<-boxhalfsize[Z]) return 0;
	
	/* Bullet 2: */
	/*  test if the box intersects the plane of the triangle */
	/*  compute plane equation of triangle: normal*x+d=0 */
	normal = e0 ^ e1;

	if(!planeBoxOverlap(normal,v0,boxhalfsize)) return 0;
	return 1;   /* box and triangle overlaps */
}
Example #3
0
bool isBoxIntersectingTriangle(const Box_f & box, const Triangle_f & triangle) {
	/*    use separating axis theorem to test overlap between triangle and box */
	/*    need to test for overlap in these directions: */
	/*    1) the {x,y,z}-directions (actually, since we use the AABB of the triangle */
	/*       we do not even need to test these) */
	/*    2) normal of the triangle */
	/*    3) crossproduct(edge from tri, {x,y,z}-directin) */
	/*       this gives 3x3=9 more tests */

	Vec3 boxcenter = box.getCenter();
	Vec3 boxhalfsize(0.5f * box.getExtentX(), 0.5f * box.getExtentY(), 0.5f * box.getExtentZ());

	/* This is the fastest branch on Sun */
	/* move everything so that the boxcenter is in (0,0,0) */
	const auto v0 = triangle.getVertexA() - boxcenter;
	const auto v1 = triangle.getVertexB() - boxcenter;
	const auto v2 = triangle.getVertexC() - boxcenter;

	/* compute triangle edges */
	const auto e0 = triangle.getEdgeAB();
	const auto e1 = triangle.getEdgeBC();
	const auto e2 = triangle.getEdgeCA();

	/* Bullet 3:  */
	/*  test the 9 tests first (this was faster) */
	float p0, p1, p2, rad, pMin, pMax;

	Vec3 fe = e0.getAbs();
	p0 = e0.z() * v0.y() - e0.y() * v0.z();
	p2 = e0.z() * v2.y() - e0.y() * v2.z();
	if (p0 < p2) {
		pMin = p0;
		pMax = p2;
	} else {
		pMin = p2;
		pMax = p0;
	}
	rad = fe.z() * boxhalfsize.y() + fe.y() * boxhalfsize.z();
	if (pMin > rad || pMax < -rad)
		return 0;

	p0 = -e0.z() * v0.x() + e0.x() * v0.z();
	p2 = -e0.z() * v2.x() + e0.x() * v2.z();
	if (p0 < p2) {
		pMin = p0;
		pMax = p2;
	} else {
		pMin = p2;
		pMax = p0;
	}
	rad = fe.z() * boxhalfsize.x() + fe.x() * boxhalfsize.z();
	if (pMin > rad || pMax < -rad)
		return 0;

	p1 = e0.y() * v1.x() - e0.x() * v1.y();
	p2 = e0.y() * v2.x() - e0.x() * v2.y();
	if (p2 < p1) {
		pMin = p2;
		pMax = p1;
	} else {
		pMin = p1;
		pMax = p2;
	}
	rad = fe.y() * boxhalfsize.x() + fe.x() * boxhalfsize.y();
	if (pMin > rad || pMax < -rad)
		return 0;

	fe = e1.getAbs();
	p0 = e1.z() * v0.y() - e1.y() * v0.z();
	p2 = e1.z() * v2.y() - e1.y() * v2.z();
	if (p0 < p2) {
		pMin = p0;
		pMax = p2;
	} else {
		pMin = p2;
		pMax = p0;
	}
	rad = fe.z() * boxhalfsize.y() + fe.y() * boxhalfsize.z();
	if (pMin > rad || pMax < -rad)
		return 0;

	p0 = -e1.z() * v0.x() + e1.x() * v0.z();
	p2 = -e1.z() * v2.x() + e1.x() * v2.z();
	if (p0 < p2) {
		pMin = p0;
		pMax = p2;
	} else {
		pMin = p2;
		pMax = p0;
	}
	rad = fe.z() * boxhalfsize.x() + fe.x() * boxhalfsize.z();
	if (pMin > rad || pMax < -rad)
		return 0;

	p0 = e1.y() * v0.x() - e1.x() * v0.y();
	p1 = e1.y() * v1.x() - e1.x() * v1.y();
	if (p0 < p1) {
		pMin = p0;
		pMax = p1;
	} else {
		pMin = p1;
		pMax = p0;
	}
	rad = fe.y() * boxhalfsize.x() + fe.x() * boxhalfsize.y();
	if (pMin > rad || pMax < -rad)
		return 0;

	fe = e2.getAbs();
	p0 = e2.z() * v0.y() - e2.y() * v0.z();
	p1 = e2.z() * v1.y() - e2.y() * v1.z();
	if (p0 < p1) {
		pMin = p0;
		pMax = p1;
	} else {
		pMin = p1;
		pMax = p0;
	}
	rad = fe.z() * boxhalfsize.y() + fe.y() * boxhalfsize.z();
	if (pMin > rad || pMax < -rad)
		return 0;

	p0 = -e2.z() * v0.x() + e2.x() * v0.z();
	p1 = -e2.z() * v1.x() + e2.x() * v1.z();
	if (p0 < p1) {
		pMin = p0;
		pMax = p1;
	} else {
		pMin = p1;
		pMax = p0;
	}
	rad = fe.z() * boxhalfsize.x() + fe.x() * boxhalfsize.z();
	if (pMin > rad || pMax < -rad)
		return 0;

	p1 = e2.y() * v1.x() - e2.x() * v1.y();
	p2 = e2.y() * v2.x() - e2.x() * v2.y();
	if (p2 < p1) {
		pMin = p2;
		pMax = p1;
	} else {
		pMin = p1;
		pMax = p2;
	}
	rad = fe.y() * boxhalfsize.x() + fe.x() * boxhalfsize.y();
	if (pMin > rad || pMax < -rad)
		return 0;

	/* Bullet 1: */
	/*  first test overlap in the {x,y,z}-directions */
	/*  find min, max of the triangle each direction, and test for overlap in */
	/*  that direction -- this is equivalent to testing a minimal AABB around */
	/*  the triangle against the AABB */

	/* test in X-direction */
	if (std::min(std::min(v0.x(), v1.x()), v2.x()) > boxhalfsize[0]
		|| std::max(std::max(v0.x(), v1.x()), v2.x()) < -boxhalfsize[0])
		return 0;

	/* test in Y-direction */
	if (std::min(std::min(v0.y(), v1.y()), v2.y()) > boxhalfsize[1]
		|| std::max(std::max(v0.y(), v1.y()), v2.y()) < -boxhalfsize[1])
		return 0;

	/* test in Z-direction */
	if (std::min(std::min(v0.z(), v1.z()), v2.z()) > boxhalfsize[2]
		|| std::max(std::max(v0.z(), v1.z()), v2.z()) < -boxhalfsize[2])
		return 0;

	/* Bullet 2: */
	/*  test if the box intersects the plane of the triangle */
	/*  compute plane equation of triangle: normal*x+d=0 */
	Vec3 normal = e0.cross(e1);
	float d = -normal.dot(v0); /* plane eq: normal.x+d=0 */

	Vec3 vmin, vmax;
	for (int q = 0; q < 3; q++) {
		if (normal[q] > 0.0f) {
			vmin[q] = -boxhalfsize[q];
			vmax[q] = boxhalfsize[q];
		} else {
			vmin[q] = boxhalfsize[q];
			vmax[q] = -boxhalfsize[q];
		}
	}
	if (normal.dot(vmin) + d > 0.0f)
		return 0;
	if (normal.dot(vmax) + d >= 0.0f)
		return 1;

	return 0;
}
Example #4
0
void Grid::insertOccluder(Polygon3r* occluder) {
  const vector<Vec3r> vertices = occluder->getVertices();
  if (vertices.size() == 0)
    return;

  // add this occluder to the grid's occluders list
  addOccluder(occluder);

  // find the bbox associated to this polygon
  Vec3r min, max;
  occluder->getBBox(min, max);

  // Retrieve the cell x, y, z cordinates associated with these min and max
  Vec3u imax, imin;
  getCellCoordinates(max, imax);
  getCellCoordinates(min, imin);
  
  // We are now going to fill in the cells overlapping with the
  // polygon bbox.
  // If the polygon is a triangle (most of cases), we also
  // check for each of these cells if it is overlapping with
  // the triangle in order to only fill in the ones really overlapping
  // the triangle.

  unsigned i, x, y, z;
  vector<Vec3r>::const_iterator it;
  Vec3u coord;

  if (vertices.size() == 3) { // Triangle case
    Vec3r triverts[3];
    i = 0;
    for(it = vertices.begin();
	it != vertices.end();
	it++) {
      triverts[i] = Vec3r(*it);
      i++;
    }

    Vec3r boxmin, boxmax;

    for (z = imin[2]; z <= imax[2]; z++)
      for (y = imin[1]; y <= imax[1]; y++)
	for (x = imin[0]; x <= imax[0]; x++) {
	  coord[0] = x;
	  coord[1] = y;
	  coord[2] = z;
	  // We retrieve the box coordinates of the current cell
	  getCellBox(coord, boxmin, boxmax);
	  // We check whether the triangle and the box ovewrlap:
	  Vec3r boxcenter((boxmin + boxmax) / 2.0);
	  Vec3r boxhalfsize(_cell_size / 2.0);
	  if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
	    // We must then create the Cell and add it to the cells list
	    // if it does not exist yet.
	    // We must then add the occluder to the occluders list of this cell.
	    Cell* cell = getCell(coord);
	    if (!cell) {
	      cell = new Cell(boxmin);
	      fillCell(coord, *cell);
	    }
	    cell->addOccluder(occluder);
	  }
	}
  }
  else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
    for (z = imin[2]; z <= imax[2]; z++)
      for (y = imin[1]; y <= imax[1]; y++)
	for (x = imin[0]; x <= imax[0]; x++) {
	  coord[0] = x;
	  coord[1] = y;
	  coord[2] = z;
	  Cell* cell = getCell(coord);
	  if (!cell) {
	    Vec3r orig;
	    getCellOrigin(coord, orig);
	    cell = new Cell(orig);
	    fillCell(coord, *cell);
	  }
	  cell->addOccluder(occluder);
	}
  }
}