Search in sources :

Example 26 with Face

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

the class TemporalMesh method prepareFacesGeometry.

/**
     * The method creates geometries from faces.
     * @param result
     *            the list where new geometries will be appended
     * @param meshHelper
     *            the mesh helper
     */
protected void prepareFacesGeometry(List<Geometry> result, MeshHelper meshHelper) {
    LOGGER.fine("Preparing faces geometries.");
    this.triangulate();
    Vector3f[] tempVerts = new Vector3f[3];
    Vector3f[] tempNormals = new Vector3f[3];
    byte[][] tempVertColors = new byte[3][];
    List<Map<Float, Integer>> boneBuffers = new ArrayList<Map<Float, Integer>>(3);
    LOGGER.log(Level.FINE, "Appending {0} faces to mesh buffers.", faces.size());
    Map<Integer, MeshBuffers> faceMeshes = new HashMap<Integer, MeshBuffers>();
    for (Face face : faces) {
        MeshBuffers meshBuffers = faceMeshes.get(face.getMaterialNumber());
        if (meshBuffers == null) {
            meshBuffers = new MeshBuffers(face.getMaterialNumber());
            faceMeshes.put(face.getMaterialNumber(), meshBuffers);
        }
        List<List<Integer>> triangulatedIndexes = face.getCurrentIndexes();
        List<byte[]> vertexColors = face.getVertexColors();
        for (List<Integer> indexes : triangulatedIndexes) {
            assert indexes.size() == 3 : "The mesh has not been properly triangulated!";
            Vector3f normal = null;
            if (!face.isSmooth()) {
                normal = FastMath.computeNormal(vertices.get(indexes.get(0)), vertices.get(indexes.get(1)), vertices.get(indexes.get(2)));
            }
            boneBuffers.clear();
            for (int i = 0; i < 3; ++i) {
                int vertIndex = indexes.get(i);
                tempVerts[i] = vertices.get(vertIndex);
                tempNormals[i] = normal != null ? normal : normals.get(vertIndex);
                tempVertColors[i] = vertexColors != null ? vertexColors.get(face.getIndexes().indexOf(vertIndex)) : null;
                if (boneIndexes.size() > 0 && vertexGroups.size() > 0) {
                    Map<Float, Integer> boneBuffersForVertex = new HashMap<Float, Integer>();
                    Map<String, Float> vertexGroupsForVertex = vertexGroups.get(vertIndex);
                    for (Entry<String, Integer> entry : boneIndexes.entrySet()) {
                        if (vertexGroupsForVertex.containsKey(entry.getKey())) {
                            float weight = vertexGroupsForVertex.get(entry.getKey());
                            if (weight > MINIMUM_BONE_WEIGHT) {
                                // only values of weight greater than MINIMUM_BONE_WEIGHT are used
                                // if all non zero weights were used, and they were samm enough, problems with normalisation would occur
                                // because adding a very small value to 1.0 will give 1.0
                                // so in order to avoid such errors, which can cause severe animation artifacts we need to use some minimum weight value
                                boneBuffersForVertex.put(weight, entry.getValue());
                            }
                        }
                    }
                    if (boneBuffersForVertex.size() == 0) {
                        // attach the vertex to zero-indexed bone so that it does not collapse to (0, 0, 0)
                        boneBuffersForVertex.put(1.0f, 0);
                    }
                    boneBuffers.add(boneBuffersForVertex);
                }
            }
            Map<String, List<Vector2f>> uvs = meshHelper.selectUVSubset(face, indexes.toArray(new Integer[indexes.size()]));
            meshBuffers.append(face.isSmooth(), tempVerts, tempNormals, uvs, tempVertColors, boneBuffers);
        }
    }
    LOGGER.fine("Converting mesh buffers to geometries.");
    Map<Geometry, MeshBuffers> geometryToBuffersMap = new HashMap<Geometry, MeshBuffers>();
    for (Entry<Integer, MeshBuffers> entry : faceMeshes.entrySet()) {
        MeshBuffers meshBuffers = entry.getValue();
        Mesh mesh = new Mesh();
        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());
        if (meshBuffers.areVertexColorsUsed()) {
            mesh.setBuffer(Type.Color, 4, meshBuffers.getVertexColorsBuffer());
            mesh.getBuffer(Type.Color).setNormalized(true);
        }
        BoneBuffersData boneBuffersData = meshBuffers.getBoneBuffers();
        if (boneBuffersData != null) {
            mesh.setMaxNumWeights(boneBuffersData.maximumWeightsPerVertex);
            mesh.setBuffer(boneBuffersData.verticesWeights);
            mesh.setBuffer(boneBuffersData.verticesWeightsIndices);
            LOGGER.fine("Generating bind pose and normal buffers.");
            mesh.generateBindPose(true);
            // change the usage type of vertex and normal buffers from Static to Stream
            mesh.getBuffer(Type.Position).setUsage(Usage.Stream);
            mesh.getBuffer(Type.Normal).setUsage(Usage.Stream);
            // creating empty buffers for HW skinning; the buffers will be setup if ever used
            VertexBuffer verticesWeightsHW = new VertexBuffer(Type.HWBoneWeight);
            VertexBuffer verticesWeightsIndicesHW = new VertexBuffer(Type.HWBoneIndex);
            mesh.setBuffer(verticesWeightsHW);
            mesh.setBuffer(verticesWeightsIndicesHW);
        }
        Geometry geometry = new Geometry(name + (result.size() + 1), mesh);
        if (properties != null && properties.getValue() != null) {
            meshHelper.applyProperties(geometry, properties);
        }
        result.add(geometry);
        geometryToBuffersMap.put(geometry, meshBuffers);
    }
    LOGGER.fine("Applying materials to geometries.");
    for (Entry<Geometry, MeshBuffers> entry : geometryToBuffersMap.entrySet()) {
        int materialIndex = entry.getValue().getMaterialIndex();
        Geometry geometry = entry.getKey();
        if (materialIndex >= 0 && materials != null && materials.length > materialIndex && materials[materialIndex] != null) {
            materials[materialIndex].applyMaterial(geometry, meshStructure.getOldMemoryAddress(), entry.getValue().getUvCoords(), blenderContext);
        } else {
            Material defaultMaterial = blenderContext.getDefaultMaterial().clone();
            defaultMaterial.getAdditionalRenderState().setFaceCullMode(FaceCullMode.Off);
            geometry.setMaterial(defaultMaterial);
        }
    }
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) VertexBuffer(com.jme3.scene.VertexBuffer) ArrayList(java.util.ArrayList) BoneBuffersData(com.jme3.scene.plugins.blender.meshes.MeshBuffers.BoneBuffersData) ArrayList(java.util.ArrayList) List(java.util.List) Mesh(com.jme3.scene.Mesh) Material(com.jme3.material.Material) Geometry(com.jme3.scene.Geometry) Vector3f(com.jme3.math.Vector3f) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 27 with Face

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

