Search in sources :

Example 6 with BlenderFileException

use of com.jme3.scene.plugins.blender.file.BlenderFileException 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 7 with BlenderFileException

use of com.jme3.scene.plugins.blender.file.BlenderFileException 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)

Example 8 with BlenderFileException

use of com.jme3.scene.plugins.blender.file.BlenderFileException in project jmonkeyengine by jMonkeyEngine.

the class MeshHelper method loadUVCoordinates.

/**
     * The method loads the UV coordinates. The result is a map where the key is the user's UV set name and the values are UV coordinates.
     * But depending on the mesh type (triangle/quads or bmesh) the lists in the map have different meaning.
     * For bmesh they are enlisted just like they are stored in the blend file (in loops).
     * For traditional faces every 4 UV's should be assigned for a single face.
     * @param meshStructure
     *            the mesh structure
     * @return a map that sorts UV coordinates between different UV sets
     * @throws BlenderFileException
     *             an exception is thrown when problems with blend file occur
     */
@SuppressWarnings("unchecked")
public LinkedHashMap<String, List<Vector2f>> loadUVCoordinates(Structure meshStructure) throws BlenderFileException {
    LOGGER.log(Level.FINE, "Loading UV coordinates from mesh: {0}.", meshStructure.getName());
    LinkedHashMap<String, List<Vector2f>> result = new LinkedHashMap<String, List<Vector2f>>();
    if (this.isBMeshCompatible(meshStructure)) {
        // in this case the UV's are assigned to vertices (an array is the same length as the vertex array)
        Structure loopData = (Structure) meshStructure.getFieldValue("ldata");
        Pointer pLoopDataLayers = (Pointer) loopData.getFieldValue("layers");
        List<Structure> loopDataLayers = pLoopDataLayers.fetchData();
        for (Structure structure : loopDataLayers) {
            Pointer p = (Pointer) structure.getFieldValue("data");
            if (p.isNotNull() && ((Number) structure.getFieldValue("type")).intValue() == MeshHelper.UV_DATA_LAYER_TYPE_BMESH) {
                String uvSetName = structure.getFieldValue("name").toString();
                List<Structure> uvsStructures = p.fetchData();
                List<Vector2f> uvs = new ArrayList<Vector2f>(uvsStructures.size());
                for (Structure uvStructure : uvsStructures) {
                    DynamicArray<Number> loopUVS = (DynamicArray<Number>) uvStructure.getFieldValue("uv");
                    uvs.add(new Vector2f(loopUVS.get(0).floatValue(), loopUVS.get(1).floatValue()));
                }
                result.put(uvSetName, uvs);
            }
        }
    } else {
        // in this case UV's are assigned to faces (the array has the same legnth as the faces count)
        Structure facesData = (Structure) meshStructure.getFieldValue("fdata");
        Pointer pFacesDataLayers = (Pointer) facesData.getFieldValue("layers");
        if (pFacesDataLayers.isNotNull()) {
            List<Structure> facesDataLayers = pFacesDataLayers.fetchData();
            for (Structure structure : facesDataLayers) {
                Pointer p = (Pointer) structure.getFieldValue("data");
                if (p.isNotNull() && ((Number) structure.getFieldValue("type")).intValue() == MeshHelper.UV_DATA_LAYER_TYPE_FMESH) {
                    String uvSetName = structure.getFieldValue("name").toString();
                    List<Structure> uvsStructures = p.fetchData();
                    List<Vector2f> uvs = new ArrayList<Vector2f>(uvsStructures.size());
                    for (Structure uvStructure : uvsStructures) {
                        DynamicArray<Number> mFaceUVs = (DynamicArray<Number>) uvStructure.getFieldValue("uv");
                        uvs.add(new Vector2f(mFaceUVs.get(0).floatValue(), mFaceUVs.get(1).floatValue()));
                        uvs.add(new Vector2f(mFaceUVs.get(2).floatValue(), mFaceUVs.get(3).floatValue()));
                        uvs.add(new Vector2f(mFaceUVs.get(4).floatValue(), mFaceUVs.get(5).floatValue()));
                        uvs.add(new Vector2f(mFaceUVs.get(6).floatValue(), mFaceUVs.get(7).floatValue()));
                    }
                    result.put(uvSetName, uvs);
                }
            }
        }
    }
    return result;
}
Also used : ArrayList(java.util.ArrayList) Pointer(com.jme3.scene.plugins.blender.file.Pointer) LinkedHashMap(java.util.LinkedHashMap) Vector2f(com.jme3.math.Vector2f) DynamicArray(com.jme3.scene.plugins.blender.file.DynamicArray) ArrayList(java.util.ArrayList) List(java.util.List) Structure(com.jme3.scene.plugins.blender.file.Structure)

Example 9 with BlenderFileException

use of com.jme3.scene.plugins.blender.file.BlenderFileException in project jmonkeyengine by jMonkeyEngine.

the class MeshHelper method loadVerticesColors.

/**
     * This method returns the vertices colors. Each vertex is stored in byte[4] array.
     * 
     * @param meshStructure
     *            the structure containing the mesh data
     * @param blenderContext
     *            the blender context
     * @return a list of vertices colors, each color belongs to a single vertex or empty list of colors are not specified
     * @throws BlenderFileException
     *             this exception is thrown when the blend file structure is somehow invalid or corrupted
     */
