Search in sources :

Example 26 with Triangle

use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.

the class UVProjectionGenerator method sphereProjection.

/**
     * Sphere projection for 2D textures.
     * 
     * @param positions
     *            points to be projected
     * @param bb
     *            the bounding box for projecting
     * @return UV coordinates after the projection
     */
public static float[] sphereProjection(float[] positions, BoundingSphere bs) {
    // TODO: rotate it to be vertical
    float[] uvCoordinates = new float[positions.length / 3 * 2];
    Vector3f v = new Vector3f();
    float cx = bs.getCenter().x, cy = bs.getCenter().y, cz = bs.getCenter().z;
    Vector3f uBase = new Vector3f(0, -1, 0);
    Vector3f vBase = new Vector3f(0, 0, -1);
    for (int i = 0, j = 0; i < positions.length; i += 3, j += 2) {
        // calculating U
        v.set(positions[i] - cx, positions[i + 1] - cy, 0);
        v.normalizeLocal();
        // result between [0; PI]
        float angle = v.angleBetween(uBase);
        if (v.x < 0) {
            // the angle should be greater than PI, we're on the other part of the image then
            angle = FastMath.TWO_PI - angle;
        }
        uvCoordinates[j] = angle / FastMath.TWO_PI;
        // calculating V
        v.set(positions[i] - cx, positions[i + 1] - cy, positions[i + 2] - cz);
        v.normalizeLocal();
        // result between [0; PI]
        angle = v.angleBetween(vBase);
        uvCoordinates[j + 1] = angle / FastMath.PI;
    }
    // looking for splitted triangles
    Triangle triangle = new Triangle();
    for (int i = 0; i < positions.length; i += 9) {
        triangle.set(0, positions[i], positions[i + 1], positions[i + 2]);
        triangle.set(1, positions[i + 3], positions[i + 4], positions[i + 5]);
        triangle.set(2, positions[i + 6], positions[i + 7], positions[i + 8]);
        float sgn1 = Math.signum(triangle.get1().x - cx);
        float sgn2 = Math.signum(triangle.get2().x - cx);
        float sgn3 = Math.signum(triangle.get3().x - cx);
        float xSideFactor = sgn1 + sgn2 + sgn3;
        float ySideFactor = Math.signum(triangle.get1().y - cy) + Math.signum(triangle.get2().y - cy) + Math.signum(triangle.get3().y - cy);
        if ((xSideFactor > -3 || xSideFactor < 3) && ySideFactor < 0) {
            // the triangle is on the splitting plane
            if (sgn1 == 1.0f) {
                uvCoordinates[i / 3 * 2] += 1.0f;
            }
            if (sgn2 == 1.0f) {
                uvCoordinates[(i / 3 + 1) * 2] += 1.0f;
            }
            if (sgn3 == 1.0f) {
                uvCoordinates[(i / 3 + 2) * 2] += 1.0f;
            }
        }
    }
    return uvCoordinates;
}
Also used : Vector3f(com.jme3.math.Vector3f) Triangle(com.jme3.math.Triangle)

Example 27 with Triangle

use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.

the class BIHTree method createNode.