the class TemporalMesh method clone.

@Override
public TemporalMesh clone() {
    try {
        TemporalMesh result = new TemporalMesh(meshStructure, blenderContext, false);
        result.name = name;
        for (Vector3f v : vertices) {
            result.vertices.add(v.clone());
        }
        for (Vector3f n : normals) {
            result.normals.add(n.clone());
        }
        for (Map<String, Float> group : vertexGroups) {
            result.vertexGroups.add(new HashMap<String, Float>(group));
        }
        for (byte[] vertColor : verticesColors) {
            result.verticesColors.add(vertColor.clone());
        }
        result.materials = materials;
        result.properties = properties;
        result.boneIndexes.putAll(boneIndexes);
        result.postMeshCreationModifiers.addAll(postMeshCreationModifiers);
        for (Face face : faces) {
            result.faces.add(face.clone());
        }
        for (Edge edge : edges) {
            result.edges.add(edge.clone());
        }
        for (Point point : points) {
            result.points.add(point.clone());
        }
        result.rebuildIndexesMappings();
        return result;
    } catch (BlenderFileException e) {
        LOGGER.log(Level.SEVERE, "Error while cloning the temporal mesh: {0}. Returning null.", e.getLocalizedMessage());
    }
    return null;
}
Also used : Vector3f(com.jme3.math.Vector3f) BlenderFileException(com.jme3.scene.plugins.blender.file.BlenderFileException)

