Search in sources :

Example 1 with Entry

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

the class MapSerializer method writeObject.

@SuppressWarnings("unchecked")
public void writeObject(ByteBuffer buffer, Object object) throws IOException {
    Map map = (Map) object;
    int length = map.size();
    buffer.putInt(length);
    if (length == 0)
        return;
    Set<Entry> entries = map.entrySet();
    Iterator<Entry> it = entries.iterator();
    Entry entry = it.next();
    Class keyClass = entry.getKey().getClass();
    Class valClass = entry.getValue().getClass();
    while (it.hasNext()) {
        entry = it.next();
        if (entry.getKey().getClass() != keyClass) {
            keyClass = null;
            if (valClass == null)
                break;
        }
        if (entry.getValue().getClass() != valClass) {
            valClass = null;
            if (keyClass == null)
                break;
        }
    }
    boolean uniqueKeys = keyClass == null;
    boolean uniqueVals = valClass == null;
    int flags = 0;
    if (!uniqueKeys)
        flags |= 0x01;
    if (!uniqueVals)
        flags |= 0x02;
    buffer.put((byte) flags);
    Serializer keySerial = null, valSerial = null;
    if (!uniqueKeys) {
        Serializer.writeClass(buffer, keyClass);
        keySerial = Serializer.getSerializer(keyClass);
    }
    if (!uniqueVals) {
        Serializer.writeClass(buffer, valClass);
        valSerial = Serializer.getSerializer(valClass);
    }
    it = entries.iterator();
    while (it.hasNext()) {
        entry = it.next();
        if (uniqueKeys) {
            Serializer.writeClassAndObject(buffer, entry.getKey());
        } else {
            keySerial.writeObject(buffer, entry.getKey());
        }
        if (uniqueVals) {
            Serializer.writeClassAndObject(buffer, entry.getValue());
        } else {
            valSerial.writeObject(buffer, entry.getValue());
        }
    }
}
Also used : Entry(java.util.Map.Entry) Map(java.util.Map) HashMap(java.util.HashMap) Serializer(com.jme3.network.serializing.Serializer)

Example 2 with Entry

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

the class TriangulatedTexture method getResultTexture.

/**
     * This method returns the flat texture. It is calculated if required or if
     * it was not created before. Images that are identical are discarded to
     * reduce the texture size.
     * 
     * @param rebuild
     *            a variable that forces texture recomputation (even if it was
     *            computed vefore)
     * @return flat result texture (all images merged into one)
     */