//    private BIHNode createNode2(int l, int r, BoundingBox nodeBbox, int depth){
//        if ((r - l) < maxTrisPerNode || depth > 100)
//            return createLeaf(l, r);
//
//        BoundingBox currentBox = createBox(l, r);
//        int axis = depth % 3;
//        float split = currentBox.getCenter().get(axis);
//
//        TriangleAxisComparator comparator = comparators[axis];
//        Arrays.sort(tris, l, r, comparator);
//        int splitIndex = -1;
//
//        float leftPlane, rightPlane = Float.POSITIVE_INFINITY;
//        leftPlane = tris[l].getExtreme(axis, false);
//        for (int i = l; i <= r; i++){
//            BIHTriangle tri = tris[i];
//            if (splitIndex == -1){
//                float v = tri.getCenter().get(axis);
//                if (v > split){
//                    if (i == 0){
//                        // no left plane
//                        splitIndex = -2;
//                    }else{
//                        splitIndex = i;
//                        // first triangle assigned to right
//                        rightPlane = tri.getExtreme(axis, true);
//                    }
//                }else{
//                    // triangle assigned to left
//                    float ex = tri.getExtreme(axis, false);
//                    if (ex > leftPlane)
//                        leftPlane = ex;
//                }
//            }else{
//                float ex = tri.getExtreme(axis, true);
//                if (ex < rightPlane)
//                    rightPlane = ex;
//            }
//        }
//
//        if (splitIndex < 0){
//            splitIndex = (r - l) / 2;
//
//            leftPlane = Float.NEGATIVE_INFINITY;
//            rightPlane = Float.POSITIVE_INFINITY;
//
//            for (int i = l; i < splitIndex; i++){
//                float ex = tris[i].getExtreme(axis, false);
//                if (ex > leftPlane){
//                    leftPlane = ex;
//                }
//            }
//            for (int i = splitIndex; i <= r; i++){
//                float ex = tris[i].getExtreme(axis, true);
//                if (ex < rightPlane){
//                    rightPlane = ex;
//                }
//            }
//        }
//
//        BIHNode node = new BIHNode(axis);
//        node.leftPlane = leftPlane;
//        node.rightPlane = rightPlane;
//
//        node.leftIndex = l;
//        node.rightIndex = r;
//
//        BoundingBox leftBbox = new BoundingBox(currentBox);
//        setMinMax(leftBbox, false, axis, split);
//        node.left = createNode2(l, splitIndex-1, leftBbox, depth+1);
//
//        BoundingBox rightBbox = new BoundingBox(currentBox);
//        setMinMax(rightBbox, true, axis, split);
//        node.right = createNode2(splitIndex, r, rightBbox, depth+1);
//
//        return node;
//    }
private BIHNode createNode(int l, int r, BoundingBox nodeBbox, int depth) {
    if ((r - l) < maxTrisPerNode || depth > MAX_TREE_DEPTH) {
        return new BIHNode(l, r);
    }
    BoundingBox currentBox = createBox(l, r);
    Vector3f exteriorExt = nodeBbox.getExtent(null);
    Vector3f interiorExt = currentBox.getExtent(null);
    exteriorExt.subtractLocal(interiorExt);
    int axis = 0;
    if (exteriorExt.x > exteriorExt.y) {
        if (exteriorExt.x > exteriorExt.z) {
            axis = 0;
        } else {
            axis = 2;
        }
    } else {
        if (exteriorExt.y > exteriorExt.z) {
            axis = 1;
        } else {
            axis = 2;
        }
    }
    if (exteriorExt.equals(Vector3f.ZERO)) {
        axis = 0;
    }
    //        Arrays.sort(tris, l, r, comparators[axis]);
    float split = currentBox.getCenter().get(axis);
    int pivot = sortTriangles(l, r, split, axis);
    if (pivot == l || pivot == r) {
        pivot = (r + l) / 2;
    }
    //If one of the partitions is empty, continue with recursion: same level but different bbox
    if (pivot < l) {
        //Only right
        BoundingBox rbbox = new BoundingBox(currentBox);
        setMinMax(rbbox, true, axis, split);
        return createNode(l, r, rbbox, depth + 1);
    } else if (pivot > r) {
        //Only left
        BoundingBox lbbox = new BoundingBox(currentBox);
        setMinMax(lbbox, false, axis, split);
        return createNode(l, r, lbbox, depth + 1);
    } else {
        //Build the node
        BIHNode node = new BIHNode(axis);
        //Left child
        BoundingBox lbbox = new BoundingBox(currentBox);
        setMinMax(lbbox, false, axis, split);
        //The left node right border is the plane most right
        node.setLeftPlane(getMinMax(createBox(l, max(l, pivot - 1)), false, axis));
        //Recursive call
        node.setLeftChild(createNode(l, max(l, pivot - 1), lbbox, depth + 1));
        //Right Child
        BoundingBox rbbox = new BoundingBox(currentBox);
        setMinMax(rbbox, true, axis, split);
        //The right node left border is the plane most left
        node.setRightPlane(getMinMax(createBox(pivot, r), true, axis));
        //Recursive call
        node.setRightChild(createNode(pivot, r, rbbox, depth + 1));
        return node;
    }
}
Also used : BoundingBox(com.jme3.bounding.BoundingBox) Vector3f(com.jme3.math.Vector3f)

Example 28 with Triangle

use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.

the class BIHNode method intersectWhere.