Example 28 with Face

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

the class MaskModifier method removeVertexAt.

/**
     * Every face, edge and point that contains
     * the vertex will be removed.
     * @param index
     *            the index of a vertex to be removed
     * @throws IndexOutOfBoundsException
     *             thrown when given index is negative or beyond the count of vertices
     */
private void removeVertexAt(final int index, TemporalMesh temporalMesh) {
    if (index < 0 || index >= temporalMesh.getVertexCount()) {
        throw new IndexOutOfBoundsException("The given index is out of bounds: " + index);
    }
    temporalMesh.getVertices().remove(index);
    temporalMesh.getNormals().remove(index);
    if (temporalMesh.getVertexGroups().size() > 0) {
        temporalMesh.getVertexGroups().remove(index);
    }
    if (temporalMesh.getVerticesColors().size() > 0) {
        temporalMesh.getVerticesColors().remove(index);
    }
    IndexPredicate shiftPredicate = new IndexPredicate() {

        @Override
        public boolean execute(Integer i) {
            return i > index;
        }
    };
    for (int i = temporalMesh.getFaces().size() - 1; i >= 0; --i) {
        Face face = temporalMesh.getFaces().get(i);
        if (face.getIndexes().indexOf(index) >= 0) {
            temporalMesh.getFaces().remove(i);
        } else {
            face.getIndexes().shiftIndexes(-1, shiftPredicate);
        }
    }
    for (int i = temporalMesh.getEdges().size() - 1; i >= 0; --i) {
        Edge edge = temporalMesh.getEdges().get(i);
        if (edge.getFirstIndex() == index || edge.getSecondIndex() == index) {
            temporalMesh.getEdges().remove(i);
        } else {
            edge.shiftIndexes(-1, shiftPredicate);
        }
    }
    for (int i = temporalMesh.getPoints().size() - 1; i >= 0; --i) {
        Point point = temporalMesh.getPoints().get(i);
        if (point.getIndex() == index) {
            temporalMesh.getPoints().remove(i);
        } else {
            point.shiftIndexes(-1, shiftPredicate);
        }
    }
}
Also used : IndexPredicate(com.jme3.scene.plugins.blender.meshes.IndexesLoop.IndexPredicate) Point(com.jme3.scene.plugins.blender.meshes.Point) Face(com.jme3.scene.plugins.blender.meshes.Face) Edge(com.jme3.scene.plugins.blender.meshes.Edge) Point(com.jme3.scene.plugins.blender.meshes.Point)

Example 29 with Face

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

the class Face method clone.

@Override
public Face clone() {
    Face result = new Face();
    result.indexes = indexes.clone();
    result.smooth = smooth;
    result.materialNumber = materialNumber;
    if (faceUVCoords != null) {
        result.faceUVCoords = new HashMap<String, List<Vector2f>>(faceUVCoords.size());
        for (Entry<String, List<Vector2f>> entry : faceUVCoords.entrySet()) {
            List<Vector2f> uvs = new ArrayList<Vector2f>(entry.getValue().size());
            for (Vector2f v : entry.getValue()) {
                uvs.add(v.clone());
            }
            result.faceUVCoords.put(entry.getKey(), uvs);
        }
    }
    if (vertexColors != null) {
        result.vertexColors = new ArrayList<byte[]>(vertexColors.size());
        for (byte[] colors : vertexColors) {
            result.vertexColors.add(colors.clone());
        }
    }
    result.temporalMesh = temporalMesh;
    return result;
}
Also used : Vector2f(com.jme3.math.Vector2f) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 30 with Face

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

the class Face method contains.

/**
     * The method verifies if the edge is contained within the face.
     * It means it cannot cross any other edge and it must be inside the face and not outside of it.
     * @param edge
     *            the edge to be checked
     * @return <b>true</b> if the given edge is contained within the face and <b>false</b> otherwise
     */
