Search in sources :

Example 11 with Edge

use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.

the class MikktspaceTangentGenerator method initTriInfo.

static void initTriInfo(TriInfo[] pTriInfos, final int[] piTriListIn, final MikkTSpaceContext mikkTSpace, final int iNrTrianglesIn) {
    // generate neighbor info list
    for (int f = 0; f < iNrTrianglesIn; f++) {
        for (int i = 0; i < 3; i++) {
            pTriInfos[f].faceNeighbors[i] = -1;
            pTriInfos[f].assignedGroup[i] = null;
            pTriInfos[f].os.x = 0.0f;
            pTriInfos[f].os.y = 0.0f;
            pTriInfos[f].os.z = 0.0f;
            pTriInfos[f].ot.x = 0.0f;
            pTriInfos[f].ot.y = 0.0f;
            pTriInfos[f].ot.z = 0.0f;
            pTriInfos[f].magS = 0;
            pTriInfos[f].magT = 0;
            // assumed bad
            pTriInfos[f].flag |= GROUP_WITH_ANY;
        }
    }
    // evaluate first order derivatives
    for (int f = 0; f < iNrTrianglesIn; f++) {
        // initial values
        final Vector3f v1 = getPosition(mikkTSpace, piTriListIn[f * 3 + 0]);
        final Vector3f v2 = getPosition(mikkTSpace, piTriListIn[f * 3 + 1]);
        final Vector3f v3 = getPosition(mikkTSpace, piTriListIn[f * 3 + 2]);
        final Vector3f t1 = getTexCoord(mikkTSpace, piTriListIn[f * 3 + 0]);
        final Vector3f t2 = getTexCoord(mikkTSpace, piTriListIn[f * 3 + 1]);
        final Vector3f t3 = getTexCoord(mikkTSpace, piTriListIn[f * 3 + 2]);
        final float t21x = t2.x - t1.x;
        final float t21y = t2.y - t1.y;
        final float t31x = t3.x - t1.x;
        final float t31y = t3.y - t1.y;
        final Vector3f d1 = v2.subtract(v1);
        final Vector3f d2 = v3.subtract(v1);
        final float fSignedAreaSTx2 = t21x * t31y - t21y * t31x;
        //assert(fSignedAreaSTx2!=0);
        // eq 18
        Vector3f vOs = d1.mult(t31y).subtract(d2.mult(t21y));
        // eq 19
        Vector3f vOt = d1.mult(-t31x).add(d2.mult(t21x));
        pTriInfos[f].flag |= (fSignedAreaSTx2 > 0 ? ORIENT_PRESERVING : 0);
        if (isNotZero(fSignedAreaSTx2)) {
            final float fAbsArea = Math.abs(fSignedAreaSTx2);
            final float fLenOs = vOs.length();
            final float fLenOt = vOt.length();
            final float fS = (pTriInfos[f].flag & ORIENT_PRESERVING) == 0 ? (-1.0f) : 1.0f;
            if (isNotZero(fLenOs)) {
                pTriInfos[f].os = vOs.multLocal(fS / fLenOs);
            }
            if (isNotZero(fLenOt)) {
                pTriInfos[f].ot = vOt.multLocal(fS / fLenOt);
            }
            // evaluate magnitudes prior to normalization of vOs and vOt
            pTriInfos[f].magS = fLenOs / fAbsArea;
            pTriInfos[f].magT = fLenOt / fAbsArea;
            // if this is a good triangle
            if (isNotZero(pTriInfos[f].magS) && isNotZero(pTriInfos[f].magT)) {
                pTriInfos[f].flag &= (~GROUP_WITH_ANY);
            }
        }
    }
    // force otherwise healthy quads to a fixed orientation
    int t = 0;
    while (t < (iNrTrianglesIn - 1)) {
        final int iFO_a = pTriInfos[t].orgFaceNumber;
        final int iFO_b = pTriInfos[t + 1].orgFaceNumber;
        if (iFO_a == iFO_b) {
            // this is a quad
            final boolean bIsDeg_a = (pTriInfos[t].flag & MARK_DEGENERATE) != 0;
            final boolean bIsDeg_b = (pTriInfos[t + 1].flag & MARK_DEGENERATE) != 0;
            // DegenPrologue(), but just in case check bIsDeg_a and bIsDeg_a are false
            if ((bIsDeg_a || bIsDeg_b) == false) {
                final boolean bOrientA = (pTriInfos[t].flag & ORIENT_PRESERVING) != 0;
                final boolean bOrientB = (pTriInfos[t + 1].flag & ORIENT_PRESERVING) != 0;
                // if this happens the quad has extremely bad mapping!!
                if (bOrientA != bOrientB) {
                    //printf("found quad with bad mapping\n");
                    boolean bChooseOrientFirstTri = false;
                    if ((pTriInfos[t + 1].flag & GROUP_WITH_ANY) != 0) {
                        bChooseOrientFirstTri = true;
                    } else if (calcTexArea(mikkTSpace, Arrays.copyOfRange(piTriListIn, t * 3 + 0, t * 3 + 3)) >= calcTexArea(mikkTSpace, Arrays.copyOfRange(piTriListIn, (t + 1) * 3 + 0, (t + 1) * 3 + 3))) {
                        bChooseOrientFirstTri = true;
                    }
                    // force match
                    {
                        final int t0 = bChooseOrientFirstTri ? t : (t + 1);
                        final int t1 = bChooseOrientFirstTri ? (t + 1) : t;
                        // clear first
                        pTriInfos[t1].flag &= (~ORIENT_PRESERVING);
                        // copy bit
                        pTriInfos[t1].flag |= (pTriInfos[t0].flag & ORIENT_PRESERVING);
                    }
                }
            }
            t += 2;
        } else {
            ++t;
        }
    }
    // match up edge pairs
    {
        //Edge * pEdges = (Edge *) malloc(sizeof(Edge)*iNrTrianglesIn*3);
        Edge[] pEdges = new Edge[iNrTrianglesIn * 3];
        //TODO nehon weird... original algorithm check if pEdges is null but it's just been allocated... weirder, it does soemthing different if the edges are null...
        //    if (pEdges==null)
        //      BuildNeighborsSlow(pTriInfos, piTriListIn, iNrTrianglesIn);
        //    else
        //    {
        buildNeighborsFast(pTriInfos, pEdges, piTriListIn, iNrTrianglesIn);
    //    }
    }
}
Also used : Vector3f(com.jme3.math.Vector3f)