public List<byte[]> loadVerticesColors(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
    LOGGER.log(Level.FINE, "Loading vertices colors from mesh: {0}.", meshStructure.getName());
    MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
    Pointer pMCol = (Pointer) meshStructure.getFieldValue(meshHelper.isBMeshCompatible(meshStructure) ? "mloopcol" : "mcol");
    List<byte[]> verticesColors = new ArrayList<byte[]>();
    // it was likely a bug in blender untill version 2.63 (the blue and red factors were misplaced in their structure)
    // so we need to put them right
    boolean useBGRA = blenderContext.getBlenderVersion() < 263;
    if (pMCol.isNotNull()) {
        List<Structure> mCol = pMCol.fetchData();
        for (Structure color : mCol) {
            byte r = ((Number) color.getFieldValue("r")).byteValue();
            byte g = ((Number) color.getFieldValue("g")).byteValue();
            byte b = ((Number) color.getFieldValue("b")).byteValue();
            byte a = ((Number) color.getFieldValue("a")).byteValue();
            verticesColors.add(useBGRA ? new byte[] { b, g, r, a } : new byte[] { r, g, b, a });
        }
    }
    return verticesColors;
}
Also used : ArrayList(java.util.ArrayList) Pointer(com.jme3.scene.plugins.blender.file.Pointer) Structure(com.jme3.scene.plugins.blender.file.Structure)

Example 10 with BlenderFileException

use of com.jme3.scene.plugins.blender.file.BlenderFileException in project jmonkeyengine by jMonkeyEngine.

the class MeshHelper method toTemporalMesh.

/**
     * Converts the mesh structure into temporal mesh.
     * The temporal mesh is stored in blender context and here always a clone is being returned because the mesh might
     * be modified by modifiers.
     * 
     * @param meshStructure
     *            the mesh structure
     * @param blenderContext
     *            the blender context
     * @return temporal mesh read from the given structure
     * @throws BlenderFileException
     *             an exception is thrown when problems with reading blend file occur
     */
public TemporalMesh toTemporalMesh(Structure meshStructure, BlenderContext blenderContext) throws BlenderFileException {
    LOGGER.log(Level.FINE, "Loading temporal mesh named: {0}.", meshStructure.getName());
    TemporalMesh temporalMesh = (TemporalMesh) blenderContext.getLoadedFeature(meshStructure.getOldMemoryAddress(), LoadedDataType.TEMPORAL_MESH);
    if (temporalMesh != null) {
        LOGGER.fine("The mesh is already loaded. Returning its clone.");
        return temporalMesh.clone();
    }
    if ("ID".equals(meshStructure.getType())) {
        LOGGER.fine("Loading mesh from external blend file.");
        return (TemporalMesh) this.loadLibrary(meshStructure);
    }
    String name = meshStructure.getName();
    LOGGER.log(Level.FINE, "Reading mesh: {0}.", name);
    temporalMesh = new TemporalMesh(meshStructure, blenderContext);
    LOGGER.fine("Loading materials.");
    MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
    temporalMesh.setMaterials(materialHelper.getMaterials(meshStructure, blenderContext));
    LOGGER.fine("Reading custom properties.");
    Properties properties = this.loadProperties(meshStructure, blenderContext);
    temporalMesh.setProperties(properties);
    blenderContext.addLoadedFeatures(meshStructure.getOldMemoryAddress(), LoadedDataType.STRUCTURE, meshStructure);
    blenderContext.addLoadedFeatures(meshStructure.getOldMemoryAddress(), LoadedDataType.TEMPORAL_MESH, temporalMesh);
    return temporalMesh.clone();
}
Also used : MaterialHelper(com.jme3.scene.plugins.blender.materials.MaterialHelper) Properties(com.jme3.scene.plugins.blender.objects.Properties)

Aggregations

Structure (com.jme3.scene.plugins.blender.file.Structure)31 Pointer (com.jme3.scene.plugins.blender.file.Pointer)26 ArrayList (java.util.ArrayList)19 BlenderFileException (com.jme3.scene.plugins.blender.file.BlenderFileException)10 Vector3f (com.jme3.math.Vector3f)7 FileBlockHeader (com.jme3.scene.plugins.blender.file.FileBlockHeader)7 List (java.util.List)7 DynamicArray (com.jme3.scene.plugins.blender.file.DynamicArray)6 TemporalMesh (com.jme3.scene.plugins.blender.meshes.TemporalMesh)5 Map (java.util.Map)5 Node (com.jme3.scene.Node)4 AnimationHelper (com.jme3.scene.plugins.blender.animations.AnimationHelper)4 MeshHelper (com.jme3.scene.plugins.blender.meshes.MeshHelper)4 ObjectHelper (com.jme3.scene.plugins.blender.objects.ObjectHelper)4 Texture (com.jme3.texture.Texture)4 HashMap (java.util.HashMap)4 BlenderKey (com.jme3.asset.BlenderKey)3 Light (com.jme3.light.Light)3 ColorRGBA (com.jme3.math.ColorRGBA)3 Spline (com.jme3.math.Spline)3