private boolean contains(Edge edge) {
    int index1 = edge.getFirstIndex();
    int index2 = edge.getSecondIndex();
    // check if the line between the vertices is not a border edge of the face
    if (!indexes.areNeighbours(index1, index2)) {
        for (int i = 0; i < indexes.size(); ++i) {
            int i1 = this.getIndex(i - 1);
            int i2 = this.getIndex(i);
            // check if the edges have no common verts (because if they do, they cannot cross)
            if (i1 != index1 && i1 != index2 && i2 != index1 && i2 != index2) {
                if (edge.cross(new Edge(i1, i2, 0, false, temporalMesh))) {
                    return false;
                }
            }
        }
        // computing the edge's middle point
        Vector3f edgeMiddlePoint = edge.computeCentroid();
        // computing the edge that is perpendicular to the given edge and has a length of 1 (length actually does not matter)
        Vector3f edgeVector = edge.getSecondVertex().subtract(edge.getFirstVertex());
        Vector3f edgeNormal = temporalMesh.getNormals().get(index1).cross(edgeVector).normalizeLocal();
        Edge e = new Edge(edgeMiddlePoint, edgeNormal.add(edgeMiddlePoint));
        // compute the vectors from the middle point to the crossing between the extended edge 'e' and other edges of the face
        List<Vector3f> crossingVectors = new ArrayList<Vector3f>();
        for (int i = 0; i < indexes.size(); ++i) {
            int i1 = this.getIndex(i);
            int i2 = this.getIndex(i + 1);
            Vector3f crossPoint = e.getCrossPoint(new Edge(i1, i2, 0, false, temporalMesh), true, false);
            if (crossPoint != null) {
                crossingVectors.add(crossPoint.subtractLocal(edgeMiddlePoint));
            }
        }
        if (crossingVectors.size() == 0) {
            // edges do not cross
            return false;
        }
        // use only distinct vertices (doubles may appear if the crossing point is a vertex)
        List<Vector3f> distinctCrossingVectors = new ArrayList<Vector3f>();
        for (Vector3f cv : crossingVectors) {
            double minDistance = Double.MAX_VALUE;
            for (Vector3f dcv : distinctCrossingVectors) {
                minDistance = Math.min(minDistance, dcv.distance(cv));
            }
            if (minDistance > FastMath.FLT_EPSILON) {
                distinctCrossingVectors.add(cv);
            }
        }
        if (distinctCrossingVectors.size() == 0) {
            throw new IllegalStateException("There MUST be at least 2 crossing vertices!");
        }
        // checking if all crossing vectors point to the same direction (if yes then the edge is outside the face)
        // if at least one vector has different direction that this - it means that the edge is inside the face
        float direction = Math.signum(distinctCrossingVectors.get(0).dot(edgeNormal));
        for (int i = 1; i < distinctCrossingVectors.size(); ++i) {
            if (direction != Math.signum(distinctCrossingVectors.get(i).dot(edgeNormal))) {
                return true;
            }
        }
        return false;
    }
    return true;
}
Also used : Vector3f(com.jme3.math.Vector3f) ArrayList(java.util.ArrayList)

Aggregations

Vector3f (com.jme3.math.Vector3f)24 ArrayList (java.util.ArrayList)13 ColorRGBA (com.jme3.math.ColorRGBA)8 Face (com.jme3.scene.plugins.blender.meshes.Face)8 List (java.util.List)8 FloatBuffer (java.nio.FloatBuffer)7 Vector2f (com.jme3.math.Vector2f)6 Structure (com.jme3.scene.plugins.blender.file.Structure)6 VertexBuffer (com.jme3.scene.VertexBuffer)5 Pointer (com.jme3.scene.plugins.blender.file.Pointer)5 Edge (com.jme3.scene.plugins.blender.meshes.Edge)5 TextureCubeMap (com.jme3.texture.TextureCubeMap)5 BlenderFileException (com.jme3.scene.plugins.blender.file.BlenderFileException)4 ByteBuffer (java.nio.ByteBuffer)4 IndexBuffer (com.jme3.scene.mesh.IndexBuffer)3 DynamicArray (com.jme3.scene.plugins.blender.file.DynamicArray)3 Image (com.jme3.texture.Image)3 IOException (java.io.IOException)3 HashMap (java.util.HashMap)3 CubeMapWrapper (com.jme3.environment.util.CubeMapWrapper)2