Example 12 with Edge

use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.

the class MikktspaceTangentGenerator method evalTspace.

static TSpace evalTspace(int[] face_indices, final int iFaces, final int[] piTriListIn, final TriInfo[] pTriInfos, final MikkTSpaceContext mikkTSpace, final int iVertexRepresentitive) {
    TSpace res = new TSpace();
    float fAngleSum = 0;
    for (int face = 0; face < iFaces; face++) {
        final int f = face_indices[face];
        // only valid triangles get to add their contribution
        if ((pTriInfos[f].flag & GROUP_WITH_ANY) == 0) {
            int i = -1;
            if (piTriListIn[3 * f + 0] == iVertexRepresentitive) {
                i = 0;
            } else if (piTriListIn[3 * f + 1] == iVertexRepresentitive) {
                i = 1;
            } else if (piTriListIn[3 * f + 2] == iVertexRepresentitive) {
                i = 2;
            }
            assert (i >= 0 && i < 3);
            // project
            int index = piTriListIn[3 * f + i];
            Vector3f n = getNormal(mikkTSpace, index);
            Vector3f vOs = pTriInfos[f].os.subtract(n.mult(n.dot(pTriInfos[f].os)));
            Vector3f vOt = pTriInfos[f].ot.subtract(n.mult(n.dot(pTriInfos[f].ot)));
            vOs.normalizeLocal();
            vOt.normalizeLocal();
            int i2 = piTriListIn[3 * f + (i < 2 ? (i + 1) : 0)];
            int i1 = piTriListIn[3 * f + i];
            int i0 = piTriListIn[3 * f + (i > 0 ? (i - 1) : 2)];
            Vector3f p0 = getPosition(mikkTSpace, i0);
            Vector3f p1 = getPosition(mikkTSpace, i1);
            Vector3f p2 = getPosition(mikkTSpace, i2);
            Vector3f v1 = p0.subtract(p1);
            Vector3f v2 = p2.subtract(p1);
            // project
            v1.subtractLocal(n.mult(n.dot(v1))).normalizeLocal();
            v2.subtractLocal(n.mult(n.dot(v2))).normalizeLocal();
            // weight contribution by the angle
            // between the two edge vectors
            float fCos = v1.dot(v2);
            fCos = fCos > 1 ? 1 : (fCos < (-1) ? (-1) : fCos);
            float fAngle = (float) Math.acos(fCos);
            float fMagS = pTriInfos[f].magS;
            float fMagT = pTriInfos[f].magT;
            res.os.addLocal(vOs.multLocal(fAngle));
            res.ot.addLocal(vOt.multLocal(fAngle));
            res.magS += (fAngle * fMagS);
            res.magT += (fAngle * fMagT);
            fAngleSum += fAngle;
        }
    }
    // normalize
    res.os.normalizeLocal();
    res.ot.normalizeLocal();
    if (fAngleSum > 0) {
        res.magS /= fAngleSum;
        res.magT /= fAngleSum;
    }
    return res;
}
Also used : Vector3f(com.jme3.math.Vector3f)

