Search in sources :

Example 21 with IntersectionPoint

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);
    }
}
Also used : IntersectionContour(maspack.collision.IntersectionContour) IntersectionPoint(maspack.collision.IntersectionPoint)

Example 22 with IntersectionPoint

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();
                        }
                    }
                }
            }
        }
    }
}
Also used : BVNode(maspack.geometry.BVNode) Boundable(maspack.geometry.Boundable) Face(maspack.geometry.Face) IntersectionPoint(maspack.collision.IntersectionPoint)

Example 23 with IntersectionPoint

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;
    }
}
Also used : Vertex3d(maspack.geometry.Vertex3d) HalfEdge(maspack.geometry.HalfEdge) IntersectionPoint(maspack.collision.IntersectionPoint)

Example 24 with IntersectionPoint

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());
    }
}
Also used : IntersectionPoint(maspack.collision.IntersectionPoint) IntersectionPoint(maspack.collision.IntersectionPoint)

Example 25 with IntersectionPoint

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;
}
Also used : IntersectionPoint(maspack.collision.IntersectionPoint) IntersectionPoint(maspack.collision.IntersectionPoint)

Aggregations

IntersectionPoint (maspack.collision.IntersectionPoint)40 IntersectionContour (maspack.collision.IntersectionContour)3 HalfEdge (maspack.geometry.HalfEdge)3 ContactInfo (maspack.collision.ContactInfo)2 PenetratingPoint (maspack.collision.PenetratingPoint)2 BVNode (maspack.geometry.BVNode)2 Face (maspack.geometry.Face)2 Point3d (maspack.matrix.Point3d)2 Group (artisynth.core.mechmodels.Collidable.Group)1 Method (artisynth.core.mechmodels.CollisionBehavior.Method)1 ArrayList (java.util.ArrayList)1 ContactPlane (maspack.collision.ContactPlane)1 EdgeEdgeContact (maspack.collision.EdgeEdgeContact)1 PenetrationRegion (maspack.collision.PenetrationRegion)1 BVTree (maspack.geometry.BVTree)1 Boundable (maspack.geometry.Boundable)1 TriTriIntersection (maspack.geometry.TriTriIntersection)1 Vertex3d (maspack.geometry.Vertex3d)1 RenderObject (maspack.render.RenderObject)1 BooleanHolder (maspack.util.BooleanHolder)1