Search in sources :

Example 81 with Texture

use of com.jme3.texture.Texture 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 82 with Texture

use of com.jme3.texture.Texture in project jmonkeyengine by jMonkeyEngine.

the class TriangulatedTexture method blend.

/**
     * This method blends the each image using the given blender and taking base
     * texture into consideration.
     * 
     * @param textureBlender
     *            the texture blender that holds the blending definition
     * @param baseTexture
     *            the texture that is 'below' the current texture (can be null)
     * @param blenderContext
     *            the blender context
     */
public void blend(TextureBlender textureBlender, TriangulatedTexture baseTexture, BlenderContext blenderContext) {
    Format newFormat = null;
    for (TriangleTextureElement triangleTextureElement : faceTextures) {
        Image baseImage = baseTexture == null ? null : baseTexture.getFaceTextureElement(triangleTextureElement.faceIndex).image;
        triangleTextureElement.image = textureBlender.blend(triangleTextureElement.image, baseImage, blenderContext);
        if (newFormat == null) {
            newFormat = triangleTextureElement.image.getFormat();
        } else if (newFormat != triangleTextureElement.image.getFormat()) {
            throw new IllegalArgumentException("Face texture element images MUST have the same image format!");
        }
    }
    format = newFormat;
}
Also used : Format(com.jme3.texture.Image.Format) Image(com.jme3.texture.Image) BufferedImage(java.awt.image.BufferedImage)

Example 83 with Texture

use of com.jme3.texture.Texture in project jmonkeyengine by jMonkeyEngine.

the class ParticlesModifier method postMeshCreationApply.

@Override
public void postMeshCreationApply(Node node, BlenderContext blenderContext) {
    LOGGER.log(Level.FINE, "Applying particles modifier to: {0}", node);
    MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
    ParticleEmitter emitter = particleEmitter.clone();
    // veryfying the alpha function for particles' texture
    Integer alphaFunction = MaterialHelper.ALPHA_MASK_HYPERBOLE;
    char nameSuffix = emitter.getName().charAt(emitter.getName().length() - 1);
    if (nameSuffix == 'B' || nameSuffix == 'N') {
        alphaFunction = MaterialHelper.ALPHA_MASK_NONE;
    }
    // removing the type suffix from the name
    emitter.setName(emitter.getName().substring(0, emitter.getName().length() - 1));
    // applying emitter shape
    EmitterShape emitterShape = emitter.getShape();
    List<Mesh> meshes = new ArrayList<Mesh>();
    for (Spatial spatial : node.getChildren()) {
        if (spatial instanceof Geometry) {
            Mesh mesh = ((Geometry) spatial).getMesh();
            if (mesh != null) {
                meshes.add(mesh);
                Material material = materialHelper.getParticlesMaterial(((Geometry) spatial).getMaterial(), alphaFunction, blenderContext);
                // TODO: divide into several pieces
                emitter.setMaterial(material);
            }
        }
    }
    if (meshes.size() > 0 && emitterShape instanceof EmitterMeshVertexShape) {
        ((EmitterMeshVertexShape) emitterShape).setMeshes(meshes);
    }
    node.attachChild(emitter);
}
Also used : ParticleEmitter(com.jme3.effect.ParticleEmitter) Geometry(com.jme3.scene.Geometry) Spatial(com.jme3.scene.Spatial) EmitterShape(com.jme3.effect.shapes.EmitterShape) ArrayList(java.util.ArrayList) MaterialHelper(com.jme3.scene.plugins.blender.materials.MaterialHelper) TemporalMesh(com.jme3.scene.plugins.blender.meshes.TemporalMesh) Mesh(com.jme3.scene.Mesh) Material(com.jme3.material.Material) EmitterMeshVertexShape(com.jme3.effect.shapes.EmitterMeshVertexShape)

Example 84 with Texture

use of com.jme3.texture.Texture 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 85 with Texture

use of com.jme3.texture.Texture in project jmonkeyengine by jMonkeyEngine.

the class MaterialContext method applyMaterial.

/**
     * Applies material to a given geometry.
     * 
     * @param geometry
     *            the geometry
     * @param geometriesOMA
     *            the geometries OMA
     * @param userDefinedUVCoordinates
     *            UV coords defined by user
     * @param blenderContext
     *            the blender context
     */