public final int intersectWhere(Collidable col, BoundingBox box, Matrix4f worldMatrix, BIHTree tree, CollisionResults results) {
    TempVars vars = TempVars.get();
    ArrayList<BIHStackData> stack = vars.bihStack;
    stack.clear();
    float[] minExts = { box.getCenter().x - box.getXExtent(), box.getCenter().y - box.getYExtent(), box.getCenter().z - box.getZExtent() };
    float[] maxExts = { box.getCenter().x + box.getXExtent(), box.getCenter().y + box.getYExtent(), box.getCenter().z + box.getZExtent() };
    stack.add(new BIHStackData(this, 0, 0));
    Triangle t = new Triangle();
    int cols = 0;
    stackloop: while (stack.size() > 0) {
        BIHNode node = stack.remove(stack.size() - 1).node;
        while (node.axis != 3) {
            int a = node.axis;
            float maxExt = maxExts[a];
            float minExt = minExts[a];
            if (node.leftPlane < node.rightPlane) {
                // if the box is in that gap, we stop there
                if (minExt > node.leftPlane && maxExt < node.rightPlane) {
                    continue stackloop;
                }
            }
            if (maxExt < node.rightPlane) {
                node = node.left;
            } else if (minExt > node.leftPlane) {
                node = node.right;
            } else {
                stack.add(new BIHStackData(node.right, 0, 0));
                node = node.left;
            }
        //                if (maxExt < node.leftPlane
        //                 && maxExt < node.rightPlane){
        //                    node = node.left;
        //                }else if (minExt > node.leftPlane
        //                       && minExt > node.rightPlane){
        //                    node = node.right;
        //                }else{
        //                }
        }
        for (int i = node.leftIndex; i <= node.rightIndex; i++) {
            tree.getTriangle(i, t.get1(), t.get2(), t.get3());
            if (worldMatrix != null) {
                worldMatrix.mult(t.get1(), t.get1());
                worldMatrix.mult(t.get2(), t.get2());
                worldMatrix.mult(t.get3(), t.get3());
            }
            int added = col.collideWith(t, results);
            if (added > 0) {
                int index = tree.getTriangleIndex(i);
                int start = results.size() - added;
                for (int j = start; j < results.size(); j++) {
                    CollisionResult cr = results.getCollisionDirect(j);
                    cr.setTriangleIndex(index);
                }
                cols += added;
            }
        }
    }
    vars.release();
    return cols;
}
Also used : CollisionResult(com.jme3.collision.CollisionResult) Triangle(com.jme3.math.Triangle) TempVars(com.jme3.util.TempVars)

Example 29 with Triangle

use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.

the class LodGenerator method computeEdgeCollapseCost.

float computeEdgeCollapseCost(Vertex src, Edge dstEdge) {
    // This is based on Ogre's collapse cost calculation algorithm.
    Vertex dest = dstEdge.destination;
    // then this would destroy the shape, so don't do this
    if (src.triangles.size() == 1 && dest.triangles.size() == 1) {
        return NEVER_COLLAPSE_COST;
    }
    // Look for a face normal changing by > 90 degrees
    for (Triangle triangle : src.triangles) {
        // Ignore the deleted faces (those including src & dest)
        if (!triangle.hasVertex(dest)) {
            // Test the new face normal
            Vertex pv0, pv1, pv2;
            // Replace src with dest wherever it is
            pv0 = (triangle.vertex[0] == src) ? dest : triangle.vertex[0];
            pv1 = (triangle.vertex[1] == src) ? dest : triangle.vertex[1];
            pv2 = (triangle.vertex[2] == src) ? dest : triangle.vertex[2];
            // Cross-product 2 edges
            tmpV1.set(pv1.position).subtractLocal(pv0.position);
            tmpV2.set(pv2.position).subtractLocal(pv1.position);
            //computing the normal
            Vector3f newNormal = tmpV1.crossLocal(tmpV2);
            newNormal.normalizeLocal();
            // If < 0 then more than 90 degree difference
            if (newNormal.dot(triangle.normal) < 0.0f) {
                // Don't do it!
                return NEVER_COLLAPSE_COST;
            }
        }
    }
    float cost;
    // If we're looking at a border vertex
    if (isBorderVertex(src)) {
        if (dstEdge.refCount > 1) {
            // src is on a border, but the src-dest edge has more than one tri on it
            // So it must be collapsing inwards
            // Mark as very high-value cost
            // curvature = 1.0f;
            cost = 1.0f;
        } else {
            // Collapsing ALONG a border
            // We can't use curvature to measure the effect on the model
            // Instead, see what effect it has on 'pulling' the other border edges
            // The more colinear, the less effect it will have
            // So measure the 'kinkiness' (for want of a better term)
            // Find the only triangle using this edge.
            // PMTriangle* triangle = findSideTriangle(src, dst);
            cost = 0.0f;
            Vector3f collapseEdge = tmpV1.set(src.position).subtractLocal(dest.position);
            collapseEdge.normalizeLocal();
            for (Edge edge : src.edges) {
                Vertex neighbor = edge.destination;
                //reference check intended
                if (neighbor != dest && edge.refCount == 1) {
                    Vector3f otherBorderEdge = tmpV2.set(src.position).subtractLocal(neighbor.position);
                    otherBorderEdge.normalizeLocal();
                    // This time, the nearer the dot is to -1, the better, because that means
                    // the edges are opposite each other, therefore less kinkiness
                    // Scale into [0..1]
                    float kinkiness = (otherBorderEdge.dot(collapseEdge) + 1.002f) * 0.5f;
                    cost = Math.max(cost, kinkiness);
                }
            }
        }
    } else {
        // not a border
        // Standard inner vertex
        // Calculate curvature
        // use the triangle facing most away from the sides
        // to determine our curvature term
        // Iterate over src's faces again
        cost = 0.001f;
        for (Triangle triangle : src.triangles) {
            // curve for face i and closer side to it
            float mincurv = 1.0f;
            for (Triangle triangle2 : src.triangles) {
                if (triangle2.hasVertex(dest)) {
                    // Dot product of face normal gives a good delta angle
                    float dotprod = triangle.normal.dot(triangle2.normal);
                    // NB we do (1-..) to invert curvature where 1 is high curvature [0..1]
                    // Whilst dot product is high when angle difference is low
                    mincurv = Math.min(mincurv, (1.002f - dotprod) * 0.5f);
                }
            }
            cost = Math.max(cost, mincurv);
        }
    }
    // check for texture seam ripping
    if (src.isSeam) {
        if (!dest.isSeam) {
            cost += meshBoundingSphereRadius;
        } else {
            cost += meshBoundingSphereRadius * 0.5;
        }
    }
    return cost * src.position.distanceSquared(dest.position);
}
Also used : Vector3f(com.jme3.math.Vector3f)