public Texture2D getResultTexture(boolean rebuild) {
    if (resultTexture == null || rebuild) {
        // sorting the parts by their height (from highest to the lowest)
        List<TriangleTextureElement> list = new ArrayList<TriangleTextureElement>(faceTextures);
        Collections.sort(list, new Comparator<TriangleTextureElement>() {

            public int compare(TriangleTextureElement o1, TriangleTextureElement o2) {
                return o2.image.getHeight() - o1.image.getHeight();
            }
        });
        // arraging the images on the resulting image (calculating the result image width and height)
        Set<Integer> duplicatedFaceIndexes = new HashSet<Integer>();
        int resultImageHeight = list.get(0).image.getHeight();
        int resultImageWidth = 0;
        int currentXPos = 0, currentYPos = 0;
        Map<TriangleTextureElement, Integer[]> imageLayoutData = new HashMap<TriangleTextureElement, Integer[]>(list.size());
        while (list.size() > 0) {
            TriangleTextureElement currentElement = list.remove(0);
            if (currentXPos + currentElement.image.getWidth() > maxTextureSize) {
                currentXPos = 0;
                currentYPos = resultImageHeight;
                resultImageHeight += currentElement.image.getHeight();
            }
            Integer[] currentPositions = new Integer[] { currentXPos, currentYPos };
            imageLayoutData.put(currentElement, currentPositions);
            if (keepIdenticalTextures) {
                // removing identical images
                for (int i = 0; i < list.size(); ++i) {
                    if (currentElement.image.equals(list.get(i).image)) {
                        duplicatedFaceIndexes.add(list.get(i).faceIndex);
                        imageLayoutData.put(list.remove(i--), currentPositions);
                    }
                }
            }
            currentXPos += currentElement.image.getWidth();
            resultImageWidth = Math.max(resultImageWidth, currentXPos);
        // currentYPos += currentElement.image.getHeight();
        // TODO: implement that to compact the result image
        // try to add smaller images below the current one
        // int remainingHeight = resultImageHeight -
        // currentElement.image.getHeight();
        // while(remainingHeight > 0) {
        // for(int i=list.size() - 1;i>=0;--i) {
        //
        // }
        // }
        }
        // computing the result UV coordinates
        resultUVS = new ArrayList<Vector2f>(imageLayoutData.size() * 3);
        for (int i = 0; i < imageLayoutData.size() * 3; ++i) {
            resultUVS.add(null);
        }
        Vector2f[] uvs = new Vector2f[3];
        for (Entry<TriangleTextureElement, Integer[]> entry : imageLayoutData.entrySet()) {
            Integer[] position = entry.getValue();
            entry.getKey().computeFinalUVCoordinates(resultImageWidth, resultImageHeight, position[0], position[1], uvs);
            resultUVS.set(entry.getKey().faceIndex * 3, uvs[0]);
            resultUVS.set(entry.getKey().faceIndex * 3 + 1, uvs[1]);
            resultUVS.set(entry.getKey().faceIndex * 3 + 2, uvs[2]);
        }
        Image resultImage = new Image(format, resultImageWidth, resultImageHeight, BufferUtils.createByteBuffer(resultImageWidth * resultImageHeight * (format.getBitsPerPixel() >> 3)), ColorSpace.Linear);
        resultTexture = new Texture2D(resultImage);
        for (Entry<TriangleTextureElement, Integer[]> entry : imageLayoutData.entrySet()) {
            if (!duplicatedFaceIndexes.contains(entry.getKey().faceIndex)) {
                this.draw(resultImage, entry.getKey().image, entry.getValue()[0], entry.getValue()[1]);
            }
        }
        // setting additional data
        resultTexture.setWrap(WrapAxis.S, this.getWrap(WrapAxis.S));
        resultTexture.setWrap(WrapAxis.T, this.getWrap(WrapAxis.T));
        resultTexture.setMagFilter(this.getMagFilter());
        resultTexture.setMinFilter(this.getMinFilter());
    }
    return resultTexture;
}
Also used : Texture2D(com.jme3.texture.Texture2D) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Image(com.jme3.texture.Image) BufferedImage(java.awt.image.BufferedImage) Vector2f(com.jme3.math.Vector2f) HashSet(java.util.HashSet)

Example 3 with Entry

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

the class SubdivisionSurfaceModifier method subdivideSimple.

/**
     * The method performs a simple subdivision of the mesh.
     * 
     * @param temporalMesh
     *            the mesh to be subdivided
     */
