Search in sources :

Example 16 with Entry

use of com.jme3.util.IntMap.Entry 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 17 with Entry

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

the class TextureHelper method readTextureData.

/**
     * Reads the texture data from the given material or sky structure.
     * @param structure
     *            the structure of material or sky
     * @param diffuseColorArray
     *            array of diffuse colors
     * @param skyTexture
     *            indicates it we're going to read sky texture or not
     * @return a list of combined textures
     * @throws BlenderFileException
     *             an exception is thrown when problems with reading the blend file occur
     */
@SuppressWarnings("unchecked")
public List<CombinedTexture> readTextureData(Structure structure, float[] diffuseColorArray, boolean skyTexture) throws BlenderFileException {
    DynamicArray<Pointer> mtexsArray = (DynamicArray<Pointer>) structure.getFieldValue("mtex");
    int separatedTextures = skyTexture ? 0 : ((Number) structure.getFieldValue("septex")).intValue();
    List<TextureData> texturesList = new ArrayList<TextureData>();
    for (int i = 0; i < mtexsArray.getTotalSize(); ++i) {
        Pointer p = mtexsArray.get(i);
        if (p.isNotNull() && (separatedTextures & 1 << i) == 0) {
            TextureData textureData = new TextureData();
            textureData.mtex = p.fetchData().get(0);
            textureData.uvCoordinatesType = skyTexture ? UVCoordinatesType.TEXCO_ORCO.blenderValue : ((Number) textureData.mtex.getFieldValue("texco")).intValue();
            textureData.projectionType = ((Number) textureData.mtex.getFieldValue("mapping")).intValue();
            textureData.uvCoordinatesName = textureData.mtex.getFieldValue("uvName").toString();
            if (textureData.uvCoordinatesName != null && textureData.uvCoordinatesName.trim().length() == 0) {
                textureData.uvCoordinatesName = null;
            }
            Pointer pTex = (Pointer) textureData.mtex.getFieldValue("tex");
            if (pTex.isNotNull()) {
                Structure tex = pTex.fetchData().get(0);
                textureData.textureStructure = tex;
                texturesList.add(textureData);
            }
        }
    }
    LOGGER.info("Loading model's textures.");
    List<CombinedTexture> loadedTextures = new ArrayList<CombinedTexture>();
    if (blenderContext.getBlenderKey().isOptimiseTextures()) {
        LOGGER.fine("Optimising the useage of model's textures.");
        Map<Number, List<TextureData>> textureDataMap = this.sortTextures(texturesList);
        for (Entry<Number, List<TextureData>> entry : textureDataMap.entrySet()) {
            if (entry.getValue().size() > 0) {
                CombinedTexture combinedTexture = new CombinedTexture(entry.getKey().intValue(), !skyTexture);
                for (TextureData textureData : entry.getValue()) {
                    int texflag = ((Number) textureData.mtex.getFieldValue("texflag")).intValue();
                    boolean negateTexture = (texflag & 0x04) != 0;
                    Texture texture = this.getTexture(textureData.textureStructure, textureData.mtex, blenderContext);
                    if (texture != null) {
                        int blendType = ((Number) textureData.mtex.getFieldValue("blendtype")).intValue();
                        float[] color = new float[] { ((Number) textureData.mtex.getFieldValue("r")).floatValue(), ((Number) textureData.mtex.getFieldValue("g")).floatValue(), ((Number) textureData.mtex.getFieldValue("b")).floatValue() };
                        float colfac = ((Number) textureData.mtex.getFieldValue("colfac")).floatValue();
                        TextureBlender textureBlender = TextureBlenderFactory.createTextureBlender(texture.getImage().getFormat(), texflag, negateTexture, blendType, diffuseColorArray, color, colfac);
                        combinedTexture.add(texture, textureBlender, textureData.uvCoordinatesType, textureData.projectionType, textureData.textureStructure, textureData.uvCoordinatesName, blenderContext);
                    }
                }
                if (combinedTexture.getTexturesCount() > 0) {
                    loadedTextures.add(combinedTexture);
                }
            }
        }
    } else {
        LOGGER.fine("No textures optimisation applied.");
        int[] mappings = new int[] { MaterialContext.MTEX_COL, MaterialContext.MTEX_NOR, MaterialContext.MTEX_EMIT, MaterialContext.MTEX_SPEC, MaterialContext.MTEX_ALPHA, MaterialContext.MTEX_AMB };
        for (TextureData textureData : texturesList) {
            Texture texture = this.getTexture(textureData.textureStructure, textureData.mtex, blenderContext);
            if (texture != null) {
                Number mapto = (Number) textureData.mtex.getFieldValue("mapto");
                int texflag = ((Number) textureData.mtex.getFieldValue("texflag")).intValue();
                boolean negateTexture = (texflag & 0x04) != 0;
                for (int i = 0; i < mappings.length; ++i) {
                    if ((mappings[i] & mapto.intValue()) != 0) {
                        CombinedTexture combinedTexture = new CombinedTexture(mappings[i], !skyTexture);
                        int blendType = ((Number) textureData.mtex.getFieldValue("blendtype")).intValue();
                        float[] color = new float[] { ((Number) textureData.mtex.getFieldValue("r")).floatValue(), ((Number) textureData.mtex.getFieldValue("g")).floatValue(), ((Number) textureData.mtex.getFieldValue("b")).floatValue() };
                        float colfac = ((Number) textureData.mtex.getFieldValue("colfac")).floatValue();
                        TextureBlender textureBlender = TextureBlenderFactory.createTextureBlender(texture.getImage().getFormat(), texflag, negateTexture, blendType, diffuseColorArray, color, colfac);
                        combinedTexture.add(texture, textureBlender, textureData.uvCoordinatesType, textureData.projectionType, textureData.textureStructure, textureData.uvCoordinatesName, blenderContext);
                        if (combinedTexture.getTexturesCount() > 0) {
                            // the added texture might not have been accepted (if for example loading generated textures is disabled)
                            loadedTextures.add(combinedTexture);
                        }
                    }
                }
            }
        }
    }
    return loadedTextures;
}
Also used : ArrayList(java.util.ArrayList) Pointer(com.jme3.scene.plugins.blender.file.Pointer) TextureBlender(com.jme3.scene.plugins.blender.textures.blending.TextureBlender) Texture(com.jme3.texture.Texture) 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 18 with Entry

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

