Search in sources :

Example 61 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method updateSubdivisionMesh.

/**
 * Updates a subdivision mesh.
 *
 * @param mesh
 * Must be a mesh generated by calling getSubdivisionMesh on this mesh.
 */
public void updateSubdivisionMesh(PolygonalMesh mesh) {
    if (mesh != null) {
        TrianglePatch patch = null;
        Face lastFace = null;
        Vector3d[] normals = new Vector3d[myVertices.size()];
        for (int v = 0; v < normals.length; v++) {
            ((Vertex3d) myVertices.get(v)).computeNormal(normals[v] = new Vector3d());
        }
        for (Object vertexobject : mesh.myVertices) {
            SubdivisionVertex3d vertex = (SubdivisionVertex3d) vertexobject;
            double w = 1.0 - vertex.u - vertex.v;
            HalfEdge he = vertex.f.he0;
            Vertex3d v0 = he.head;
            he = he.next;
            Vertex3d v1 = he.head;
            Vertex3d v2 = he.next.head;
            Vector3d n0 = normals[v0.idx], n1 = normals[v1.idx], n2 = normals[v2.idx];
            if (vertex.f != lastFace)
                patch = new TrianglePatch(v0.pnt, n0, v1.pnt, n1, v2.pnt, n2);
            lastFace = vertex.f;
            vertex.normal.scale(vertex.u, n0);
            vertex.normal.scaledAdd(vertex.v, n1, vertex.normal);
            vertex.normal.scaledAdd(w, n2, vertex.normal);
            vertex.normal.normalize();
            vertex.pnt.scale(vertex.u, v0.pnt);
            vertex.pnt.scaledAdd(vertex.v, v1.pnt, vertex.pnt);
            vertex.pnt.scaledAdd(w, v2.pnt, vertex.pnt);
            patch.interpolate(vertex.pnt, vertex.u, vertex.v, w);
        }
    }
}
Also used : Vector3d(maspack.matrix.Vector3d)

Example 62 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method checkForDegenerateFaces.

public void checkForDegenerateFaces() {
    for (Face face : getFaces()) {
        Vector3d nrm = face.getNormal();
        if (nrm.containsNaN()) {
            System.out.println("face " + face.getIndex() + " badly formed");
            for (int i = 0; i < 3; i++) {
                Vertex3d v = face.getVertex(i);
                System.out.println(" " + v + " " + v.pnt + " " + v.numIncidentHalfEdges());
            }
        }
    }
}
Also used : Vector3d(maspack.matrix.Vector3d)

Example 63 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method computeVolumeIntegrals.

/**
 * Computes the volume integrals of this mesh, on the assumption that it is
 * manifold and closed. The code for this was taken from vclip, by Brian
 * Mirtich. See "Fast and Accurate Computation of Polyhedral Mass
 * Properties," Brian Mirtich, journal of graphics tools, volume 1, number 2,
 * 1996.
 *
 * @param mov1
 * if non-null, returns the first moment of volume
 * @param mov2
 * if non-null, returns the second moment of volume
 * @param pov
 * if non-null, returns the product of volume
 * @return closed volume of the mesh
 */
