use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class MeshCollisionViewer method render.
public void render(Renderer renderer, int flags) {
ContactInfo cinfo = myContactInfo;
if (contourWidth > 0 && cinfo != null) {
renderer.setShading(Shading.NONE);
renderer.setLineWidth(contourWidth);
renderer.setPointSize(contourWidth);
renderer.setColor(contourColor, /*highlight=*/
false);
if (cinfo.getContours() != null) {
for (IntersectionContour contour : cinfo.getContours()) {
renderer.beginDraw(DrawMode.LINE_LOOP);
for (IntersectionPoint p : contour) {
renderer.addVertex(p);
}
renderer.endDraw();
}
}
Point3d pnt = new Point3d();
renderer.beginDraw(DrawMode.POINTS);
for (PenetratingPoint p : cinfo.getPenetratingPoints(0)) {
pnt.set(p.vertex.pnt);
pnt.transform(myMesh1.getMeshToWorld());
renderer.addVertex(pnt);
}
for (PenetratingPoint p : cinfo.getPenetratingPoints(1)) {
pnt.set(p.vertex.pnt);
pnt.transform(myMesh2.getMeshToWorld());
renderer.addVertex(pnt);
}
renderer.endDraw();
renderer.setShading(Shading.FLAT);
renderer.setLineWidth(1);
renderer.setPointSize(1);
}
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method getOneContour.
/**
* From an non-empty list of MIPs, create a new MeshIntersectionContour and
* return it. It might be open or closed. MIPs are removed from mips as they
* are used.
*
* @param mips List of possible MeshIntersectionPoints to check. This method
* deletes MIPs in mips as it goes along.
* @return new MeshIntersectionContour, or <code>null</code>
* if <code>mips</code> is empty
*/
protected IntersectionContour getOneContour(ArrayList<IntersectionPoint> mips) throws DegenerateLoopCaseException {
if (mips.size() == 0) {
return null;
}
IntersectionContour contour = new IntersectionContour();
contour.setClosed(true);
IntersectionPoint firstMip = mips.get(0);
IntersectionPoint mip = firstMip;
IntersectionPoint nextMip = null;
// Start the contour
contour.add(mip);
Face fPrev = null;
while (nextMip != contour.get(0) || contour.size() < 2) {
nextMip = null;
// First search this edge's face's edges for intersection with mip.face
Face thisEdgesFace;
if (mip.edge.getFace() == fPrev) {
if (mip.edge.opposite == null) {
thisEdgesFace = null;
} else {
thisEdgesFace = mip.edge.opposite.getFace();
}
} else {
thisEdgesFace = mip.edge.getFace();
}
/*
* We have found the edge of an open mesh. This contour is
* definitely open. Continue from contour.get(0) and go in
* opposite direction. If we already did that, then we're finished.
*/
if (thisEdgesFace == null) {
if (!contour.isClosed()) {
// We're finished, since we already did this
break;
}
contour.setClosed(false);
nextMip = firstMip;
contour.reverse();
mip = nextMip;
mips.remove(mip);
// mip.edge.getFace was already checked in first pass,
// so we should use this as previous to switch directions.
fPrev = mip.edge.getFace();
continue;
}
/*
* Now the meat of the algorithm. Search this edge's faces edges
* for another match. If found, this is the next mip in the contour
*/
for (int i = 0; i < 3; i++) {
HalfEdge candEdge = thisEdgesFace.getEdge(i).getPrimary();
if (candEdge == mip.edge.getPrimary()) {
// We already know about this edge
continue;
}
EdgeFacePair testPair = new EdgeFacePair(candEdge, mip.face);
nextMip = mySavedEdgeFaceResults.get(testPair);
if (nextMip == null) {
continue;
} else {
fPrev = thisEdgesFace;
break;
}
}
/*
* if nextMip is still null, the next mip must be on the other mesh's face
*/
if (nextMip == null) {
for (int i = 0; i < 3; i++) {
HalfEdge candEdge = mip.face.getEdge(i).getPrimary();
EdgeFacePair testPair = new EdgeFacePair(candEdge, thisEdgesFace);
nextMip = mySavedEdgeFaceResults.get(testPair);
if (nextMip == null) {
continue;
} else {
fPrev = mip.face;
break;
}
}
}
/*
* If we still haven't found the next MIP at this point,
* we're basically screwed. We should probably give up or something
*/
if (nextMip == null) {
System.out.println("mips.size(): " + mips.size());
System.out.println("contour.size(): " + contour.size());
throw new DegenerateLoopCaseException("Couldn't find next intersection point!");
}
mip = nextMip;
contour.add(mip);
if (!mips.remove(mip)) {
// This shouldn't happen
System.out.println("mips.size(): " + mips.size());
System.out.println("contour.size(): " + contour.size());
if (!contour.isClosed()) {
System.out.println("Open contour");
}
throw new DegenerateLoopCaseException("Warning! nextMip wasn't in mips!!! aborting");
}
}
return contour;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method findContours.
/*
* Main interface for collision -- called by CollisionPair. Returns a
* ContactInfo populated with the results of the collision analysis. Returns
* null if there is no collision. mesh0, mesh1 are the candidate colliding
* surface meshes, which can be the same mesh.
*
* isRigidBodyRigidBody should be specified as true only if mesh0 and mesh1
* both represent rigid bodies. This controls the type of data returned in
* ContactInfo.
*/
public boolean findContours(PolygonalMesh mesh0, PolygonalMesh mesh1) {
if (mesh0 != mesh1) {
if (mesh0.canSelfIntersect)
if (findContours(mesh0, mesh0))
throw new RuntimeException("self-intersecting mesh");
if (mesh1.canSelfIntersect)
if (findContours(mesh1, mesh1))
throw new RuntimeException("self-intersecting mesh");
}
this.mesh0 = mesh0;
this.mesh1 = mesh1;
double maxRadius = Math.max(RenderableUtils.getRadius(mesh0), RenderableUtils.getRadius(mesh1));
myMaxLength = 2 * maxRadius;
mesh0.updateFaceNormals();
mesh1.updateFaceNormals();
if (!mesh0.isTriangular() | !mesh1.isTriangular())
throw new IllegalArgumentException("collision with non-triangular mesh");
ArrayList<IntersectionPoint> allMips = new ArrayList<IntersectionPoint>();
// Try getting allMips continuously until no DegenerateCases are caught
boolean intersected;
int exceptCntr = 0;
while (true) {
// Clear old saved results
mySavedEdgeFaceResults.clear();
myContours.clear();
allMips.clear();
BVTree bvh0 = mesh0.getBVTree();
BVTree bvh1 = mesh1.getBVTree();
ArrayList<BVNode> nodes0 = new ArrayList<BVNode>();
ArrayList<BVNode> nodes1 = new ArrayList<BVNode>();
bvh0.intersectTree(nodes0, nodes1, bvh1);
try {
getAllMIPs(allMips, nodes0, nodes1);
if (allMips.size() > 0) {
buildContours(myContours, allMips);
intersected = true;
} else {
intersected = false;
}
return intersected;
// break;
} catch (DegeneratePairCaseException e) {
System.out.println("Caught a DegeneratePairCaseException, points perturbed and retrying");
mesh0.notifyVertexPositionsModified();
mesh1.notifyVertexPositionsModified();
} catch (DegenerateLoopCaseException e) {
if (exceptCntr > 5) {
System.out.println("SurfaceMeshContourIxer failed! Giving up after 5 tries");
break;
}
System.out.println("Caught a DegenerateLoopCaseException, points perturbed and retrying");
System.out.println(e.getMessage());
perturbVertices(mesh0);
perturbVertices(mesh1);
mesh0.notifyVertexPositionsModified();
mesh1.notifyVertexPositionsModified();
exceptCntr++;
continue;
}
}
return false;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method doFaceFaceCollision.
/**
* Collide one triangular face with the second, but not the other way around.
*
* @param allMips new MIPs are appended to this list
* @param f0 The face which has its edges checked
* @param f1 The face which has its face checked
*
* @return the number of edge/face collisions detected in this call.
*/
protected int doFaceFaceCollision(ArrayList<IntersectionPoint> allMips, Face f0, Face f1, boolean edgeOnMesh0) {
int numFound = 0;
// Faces assumed to be triangular here!
for (int eidx = 0; eidx < 3; eidx++) {
HalfEdge e = f0.getEdge(eidx).getPrimary();
EdgeFacePair pair = new EdgeFacePair(e, f1);
// First check if we've already tested this edge/face pair
if (mySavedEdgeFaceResults.containsKey(pair)) {
if (mySavedEdgeFaceResults.get(pair) != null) {
numFound++;
}
continue;
}
IntersectionPoint mip = new IntersectionPoint();
boolean collided = robustIntersectionWithFace(e, f1, mip, edgeOnMesh0);
if (collided) {
mySavedEdgeFaceResults.put(pair, mip);
allMips.add(mip);
numFound++;
} else {
mySavedEdgeFaceResults.put(pair, null);
}
}
return numFound;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method markEmptySegEnd.
void markEmptySegEnd(IntersectionPoint mip, HalfEdge edge, boolean clockwise) {
Face face = edge.getFace();
PolygonalMesh mesh = (PolygonalMesh) face.getMesh();
int meshNum = (mesh == myMesh0 ? 0 : 1);
int mark = IntersectionPoint.EMPTY_END;
EdgeInfo einfo = getEdgeInfo(edge.getPrimary());
if (mip.edge.getHead().getMesh() != mesh) {
boolean tailToHead = (edge == einfo.myEdge);
if (!clockwise) {
tailToHead = !tailToHead;
}
EdgeInfo.PointData xdata = null;
double s = einfo.project(mip);
int idx;
if (!tailToHead) {
double si = 0;
for (idx = 0; idx < einfo.numXips(); idx++) {
double sx = einfo.getXipData(idx).s;
if (sx - myPositionTol >= s) {
break;
}
si = sx;
}
if (s > si + myPositionTol) {
mark |= IntersectionPoint.EMPTY_PROJECTED;
}
} else {
double si = einfo.myUlen;
for (idx = einfo.numXips() - 1; idx >= 0; idx--) {
double sx = einfo.getXipData(idx).s;
if (sx + myPositionTol <= s) {
break;
}
si = sx;
}
idx++;
if (s < si - myPositionTol) {
mark |= IntersectionPoint.EMPTY_PROJECTED;
}
}
if (useEmptySegmentProjection) {
einfo.addXip(idx, mip, s);
}
mip.setNearEdge(meshNum, edge);
}
if (useEmptySegmentProjection) {
mip.setEmptyMark(meshNum, mark);
}
}
Aggregations