Example 13 with Edge

use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.

the class CurvesTemporalMesh method applyBevelAndTaper.

/**
     * This method applies bevel and taper objects to the curve.
     * @param curve
     *            the curve we apply the objects to
     * @param bevelObject
     *            the bevel object
     * @param taperObject
     *            the taper object
     * @param blenderContext
     *            the blender context
     * @return a list of geometries representing the beveled and/or tapered curve
     * @throws BlenderFileException
     *             an exception is thrown when problems with reading occur
     */
private CurvesTemporalMesh applyBevelAndTaper(CurvesTemporalMesh curve, CurvesTemporalMesh bevelObject, CurvesTemporalMesh taperObject, BlenderContext blenderContext) throws BlenderFileException {
    List<BezierLine> bevelBezierLines = bevelObject.getScaledBeziers();
    List<BezierLine> curveLines = curve.beziers;
    if (bevelBezierLines.size() == 0 || curveLines.size() == 0) {
        return null;
    }
    CurvesTemporalMesh result = new CurvesTemporalMesh(blenderContext);
    for (BezierLine curveLine : curveLines) {
        Vector3f[] curveLineVertices = curveLine.getVertices(bevelStart, bevelEnd);
        for (BezierLine bevelBezierLine : bevelBezierLines) {
            CurvesTemporalMesh partResult = new CurvesTemporalMesh(blenderContext);
            Vector3f[] bevelLineVertices = bevelBezierLine.getVertices();
            List<Vector3f[]> bevels = new ArrayList<Vector3f[]>();
            Vector3f[] bevelPoints = curvesHelper.transformToFirstLineOfBevelPoints(bevelLineVertices, curveLineVertices[0], curveLineVertices[1]);
            bevels.add(bevelPoints);
            for (int i = 1; i < curveLineVertices.length - 1; ++i) {
                bevelPoints = curvesHelper.transformBevel(bevelPoints, curveLineVertices[i - 1], curveLineVertices[i], curveLineVertices[i + 1]);
                bevels.add(bevelPoints);
            }
            bevelPoints = curvesHelper.transformBevel(bevelPoints, curveLineVertices[curveLineVertices.length - 2], curveLineVertices[curveLineVertices.length - 1], null);
            bevels.add(bevelPoints);
            Vector3f subtractResult = new Vector3f();
            if (bevels.size() > 2) {
                // changing the first and last bevel so that they are parallel to their neighbours (blender works this way)
                // notice this implicates that the distances of every corresponding point in the two bevels must be identical and
                // equal to the distance between the points on curve that define the bevel position
                // so instead doing complicated rotations on each point we will simply properly translate each of them
                int[][] pointIndexes = new int[][] { { 0, 1 }, { curveLineVertices.length - 1, curveLineVertices.length - 2 } };
                for (int[] indexes : pointIndexes) {
                    float distance = curveLineVertices[indexes[1]].subtract(curveLineVertices[indexes[0]], subtractResult).length();
                    Vector3f[] bevel = bevels.get(indexes[0]);
                    Vector3f[] nextBevel = bevels.get(indexes[1]);
                    for (int i = 0; i < bevel.length; ++i) {
                        float d = bevel[i].subtract(nextBevel[i], subtractResult).length();
                        subtractResult.normalizeLocal().multLocal(distance - d);
                        bevel[i].addLocal(subtractResult);
                    }
                }
            }
            if (taperObject != null) {
                float curveLength = curveLine.getLength(), lengthAlongCurve = bevelStart;
                for (int i = 0; i < curveLineVertices.length; ++i) {
                    if (i > 0) {
                        lengthAlongCurve += curveLineVertices[i].subtract(curveLineVertices[i - 1], subtractResult).length();
                    }
                    float taperScale = -taperObject.getValueAlongCurve(lengthAlongCurve / curveLength).z * taperObject.scale.z;
                    if (taperScale != 1) {
                        this.applyScale(bevels.get(i), curveLineVertices[i], taperScale);
                    }
                }
            }
            // adding vertices to the part result
            for (Vector3f[] bevel : bevels) {
                for (Vector3f d : bevel) {
                    partResult.getVertices().add(d);
                }
            }
            // preparing faces for the part result (each face is a quad)
            int bevelVertCount = bevelPoints.length;
            for (int i = 0; i < bevels.size() - 1; ++i) {
                for (int j = 0; j < bevelVertCount - 1; ++j) {
                    Integer[] indexes = new Integer[] { i * bevelVertCount + j + 1, (i + 1) * bevelVertCount + j + 1, (i + 1) * bevelVertCount + j, i * bevelVertCount + j };
                    partResult.getFaces().add(new Face(indexes, curveLine.isSmooth(), curveLine.getMaterialNumber(), null, null, partResult));
                    partResult.getEdges().add(new Edge(indexes[0], indexes[1], 0, true, partResult));
                    partResult.getEdges().add(new Edge(indexes[1], indexes[2], 0, true, partResult));
                    partResult.getEdges().add(new Edge(indexes[2], indexes[3], 0, true, partResult));
                    partResult.getEdges().add(new Edge(indexes[3], indexes[0], 0, true, partResult));
                }
                if (bevelBezierLine.isCyclic()) {
                    int j = bevelVertCount - 1;
                    Integer[] indexes = new Integer[] { i * bevelVertCount, (i + 1) * bevelVertCount, (i + 1) * bevelVertCount + j, i * bevelVertCount + j };
                    partResult.getFaces().add(new Face(indexes, curveLine.isSmooth(), curveLine.getMaterialNumber(), null, null, partResult));
                    partResult.getEdges().add(new Edge(indexes[0], indexes[1], 0, true, partResult));
                    partResult.getEdges().add(new Edge(indexes[1], indexes[2], 0, true, partResult));
                    partResult.getEdges().add(new Edge(indexes[2], indexes[3], 0, true, partResult));
                    partResult.getEdges().add(new Edge(indexes[3], indexes[0], 0, true, partResult));
                }
            }
            partResult.generateNormals();
            if (fillCaps) {
                // caps in blender behave as if they weren't affected by the smooth factor
                // START CAP
                Vector3f[] cap = bevels.get(0);
                List<Integer> capIndexes = new ArrayList<Integer>(cap.length);
                Vector3f capNormal = curveLineVertices[0].subtract(curveLineVertices[1]).normalizeLocal();
                for (int i = 0; i < cap.length; ++i) {
                    capIndexes.add(partResult.getVertices().size());
                    partResult.getVertices().add(cap[i]);
                    partResult.getNormals().add(capNormal);
                }
                // the indexes ned to be reversed for the face to have fron face outside the beveled line
                Collections.reverse(capIndexes);
                partResult.getFaces().add(new Face(capIndexes.toArray(new Integer[capIndexes.size()]), false, curveLine.getMaterialNumber(), null, null, partResult));
                for (int i = 1; i < capIndexes.size(); ++i) {
                    partResult.getEdges().add(new Edge(capIndexes.get(i - 1), capIndexes.get(i), 0, true, partResult));
                }
                // END CAP
                cap = bevels.get(bevels.size() - 1);
                capIndexes.clear();
                capNormal = curveLineVertices[curveLineVertices.length - 1].subtract(curveLineVertices[curveLineVertices.length - 2]).normalizeLocal();
                for (int i = 0; i < cap.length; ++i) {
                    capIndexes.add(partResult.getVertices().size());
                    partResult.getVertices().add(cap[i]);
                    partResult.getNormals().add(capNormal);
                }
                partResult.getFaces().add(new Face(capIndexes.toArray(new Integer[capIndexes.size()]), false, curveLine.getMaterialNumber(), null, null, partResult));
                for (int i = 1; i < capIndexes.size(); ++i) {
                    partResult.getEdges().add(new Edge(capIndexes.get(i - 1), capIndexes.get(i), 0, true, partResult));
                }
            }
            result.append(partResult);
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) Vector3f(com.jme3.math.Vector3f) Face(com.jme3.scene.plugins.blender.meshes.Face) Edge(com.jme3.scene.plugins.blender.meshes.Edge)

Example 14 with Edge

use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.

the class Point method loadAll.

/**
     * Loads all points of the mesh that do not belong to any edge.
     * @param meshStructure
     *            the mesh structure
     * @return a list of points
     * @throws BlenderFileException
     *             an exception is thrown when problems with file reading occur
     */
public static List<Point> loadAll(Structure meshStructure) throws BlenderFileException {
    LOGGER.log(Level.FINE, "Loading all points that do not belong to any edge from mesh: {0}", meshStructure.getName());
    List<Point> result = new ArrayList<Point>();
    Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge");
    if (pMEdge.isNotNull()) {
        int count = ((Number) meshStructure.getFieldValue("totvert")).intValue();
        Set<Integer> unusedVertices = new HashSet<Integer>(count);
        for (int i = 0; i < count; ++i) {
            unusedVertices.add(i);
        }
        List<Structure> edges = pMEdge.fetchData();
        for (Structure edge : edges) {
            unusedVertices.remove(((Number) edge.getFieldValue("v1")).intValue());
            unusedVertices.remove(((Number) edge.getFieldValue("v2")).intValue());
        }
        for (Integer unusedIndex : unusedVertices) {
            result.add(new Point(unusedIndex));
        }
    }
    LOGGER.log(Level.FINE, "Loaded {0} points.", result.size());
    return result;
}
Also used : ArrayList(java.util.ArrayList) Pointer(com.jme3.scene.plugins.blender.file.Pointer) Structure(com.jme3.scene.plugins.blender.file.Structure) HashSet(java.util.HashSet)

Example 15 with Edge

use of com.jme3.scene.plugins.blender.meshes.Edge in project jmonkeyengine by jMonkeyEngine.

the class TemporalMesh method prepareLinesGeometry.

/**
     * The method creates geometries from lines.
     * @param result
     *            the list where new geometries will be appended
     * @param meshHelper
     *            the mesh helper
     */
protected void prepareLinesGeometry(List<Geometry> result, MeshHelper meshHelper) {
    if (edges.size() > 0) {
        LOGGER.fine("Preparing lines geometries.");
        List<List<Integer>> separateEdges = new ArrayList<List<Integer>>();
        List<Edge> edges = new ArrayList<Edge>(this.edges.size());
        for (Edge edge : this.edges) {
            if (!edge.isInFace()) {
                edges.add(edge);
            }
        }
        while (edges.size() > 0) {
            boolean edgeAppended = false;
            int edgeIndex = 0;
            for (List<Integer> list : separateEdges) {
                for (edgeIndex = 0; edgeIndex < edges.size() && !edgeAppended; ++edgeIndex) {
                    Edge edge = edges.get(edgeIndex);
                    if (list.get(0).equals(edge.getFirstIndex())) {
                        list.add(0, edge.getSecondIndex());
                        --edgeIndex;
                        edgeAppended = true;
                    } else if (list.get(0).equals(edge.getSecondIndex())) {
                        list.add(0, edge.getFirstIndex());
                        --edgeIndex;
                        edgeAppended = true;
                    } else if (list.get(list.size() - 1).equals(edge.getFirstIndex())) {
                        list.add(edge.getSecondIndex());
                        --edgeIndex;
                        edgeAppended = true;
                    } else if (list.get(list.size() - 1).equals(edge.getSecondIndex())) {
                        list.add(edge.getFirstIndex());
                        --edgeIndex;
                        edgeAppended = true;
                    }
                }
                if (edgeAppended) {
                    break;
                }
            }
            Edge edge = edges.remove(edgeAppended ? edgeIndex : 0);
            if (!edgeAppended) {
                separateEdges.add(new ArrayList<Integer>(Arrays.asList(edge.getFirstIndex(), edge.getSecondIndex())));
            }
        }
        for (List<Integer> list : separateEdges) {
            MeshBuffers meshBuffers = new MeshBuffers(0);
            for (int index : list) {
                meshBuffers.append(vertices.get(index), normals.get(index));
            }
            Mesh mesh = new Mesh();
            mesh.setLineWidth(blenderContext.getBlenderKey().getLinesWidth());
            mesh.setMode(Mode.LineStrip);
            if (meshBuffers.isShortIndexBuffer()) {
                mesh.setBuffer(Type.Index, 1, (ShortBuffer) meshBuffers.getIndexBuffer());
            } else {
                mesh.setBuffer(Type.Index, 1, (IntBuffer) meshBuffers.getIndexBuffer());
            }
            mesh.setBuffer(meshBuffers.getPositionsBuffer());
            mesh.setBuffer(meshBuffers.getNormalsBuffer());
            Geometry geometry = new Geometry(meshStructure.getName() + (result.size() + 1), mesh);
            geometry.setMaterial(meshHelper.getBlackUnshadedMaterial(blenderContext));
            if (properties != null && properties.getValue() != null) {
                meshHelper.applyProperties(geometry, properties);
            }
            result.add(geometry);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) Mesh(com.jme3.scene.Mesh) Geometry(com.jme3.scene.Geometry) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Vector3f (com.jme3.math.Vector3f)17 ArrayList (java.util.ArrayList)7 Edge (com.jme3.scene.plugins.blender.meshes.Edge)5 Face (com.jme3.scene.plugins.blender.meshes.Face)5 Test (org.junit.Test)5 BoundingBox (com.jme3.bounding.BoundingBox)3 BoundingSphere (com.jme3.bounding.BoundingSphere)3 Structure (com.jme3.scene.plugins.blender.file.Structure)3 TempVars (com.jme3.util.TempVars)3 Node (com.jme3.scene.Node)2 BlenderFileException (com.jme3.scene.plugins.blender.file.BlenderFileException)2 Pointer (com.jme3.scene.plugins.blender.file.Pointer)2 HashSet (java.util.HashSet)2 LinkedHashSet (java.util.LinkedHashSet)2 List (java.util.List)2 CollisionResult (com.jme3.collision.CollisionResult)1 DirectionalLight (com.jme3.light.DirectionalLight)1 PointLight (com.jme3.light.PointLight)1 SpotLight (com.jme3.light.SpotLight)1 Plane (com.jme3.math.Plane)1