use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class IntersectorTestViewer method render.
public void render(Renderer renderer, int flags) {
RenderObjs objs = myRenderObjs;
if (objs == null) {
return;
}
if (objs.mesh0 != null) {
objs.mesh0.render(renderer, myRenderProps, flags);
}
if (objs.mesh1 != null) {
objs.mesh1.render(renderer, myRenderProps, flags);
}
if (myDrawIntersection && objs.imesh != null) {
objs.imesh.render(renderer, myCSGRenderProps, flags);
}
if (myDrawUnion && objs.umesh != null) {
objs.umesh.render(renderer, myCSGRenderProps, flags);
}
ArrayList<IntersectionContour> contours = null;
if (objs.contactInfo != null) {
contours = objs.contactInfo.getContours();
}
if (contours != null) {
renderer.setLineWidth(3);
renderer.setColor(Color.RED);
renderer.setShading(Shading.NONE);
for (IntersectionContour c : contours) {
if (c.isClosed()) {
renderer.beginDraw(DrawMode.LINE_LOOP);
} else {
renderer.beginDraw(DrawMode.LINE_STRIP);
}
for (IntersectionPoint p : c) {
renderer.addVertex((float) p.x, (float) p.y, (float) p.z);
}
renderer.endDraw();
}
renderer.setShading(Shading.FLAT);
renderer.setLineWidth(1);
}
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method getAllMIPs.
/**
* Return an unordered list of MeshIntersectionPoints representing all
* edge/face collisions between the lists of BVs nodes0 and nodes1.
*
* New MeshIntersectionPoints are generated and appended to allMips.
* All Faces are assumed to be triangular! Undetermined behaviour if not the case.
*
* @param allMips Initialized ArrayList of MeshIntersectionPoints
* @param nodes0 first list of BVs from BVTree.intersectTree
* @param nodes1 second list of BVs from BVTree.intersectTree (same length as nodes0)
*
* @throws DegeneratePairCaseException if a degenerate case is detected.
* Points of those faces are perturbed before this exception is re-thrown
*/
protected void getAllMIPs(ArrayList<IntersectionPoint> allMips, ArrayList<BVNode> nodes0, ArrayList<BVNode> nodes1) throws DegeneratePairCaseException {
assert nodes0.size() == nodes1.size();
for (int i = 0; i < nodes0.size(); i++) {
BVNode n0 = nodes0.get(i);
BVNode n1 = nodes1.get(i);
for (Boundable b0 : n0.getElements()) {
for (Boundable b1 : n1.getElements()) {
if (b0 instanceof Face && b1 instanceof Face) {
Face f0 = (Face) b0;
Face f1 = (Face) b1;
int numFound = 0;
numFound += doFaceFaceCollision(allMips, f0, f1, true);
numFound += doFaceFaceCollision(allMips, f1, f0, false);
if (myHandleDegen) {
if (numFound != 0 && numFound != 2) {
perturbVertices(f0);
perturbVertices(f1);
// System.out.println("Found " + numFound + " ixps");
throw new DegeneratePairCaseException();
}
}
}
}
}
}
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshContourIxer method robustIntersectionWithFace.
/*
* Test for intersection using adaptive exact arithmetic and SOS tiebreaking.
*/
protected boolean robustIntersectionWithFace(HalfEdge he, Face face, IntersectionPoint mip, boolean edgeOnMesh0) {
HalfEdge he0 = face.firstHalfEdge();
Vertex3d v = he0.tail;
if (v == he.head)
return false;
if (v == he.tail)
return false;
v = he0.head;
if (v == he.head)
return false;
if (v == he.tail)
return false;
v = he0.getNext().head;
if (v == he.head)
return false;
if (v == he.tail)
return false;
int res = RobustPreds.intersectEdgeTriangle(mip, he, face, myMaxLength, edgeOnMesh0, /*worldCoords=*/
true);
if (res == 0) {
return false;
} else {
mip.edge = he;
mip.face = face;
// mip.edgeOnMesh0 = edgeOnMesh0;
mip.intersectionCode = res;
// mip.degeneracies = (res & RobustPreds.DEGENERACY_MASK);
return true;
}
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method addIntersectionToEdge.
/*
* Remember all the intersection points for the edge, in sorted order of
* increasing distance from edge.tail. Mark coincident einfo.
*/
void addIntersectionToEdge(IntersectionPoint mip) {
EdgeInfo einfo = getEdgeInfo(mip.edge);
numEdgeAdds++;
if (einfo.numMips() == 0) {
einfo.addMip(mip);
return;
}
// insertion index within mips list
int idx;
// comparision variable between mips
int q = 0;
int firstCoincidentIdx = -1;
EdgeInfo.PointData mdata = null;
double s = einfo.project(mip);
for (idx = 0; idx < einfo.numMips(); idx++) {
mdata = einfo.getMipData(idx);
if (mdata.s < s - myPositionTol) {
q = 1;
} else if (mdata.s > s + myPositionTol) {
q = -1;
} else {
long t0 = System.nanoTime();
q = RobustPreds.closestIntersection(mip.face, mip.edge, mdata.pnt.face);
long t1 = System.nanoTime();
tot += (t1 - t0);
numClosestIntersectionCalls++;
}
if (q == 0) {
if (firstCoincidentIdx == -1) {
firstCoincidentIdx = idx;
}
}
if (q < 0) {
break;
}
}
if (firstCoincidentIdx != -1) {
IntersectionPoint m = einfo.getMip(firstCoincidentIdx);
if (!m.isCoincident()) {
// first conincident pair
m.primaryCoincident = m;
}
mip.primaryCoincident = m.primaryCoincident;
}
einfo.addMip(idx, mip, s);
if (debug) {
// System.out.println ("Face mips");
// printFaceMips (mip.edge.getFace());
}
}
use of maspack.collision.IntersectionPoint in project artisynth_core by artisynth.
the class SurfaceMeshIntersector method createCSGMesh.
/**
* Computes the boundary mesh formed by the union of the penetration
* regions associated with two meshes. The meshes, intersection
* contours, and penetration regions are described in the supplied
* {@link ContactInfo} object. These meshes and contours must also
* correspond to those associated with the most recent intersection
* contours computed by this intersector.
*
* <p>Whether or not the penetration regions for each mesh are
* "inside" or "outside" the opposite mesh determines the type
* of CSG volume produced:
*
* <table summary="">
* <tr>
* <th>mesh0 regions</th>
* <th>mesh1 regions</th>
* <th>CSG volume</th>
* </tr>
* <tr>
* <td>inside</td>
* <td>inside</td>
* <td>intersection</td>
* </tr>
* <tr>
* <td>outside</td>
* <td>outside</td>
* <td>union</td>
* </tr>
* <tr>
* <td>outside</td>
* <td>inside</td>
* <td>difference (mesh0-mesh1)</td>
* </tr>
* <tr>
* <td>inside</td>
* <td>outside</td>
* <td>difference (mesh1-mesh0)</td>
* </tr>
* </table>
* @param cinfo meshes, contours and penetration regions from
* which the CSG boundary is to be constructed
* @return bounding mesh for resulting CSG volume
* @throws IllegalStateException if the contours and meshes
* do not match the contours most recently produced by this intersector
*/
public PolygonalMesh createCSGMesh(ContactInfo cinfo) {
if (cinfo.myMesh0 != myMesh0 || cinfo.myMesh1 != myMesh1 || cinfo.myContours != myContours) {
throw new IllegalStateException("Meshes and/or contours contained in <code>cinfo</code> do not " + "match the contours most recently produced by this intersector");
}
PolygonalMesh csgMesh;
RegionType regions0 = cinfo.getRegionsType(0);
RegionType regions1 = cinfo.getRegionsType(1);
if (cinfo.myContours.size() == 0) {
// what to do here depends on the operation
if (regions0 == RegionType.INSIDE && regions1 == RegionType.INSIDE) {
// intersection
if (isInside(myMesh0, myMesh1)) {
csgMesh = myMesh0.copy();
} else if (isInside(myMesh1, myMesh0)) {
csgMesh = myMesh1.copy();
} else {
csgMesh = new PolygonalMesh();
}
} else if (regions0 == RegionType.OUTSIDE && regions1 == RegionType.OUTSIDE) {
// union
csgMesh = myMesh0.copy();
csgMesh.addMesh(myMesh1, /*respectTransforms=*/
true);
} else if (regions0 == RegionType.OUTSIDE && regions1 == RegionType.INSIDE) {
// difference mesh0 - mesh1
if (isInside(myMesh0, myMesh1)) {
csgMesh = new PolygonalMesh();
} else {
csgMesh = new PolygonalMesh(myMesh0);
if (isInside(myMesh1, myMesh0)) {
PolygonalMesh inside = myMesh1.copy();
inside.flip();
csgMesh.addMesh(inside, /*respectTransforms=*/
true);
}
}
} else {
// difference mesh1 - mesh0
if (isInside(myMesh1, myMesh0)) {
csgMesh = new PolygonalMesh();
} else {
csgMesh = new PolygonalMesh(myMesh1);
if (isInside(myMesh0, myMesh1)) {
PolygonalMesh inside = myMesh0.copy();
inside.flip();
csgMesh.addMesh(inside, /*respectTransforms=*/
true);
}
}
}
return csgMesh;
}
// if (cinfo.myContours == null || cinfo.myContours.size() == 0) {
// return null;
// }
csgMesh = new PolygonalMesh();
triangulationError = false;
// create the xips
for (EdgeInfo einfo : myEdgeInfos.values()) {
einfo.initializeXips();
}
// create the vertices
ArrayList<Vertex3d> contourVtxs = new ArrayList<Vertex3d>();
HashMap<Vertex3d, Vertex3d> vertexMap = createCSGVertices(cinfo, contourVtxs);
for (Vertex3d vtx : vertexMap.values()) {
csgMesh.addVertex(vtx);
}
for (Vertex3d vtx : contourVtxs) {
csgMesh.addVertex(vtx);
}
if (printContours) {
for (IntersectionContour c : cinfo.myContours) {
System.out.println("contour " + getContourIndex(c));
for (IntersectionPoint p : c) {
System.out.println(toString(p));
}
}
}
// create the faces. Allocate vertex space for faces based on the
// approximation that there are two triangles per vertex
ArrayList<Vertex3d> triVtxs = new ArrayList<Vertex3d>(csgMesh.numVertices() * 6);
HashMap<Face, ArrayList<IntersectionContour>> faceContourMap = new HashMap<Face, ArrayList<IntersectionContour>>();
ArrayList<Vertex3dList> innerHoles = new ArrayList<Vertex3dList>();
ArrayList<Vertex3dList> outerHoles = new ArrayList<Vertex3dList>();
boolean clockwise0 = (regions0 == RegionType.OUTSIDE);
boolean clockwise1 = (regions1 == RegionType.INSIDE);
for (int meshNum = 0; meshNum < 2; meshNum++) {
triVtxs.clear();
boolean clockwise = (meshNum == 0 ? clockwise0 : clockwise1);
boolean flipFaces = ((meshNum == 1 && clockwise0 && clockwise1) || (meshNum == 0 && !clockwise0 && !clockwise1));
// "mesh "+meshNum+" numr="+cinfo.getPenetrationRegions(meshNum).size());
for (PenetrationRegion r : cinfo.getRegions(meshNum)) {
faceContourMap.clear();
for (IntersectionContour c : r.myContours) {
Face face = c.containingFace;
if (face != null) {
ArrayList<IntersectionContour> contours = faceContourMap.get(face);
if (contours == null) {
contours = new ArrayList<IntersectionContour>();
faceContourMap.put(face, contours);
}
contours.add(c);
}
}
for (Face face : r.myFaces) {
ArrayList<IntersectionContour> contours = faceContourMap.get(face);
if (contours != null) {
innerHoles.clear();
outerHoles.clear();
for (IntersectionContour c : contours) {
Vertex3dList hole = createPolyFromContour(c);
if (clockwise) {
hole.reverse();
}
if (c.singleFaceArea < 0) {
// connected to the face, and so is no longer a hole
if (!c.emptySegmentsMarked) {
innerHoles.add(hole);
}
} else {
if (!c.emptySegmentsMarked) {
outerHoles.add(hole);
}
}
}
triangulateFace(triVtxs, face, r, clockwise, outerHoles, innerHoles, vertexMap);
} else {
triangulateFace(triVtxs, face, r, clockwise, null, null, vertexMap);
}
}
}
for (int i = 0; i < triVtxs.size(); i += 3) {
if (flipFaces) {
csgMesh.addFace(triVtxs.get(i), triVtxs.get(i + 2), triVtxs.get(i + 1));
} else {
csgMesh.addFace(triVtxs.get(i), triVtxs.get(i + 1), triVtxs.get(i + 2));
}
}
}
return csgMesh;
}
Aggregations