public double computeVolumeIntegrals(Vector3d mov1, Vector3d mov2, Vector3d pov) {
    int a, b, c;
    // Edge e;
    // Face f;
    double a0, a1, da;
    // al
    double b0, b1, db;
    double a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
    double a1_2, a1_3, b1_2, b1_3;
    double d, na, nb, nc, inv;
    double I, Ia, Ib, Iaa, Iab, Ibb, Iaaa, Iaab, Iabb, Ibbb;
    double Icc, Iccc, Ibbc, Icca;
    double C0, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
    double Cab, Kab, Caab, Kaab, Cabb, Kabb;
    // h, w;
    Vector3d v;
    if (mov1 != null) {
        mov1.setZero();
    }
    if (mov2 != null) {
        mov2.setZero();
    }
    if (pov != null) {
        pov.setZero();
    }
    // double rad_ = 0;
    double vol_ = 0.0;
    for (int i = 0; i < myFaces.size(); i++) {
        Face f = myFaces.get(i);
        // compute projection direction
        Vector3d nrml = f.getNormal();
        if (nrml.containsNaN()) {
            // sanity check for badly formed meshes
            continue;
        }
        v = new Vector3d();
        v.set(Math.abs(nrml.x), Math.abs(nrml.y), Math.abs(nrml.z));
        c = (v.x >= v.y) ? ((v.x >= v.z) ? 0 : 2) : ((v.y >= v.z) ? 1 : 2);
        a = (c + 1) % 3;
        b = (c + 2) % 3;
        I = Ia = Ib = Iaa = Iab = Ibb = Iaaa = Iaab = Iabb = Ibbb = 0.0;
        // walk around face
        HalfEdge he0 = f.firstHalfEdge();
        HalfEdge he = he0;
        do {
            a0 = he.getTail().pnt.get(a);
            b0 = he.getTail().pnt.get(b);
            a1 = he.getHead().pnt.get(a);
            b1 = he.getHead().pnt.get(b);
            da = a1 - a0;
            db = b1 - b0;
            a0_2 = a0 * a0;
            a0_3 = a0_2 * a0;
            a0_4 = a0_3 * a0;
            b0_2 = b0 * b0;
            b0_3 = b0_2 * b0;
            b0_4 = b0_3 * b0;
            a1_2 = a1 * a1;
            a1_3 = a1_2 * a1;
            b1_2 = b1 * b1;
            b1_3 = b1_2 * b1;
            C0 = a1 + a0;
            Ca = a1 * C0 + a0_2;
            Caa = a1 * Ca + a0_3;
            Caaa = a1 * Caa + a0_4;
            Cb = b1 * (b1 + b0) + b0_2;
            Cbb = b1 * Cb + b0_3;
            Cbbb = b1 * Cbb + b0_4;
            Cab = 3 * a1_2 + 2 * a1 * a0 + a0_2;
            Kab = a1_2 + 2 * a1 * a0 + 3 * a0_2;
            Caab = a0 * Cab + 4 * a1_3;
            Kaab = a1 * Kab + 4 * a0_3;
            Cabb = 4 * b1_3 + 3 * b1_2 * b0 + 2 * b1 * b0_2 + b0_3;
            Kabb = b1_3 + 2 * b1_2 * b0 + 3 * b1 * b0_2 + 4 * b0_3;
            I += db * C0;
            Ia += db * Ca;
            Iaa += db * Caa;
            Iaaa += db * Caaa;
            Ib += da * Cb;
            Ibb += da * Cbb;
            Ibbb += da * Cbbb;
            Iab += db * (b1 * Cab + b0 * Kab);
            Iaab += db * (b1 * Caab + b0 * Kaab);
            Iabb += da * (a1 * Cabb + a0 * Kabb);
            he = he.getNext();
        } while (he != he0);
        I /= 2.0;
        Ia /= 6.0;
        Iaa /= 12.0;
        Iaaa /= 20.0;
        Ib /= -6.0;
        Ibb /= -12.0;
        Ibbb /= -20.0;
        Iab /= 24.0;
        Iaab /= 60.0;
        Iabb /= -60.0;
        d = -nrml.dot(f.firstHalfEdge().getHead().pnt);
        na = nrml.get(a);
        nb = nrml.get(b);
        nc = nrml.get(c);
        inv = 1.0 / nc;
        if (a == 0) {
            vol_ += inv * na * Ia;
        } else if (b == 0) {
            vol_ += inv * nb * Ib;
        } else {
            vol_ -= ((d * I + na * Ia + nb * Ib) / nc);
        }
        if (vol_ != vol_) {
            throw new NumericalException("nrml=" + nrml + ", face " + i);
        }
        Icc = (SQR(na) * Iaa + 2 * na * nb * Iab + SQR(nb) * Ibb + d * (2 * (na * Ia + nb * Ib) + d * I)) * SQR(inv);
        if (mov1 != null) {
            mov1.set(a, mov1.get(a) + inv * na * Iaa);
            mov1.set(b, mov1.get(b) + inv * nb * Ibb);
            mov1.set(c, mov1.get(c) + Icc);
        }
        Iccc = -(CUBE(na) * Iaaa + 3 * SQR(na) * nb * Iaab + 3 * na * SQR(nb) * Iabb + CUBE(nb) * Ibbb + 3 * (SQR(na) * Iaa + 2 * na * nb * Iab + SQR(nb) * Ibb) * d + d * d * (3 * (na * Ia + nb * Ib) + d * I)) * CUBE(inv);
        if (mov2 != null) {
            mov2.set(a, mov2.get(a) + inv * na * Iaaa);
            mov2.set(b, mov2.get(b) + inv * nb * Ibbb);
            mov2.set(c, mov2.get(c) + Iccc);
        }
        Ibbc = -(d * Ibb + na * Iabb + nb * Ibbb) * inv;
        Icca = (SQR(na) * Iaaa + 2 * na * nb * Iaab + SQR(nb) * Iabb + d * (2 * (na * Iaa + nb * Iab) + d * Ia)) * SQR(inv);
        if (pov != null) {
            pov.set(c, pov.get(c) + inv * na * Iaab);
            pov.set(a, pov.get(a) + inv * nb * Ibbc);
            pov.set(b, pov.get(b) + Icca);
        }
    }
    if (mov1 != null) {
        mov1.scale(0.5);
    }
    if (mov2 != null) {
        mov2.scale(1.0 / 3.0);
    }
    if (pov != null) {
        pov.scale(0.5);
    }
    return vol_;
}
Also used : Vector3d(maspack.matrix.Vector3d) NumericalException(maspack.matrix.NumericalException)

Example 64 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMesh method computeVertexNormals.

/**
 * Computes a set of vertex normals for this mesh, using an
 * angle-weighted average of the normals formed by the edges incident on
 * each vertex. If the angle-weighted average would result in a zero normal
 * (e.g. vertices on a straight line), then the adjacent face normals
 * are used.  If <code>multiNormals</code> is <code>true</code>, then
 * multiple normals may be computed for each vertex, with different normals
 * being computed for edge regions that are separated by open or hard
 * edges. Otherwise, only one normal is computed per vertex.
 *
 * <p>If <code>normals</code> is passed in with zero size, then the normals
 * are computed and returned in new <code>Vector3d</code> objects that are
 * and added to it. Also, the method returns a set of computed normal
 * indices. This option is used for the initial creation of normals.
 *
 * <p>If <code>normals</code> is passed in with non-zero size, then it is
 * assumed to contain enough <code>Vector3d</code> objects to store all the
 * computed normals, and the method returns <code>null</code>.  This option
 * is used for updating normals.
 *
 * @param normals returns the computed normals
 * @param multiNormals if <code>true</code>, then multiple normals
 * may be computed for each vertex
 * @return normals indices, if <code>normals</code> has zero size,
 * otherwise <code>null</code>.
 */
public int[] computeVertexNormals(ArrayList<Vector3d> normals, boolean multiNormals) {
    boolean creatingNormals = (normals.size() == 0);
    if (multiNormals) {
        // make sure hard edges are properly set
        updateHardEdgeCount();
    }
    HashMap<HalfEdge, Integer> normalIndexMap = null;
    if (creatingNormals) {
        // Each half edge will be associated with a normal for its head vertex.
        normalIndexMap = new HashMap<HalfEdge, Integer>();
    }
    // Start by allocating normals and determining the normal index
    // associated with each half-face
    int idx = 0;
    for (Vertex3d vtx : myVertices) {
        HalfEdgeNode node = vtx.getIncidentHedges();
        Vector3d nrm;
        while (node != null) {
            if (creatingNormals) {
                // create a new vector to store the normal
                nrm = new Vector3d();
                normals.add(nrm);
            } else {
                // use the existing normal vector
                nrm = normals.get(idx);
                nrm.setZero();
            }
            // reach a normal boundary.
            do {
                HalfEdge he = node.he;
                nrm.angleWeightedCrossAdd(he.tail.pnt, he.head.pnt, he.next.head.pnt);
                if (creatingNormals) {
                    normalIndexMap.put(node.he, idx);
                }
                node = node.next;
            } while (node != null && (!multiNormals || !vtx.isNormalBoundary(node.he)));
            double n2 = nrm.normSquared();
            if (n2 == 0) {
                // backup, just in case angle weighted normals fails
                vtx.computeAreaWeightedNormal(nrm);
            // nmag = nrm.norm();
            }
            nrm.normalize();
            // if (nmag > 0) {
            // nrm.scale(1.0/nmag);
            // }
            idx++;
        }
    }
    if (creatingNormals) {
        // Now assign the normal indices for each face. These are the indices of
        // the normals associated with each of the face's half edges.
        int[] indexOffs = getFeatureIndexOffsets();
        int[] indices = new int[indexOffs[indexOffs.length - 1]];
        int k = 0;
        for (Face face : myFaces) {
            HalfEdge he0 = face.firstHalfEdge();
            HalfEdge he = he0;
            do {
                Integer id = normalIndexMap.get(he);
                if (id == null) {
                    throw new InternalErrorException("Normal not computed for halfEge on face " + face.getIndex());
                }
                indices[k++] = id;
                he = he.getNext();
            } while (he != he0);
        }
        return indices;
    } else {
        return null;
    }
}
Also used : Vector3d(maspack.matrix.Vector3d) InternalErrorException(maspack.util.InternalErrorException)

