Commit 4fe54ed9 authored by Will Schroeder's avatar Will Schroeder
Browse files

ENH: Organize for collision detection

parent 770f22cd
......@@ -216,8 +216,8 @@ public:
float GetLength2();
// Quick intersection of cell bounding box. Returns != 0 for hit.
char HitBBox(float bounds[6], float origin[3], float dir[3],
float coord[3], float& t);
static char HitBBox(float bounds[6], float origin[3], float dir[3],
float coord[3], float& t);
// left public for quick computational access
vtkFloatPoints Points;
......
......@@ -84,8 +84,8 @@ public:
int dim, float *derivs);
// Hexahedron specific
void InterpolationFunctions(float pcoords[3], float weights[8]);
void InterpolationDerivs(float pcoords[3], float derivs[24]);
static void InterpolationFunctions(float pcoords[3], float weights[8]);
static void InterpolationDerivs(float pcoords[3], float derivs[24]);
void JacobianInverse(float pcoords[3], double **inverse, float derivs[24]);
};
......
......@@ -100,12 +100,11 @@ void vtkLine::EvaluateLocation(int& vtkNotUsed(subId), float pcoords[3],
weights[1] = 1.0 - pcoords[0];
}
//
// Intersect two 3D lines
//
// returns if the projectstion of thw two lines onto the plane defined by the
// vector orthogonal to both lines. The method may report skewed lines as
// intersecting and (u,v) represent the parametric coords of closest approach
// Description:
// Performs intersection of two finite 3D lines. An intersection is found if
// the projection of the two lines onto the plane perpendicular to the cross
// product of the two lines intersect. The parameters (u,v) are the
// parametric coordinates of the lines at the position of closest approach.
int vtkLine::Intersection (float a1[3], float a2[3], float b1[3], float b2[3],
float& u, float& v)
{
......
......@@ -86,8 +86,8 @@ public:
int dim, float *derivs);
// pixel specific
void InterpolationFunctions(float pcoords[3], float weights[4]);
void InterpolationDerivs(float pcoords[3], float derivs[8]);
static void InterpolationFunctions(float pcoords[3], float weights[4]);
static void InterpolationDerivs(float pcoords[3], float derivs[8]);
};
#endif
......
......@@ -71,7 +71,8 @@ vtkPolygon::vtkPolygon(const vtkPolygon& p)
// Description:
// Compute the polygon normal from a points list, and a list of point ids
// that index into the points list.
// that index into the points list. This version will handle non-convex
// polygons.
void vtkPolygon::ComputeNormal(vtkPoints *p, int numPts, int *pts, float *n)
{
int i;
......@@ -115,7 +116,8 @@ void vtkPolygon::ComputeNormal(vtkPoints *p, int numPts, int *pts, float *n)
}
// Description:
// Compute the polygon normal from a list of floating points.
// Compute the polygon normal from a list of floating points. This version
// will handle non-convex polygons.
void vtkPolygon::ComputeNormal(vtkFloatPoints *p, float *n)
{
int i, numPts;
......@@ -143,11 +145,56 @@ void vtkPolygon::ComputeNormal(vtkFloatPoints *p, float *n)
n[0] += (ay * bz - az * by);
n[1] += (az * bx - ax * bz);
n[2] += (ax * by - ay * bx);
}
}//over all points
vtkMath::Normalize(n);
}
// Description:
// Compute the polygon normal from an array of points. This version assumes that
// the polygon is convex, and looks for the first valid normal.
void vtkPolygon::ComputeNormal (int numPts, float *pts, float n[3])
{
int i;
float *v1, *v2, *v3;
float length;
float ax, ay, az;
float bx, by, bz;
//
// Because some polygon vertices are colinear, need to make sure
// first non-zero normal is found.
//
v1 = pts;
v2 = pts + 3;
v3 = pts + 6;
for (i=0; i<numPts; i++)
{
ax = v2[0] - v1[0]; ay = v2[1] - v1[1]; az = v2[2] - v1[2];
bx = v3[0] - v1[0]; by = v3[1] - v1[1]; bz = v3[2] - v1[2];
n[0] = (ay * bz - az * by);
n[1] = (az * bx - ax * bz);
n[2] = (ax * by - ay * bx);
length = sqrt (n[0] * n[0] + n[1] * n[1] + n[2] * n[2]);
if (length != 0.0)
{
n[0] /= length;
n[1] /= length;
n[2] /= length;
return;
}
else
{
v1 = v2;
v2 = v3;
v3 = pts + 9 + 3*i;
}
} //over all points
}
int vtkPolygon::EvaluatePosition(float x[3], float closestPoint[3],
int& vtkNotUsed(subId), float pcoords[3],
float& minDist2, float *weights)
......@@ -166,7 +213,8 @@ int vtkPolygon::EvaluatePosition(float x[3], float closestPoint[3],
if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 &&
pcoords[1] >= 0.0 && pcoords[1] <= 1.0 &&
this->PointInPolygon(this->GetBounds(),closestPoint,n) == INSIDE )
(this->PointInPolygon(closestPoint, this->Points.GetNumberOfPoints(),
this->Points.GetPtr(0), this->GetBounds(),n) == INSIDE) )
{
minDist2 = vtkMath::Distance2BetweenPoints(x,closestPoint);
return 1;
......@@ -300,7 +348,8 @@ int vtkPolygon::ParameterizePolygon(float *p0, float *p10, float& l10,
// Determine whether point is inside polygon.
// Function uses ray-casting to determine if point is inside polygon.
// Works for arbitrary polygon shape (e.g., non-convex).
int vtkPolygon::PointInPolygon (float bounds[6], float *x, float *n)
int vtkPolygon::PointInPolygon (float x[3], int numPts, float *pts,
float bounds[6], float *n)
{
float *x1, *x2, xray[3], u, v;
float rayMag, mag=1, ray[3];
......@@ -308,7 +357,6 @@ int vtkPolygon::PointInPolygon (float bounds[6], float *x, float *n)
int iterNumber;
int maxComp, comps[2];
int deltaVotes;
int numPts=this->Points.GetNumberOfPoints();
//
// Define a ray to fire. The ray is a random ray normal to the
// normal of the face. The length of the ray is a function of the
......@@ -396,8 +444,8 @@ int vtkPolygon::PointInPolygon (float bounds[6], float *x, float *n)
//
for (numInts=0, testResult=CERTAIN, i=0; i<numPts; i++)
{
x1 = this->Points.GetPoint(i);
x2 = this->Points.GetPoint((i+1)%numPts);
x1 = pts + 3*i;
x2 = pts + 3*((i+1)%numPts);
//
// Fire the ray and compute the number of intersections. Be careful of
// degenerate cases (e.g., ray intersects at vertex).
......@@ -421,7 +469,7 @@ int vtkPolygon::PointInPolygon (float bounds[6], float *x, float *n)
else
++deltaVotes;
}
} /* try another ray */
} //try another ray
//
// If the number of intersections is odd, the point is in the polygon.
//
......@@ -817,7 +865,8 @@ int vtkPolygon::CellBoundary(int vtkNotUsed(subId), float pcoords[3],
// determine whether point is inside of polygon
if ( pcoords[0] >= 0.0 && pcoords[0] <= 1.0 &&
pcoords[1] >= 0.0 && pcoords[1] <= 1.0 &&
this->PointInPolygon(this->GetBounds(),closest,n) == INSIDE )
(this->PointInPolygon(closest, this->Points.GetNumberOfPoints(),
this->Points.GetPtr(0), this->GetBounds(),n) == INSIDE) )
{
return 1;
}
......@@ -1141,3 +1190,75 @@ void vtkPolygon::Clip(float value, vtkFloatScalars *cellScalars,
}
delete [] polyVerts;
}
// Description:
// Method intersects two polygons. You must supply the number of points and
// point coordinates (npts, *pts) and the bounding box (bounds) of the two
// polygons. Also supply a tolerance squared for controlling error.
int vtkPolygon::IntersectPolygonWithPolygon(int npts, float *pts,float bounds[6],
int npts2, float *pts2,
float bounds2[6], float tol2)
{
float n[3], x[3], coords[3];
int i, j, retStat;
float *p1, *p2, ray[3];
float t;
//
// Intersect each edge of first polygon against second
//
vtkPolygon::ComputeNormal(npts2, pts2, n);
for (i=0; i<npts; i++)
{
p1 = pts + 3*i;
p2 = pts + 3*((i+1)%npts);
for (j=0; j<3; j++) ray[j] = p2[j] - p1[j];
if ( ! vtkCell::HitBBox(bounds2, p1, ray, coords, t) )
continue;
if ( (retStat=vtkPlane::IntersectWithLine(p1,p2,n,pts2,t,x)) == 1 )
{
if ( (npts2==3 && vtkTriangle::PointInTriangle(x,pts2,pts2+3,pts2+6,tol2))
|| (npts2>3 && vtkPolygon::PointInPolygon(x,npts2,pts2,bounds2,n)==INSIDE))
{
return 1;
}
}
else //if ( retStat == ON_PLANE )
{
return 0;
}
}
//
// Intersect each edge of second polygon against first
//
vtkPolygon::ComputeNormal(npts, pts, n);
for (i=0; i<npts2; i++)
{
p1 = pts2 + 3*i;
p2 = pts2 + 3*((i+1)%npts2);
for (j=0; j<3; j++) ray[j] = p2[j] - p1[j];
if ( ! vtkCell::HitBBox(bounds, p1, ray, coords, t) )
continue;
if ( (retStat=vtkPlane::IntersectWithLine(p1,p2,n,pts,t,x)) == 1 )
{
if ( (npts==3 && vtkTriangle::PointInTriangle(x,pts,pts+3,pts+6,tol2))
|| (npts>3 && vtkPolygon::PointInPolygon(x,npts,pts,bounds,n)==INSIDE))
{
return 1;
}
}
else //if ( retStat == ON_PLANE )
{
return 0;
}
}
return 0;
}
......@@ -88,13 +88,15 @@ public:
// Polygon specific
static void ComputeNormal(vtkPoints *p, int numPts, int *pts, float n[3]);
static void ComputeNormal(vtkFloatPoints *p, float n[3]);
static void ComputeNormal(int numPts, float *pts, float n[3]);
void ComputeWeights(float x[3], float *weights);
int ParameterizePolygon(float p0[3], float p10[3], float &l10,
float p20[3], float &l20, float n[3]);
int PointInPolygon(float bounds[6], float x[3], float n[3]);
static int PointInPolygon(float x[3], int numPts, float *pts, float bounds[6],
float n[3]);
int Triangulate(vtkIdList &outTris);
int FastTriangulate(int numVerts, int *verts, vtkIdList& Tris);
......@@ -105,6 +107,10 @@ public:
void SplitLoop (int fedges[2], int numVerts, int *verts, int& n1, int *l1,
int& n2, int* l2);
static int IntersectPolygonWithPolygon(int npts, float *pts, float bounds[6],
int npts2, float *pts2,
float bounds2[3], float tol);
};
#endif
......
......@@ -84,8 +84,8 @@ public:
int dim, float *derivs);
// quad specific
void InterpolationFunctions(float pcoords[3], float sf[4]);
void InterpolationDerivs(float pcoords[3], float derivs[8]);
static void InterpolationFunctions(float pcoords[3], float sf[4]);
static void InterpolationDerivs(float pcoords[3], float derivs[8]);
};
......
......@@ -377,7 +377,7 @@ int vtkVoxel::IntersectWithLine(float p1[3], float p2[3], float vtkNotUsed(tol),
bounds[2*i+1] = maxPt[i];
}
if ( ! this->HitBBox(bounds, p1, p21, x, t) )
if ( ! vtkCell::HitBBox(bounds, p1, p21, x, t) )
return 0;
//
// Evaluate intersection
......
......@@ -41,7 +41,6 @@ MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
#include <stdlib.h>
#include <math.h>
#include "vtkCellLocator.h"
#include "vtkVoxel.h"
#include "vtkPolyData.h"
#define OUTSIDE 0
......@@ -102,7 +101,6 @@ int vtkCellLocator::IntersectWithLine(float a0[3], float a1[3], float tol,
float& t, float x[3], float pcoords[3],
int &subId)
{
static vtkVoxel voxel; // use to take advantage of Hitbbox() method
float origin[3];
float direction2[3];
float direction3[3];
......@@ -141,7 +139,7 @@ int vtkCellLocator::IntersectWithLine(float a0[3], float a1[3], float tol,
direction3[i] = direction2[i]/tMax;
}
if (voxel.HitBBox(bounds2, origin, direction2, hitPosition, result))
if (vtkCell::HitBBox(bounds2, origin, direction2, hitPosition, result))
{
// start walking through the octants
prod = this->NumberOfDivisions*this->NumberOfDivisions;
......
......@@ -113,7 +113,6 @@ int vtkPicker::Pick(float selectionX, float selectionY, float selectionZ,
vtkCamera *camera;
vtkMapper *mapper;
float p1World[4], p2World[4], p1Mapper[4], p2Mapper[4];
static vtkVertex cell; // use to take advantage of Hitbbox() method
int picked=0;
int *winSize;
float x, y, t;
......@@ -268,7 +267,7 @@ int vtkPicker::Pick(float selectionX, float selectionY, float selectionZ,
// bounding box are picked correctly.
//
bounds = mapper->GetBounds();
if ( cell.HitBBox(bounds, (float *)p1Mapper, ray, hitPosition, t) )
if ( vtkCell::HitBBox(bounds, (float *)p1Mapper, ray, hitPosition, t) )
{
picked = 1;
this->IntersectWithLine((float *)p1Mapper, (float *)p2Mapper,tol,actor,part,mapper);
......
......@@ -365,7 +365,6 @@ void vtkVolumeRenderer::TraceOneRay(float p1World[4],float p2World[4],
float p1Mapper[4], p2Mapper[4];
float ray[3];
vtkStructuredPoints *strPts;
static vtkVoxel cell; // use to take advantage of Hitbbox() method
float *bounds;
float hitPosition[3];
float t,t2;
......@@ -421,14 +420,14 @@ void vtkVolumeRenderer::TraceOneRay(float p1World[4],float p2World[4],
{
// Get the bounding box of the modeller.
bounds = strPts->GetBounds();
if (cell.HitBBox(bounds, (float *)p1Mapper, ray, hitPosition, t) )
if (vtkCell::HitBBox(bounds, (float *)p1Mapper, ray, hitPosition, t) )
{
// find the exit point of the ray
for (i=0; i<3; i++)
{
ray[i] = p1Mapper[i] - p2Mapper[i];
}
cell.HitBBox(bounds, (float *)p2Mapper, ray, hitPosition, t2);
vtkCell::HitBBox(bounds, (float *)p2Mapper, ray, hitPosition, t2);
t2 = 1.0 - t2;
// calc wc length of ray
......@@ -475,7 +474,7 @@ void vtkVolumeRenderer::TraceOneRay(float p1World[4],float p2World[4],
{
for (i = 0; i < 3; i++) pcoords[i] = (hitPosition[i] - index[i]);
cell.InterpolationFunctions(pcoords,sf);
vtkVoxel::InterpolationFunctions(pcoords,sf);
if ( newVoxel )
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment