Search in sources :

Example 1 with IntMap

use of com.jme3.util.IntMap 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)

Example 2 with IntMap

use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.

the class GLTracer method generateConstantMap.

private static IntMap<String> generateConstantMap(Class<?>... classes) {
    IntMap<String> constMap = new IntMap<String>();
    for (Class<?> clazz : classes) {
        for (Field field : clazz.getFields()) {
            if (field.getType() == int.class) {
                try {
                    int val = field.getInt(null);
                    String name = field.getName();
                    constMap.put(val, name);
                } catch (IllegalArgumentException ex) {
                } catch (IllegalAccessException ex) {
                }
            }
        }
    }
    // GL_ONE is more common than GL_TRUE (which is a boolean anyway..)
    constMap.put(1, "GL_ONE");
    return constMap;
}
Also used : Field(java.lang.reflect.Field) IntMap(com.jme3.util.IntMap)

Example 3 with IntMap

use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.

the class GLRenderer method renderMeshVertexArray.

private void renderMeshVertexArray(Mesh mesh, int lod, int count, VertexBuffer instanceData) {
    if (mesh.getId() == -1) {
        updateVertexArray(mesh, instanceData);
    } else {
    // TODO: Check if it was updated
    }
    if (context.boundVertexArray != mesh.getId()) {
        gl3.glBindVertexArray(mesh.getId());
        context.boundVertexArray = mesh.getId();
    }
    //        IntMap<VertexBuffer> buffers = mesh.getBuffers();
    VertexBuffer indices;
    if (mesh.getNumLodLevels() > 0) {
        indices = mesh.getLodLevel(lod);
    } else {
        indices = mesh.getBuffer(Type.Index);
    }
    if (indices != null) {
        drawTriangleList(indices, mesh, count);
    } else {
        drawTriangleArray(mesh.getMode(), count, mesh.getVertexCount());
    }
    clearVertexAttribs();
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer)

Example 4 with IntMap

use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.

the class FbxMesh method toJmeObject.

@Override
protected IntMap<Mesh> toJmeObject() {
    // Load clusters from SkinDeformer
    if (skinDeformer != null) {
        for (FbxCluster cluster : skinDeformer.getJmeObject()) {
            applyCluster(cluster);
        }
    }
    IrMesh irMesh = toIRMesh();
    // Trim bone weights to 4 weights per vertex.
    IrUtils.trimBoneWeights(irMesh);
    // Convert tangents / binormals to tangents with parity.
    IrUtils.toTangentsWithParity(irMesh);
    // Triangulate quads.
    IrUtils.triangulate(irMesh);
    // Split meshes by material indices.
    IntMap<IrMesh> irMeshes = IrUtils.splitByMaterial(irMesh);
    // Create a jME3 Mesh for each material index.
    IntMap<Mesh> jmeMeshes = new IntMap<Mesh>();
    for (IntMap.Entry<IrMesh> irMeshEntry : irMeshes) {
        Mesh jmeMesh = IrUtils.convertIrMeshToJmeMesh(irMeshEntry.getValue());
        jmeMeshes.put(irMeshEntry.getKey(), jmeMesh);
    }
    if (jmeMeshes.size() == 0) {
        // When will this actually happen? Not sure.
        logger.log(Level.WARNING, "Empty FBX mesh found (unusual).");
    }
    // It makes sense only if the mesh uses a single material!
    if (jmeMeshes.containsKey(-1) && jmeMeshes.size() > 1) {
        logger.log(Level.WARNING, "Mesh has polygons with no material " + "indices (unusual) - they will use material index 0.");
    }
    return jmeMeshes;
}
Also used : FbxCluster(com.jme3.scene.plugins.fbx.anim.FbxCluster) IntMap(com.jme3.util.IntMap) IrMesh(com.jme3.scene.plugins.IrMesh) Mesh(com.jme3.scene.Mesh) IrMesh(com.jme3.scene.plugins.IrMesh)

Example 5 with IntMap

use of com.jme3.util.IntMap in project jmonkeyengine by jMonkeyEngine.

the class FbxNode method toJmeObject.