private void subdivideSimple(TemporalMesh temporalMesh) {
    Map<Edge, Integer> edgePoints = new HashMap<Edge, Integer>();
    Map<Face, Integer> facePoints = new HashMap<Face, Integer>();
    Set<Face> newFaces = new LinkedHashSet<Face>();
    Set<Edge> newEdges = new LinkedHashSet<Edge>(temporalMesh.getEdges().size() * 4);
    int originalFacesCount = temporalMesh.getFaces().size();
    List<Map<String, Float>> vertexGroups = temporalMesh.getVertexGroups();
    // the result vertex array will have verts in the following order [[original_verts], [face_verts], [edge_verts]]
    List<Vector3f> vertices = temporalMesh.getVertices();
    List<Vector3f> edgeVertices = new ArrayList<Vector3f>();
    List<Vector3f> faceVertices = new ArrayList<Vector3f>();
    // the same goes for normals
    List<Vector3f> normals = temporalMesh.getNormals();
    List<Vector3f> edgeNormals = new ArrayList<Vector3f>();
    List<Vector3f> faceNormals = new ArrayList<Vector3f>();
    List<Face> faces = temporalMesh.getFaces();
    for (Face face : faces) {
        Map<String, List<Vector2f>> uvSets = face.getUvSets();
        Vector3f facePoint = face.computeCentroid();
        Integer facePointIndex = vertices.size() + faceVertices.size();
        facePoints.put(face, facePointIndex);
        faceVertices.add(facePoint);
        faceNormals.add(this.computeFaceNormal(face));
        Map<String, Vector2f> faceUV = this.computeFaceUVs(face);
        byte[] faceVertexColor = this.computeFaceVertexColor(face);
        Map<String, Float> faceVertexGroups = this.computeFaceVertexGroups(face);
        if (vertexGroups.size() > 0) {
            vertexGroups.add(faceVertexGroups);
        }
        for (int i = 0; i < face.getIndexes().size(); ++i) {
            int vIndex = face.getIndexes().get(i);
            int vPrevIndex = i == 0 ? face.getIndexes().get(face.getIndexes().size() - 1) : face.getIndexes().get(i - 1);
            int vNextIndex = i == face.getIndexes().size() - 1 ? face.getIndexes().get(0) : face.getIndexes().get(i + 1);
            Edge prevEdge = this.findEdge(temporalMesh, vPrevIndex, vIndex);
            Edge nextEdge = this.findEdge(temporalMesh, vIndex, vNextIndex);
            int vPrevEdgeVertIndex = edgePoints.containsKey(prevEdge) ? edgePoints.get(prevEdge) : -1;
            int vNextEdgeVertIndex = edgePoints.containsKey(nextEdge) ? edgePoints.get(nextEdge) : -1;
            Vector3f v = temporalMesh.getVertices().get(vIndex);
            if (vPrevEdgeVertIndex < 0) {
                vPrevEdgeVertIndex = vertices.size() + originalFacesCount + edgeVertices.size();
                verticesOnOriginalEdges.add(vPrevEdgeVertIndex);
                edgeVertices.add(vertices.get(vPrevIndex).add(v).divideLocal(2));
                edgeNormals.add(normals.get(vPrevIndex).add(normals.get(vIndex)).normalizeLocal());
                edgePoints.put(prevEdge, vPrevEdgeVertIndex);
                if (vertexGroups.size() > 0) {
                    vertexGroups.add(this.interpolateVertexGroups(Arrays.asList(vertexGroups.get(vPrevIndex), vertexGroups.get(vIndex))));
                }
            }
            if (vNextEdgeVertIndex < 0) {
                vNextEdgeVertIndex = vertices.size() + originalFacesCount + edgeVertices.size();
                verticesOnOriginalEdges.add(vNextEdgeVertIndex);
                edgeVertices.add(vertices.get(vNextIndex).add(v).divideLocal(2));
                edgeNormals.add(normals.get(vNextIndex).add(normals.get(vIndex)).normalizeLocal());
                edgePoints.put(nextEdge, vNextEdgeVertIndex);
                if (vertexGroups.size() > 0) {
                    vertexGroups.add(this.interpolateVertexGroups(Arrays.asList(vertexGroups.get(vNextIndex), vertexGroups.get(vIndex))));
                }
            }
            Integer[] indexes = new Integer[] { vIndex, vNextEdgeVertIndex, facePointIndex, vPrevEdgeVertIndex };
            Map<String, List<Vector2f>> newUVSets = null;
            if (uvSets != null) {
                newUVSets = new HashMap<String, List<Vector2f>>(uvSets.size());
                for (Entry<String, List<Vector2f>> uvset : uvSets.entrySet()) {
                    int indexOfvIndex = i;
                    int indexOfvPrevIndex = face.getIndexes().indexOf(vPrevIndex);
                    int indexOfvNextIndex = face.getIndexes().indexOf(vNextIndex);
                    Vector2f uv1 = uvset.getValue().get(indexOfvIndex);
                    Vector2f uv2 = uvset.getValue().get(indexOfvNextIndex).add(uv1).divideLocal(2);
                    Vector2f uv3 = faceUV.get(uvset.getKey());
                    Vector2f uv4 = uvset.getValue().get(indexOfvPrevIndex).add(uv1).divideLocal(2);
                    List<Vector2f> uvList = Arrays.asList(uv1, uv2, uv3, uv4);
                    newUVSets.put(uvset.getKey(), new ArrayList<Vector2f>(uvList));
                }
            }
            List<byte[]> vertexColors = null;
            if (face.getVertexColors() != null) {
                int indexOfvIndex = i;
                int indexOfvPrevIndex = face.getIndexes().indexOf(vPrevIndex);
                int indexOfvNextIndex = face.getIndexes().indexOf(vNextIndex);
                byte[] vCol1 = face.getVertexColors().get(indexOfvIndex);
                byte[] vCol2 = this.interpolateVertexColors(face.getVertexColors().get(indexOfvNextIndex), vCol1);
                byte[] vCol3 = faceVertexColor;
                byte[] vCol4 = this.interpolateVertexColors(face.getVertexColors().get(indexOfvPrevIndex), vCol1);
                vertexColors = new ArrayList<byte[]>(Arrays.asList(vCol1, vCol2, vCol3, vCol4));
            }
            newFaces.add(new Face(indexes, face.isSmooth(), face.getMaterialNumber(), newUVSets, vertexColors, temporalMesh));
            newEdges.add(new Edge(vIndex, vNextEdgeVertIndex, nextEdge.getCrease(), true, temporalMesh));
            newEdges.add(new Edge(vNextEdgeVertIndex, facePointIndex, 0, true, temporalMesh));
            newEdges.add(new Edge(facePointIndex, vPrevEdgeVertIndex, 0, true, temporalMesh));
            newEdges.add(new Edge(vPrevEdgeVertIndex, vIndex, prevEdge.getCrease(), true, temporalMesh));
        }
    }
    vertices.addAll(faceVertices);
    vertices.addAll(edgeVertices);
    normals.addAll(faceNormals);
    normals.addAll(edgeNormals);
    for (Edge edge : temporalMesh.getEdges()) {
        if (!edge.isInFace()) {
            int newVertexIndex = vertices.size();
            vertices.add(vertices.get(edge.getFirstIndex()).add(vertices.get(edge.getSecondIndex())).divideLocal(2));
            normals.add(normals.get(edge.getFirstIndex()).add(normals.get(edge.getSecondIndex())).normalizeLocal());
            newEdges.add(new Edge(edge.getFirstIndex(), newVertexIndex, edge.getCrease(), false, temporalMesh));
            newEdges.add(new Edge(newVertexIndex, edge.getSecondIndex(), edge.getCrease(), false, temporalMesh));
            verticesOnOriginalEdges.add(newVertexIndex);
        }
    }
    temporalMesh.getFaces().clear();
    temporalMesh.getFaces().addAll(newFaces);
    temporalMesh.getEdges().clear();
    temporalMesh.getEdges().addAll(newEdges);
    temporalMesh.rebuildIndexesMappings();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Vector2f(com.jme3.math.Vector2f) ArrayList(java.util.ArrayList) List(java.util.List) Face(com.jme3.scene.plugins.blender.meshes.Face) Vector3f(com.jme3.math.Vector3f) Edge(com.jme3.scene.plugins.blender.meshes.Edge) HashMap(java.util.HashMap) Map(java.util.Map)

Example 4 with Entry

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

the class SubdivisionSurfaceModifier method subdivideUVs.

/**
     * The method subdivides mesh's UV coordinates. It actually performs only Catmull-Clark modifications because if any UV's are present then they are
     * automatically subdivided by the simple algorithm.
     * @param temporalMesh
     *            the mesh whose UV coordinates will be applied Catmull-Clark algorithm
     */
private void subdivideUVs(TemporalMesh temporalMesh) {
    List<Face> faces = temporalMesh.getFaces();
    Map<String, UvCoordsSubdivideTemporalMesh> subdividedUVS = new HashMap<String, UvCoordsSubdivideTemporalMesh>();
    for (Face face : faces) {
        if (face.getUvSets() != null) {
            for (Entry<String, List<Vector2f>> uvset : face.getUvSets().entrySet()) {
                UvCoordsSubdivideTemporalMesh uvCoordsSubdivideTemporalMesh = subdividedUVS.get(uvset.getKey());
                if (uvCoordsSubdivideTemporalMesh == null) {
                    try {
                        uvCoordsSubdivideTemporalMesh = new UvCoordsSubdivideTemporalMesh(temporalMesh.getBlenderContext());
                    } catch (BlenderFileException e) {
                        assert false : "Something went really wrong! The UvCoordsSubdivideTemporalMesh class should NOT throw exceptions here!";
                    }
                    subdividedUVS.put(uvset.getKey(), uvCoordsSubdivideTemporalMesh);
                }
                uvCoordsSubdivideTemporalMesh.addFace(uvset.getValue());
            }
        }
    }
    for (Entry<String, UvCoordsSubdivideTemporalMesh> entry : subdividedUVS.entrySet()) {
        entry.getValue().rebuildIndexesMappings();
        this.subdivideCatmullClark(entry.getValue());
        for (int i = 0; i < faces.size(); ++i) {
            List<Vector2f> uvs = faces.get(i).getUvSets().get(entry.getKey());
            if (uvs != null) {
                uvs.clear();
                uvs.addAll(entry.getValue().faceToUVs(i));
            }
        }
    }
}
Also used : HashMap(java.util.HashMap) BlenderFileException(com.jme3.scene.plugins.blender.file.BlenderFileException) Vector2f(com.jme3.math.Vector2f) ArrayList(java.util.ArrayList) List(java.util.List) Face(com.jme3.scene.plugins.blender.meshes.Face)

Example 5 with Entry

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

the class Face method loadAll.

/**
     * Loads all faces of a given mesh.
     * @param meshStructure
     *            the mesh structure we read the faces from
     * @param userUVGroups
     *            UV groups defined by the user
     * @param verticesColors
     *            the vertices colors of the mesh
     * @param temporalMesh
     *            the temporal mesh the faces will belong to
     * @param blenderContext
     *            the blender context
     * @return list of faces read from the given mesh structure
     * @throws BlenderFileException
     *             an exception is thrown when problems with file reading occur
     */
public static List<Face> loadAll(Structure meshStructure, Map<String, List<Vector2f>> userUVGroups, List<byte[]> verticesColors, TemporalMesh temporalMesh, BlenderContext blenderContext) throws BlenderFileException {
    LOGGER.log(Level.FINE, "Loading all faces from mesh: {0}", meshStructure.getName());
    List<Face> result = new ArrayList<Face>();
    MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
    if (meshHelper.isBMeshCompatible(meshStructure)) {
        LOGGER.fine("Reading BMesh.");
        Pointer pMLoop = (Pointer) meshStructure.getFieldValue("mloop");
        Pointer pMPoly = (Pointer) meshStructure.getFieldValue("mpoly");
        if (pMPoly.isNotNull() && pMLoop.isNotNull()) {
            List<Structure> polys = pMPoly.fetchData();
            List<Structure> loops = pMLoop.fetchData();
            for (Structure poly : polys) {
                int materialNumber = ((Number) poly.getFieldValue("mat_nr")).intValue();
                int loopStart = ((Number) poly.getFieldValue("loopstart")).intValue();
                int totLoop = ((Number) poly.getFieldValue("totloop")).intValue();
                boolean smooth = (((Number) poly.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
                Integer[] vertexIndexes = new Integer[totLoop];
                for (int i = loopStart; i < loopStart + totLoop; ++i) {
                    vertexIndexes[i - loopStart] = ((Number) loops.get(i).getFieldValue("v")).intValue();
                }
                // uvs always must be added wheater we have texture or not
                Map<String, List<Vector2f>> uvCoords = new HashMap<String, List<Vector2f>>();
                for (Entry<String, List<Vector2f>> entry : userUVGroups.entrySet()) {
                    List<Vector2f> uvs = entry.getValue().subList(loopStart, loopStart + totLoop);
                    uvCoords.put(entry.getKey(), new ArrayList<Vector2f>(uvs));
                }
                List<byte[]> vertexColors = null;
                if (verticesColors != null && verticesColors.size() > 0) {
                    vertexColors = new ArrayList<byte[]>(totLoop);
                    for (int i = loopStart; i < loopStart + totLoop; ++i) {
                        vertexColors.add(verticesColors.get(i));
                    }
                }
                result.add(new Face(vertexIndexes, smooth, materialNumber, uvCoords, vertexColors, temporalMesh));
            }
        }
    } else {
        LOGGER.fine("Reading traditional faces.");
        Pointer pMFace = (Pointer) meshStructure.getFieldValue("mface");
        List<Structure> mFaces = pMFace.isNotNull() ? pMFace.fetchData() : null;
        if (mFaces != null && mFaces.size() > 0) {
            // indicates if the material with the specified number should have a texture attached
            for (int i = 0; i < mFaces.size(); ++i) {
                Structure mFace = mFaces.get(i);
                int materialNumber = ((Number) mFace.getFieldValue("mat_nr")).intValue();
                boolean smooth = (((Number) mFace.getFieldValue("flag")).byteValue() & 0x01) != 0x00;
                int v1 = ((Number) mFace.getFieldValue("v1")).intValue();
                int v2 = ((Number) mFace.getFieldValue("v2")).intValue();
                int v3 = ((Number) mFace.getFieldValue("v3")).intValue();
                int v4 = ((Number) mFace.getFieldValue("v4")).intValue();
                int vertCount = v4 == 0 ? 3 : 4;
                // uvs always must be added wheater we have texture or not
                Map<String, List<Vector2f>> faceUVCoords = new HashMap<String, List<Vector2f>>();
                for (Entry<String, List<Vector2f>> entry : userUVGroups.entrySet()) {
                    List<Vector2f> uvCoordsForASingleFace = new ArrayList<Vector2f>(vertCount);
                    for (int j = 0; j < vertCount; ++j) {
                        uvCoordsForASingleFace.add(entry.getValue().get(i * 4 + j));
                    }
                    faceUVCoords.put(entry.getKey(), uvCoordsForASingleFace);
                }
                List<byte[]> vertexColors = null;
                if (verticesColors != null && verticesColors.size() > 0) {
                    vertexColors = new ArrayList<byte[]>(vertCount);
                    vertexColors.add(verticesColors.get(v1));
                    vertexColors.add(verticesColors.get(v2));
                    vertexColors.add(verticesColors.get(v3));
                    if (vertCount == 4) {
                        vertexColors.add(verticesColors.get(v4));
                    }
                }
                result.add(new Face(vertCount == 4 ? new Integer[] { v1, v2, v3, v4 } : new Integer[] { v1, v2, v3 }, smooth, materialNumber, faceUVCoords, vertexColors, temporalMesh));
            }
        }
    }
    LOGGER.log(Level.FINE, "Loaded {0} faces.", result.size());
    return result;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Pointer(com.jme3.scene.plugins.blender.file.Pointer) Vector2f(com.jme3.math.Vector2f) ArrayList(java.util.ArrayList) List(java.util.List) Structure(com.jme3.scene.plugins.blender.file.Structure)

Aggregations

HashMap (java.util.HashMap)17 Map (java.util.Map)13 ArrayList (java.util.ArrayList)11 List (java.util.List)11 Vector2f (com.jme3.math.Vector2f)8 Vector3f (com.jme3.math.Vector3f)7 Node (com.jme3.scene.Node)6 Spatial (com.jme3.scene.Spatial)6 VertexBuffer (com.jme3.scene.VertexBuffer)5 Material (com.jme3.material.Material)4 FloatBuffer (java.nio.FloatBuffer)4 Bone (com.jme3.animation.Bone)3 Geometry (com.jme3.scene.Geometry)3 Mesh (com.jme3.scene.Mesh)3 Pointer (com.jme3.scene.plugins.blender.file.Pointer)3 Structure (com.jme3.scene.plugins.blender.file.Structure)3 Face (com.jme3.scene.plugins.blender.meshes.Face)3 Image (com.jme3.texture.Image)3 IntMap (com.jme3.util.IntMap)3 ByteBuffer (java.nio.ByteBuffer)3