use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method findIntersectionContour.
/*
* Given a Face and a HalfEdge from two PolygonalMeshes that intersect at an
* initial MeshIntersectionPoint, trace their intersection contour. Return a
* MeshIntersectionContour of MeshIntersectionPoints. Stop tracing when: -
* the contour is closed, - a duplicate intersection point is encountered -
* the maximum number of points (maxContourPoints) is exceeded, or - the edge
* of the mesh surface is encountered.
*/
private IntersectionContour findIntersectionContour(HalfEdge edge, Face f, boolean edgeOnMesh0) {
IntersectionContour contour = new IntersectionContour();
IntersectionPoint mip = myWorkPoint;
if (!addContourPoint(myWorkPoint, contour)) {
// May be rejected if it's a duplicate intersection.
return null;
}
myWorkPoint = new IntersectionPoint();
// There are two possible directions to trace. First choose the one
// associated with this half edge.
Face edgeFace = mip.edge.getFace();
if (edgeFace != null) {
traceIntersectionContour(contour, edgeFace, edgeOnMesh0);
}
if (traceContourDebug) {
System.out.println("isContinuable=" + contour.isContinuable);
System.out.println("isClosed=" + contour.isClosed());
}
if (contour.isContinuable) {
// The contour encountered a mesh edge and is open. Continue the trace
// in the opposite direction.
HalfEdge opposite = mip.edge.opposite;
if (opposite != null) {
edgeFace = opposite.getFace();
if (edgeFace != null) {
contour.reverse();
traceIntersectionContour(contour, edgeFace, edgeOnMesh0);
}
}
}
if (contour.size() == 1) {
if (traceContourDebug) {
System.out.println("single point or coincident contour");
}
removeContourPoint(contour.get(0));
return null;
}
return contour;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method differentEdgeIntersectingFace.
/*
* Return a HalfEdge of a Face which intersects another Face, and
* add the new intersection point to the contour. Return null if no HalfEdge
* of the Face intersects the other Face, or if no intersection point is
* found that can be added to the contour (duplicate points will be rejected,
* or the contour may be full). If excludeEdge is specified: - excludeEdge
* must be a HalfEdge of the Face - only test the other two HalfEdges of
* this Face for intersection, and return null if neither intersect.
*/
private HalfEdge differentEdgeIntersectingFace(Face face, Face otherFace, HalfEdge excludeEdge, IntersectionContour contour) {
HalfEdge he0 = face.firstHalfEdge();
boolean edgeOnMesh0 = (otherFace.getMesh() == myMesh1);
HalfEdge he = he0;
do {
if (he != excludeEdge & he != excludeEdge.opposite) {
if (intersectEdgeFace(he.getPrimary(), otherFace, myWorkPoint, edgeOnMesh0)) {
if (addContourPoint(myWorkPoint, contour)) {
Point3d wpnt = new Point3d();
if (debug2) {
wpnt.set(myWorkPoint);
if (debugTBW != null) {
}
}
myWorkPoint = new IntersectionPoint();
return he;
}
}
}
he = he.getNext();
} while (he != he0);
return null;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method findPenetrationRegion.
/**
* Finds the penetration region on <code>mesh0</code> that is associated
* with a single specific contour. As the region is traversed, other
* contours may be found to be associated with it; these may be determined
* by querying the {@link PenetrationRegion#getContours} method for the
* returned region.
*
* @param contour contour
* @param mesh0 mesh on which the region resides
* @param mesh1 other mesh which is intersecting <code>mesh0</code>
* @param clockwise <code>true</code> if intersection contours are
* oriented clockwise with respect to <code>mesh0</code>
* @return penetration region associated with <code>contour</code>
*/
PenetrationRegion findPenetrationRegion(IntersectionContour contour, PolygonalMesh mesh0, PolygonalMesh mesh1, boolean clockwise) {
PenetrationRegion region = new PenetrationRegion(mesh0, clockwise, myPositionTol);
Deque<IntersectionContour> contoursToTrace = new ArrayDeque<IntersectionContour>();
region.myContours.add(contour);
contoursToTrace.offerLast(contour);
Deque<Vertex3d> verticesToTrace = new ArrayDeque<Vertex3d>();
FaceCalculator[] faceCalcs = (mesh0 == myMesh0 ? myFaceCalcs0 : myFaceCalcs1);
boolean[] visitedFaces = new boolean[mesh0.numFaces()];
IntersectionContour c;
while ((c = contoursToTrace.pollFirst()) != null) {
// (getContourIndex(c) == 0 && mesh0 == myMesh0);
boolean debug = false;
int kenter = c.getFirstFaceEntryIndex(mesh0, /*face=*/
null);
if (kenter == -1) {
// contour is not open and is confined to a single face
// region.myInsideFaces.add (lastFace);
Face face = c.findSegmentFace(0, mesh0);
region.mySingleFace = face;
c.containingFace = face;
FaceCalculator fcalc = getFaceCalculator(face, faceCalcs);
fcalc.setContour(c);
if (!visitedFaces[face.getIndex()]) {
visitedFaces[face.getIndex()] = true;
fcalc.outsideArea = 0;
}
for (int i = 0; i < c.size(); i++) {
IntersectionPoint pa = c.get(i);
IntersectionPoint pb = c.getWrapped(i + 1);
fcalc.addOutsideArea(pa, pb, clockwise);
}
region.mySingleFaceArea = -fcalc.outsideArea;
c.singleFaceArea = region.mySingleFaceArea;
if (fcalc.outsideArea <= 0) {
fcalc.outsideArea += face.computeArea();
}
} else {
// Go along the contour, looking for face transitions. At each
// transition, examine the associated edge for adjacent vertices or
// contours.
// point where the contour enters
IntersectionPoint pentry = null;
// a face
FaceCalculator fcalc = null;
Face lastFace = c.findSegmentFace(kenter - 1, mesh0);
int k = kenter;
for (int i = 0; i < c.size(); i++) {
IntersectionPoint pa = c.getWrapped(k);
IntersectionPoint pb = c.getWrapped(k + 1);
Face face = c.findSegmentFace(k, mesh0);
if (lastFace != face) {
boolean headInsideFace;
HalfEdge faceEdge;
if (face != null) {
// we are leaving lastFace and entering face
// region.myInsideFaces.add (face);
faceEdge = getPointEdge(pa, face);
pentry = pa;
fcalc = getFaceCalculator(face, faceCalcs);
if (fcalc.contour != c) {
fcalc.setContour(c);
}
if (!visitedFaces[face.getIndex()]) {
visitedFaces[face.getIndex()] = true;
fcalc.outsideArea = 0;
}
headInsideFace = clockwise;
} else {
// Last point of an open contour. Choose faceEdge using
// lastFace
faceEdge = getPointEdge(pa, lastFace);
headInsideFace = !clockwise;
}
Vertex3d insideVtx;
if (headInsideFace) {
insideVtx = faceEdge.getHead();
} else {
insideVtx = faceEdge.getTail();
}
EdgeInfo einfo = myEdgeInfos.get(faceEdge.getPrimary());
if (einfo != null && einfo.indexOfMip(pa) != -1) {
region.myEdges.add(faceEdge.getPrimary());
if (debug)
debugMipEdge = faceEdge.vertexStr();
IntersectionPoint insideMip = nearestInsideMip(pa, faceEdge, insideVtx, mesh0);
if (debug) {
// DBG
debugMipEdge = "";
System.out.println(" insideMip=" + insideMip);
}
if (insideMip == null) {
if (region.myVertices.add(insideVtx)) {
verticesToTrace.offerLast(insideVtx);
}
} else {
String rname = getRegionName(region);
if (region.myContours.add(insideMip.contour)) {
if (regionAddingDebug) {
System.out.println("added " + getContourIndex(insideMip.contour) + " to " + rname);
}
contoursToTrace.offerLast(insideMip.contour);
}
}
}
}
if (face != null) {
fcalc.addOutsideArea(pa, pb, clockwise);
Face nextFace = c.findSegmentFace(k + 1, mesh0);
if (nextFace != face) {
// exiting face
// compute area contribution for face boundary from exit to
// entry
fcalc.addBoundaryArea(pb, pentry, clockwise);
}
}
lastFace = face;
k = c.getWrappedIndex(k + 1);
}
}
Vertex3d vtx;
while ((vtx = verticesToTrace.pollFirst()) != null) {
Iterator<HalfEdge> incidentEdges = vtx.getIncidentHalfEdges();
while (incidentEdges.hasNext()) {
HalfEdge edge = incidentEdges.next().getPrimary();
if (region.myEdges.add(edge)) {
visitedFaces[edge.getFace().getIndex()] = true;
if (edge.opposite != null) {
visitedFaces[edge.opposite.getFace().getIndex()] = true;
}
Vertex3d v = edge.head;
if (v == vtx) {
v = edge.tail;
}
IntersectionPoint mip = nearestMipToVertex(edge, vtx, mesh0);
if (mip != null) {
String rname = getRegionName(region);
if (region.myContours.add(mip.contour)) {
if (regionAddingDebug) {
System.out.println("added (v) " + getContourIndex(mip.contour) + " to " + rname);
}
contoursToTrace.offerLast(mip.contour);
}
} else {
if (region.myVertices.add(v)) {
verticesToTrace.offerLast(v);
}
}
}
}
}
}
double regionArea = 0;
for (int i = 0; i < visitedFaces.length; i++) {
// for (FaceCalculator fcalc : faceCalcMap.values()) {
if (visitedFaces[i]) {
Face face = mesh0.getFace(i);
double insideArea = face.computeArea();
FaceCalculator fcalc = faceCalcs[i];
if (fcalc != null) {
insideArea = face.computeArea() - fcalc.outsideArea;
fcalc.outsideArea = 0;
}
regionArea += insideArea;
double atol = (removeZeroAreaFaces ? myAreaTol : 0);
if (insideArea >= atol) {
region.myFaces.add(face);
}
}
}
region.setArea(regionArea);
return region;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method createPolyFromContour.
Vertex3dList createPolyFromContour(IntersectionContour contour) {
Vertex3dList poly = new Vertex3dList(/*closed=*/
true);
Vertex3d curVtx = null;
IntersectionPoint mip = contour.get(0);
if (contour.isClosed()) {
// back up until previous mip has a different vertex
IntersectionPoint prev = mip.prev();
if (prev.myVertex == mip.myVertex) {
IntersectionPoint mip0 = contour.get(0);
do {
mip = prev;
prev = mip.prev();
} while (prev.myVertex == mip.myVertex && mip != mip0);
}
}
for (int i = 0; i < contour.size(); i++) {
if (mip.myVertex != curVtx) {
curVtx = mip.myVertex;
poly.add(curVtx);
}
mip = mip.next();
}
return poly;
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class CollisionRenderer method prerender.
public void prerender(CollisionHandler handler, RenderProps props) {
RenderObject ro = new RenderObject();
ro.clearAll();
// constraints
ro.createLineGroup();
// segments
ro.createLineGroup();
// contours
ro.createLineGroup();
// contact info
ro.createPointGroup();
// intersection faces
ro.createTriangleGroup();
// create default dummy normal
ro.addNormal(0, 0, 0);
CollisionBehavior behav = handler.myBehavior;
ContactInfo cinfo = handler.getLastContactInfo();
if (behav.myDrawConstraints) {
ro.lineGroup(CONSTRAINT_GRP);
double nrmlLen = handler.getContactNormalLen();
if (nrmlLen > 0) {
addConstraintRenderInfo(ro, handler.myBilaterals0.values(), nrmlLen);
addConstraintRenderInfo(ro, handler.myBilaterals1.values(), nrmlLen);
addConstraintRenderInfo(ro, handler.myUnilaterals, nrmlLen);
}
}
double normalLen = 0;
if (behav.getDrawContactNormals()) {
normalLen = handler.getContactNormalLen();
}
if (normalLen != 0 && cinfo != null) {
ro.lineGroup(SEGMENT_GRP);
Method method = handler.getMethod();
if (method == Method.CONTOUR_REGION) {
int numc = 0;
for (ContactPlane region : cinfo.getContactPlanes()) {
for (Point3d p : region.points) {
if (numc >= handler.myMaxUnilaterals) {
break;
}
addLineSeg(ro, p, region.normal, normalLen);
}
}
} else if (method != Method.INACTIVE) {
for (ContactConstraint cc : handler.myBilaterals0.values()) {
maybeAddVertexFaceNormal(ro, cc, normalLen);
}
for (ContactConstraint cc : handler.myBilaterals1.values()) {
maybeAddVertexFaceNormal(ro, cc, normalLen);
}
}
}
if (behav.myDrawIntersectionContours && props.getEdgeWidth() > 0 && cinfo != null) {
ro.lineGroup(CONTOUR_GRP);
// offset lines
if (cinfo.getContours() != null) {
for (IntersectionContour contour : cinfo.getContours()) {
int vidx0 = ro.numVertices();
for (IntersectionPoint p : contour) {
ro.addVertex(ro.addPosition((float) p.x, (float) p.y, (float) p.z));
}
int vidx1 = ro.numVertices() - 1;
ro.addLineLoop(vidx0, vidx1);
}
} else if (cinfo.getIntersections() != null) {
// use intersections to render lines
for (TriTriIntersection tsect : cinfo.getIntersections()) {
addLineSeg(ro, tsect.points[0], tsect.points[1]);
}
}
}
if (behav.myDrawIntersectionPoints && cinfo != null) {
if (cinfo.getIntersections() != null) {
for (TriTriIntersection tsect : cinfo.getIntersections()) {
for (Point3d pnt : tsect.points) {
addPoint(ro, pnt);
}
}
}
for (PenetratingPoint cpp : cinfo.getPenetratingPoints(0)) {
if (cpp.distance > 0) {
addPoint(ro, cpp.vertex.getWorldPoint());
}
}
for (PenetratingPoint cpp : cinfo.getPenetratingPoints(1)) {
if (cpp.distance > 0) {
addPoint(ro, cpp.vertex.getWorldPoint());
}
}
if (behav.getMethod() == CollisionBehavior.Method.VERTEX_EDGE_PENETRATION) {
if (cinfo.getEdgeEdgeContacts() != null) {
for (EdgeEdgeContact eec : cinfo.getEdgeEdgeContacts()) {
addPoint(ro, eec.point0);
addPoint(ro, eec.point1);
}
}
}
}
if (behav.myDrawIntersectionFaces && cinfo != null) {
ArrayList<TriTriIntersection> intersections = cinfo.getIntersections();
if (intersections != null) {
buildFaceSegments(ro, handler, intersections);
}
}
RenderObject oldRob = myRob;
myRob = ro;
// if (oldRob != null) {
// oldRob.dispose();
// }
RenderObject rd = null;
if (behav.myDrawPenetrationDepth != -1 && cinfo != null) {
int num = behav.myDrawPenetrationDepth;
Collidable b0 = behav.getCollidable(0);
CollidableBody h0 = handler.getCollidable(0);
if (!(b0 instanceof Group)) {
if (h0 != b0 && h0.getCollidableAncestor() != b0) {
// then we want the *other* collidable body, so switch num
num = (num == 0 ? 1 : 0);
}
}
ArrayList<PenetrationRegion> regions;
ArrayList<PenetratingPoint> points;
if (num == 0) {
regions = cinfo.getRegions(0);
points = cinfo.getPenetratingPoints(0);
} else {
regions = cinfo.getRegions(1);
points = cinfo.getPenetratingPoints(1);
}
if (regions != null && regions.size() > 0) {
rd = createPenetrationRenderObject(handler, points, regions);
}
}
oldRob = myDepthRob;
myDepthRob = rd;
// if (oldRob != null) {
// oldRob.dispose();
// }
}
Aggregations