the class TriangulatedTexture method castToUVS.

/**
     * This method alters the images to fit them into UV coordinates of the
     * given target texture.
     * 
     * @param targetTexture
     *            the texture to whose UV coordinates we fit current images
     * @param blenderContext
     *            the blender context
     */
public void castToUVS(TriangulatedTexture targetTexture, BlenderContext blenderContext) {
    int[] sourceSize = new int[2], targetSize = new int[2];
    ImageLoader imageLoader = new ImageLoader();
    TextureHelper textureHelper = blenderContext.getHelper(TextureHelper.class);
    for (TriangleTextureElement entry : faceTextures) {
        TriangleTextureElement targetFaceTextureElement = targetTexture.getFaceTextureElement(entry.faceIndex);
        Vector2f[] dest = targetFaceTextureElement.uv;
        // get the sizes of the source and target images
        sourceSize[0] = entry.image.getWidth();
        sourceSize[1] = entry.image.getHeight();
        targetSize[0] = targetFaceTextureElement.image.getWidth();
        targetSize[1] = targetFaceTextureElement.image.getHeight();
        // create triangle transformation
        AffineTransform affineTransform = textureHelper.createAffineTransform(entry.uv, dest, sourceSize, targetSize);
        // compute the result texture
        BufferedImage sourceImage = ImageToAwt.convert(entry.image, false, true, 0);
        BufferedImage targetImage = new BufferedImage(targetSize[0], targetSize[1], sourceImage.getType());
        Graphics2D g = targetImage.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(sourceImage, affineTransform, null);
        g.dispose();
        Image output = imageLoader.load(targetImage, false);
        entry.image = output;
        entry.uv[0].set(dest[0]);
        entry.uv[1].set(dest[1]);
        entry.uv[2].set(dest[2]);
    }
}
Also used : Vector2f(com.jme3.math.Vector2f) AffineTransform(java.awt.geom.AffineTransform) Image(com.jme3.texture.Image) BufferedImage(java.awt.image.BufferedImage) BufferedImage(java.awt.image.BufferedImage) Graphics2D(java.awt.Graphics2D)

Example 19 with Entry

use of com.jme3.util.IntMap.Entry 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 20 with Entry

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

the class MeshBuffers method getBoneBuffers.

/**
     * @return bone buffers
     */
public BoneBuffersData getBoneBuffers() {
    BoneBuffersData result = null;
    if (maximumWeightsPerVertex > 0) {
        this.normalizeBoneBuffers(MAXIMUM_WEIGHTS_PER_VERTEX);
        maximumWeightsPerVertex = MAXIMUM_WEIGHTS_PER_VERTEX;
        FloatBuffer weightsFloatData = BufferUtils.createFloatBuffer(boneWeightAndIndexes.size() * MAXIMUM_WEIGHTS_PER_VERTEX);
        ByteBuffer indicesData = BufferUtils.createByteBuffer(boneWeightAndIndexes.size() * MAXIMUM_WEIGHTS_PER_VERTEX);
        int index = 0;
        for (Map<Float, Integer> boneBuffersData : boneWeightAndIndexes) {
            if (boneBuffersData.size() > 0) {
                int count = 0;
                for (Entry<Float, Integer> entry : boneBuffersData.entrySet()) {
                    weightsFloatData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX + count, entry.getKey());
                    indicesData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX + count, entry.getValue().byteValue());
                    ++count;
                }
            } else {
                // if no bone is assigned to this vertex then attach it to the 0-indexed root bone
                weightsFloatData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX, 1.0f);
                indicesData.put(index * MAXIMUM_WEIGHTS_PER_VERTEX, (byte) 0);
            }
            ++index;
        }
        VertexBuffer verticesWeights = new VertexBuffer(Type.BoneWeight);
        verticesWeights.setupData(Usage.CpuOnly, maximumWeightsPerVertex, Format.Float, weightsFloatData);
        VertexBuffer verticesWeightsIndices = new VertexBuffer(Type.BoneIndex);
        verticesWeightsIndices.setupData(Usage.CpuOnly, maximumWeightsPerVertex, Format.UnsignedByte, indicesData);
        result = new BoneBuffersData(maximumWeightsPerVertex, verticesWeights, verticesWeightsIndices);
    }
    return result;
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer) FloatBuffer(java.nio.FloatBuffer) ByteBuffer(java.nio.ByteBuffer)

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