Search in sources :

Example 11 with Triangle

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

the class LODGeomap method getGridTrianglesAtPoint.

/**
     * Get the two triangles that make up the grid section at the specified point.
     *
     * For every grid space there are two triangles oriented like this:
     *  *----*
     *  |a / |
     *  | / b|
     *  *----*
     * The corners of the mesh have differently oriented triangles. The two
     * corners that we have to special-case are the top left and bottom right
     * corners. They are oriented inversely:
     *  *----*
     *  | \ b|
     *  |a \ |
     *  *----*
     *
     * @param x local x coordinate
     * @param z local z coordinate
     * @return
     */
protected Triangle[] getGridTrianglesAtPoint(float x, float z) {
    int gridX = (int) x;
    int gridY = (int) z;
    int index = findClosestHeightIndex(gridX, gridY);
    if (index < 0) {
        return null;
    }
    Triangle t = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
    Triangle t2 = new Triangle(new Vector3f(), new Vector3f(), new Vector3f());
    // top left
    float h1 = hdata[index];
    // top right
    float h2 = hdata[index + 1];
    // bottom left
    float h3 = hdata[index + width];
    // bottom right
    float h4 = hdata[index + width + 1];
    if ((gridX == 0 && gridY == 0) || (gridX == width - 2 && gridY == width - 2)) {
        // top left or bottom right grid point
        t.get(0).x = (gridX);
        t.get(0).y = (h1);
        t.get(0).z = (gridY);
        t.get(1).x = (gridX);
        t.get(1).y = (h3);
        t.get(1).z = (gridY + 1);
        t.get(2).x = (gridX + 1);
        t.get(2).y = (h4);
        t.get(2).z = (gridY + 1);
        t2.get(0).x = (gridX);
        t2.get(0).y = (h1);
        t2.get(0).z = (gridY);
        t2.get(1).x = (gridX + 1);
        t2.get(1).y = (h4);
        t2.get(1).z = (gridY + 1);
        t2.get(2).x = (gridX + 1);
        t2.get(2).y = (h2);
        t2.get(2).z = (gridY);
    } else {
        // all other grid points
        t.get(0).x = (gridX);
        t.get(0).y = (h1);
        t.get(0).z = (gridY);
        t.get(1).x = (gridX);
        t.get(1).y = (h3);
        t.get(1).z = (gridY + 1);
        t.get(2).x = (gridX + 1);
        t.get(2).y = (h2);
        t.get(2).z = (gridY);
        t2.get(0).x = (gridX + 1);
        t2.get(0).y = (h2);
        t2.get(0).z = (gridY);
        t2.get(1).x = (gridX);
        t2.get(1).y = (h3);
        t2.get(1).z = (gridY + 1);
        t2.get(2).x = (gridX + 1);
        t2.get(2).y = (h4);
        t2.get(2).z = (gridY + 1);
    }
    return new Triangle[] { t, t2 };
}
Also used : Vector3f(com.jme3.math.Vector3f) Triangle(com.jme3.math.Triangle)

Example 12 with Triangle

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

the class LODGeomap method getTriangleAtPoint.

/**
     * Get the triangle that the point is on.
     * 
     * @param x coordinate in local space to the geomap
     * @param z coordinate in local space to the geomap
     * @return triangle in local space to the geomap
     */
protected Triangle getTriangleAtPoint(float x, float z) {
    Triangle[] triangles = getGridTrianglesAtPoint(x, z);
    if (triangles == null) {
        //System.out.println("x,z: " + x + "," + z);
        return null;
    }
    Vector2f point = new Vector2f(x, z);
    Vector2f t1 = new Vector2f(triangles[0].get1().x, triangles[0].get1().z);
    Vector2f t2 = new Vector2f(triangles[0].get2().x, triangles[0].get2().z);
    Vector2f t3 = new Vector2f(triangles[0].get3().x, triangles[0].get3().z);
    if (0 != FastMath.pointInsideTriangle(t1, t2, t3, point)) {
        return triangles[0];
    }
    t1.set(triangles[1].get1().x, triangles[1].get1().z);
    t1.set(triangles[1].get2().x, triangles[1].get2().z);
    t1.set(triangles[1].get3().x, triangles[1].get3().z);
    if (0 != FastMath.pointInsideTriangle(t1, t2, t3, point)) {
        return triangles[1];
    }
    return null;
}
Also used : Vector2f(com.jme3.math.Vector2f) Triangle(com.jme3.math.Triangle)