public void applyMaterial(Geometry geometry, Long geometriesOMA, Map<String, List<Vector2f>> userDefinedUVCoordinates, BlenderContext blenderContext) {
    Material material = null;
    if (shadeless) {
        material = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Misc/Unshaded.j3md");
        if (!transparent) {
            diffuseColor.a = 1;
        }
        material.setColor("Color", diffuseColor);
    } else {
        material = new Material(blenderContext.getAssetManager(), "Common/MatDefs/Light/Lighting.j3md");
        material.setBoolean("UseMaterialColors", Boolean.TRUE);
        // setting the colors
        if (!transparent) {
            diffuseColor.a = 1;
        }
        material.setColor("Diffuse", diffuseColor);
        material.setColor("Specular", specularColor);
        material.setFloat("Shininess", shininess);
        material.setColor("Ambient", new ColorRGBA(ambientFactor, ambientFactor, ambientFactor, 1f));
    }
    // applying textures
    int textureIndex = 0;
    if (loadedTextures != null && loadedTextures.size() > 0) {
        if (loadedTextures.size() > TextureHelper.TEXCOORD_TYPES.length) {
            LOGGER.log(Level.WARNING, "The blender file has defined more than {0} different textures. JME supports only {0} UV mappings.", TextureHelper.TEXCOORD_TYPES.length);
        }
        for (CombinedTexture combinedTexture : loadedTextures) {
            if (textureIndex < TextureHelper.TEXCOORD_TYPES.length) {
                String usedUserUVSet = combinedTexture.flatten(geometry, geometriesOMA, userDefinedUVCoordinates, blenderContext);
                this.setTexture(material, combinedTexture.getMappingType(), combinedTexture.getResultTexture());
                List<Vector2f> uvs = combinedTexture.getResultUVS();
                if (uvs != null && uvs.size() > 0) {
                    VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
                    uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
                    geometry.getMesh().setBuffer(uvCoordsBuffer);
                }
                if (usedUserUVSet != null) {
                    userDefinedUVCoordinates = new HashMap<>(userDefinedUVCoordinates);
                    userDefinedUVCoordinates.remove(usedUserUVSet);
                }
            } else {
                LOGGER.log(Level.WARNING, "The texture could not be applied because JME only supports up to {0} different UV's.", TextureHelper.TEXCOORD_TYPES.length);
            }
        }
    }
    if (userDefinedUVCoordinates != null && userDefinedUVCoordinates.size() > 0) {
        LOGGER.fine("Storing unused, user defined UV coordinates sets.");
        if (userDefinedUVCoordinates.size() > TextureHelper.TEXCOORD_TYPES.length) {
            LOGGER.log(Level.WARNING, "The blender file has defined more than {0} different UV coordinates for the mesh. JME supports only {0} UV coordinates buffers.", TextureHelper.TEXCOORD_TYPES.length);
        }
        for (Entry<String, List<Vector2f>> entry : userDefinedUVCoordinates.entrySet()) {
            if (textureIndex < TextureHelper.TEXCOORD_TYPES.length) {
                List<Vector2f> uvs = entry.getValue();
                VertexBuffer uvCoordsBuffer = new VertexBuffer(TextureHelper.TEXCOORD_TYPES[textureIndex++]);
                uvCoordsBuffer.setupData(Usage.Static, 2, Format.Float, BufferUtils.createFloatBuffer(uvs.toArray(new Vector2f[uvs.size()])));
                geometry.getMesh().setBuffer(uvCoordsBuffer);
            } else {
                LOGGER.log(Level.WARNING, "The user's UV set named: '{0}' could not be stored because JME only supports up to {1} different UV's.", new Object[] { entry.getKey(), TextureHelper.TEXCOORD_TYPES.length });
            }
        }
    }
    // applying additional data
    material.setName(name);
    if (vertexColor) {
        material.setBoolean(shadeless ? "VertexColor" : "UseVertexColor", true);
    }
    material.getAdditionalRenderState().setFaceCullMode(faceCullMode != null ? faceCullMode : blenderContext.getBlenderKey().getFaceCullMode());
    if (transparent) {
        material.setTransparent(true);
        material.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
        geometry.setQueueBucket(Bucket.Transparent);
    }
    geometry.setMaterial(material);
}
Also used : ColorRGBA(com.jme3.math.ColorRGBA) VertexBuffer(com.jme3.scene.VertexBuffer) Vector2f(com.jme3.math.Vector2f) Material(com.jme3.material.Material) List(java.util.List) CombinedTexture(com.jme3.scene.plugins.blender.textures.CombinedTexture)

Aggregations

Material (com.jme3.material.Material)97 Texture (com.jme3.texture.Texture)94 Vector3f (com.jme3.math.Vector3f)66 Geometry (com.jme3.scene.Geometry)40 Image (com.jme3.texture.Image)39 TextureKey (com.jme3.asset.TextureKey)31 ArrayList (java.util.ArrayList)27 Texture2D (com.jme3.texture.Texture2D)25 ColorRGBA (com.jme3.math.ColorRGBA)23 Box (com.jme3.scene.shape.Box)19 Spatial (com.jme3.scene.Spatial)18 TerrainQuad (com.jme3.terrain.geomipmap.TerrainQuad)18 ParticleEmitter (com.jme3.effect.ParticleEmitter)17 DirectionalLight (com.jme3.light.DirectionalLight)17 Vector2f (com.jme3.math.Vector2f)17 TerrainLodControl (com.jme3.terrain.geomipmap.TerrainLodControl)16 ByteBuffer (java.nio.ByteBuffer)16 AbstractHeightMap (com.jme3.terrain.heightmap.AbstractHeightMap)15 ImageBasedHeightMap (com.jme3.terrain.heightmap.ImageBasedHeightMap)15 Camera (com.jme3.renderer.Camera)14