Example 65 with Vector3d

use of maspack.matrix.Vector3d in project artisynth_core by artisynth.

the class PolygonalMeshRenderer method addFaceNormals.

protected void addFaceNormals(RenderObject r, PolygonalMesh mesh) {
    boolean useRenderData = mesh.isRenderBuffered() && !mesh.isFixed();
    updateFaceNormals(mesh);
    ArrayList<Face> faces = mesh.getFaces();
    for (int i = 0; i < faces.size(); i++) {
        Vector3d nrm;
        if (useRenderData) {
            nrm = faces.get(i).getRenderNormal();
        } else {
            nrm = faces.get(i).getNormal();
        }
        r.addNormal((float) nrm.x, (float) nrm.y, (float) nrm.z);
    }
}
Also used : Vector3d(maspack.matrix.Vector3d)

Aggregations

Vector3d (maspack.matrix.Vector3d)441 Point3d (maspack.matrix.Point3d)128 RigidTransform3d (maspack.matrix.RigidTransform3d)56 ArrayList (java.util.ArrayList)38 Matrix3d (maspack.matrix.Matrix3d)32 RotationMatrix3d (maspack.matrix.RotationMatrix3d)30 SymmetricMatrix3d (maspack.matrix.SymmetricMatrix3d)24 PolygonalMesh (maspack.geometry.PolygonalMesh)23 Vertex3d (maspack.geometry.Vertex3d)23 Face (maspack.geometry.Face)20 AxisAngle (maspack.matrix.AxisAngle)19 Vector3i (maspack.matrix.Vector3i)19 Point (artisynth.core.mechmodels.Point)18 RenderProps (maspack.render.RenderProps)17 VectorNd (maspack.matrix.VectorNd)15 AffineTransform3d (maspack.matrix.AffineTransform3d)14 IOException (java.io.IOException)13 Vector2d (maspack.matrix.Vector2d)11 Plane (maspack.matrix.Plane)10 GLViewer (maspack.render.GL.GLViewer)9