Example 13 with Triangle

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

the class LODGeomap method getTriangleAtPoint.

/**
     * Get a representation of the underlying triangle at the given point,
     * translated to world coordinates.
     * 
     * @param x local x coordinate
     * @param z local z coordinate
     * @return a triangle in world space not local space
     */
protected Triangle getTriangleAtPoint(float x, float z, Vector3f scale, Vector3f translation) {
    Triangle tri = getTriangleAtPoint(x, z);
    if (tri != null) {
        tri.get1().multLocal(scale).addLocal(translation);
        tri.get2().multLocal(scale).addLocal(translation);
        tri.get3().multLocal(scale).addLocal(translation);
    }
    return tri;
}
Also used : Triangle(com.jme3.math.Triangle)

Example 14 with Triangle

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

the class Ray method intersects.

/**
     * <code>intersects</code> does the actual intersection work.
     *
     * @param v0
     *            first point of the triangle.
     * @param v1
     *            second point of the triangle.
     * @param v2
     *            third point of the triangle.
     * @param store
     *            storage vector - if null, no intersection is calc'd
     * @param doPlanar
     *            true if we are calcing planar results.
     * @param quad
     * @return true if ray intersects triangle
     */
private boolean intersects(Vector3f v0, Vector3f v1, Vector3f v2, Vector3f store, boolean doPlanar, boolean quad) {
    TempVars vars = TempVars.get();
    Vector3f tempVa = vars.vect1, tempVb = vars.vect2, tempVc = vars.vect3, tempVd = vars.vect4;
    Vector3f diff = origin.subtract(v0, tempVa);
    Vector3f edge1 = v1.subtract(v0, tempVb);
    Vector3f edge2 = v2.subtract(v0, tempVc);
    Vector3f norm = edge1.cross(edge2, tempVd);
    float dirDotNorm = direction.dot(norm);
    float sign;
    if (dirDotNorm > FastMath.FLT_EPSILON) {
        sign = 1;
    } else if (dirDotNorm < -FastMath.FLT_EPSILON) {
        sign = -1f;
        dirDotNorm = -dirDotNorm;
    } else {
        // ray and triangle/quad are parallel
        vars.release();
        return false;
    }
    float dirDotDiffxEdge2 = sign * direction.dot(diff.cross(edge2, edge2));
    if (dirDotDiffxEdge2 >= 0.0f) {
        float dirDotEdge1xDiff = sign * direction.dot(edge1.crossLocal(diff));
        if (dirDotEdge1xDiff >= 0.0f) {
            if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) {
                float diffDotNorm = -sign * diff.dot(norm);
                if (diffDotNorm >= 0.0f) {
                    // this method always returns
                    vars.release();
                    // if storage vector is null, just return true,
                    if (store == null) {
                        return true;
                    }
                    // else fill in.
                    float inv = 1f / dirDotNorm;
                    float t = diffDotNorm * inv;
                    if (!doPlanar) {
                        store.set(origin).addLocal(direction.x * t, direction.y * t, direction.z * t);
                    } else {
                        // these weights can be used to determine
                        // interpolated values, such as texture coord.
                        // eg. texcoord s,t at intersection point:
                        // s = w0*s0 + w1*s1 + w2*s2;
                        // t = w0*t0 + w1*t1 + w2*t2;
                        float w1 = dirDotDiffxEdge2 * inv;
                        float w2 = dirDotEdge1xDiff * inv;
                        //float w0 = 1.0f - w1 - w2;
                        store.set(t, w1, w2);
                    }
                    return true;
                }
            }
        }
    }
    vars.release();
    return false;
}
Also used : TempVars(com.jme3.util.TempVars)

Example 15 with Triangle

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