Example 30 with Triangle

use of com.jme3.math.Triangle in project jmonkeyengine by jMonkeyEngine.

the class LodGenerator method gatherIndexData.

private void gatherIndexData(Mesh mesh, List<Vertex> vertexLookup) {
    VertexBuffer indexBuffer = mesh.getBuffer(VertexBuffer.Type.Index);
    indexCount = indexBuffer.getNumElements() * 3;
    Buffer b = indexBuffer.getDataReadOnly();
    b.rewind();
    while (b.remaining() != 0) {
        Triangle tri = new Triangle();
        tri.isRemoved = false;
        triangleList.add(tri);
        for (int i = 0; i < 3; i++) {
            if (b instanceof IntBuffer) {
                tri.vertexId[i] = ((IntBuffer) b).get();
            } else {
                //bit shift to avoid negative values due to conversion form short to int.
                //we need an unsigned int here.
                tri.vertexId[i] = ((ShortBuffer) b).get() & 0xffff;
            }
            // assert (tri.vertexId[i] < vertexLookup.size());
            tri.vertex[i] = vertexLookup.get(tri.vertexId[i]);
            //debug only;
            tri.vertex[i].index = tri.vertexId[i];
        }
        if (tri.isMalformed()) {
            if (!tri.isRemoved) {
                logger.log(Level.FINE, "malformed triangle found with ID:{0}\n{1} It will be excluded from Lod level calculations.", new Object[] { triangleList.indexOf(tri), tri.toString() });
                tri.isRemoved = true;
                indexCount -= 3;
            }
        } else {
            tri.computeNormal();
            addTriangleToEdges(tri);
        }
    }
    b.rewind();
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer) FloatBuffer(java.nio.FloatBuffer) ShortBuffer(java.nio.ShortBuffer) IntBuffer(java.nio.IntBuffer) Buffer(java.nio.Buffer) VertexBuffer(com.jme3.scene.VertexBuffer) IntBuffer(java.nio.IntBuffer) ShortBuffer(java.nio.ShortBuffer)

Aggregations

Vector3f (com.jme3.math.Vector3f)19 Triangle (com.jme3.math.Triangle)9 FloatBuffer (java.nio.FloatBuffer)7 TempVars (com.jme3.util.TempVars)6 CollisionResult (com.jme3.collision.CollisionResult)5 Vector2f (com.jme3.math.Vector2f)5 ShortBuffer (java.nio.ShortBuffer)5 VertexBuffer (com.jme3.scene.VertexBuffer)4 Buffer (java.nio.Buffer)4 IntBuffer (java.nio.IntBuffer)4 ArrayList (java.util.ArrayList)4 Geometry (com.jme3.scene.Geometry)3 BoundingBox (com.jme3.bounding.BoundingBox)2 UnsupportedCollisionException (com.jme3.collision.UnsupportedCollisionException)2 Mesh (com.jme3.scene.Mesh)2 Spatial (com.jme3.scene.Spatial)2 Quad (com.jme3.scene.shape.Quad)2 ByteBuffer (java.nio.ByteBuffer)2 List (java.util.List)2 Test (org.junit.Test)2