@Override
public Spatial toJmeObject() {
    Spatial spatial;
    if (nodeAttribute instanceof FbxMesh) {
        FbxMesh fbxMesh = (FbxMesh) nodeAttribute;
        IntMap<Mesh> jmeMeshes = fbxMesh.getJmeObject();
        if (jmeMeshes == null || jmeMeshes.size() == 0) {
            // No meshes found on FBXMesh (??)
            logger.log(Level.WARNING, "No meshes could be loaded. Creating empty node.");
            spatial = new Node(getName() + "-node");
        } else {
            // Multiple jME3 geometries required for a single FBXMesh.
            String nodeName;
            if (children.isEmpty()) {
                nodeName = getName() + "-mesh";
            } else {
                nodeName = getName() + "-node";
            }
            Node node = new Node(nodeName);
            boolean singleMesh = jmeMeshes.size() == 1;
            for (IntMap.Entry<Mesh> meshInfo : jmeMeshes) {
                node.attachChild(tryCreateGeometry(meshInfo.getKey(), meshInfo.getValue(), singleMesh));
            }
            spatial = node;
        }
    } else {
        if (nodeAttribute != null) {
            // Just specifies that this is a "null" node.
            nodeAttribute.getJmeObject();
        }
        // TODO: handle other node attribute types.
        //       right now everything we don't know about gets converted
        //       to jME3 Node.
        spatial = new Node(getName() + "-node");
    }
    if (!children.isEmpty()) {
        // Check uniform scale.
        // Although, if inheritType is 0 (eInheritRrSs)
        // it might not be a problem.
        Vector3f localScale = jmeLocalNodeTransform.getScale();
        if (!FastMath.approximateEquals(localScale.x, localScale.y) || !FastMath.approximateEquals(localScale.x, localScale.z)) {
            logger.log(Level.WARNING, "Non-uniform scale detected on parent node. " + "The model may appear distorted.");
        }
    }
    spatial.setLocalTransform(jmeLocalNodeTransform);
    if (visibility == 0.0) {
        spatial.setCullHint(CullHint.Always);
    }
    for (Map.Entry<String, Object> userDataEntry : userData.entrySet()) {
        spatial.setUserData(userDataEntry.getKey(), userDataEntry.getValue());
    }
    return spatial;
}
Also used : FbxMesh(com.jme3.scene.plugins.fbx.mesh.FbxMesh) FbxLimbNode(com.jme3.scene.plugins.fbx.anim.FbxLimbNode) Node(com.jme3.scene.Node) FbxAnimCurveNode(com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode) FbxMesh(com.jme3.scene.plugins.fbx.mesh.FbxMesh) Mesh(com.jme3.scene.Mesh) Spatial(com.jme3.scene.Spatial) Vector3f(com.jme3.math.Vector3f) IntMap(com.jme3.util.IntMap) FbxObject(com.jme3.scene.plugins.fbx.obj.FbxObject) IntMap(com.jme3.util.IntMap) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

IntMap (com.jme3.util.IntMap)4 Mesh (com.jme3.scene.Mesh)3 Savable (com.jme3.export.Savable)2 VertexBuffer (com.jme3.scene.VertexBuffer)2 AssetLoadException (com.jme3.asset.AssetLoadException)1 Vector3f (com.jme3.math.Vector3f)1 Geometry (com.jme3.scene.Geometry)1 Node (com.jme3.scene.Node)1 Spatial (com.jme3.scene.Spatial)1 IrMesh (com.jme3.scene.plugins.IrMesh)1 FbxAnimCurveNode (com.jme3.scene.plugins.fbx.anim.FbxAnimCurveNode)1 FbxCluster (com.jme3.scene.plugins.fbx.anim.FbxCluster)1 FbxLimbNode (com.jme3.scene.plugins.fbx.anim.FbxLimbNode)1 FbxMesh (com.jme3.scene.plugins.fbx.mesh.FbxMesh)1 FbxObject (com.jme3.scene.plugins.fbx.obj.FbxObject)1 Entry (com.jme3.util.IntMap.Entry)1 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1 FloatBuffer (java.nio.FloatBuffer)1 ArrayList (java.util.ArrayList)1