the class FbxMesh method createGeometries.

private List<Geometry> createGeometries() throws IOException {
    Mesh mesh = new Mesh();
    mesh.setMode(Mode.Triangles);
    // Moreover quads should be triangulated (this increases number of vertices)
    if (indices != null) {
        iCount = indices.length;
        srcVertexCount = vertices.length / 3;
        // Indices contains negative numbers to define polygon last index
        // Check indices strides to be sure we have triangles or quads
        vCount = 0;
        // Count number of vertices to be produced
        int polyVertCount = 0;
        for (int i = 0; i < iCount; ++i) {
            int index = indices[i];
            polyVertCount++;
            if (index < 0) {
                if (polyVertCount == 3) {
                    // A triangle
                    vCount += 3;
                } else if (polyVertCount == 4) {
                    // A quad produce two triangles
                    vCount += 6;
                } else {
                    throw new AssetLoadException("Unsupported PolygonVertexIndex stride");
                }
                polyVertCount = 0;
            }
        }
        // Unroll index array into vertex mapping
        vertexMap = new ArrayList<>(vCount);
        indexMap = new ArrayList<>(vCount);
        polyVertCount = 0;
        for (int i = 0; i < iCount; ++i) {
            int index = indices[i];
            polyVertCount++;
            if (index < 0) {
                int lastIndex = -(index + 1);
                if (polyVertCount == 3) {
                    vertexMap.add(indices[i - 2]);
                    vertexMap.add(indices[i - 1]);
                    vertexMap.add(lastIndex);
                    indexMap.add(i - 2);
                    indexMap.add(i - 1);
                    indexMap.add(i - 0);
                } else if (polyVertCount == 4) {
                    vertexMap.add(indices[i - 3]);
                    vertexMap.add(indices[i - 2]);
                    vertexMap.add(indices[i - 1]);
                    vertexMap.add(indices[i - 3]);
                    vertexMap.add(indices[i - 1]);
                    vertexMap.add(lastIndex);
                    indexMap.add(i - 3);
                    indexMap.add(i - 2);
                    indexMap.add(i - 1);
                    indexMap.add(i - 3);
                    indexMap.add(i - 1);
                    indexMap.add(i - 0);
                }
                polyVertCount = 0;
            }
        }
        // Build reverse vertex mapping
        reverseVertexMap = new ArrayList<>(srcVertexCount);
        for (int i = 0; i < srcVertexCount; ++i) reverseVertexMap.add(new ArrayList<Integer>());
        for (int i = 0; i < vCount; ++i) {
            int index = vertexMap.get(i);
            reverseVertexMap.get(index).add(i);
        }
    } else {
        // Stub for no vertex indexing (direct mapping)
        iCount = vCount = srcVertexCount;
        vertexMap = new ArrayList<>(vCount);
        indexMap = new ArrayList<>(vCount);
        reverseVertexMap = new ArrayList<>(vCount);
        for (int i = 0; i < vCount; ++i) {
            vertexMap.set(i, i);
            indexMap.set(i, i);
            List<Integer> l = new ArrayList<Integer>(1);
            l.add(i);
            reverseVertexMap.add(l);
        }
    }
    if (vertices != null) {
        // Unroll vertices data array
        FloatBuffer posBuf = BufferUtils.createFloatBuffer(vCount * 3);
        mesh.setBuffer(VertexBuffer.Type.Position, 3, posBuf);
        int srcCount = vertices.length / 3;
        for (int i = 0; i < vCount; ++i) {
            int index = vertexMap.get(i);
            if (index > srcCount)
                throw new AssetLoadException("Invalid vertex mapping. Unexpected lookup vertex " + index + " from " + srcCount);
            // XXX Why we should scale by unit size?
            float x = (float) vertices[3 * index + 0] / scene.unitSize * scene.xAxis;
            float y = (float) vertices[3 * index + 1] / scene.unitSize * scene.yAxis;
            float z = (float) vertices[3 * index + 2] / scene.unitSize * scene.zAxis;
            posBuf.put(x).put(y).put(z);
        }
    }
    if (normals != null) {
        // Unroll normals data array
        FloatBuffer normBuf = BufferUtils.createFloatBuffer(vCount * 3);
        mesh.setBuffer(VertexBuffer.Type.Normal, 3, normBuf);
        List<Integer> mapping = null;
        if (normalsMapping.equals("ByVertice"))
            mapping = vertexMap;
        else if (normalsMapping.equals("ByPolygonVertex"))
            mapping = indexMap;
        else
            throw new IOException("Unknown normals mapping type: " + normalsMapping);
        int srcCount = normals.length / 3;
        for (int i = 0; i < vCount; ++i) {
            int index = mapping.get(i);
            if (index > srcCount)
                throw new AssetLoadException("Invalid normal mapping. Unexpected lookup normal " + index + " from " + srcCount);
            float x = (float) normals[3 * index + 0] * scene.xAxis;
            float y = (float) normals[3 * index + 1] * scene.yAxis;
            float z = (float) normals[3 * index + 2] * scene.zAxis;
            normBuf.put(x).put(y).put(z);
        }
    }
    if (tangents != null) {
        // Unroll normals data array
        FloatBuffer tanBuf = BufferUtils.createFloatBuffer(vCount * 4);
        mesh.setBuffer(VertexBuffer.Type.Tangent, 4, tanBuf);
        List<Integer> mapping = null;
        if (tangentsMapping.equals("ByVertice"))
            mapping = vertexMap;
        else if (tangentsMapping.equals("ByPolygonVertex"))
            mapping = indexMap;
        else
            throw new IOException("Unknown tangents mapping type: " + tangentsMapping);
        int srcCount = tangents.length / 3;
        for (int i = 0; i < vCount; ++i) {
            int index = mapping.get(i);
            if (index > srcCount)
                throw new AssetLoadException("Invalid tangent mapping. Unexpected lookup tangent " + index + " from " + srcCount);
            float x = (float) tangents[3 * index + 0] * scene.xAxis;
            float y = (float) tangents[3 * index + 1] * scene.yAxis;
            float z = (float) tangents[3 * index + 2] * scene.zAxis;
            tanBuf.put(x).put(y).put(z).put(-1.0f);
        }
    }
    if (binormals != null) {
        // Unroll normals data array
        FloatBuffer binormBuf = BufferUtils.createFloatBuffer(vCount * 3);
        mesh.setBuffer(VertexBuffer.Type.Binormal, 3, binormBuf);
        List<Integer> mapping = null;
        if (binormalsMapping.equals("ByVertice"))
            mapping = vertexMap;
        else if (binormalsMapping.equals("ByPolygonVertex"))
            mapping = indexMap;
        else
            throw new IOException("Unknown binormals mapping type: " + binormalsMapping);
        int srcCount = binormals.length / 3;
        for (int i = 0; i < vCount; ++i) {
            int index = mapping.get(i);
            if (index > srcCount)
                throw new AssetLoadException("Invalid binormal mapping. Unexpected lookup binormal " + index + " from " + srcCount);
            float x = (float) binormals[3 * index + 0] * scene.xAxis;
            float y = (float) binormals[3 * index + 1] * scene.yAxis;
            float z = (float) binormals[3 * index + 2] * scene.zAxis;
            binormBuf.put(x).put(y).put(z);
        }
    }
    for (int uvLayer = 0; uvLayer < uvs.size(); ++uvLayer) {
        double[] uv = uvs.get(uvLayer);
        int[] uvIndex = uvIndexes.size() > uvLayer ? uvIndexes.get(uvLayer) : null;
        List<Integer> unIndexMap = vertexMap;
        if (uvIndex != null) {
            int uvIndexSrcCount = uvIndex.length;
            if (uvIndexSrcCount != iCount)
                throw new AssetLoadException("Invalid number of texcoord index data " + uvIndexSrcCount + " expected " + iCount);
            // Unroll UV index array
            unIndexMap = new ArrayList<>(vCount);
            int polyVertCount = 0;
            for (int i = 0; i < iCount; ++i) {
                int index = indices[i];
                polyVertCount++;
                if (index < 0) {
                    if (polyVertCount == 3) {
                        unIndexMap.add(uvIndex[i - 2]);
                        unIndexMap.add(uvIndex[i - 1]);
                        unIndexMap.add(uvIndex[i - 0]);
                    } else if (polyVertCount == 4) {
                        unIndexMap.add(uvIndex[i - 3]);
                        unIndexMap.add(uvIndex[i - 2]);
                        unIndexMap.add(uvIndex[i - 1]);
                        unIndexMap.add(uvIndex[i - 3]);
                        unIndexMap.add(uvIndex[i - 1]);
                        unIndexMap.add(uvIndex[i - 0]);
                    }
                    polyVertCount = 0;
                }
            }
        }
        // Unroll UV data array
        FloatBuffer tcBuf = BufferUtils.createFloatBuffer(vCount * 2);
        VertexBuffer.Type type = VertexBuffer.Type.TexCoord;
        switch(uvLayer) {
            case 1:
                type = VertexBuffer.Type.TexCoord2;
                break;
            case 2:
                type = VertexBuffer.Type.TexCoord3;
                break;
            case 3:
                type = VertexBuffer.Type.TexCoord4;
                break;
            case 4:
                type = VertexBuffer.Type.TexCoord5;
                break;
            case 5:
                type = VertexBuffer.Type.TexCoord6;
                break;
            case 6:
                type = VertexBuffer.Type.TexCoord7;
                break;
            case 7:
                type = VertexBuffer.Type.TexCoord8;
                break;
        }
        mesh.setBuffer(type, 2, tcBuf);
        int srcCount = uv.length / 2;
        for (int i = 0; i < vCount; ++i) {
            int index = unIndexMap.get(i);
            if (index > srcCount)
                throw new AssetLoadException("Invalid texcoord mapping. Unexpected lookup texcoord " + index + " from " + srcCount);
            float u = (index >= 0) ? (float) uv[2 * index + 0] : 0;
            float v = (index >= 0) ? (float) uv[2 * index + 1] : 0;
            tcBuf.put(u).put(v);
        }
    }
    List<Geometry> geometries = new ArrayList<Geometry>();
    if (materialsReference.equals("IndexToDirect") && materialsMapping.equals("ByPolygon")) {
        IntMap<List<Integer>> indexBuffers = new IntMap<>();
        for (int polygon = 0; polygon < materials.length; ++polygon) {
            int material = materials[polygon];
            List<Integer> list = indexBuffers.get(material);
            if (list == null) {
                list = new ArrayList<>();
                indexBuffers.put(material, list);
            }
            list.add(polygon * 3 + 0);
            list.add(polygon * 3 + 1);
            list.add(polygon * 3 + 2);
        }
        Iterator<Entry<List<Integer>>> iterator = indexBuffers.iterator();
        while (iterator.hasNext()) {
            Entry<List<Integer>> e = iterator.next();
            int materialId = e.getKey();
            List<Integer> indexes = e.getValue();
            Mesh newMesh = mesh.clone();
            newMesh.setBuffer(VertexBuffer.Type.Index, 3, toArray(indexes.toArray(new Integer[indexes.size()])));
            newMesh.setStatic();
            newMesh.updateBound();
            newMesh.updateCounts();
            Geometry geom = new Geometry();
            geom.setMesh(newMesh);
            geometries.add(geom);
            geom.setUserData("FBXMaterial", materialId);
        }
    } else {
        mesh.setStatic();
        mesh.updateBound();
        mesh.updateCounts();
        Geometry geom = new Geometry();
        geom.setMesh(mesh);
        geometries.add(geom);
    }
    return geometries;
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer) ArrayList(java.util.ArrayList) Mesh(com.jme3.scene.Mesh) FloatBuffer(java.nio.FloatBuffer) IOException(java.io.IOException) AssetLoadException(com.jme3.asset.AssetLoadException) Geometry(com.jme3.scene.Geometry) Entry(com.jme3.util.IntMap.Entry) IntMap(com.jme3.util.IntMap) ArrayList(java.util.ArrayList) List(java.util.List)

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