Search in sources :

Example 6 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class GeometryBatchFactory method mergeGeometries.

/**
     * Merges all geometries in the collection into
     * the output mesh. Creates a new material using the TextureAtlas.
     * 
     * @param geometries
     * @param outMesh
     */
public static void mergeGeometries(Collection<Geometry> geometries, Mesh outMesh) {
    int[] compsForBuf = new int[VertexBuffer.Type.values().length];
    Format[] formatForBuf = new Format[compsForBuf.length];
    boolean[] normForBuf = new boolean[VertexBuffer.Type.values().length];
    int totalVerts = 0;
    int totalTris = 0;
    int totalLodLevels = 0;
    int maxWeights = -1;
    Mode mode = null;
    for (Geometry geom : geometries) {
        totalVerts += geom.getVertexCount();
        totalTris += geom.getTriangleCount();
        totalLodLevels = Math.min(totalLodLevels, geom.getMesh().getNumLodLevels());
        Mode listMode;
        int components;
        switch(geom.getMesh().getMode()) {
            case Points:
                listMode = Mode.Points;
                components = 0;
                break;
            case LineLoop:
            case LineStrip:
            case Lines:
                listMode = Mode.Lines;
                components = 2;
                break;
            case TriangleFan:
            case TriangleStrip:
            case Triangles:
                listMode = Mode.Triangles;
                components = 3;
                break;
            default:
                throw new UnsupportedOperationException();
        }
        for (VertexBuffer vb : geom.getMesh().getBufferList().getArray()) {
            int currentCompsForBuf = compsForBuf[vb.getBufferType().ordinal()];
            if (vb.getBufferType() != Type.Index && currentCompsForBuf != 0 && currentCompsForBuf != vb.getNumComponents()) {
                throw new UnsupportedOperationException("The geometry " + geom + " buffer " + vb.getBufferType() + " has different number of components than the rest of the meshes " + "(this: " + vb.getNumComponents() + ", expected: " + currentCompsForBuf + ")");
            }
            compsForBuf[vb.getBufferType().ordinal()] = vb.getNumComponents();
            formatForBuf[vb.getBufferType().ordinal()] = vb.getFormat();
            normForBuf[vb.getBufferType().ordinal()] = vb.isNormalized();
        }
        maxWeights = Math.max(maxWeights, geom.getMesh().getMaxNumWeights());
        if (mode != null && mode != listMode) {
            throw new UnsupportedOperationException("Cannot combine different" + " primitive types: " + mode + " != " + listMode);
        }
        mode = listMode;
        compsForBuf[Type.Index.ordinal()] = components;
    }
    outMesh.setMaxNumWeights(maxWeights);
    outMesh.setMode(mode);
    if (totalVerts >= 65536) {
        // make sure we create an UnsignedInt buffer so
        // we can fit all of the meshes
        formatForBuf[Type.Index.ordinal()] = Format.UnsignedInt;
    } else {
        formatForBuf[Type.Index.ordinal()] = Format.UnsignedShort;
    }
    // generate output buffers based on retrieved info
    for (int i = 0; i < compsForBuf.length; i++) {
        if (compsForBuf[i] == 0) {
            continue;
        }
        Buffer data;
        if (i == Type.Index.ordinal()) {
            data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalTris);
        } else {
            data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalVerts);
        }
        VertexBuffer vb = new VertexBuffer(Type.values()[i]);
        vb.setupData(Usage.Static, compsForBuf[i], formatForBuf[i], data);
        vb.setNormalized(normForBuf[i]);
        outMesh.setBuffer(vb);
    }
    int globalVertIndex = 0;
    int globalTriIndex = 0;
    for (Geometry geom : geometries) {
        Mesh inMesh = geom.getMesh();
        geom.computeWorldMatrix();
        Matrix4f worldMatrix = geom.getWorldMatrix();
        int geomVertCount = inMesh.getVertexCount();
        int geomTriCount = inMesh.getTriangleCount();
        for (int bufType = 0; bufType < compsForBuf.length; bufType++) {
            VertexBuffer inBuf = inMesh.getBuffer(Type.values()[bufType]);
            VertexBuffer outBuf = outMesh.getBuffer(Type.values()[bufType]);
            if (inBuf == null || outBuf == null) {
                continue;
            }
            if (Type.Index.ordinal() == bufType) {
                int components = compsForBuf[bufType];
                IndexBuffer inIdx = inMesh.getIndicesAsList();
                IndexBuffer outIdx = outMesh.getIndexBuffer();
                for (int tri = 0; tri < geomTriCount; tri++) {
                    for (int comp = 0; comp < components; comp++) {
                        int idx = inIdx.get(tri * components + comp) + globalVertIndex;
                        outIdx.put((globalTriIndex + tri) * components + comp, idx);
                    }
                }
            } else if (Type.Position.ordinal() == bufType) {
                FloatBuffer inPos = (FloatBuffer) inBuf.getDataReadOnly();
                FloatBuffer outPos = (FloatBuffer) outBuf.getData();
                doTransformVerts(inPos, globalVertIndex, outPos, worldMatrix);
            } else if (Type.Normal.ordinal() == bufType) {
                FloatBuffer inPos = (FloatBuffer) inBuf.getDataReadOnly();
                FloatBuffer outPos = (FloatBuffer) outBuf.getData();
                doTransformNorms(inPos, globalVertIndex, outPos, worldMatrix);
            } else if (Type.Tangent.ordinal() == bufType) {
                FloatBuffer inPos = (FloatBuffer) inBuf.getDataReadOnly();
                FloatBuffer outPos = (FloatBuffer) outBuf.getData();
                int components = inBuf.getNumComponents();
                doTransformTangents(inPos, globalVertIndex, components, outPos, worldMatrix);
            } else {
                inBuf.copyElements(0, outBuf, globalVertIndex, geomVertCount);
            }
        }
        globalVertIndex += geomVertCount;
        globalTriIndex += geomTriCount;
    }
}
Also used : FloatBuffer(java.nio.FloatBuffer) ShortBuffer(java.nio.ShortBuffer) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) IntBuffer(java.nio.IntBuffer) Buffer(java.nio.Buffer) Mode(com.jme3.scene.Mesh.Mode) FloatBuffer(java.nio.FloatBuffer) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) Matrix4f(com.jme3.math.Matrix4f) Format(com.jme3.scene.VertexBuffer.Format)

Example 7 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class GeometryBatchFactory method alignBuffers.

/**
     * Will ensure that all the geometries' meshes of the n sub graph have the 
     * same types of buffers
     * @param n the node to gather geometries from
     * @param option the align options 
     * @see AlignOption
     * 
     * Very experimental for now.
     */
public static void alignBuffers(Node n, AlignOption option) {
    List<Geometry> geoms = new ArrayList<Geometry>();
    gatherGeoms(n, geoms);
    //gather buffer types
    Map<VertexBuffer.Type, VertexBuffer> types = new EnumMap<VertexBuffer.Type, VertexBuffer>(VertexBuffer.Type.class);
    Map<VertexBuffer.Type, Integer> typesCount = new EnumMap<VertexBuffer.Type, Integer>(VertexBuffer.Type.class);
    for (Geometry geom : geoms) {
        for (VertexBuffer buffer : geom.getMesh().getBufferList()) {
            if (types.get(buffer.getBufferType()) == null) {
                types.put(buffer.getBufferType(), buffer);
                logger.log(Level.FINE, buffer.getBufferType().toString());
            }
            Integer count = typesCount.get(buffer.getBufferType());
            if (count == null) {
                count = 0;
            }
            count++;
            typesCount.put(buffer.getBufferType(), count);
        }
    }
    switch(option) {
        case RemoveUnalignedBuffers:
            for (Geometry geom : geoms) {
                for (VertexBuffer buffer : geom.getMesh().getBufferList()) {
                    Integer count = typesCount.get(buffer.getBufferType());
                    if (count != null && count < geoms.size()) {
                        geom.getMesh().clearBuffer(buffer.getBufferType());
                        logger.log(Level.FINE, "removing {0} from {1}", new Object[] { buffer.getBufferType(), geom.getName() });
                    }
                }
            }
            break;
        case CreateMissingBuffers:
            for (Geometry geom : geoms) {
                for (VertexBuffer.Type type : types.keySet()) {
                    if (geom.getMesh().getBuffer(type) == null) {
                        VertexBuffer vb = new VertexBuffer(type);
                        Buffer b;
                        switch(type) {
                            case Index:
                            case BoneIndex:
                            case HWBoneIndex:
                                b = BufferUtils.createIntBuffer(geom.getMesh().getVertexCount() * types.get(type).getNumComponents());
                                break;
                            case InterleavedData:
                                b = BufferUtils.createByteBuffer(geom.getMesh().getVertexCount() * types.get(type).getNumComponents());
                                break;
                            default:
                                b = BufferUtils.createFloatBuffer(geom.getMesh().getVertexCount() * types.get(type).getNumComponents());
                        }
                        vb.setupData(types.get(type).getUsage(), types.get(type).getNumComponents(), types.get(type).getFormat(), b);
                        geom.getMesh().setBuffer(vb);
                        logger.log(Level.FINE, "geom {0} misses buffer {1}. Creating", new Object[] { geom.getName(), type });
                    }
                }
            }
            break;
    }
}
Also used : FloatBuffer(java.nio.FloatBuffer) ShortBuffer(java.nio.ShortBuffer) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) IntBuffer(java.nio.IntBuffer) Buffer(java.nio.Buffer) Type(com.jme3.scene.VertexBuffer.Type) Type(com.jme3.scene.VertexBuffer.Type)

Example 8 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class TextureAtlas method applyAtlasCoords.

private static void applyAtlasCoords(List<Geometry> geometries, Mesh outMesh, TextureAtlas atlas) {
    int globalVertIndex = 0;
    for (Geometry geom : geometries) {
        Mesh inMesh = geom.getMesh();
        geom.computeWorldMatrix();
        int geomVertCount = inMesh.getVertexCount();
        VertexBuffer inBuf = inMesh.getBuffer(Type.TexCoord);
        VertexBuffer outBuf = outMesh.getBuffer(Type.TexCoord);
        if (inBuf == null || outBuf == null) {
            continue;
        }
        atlas.applyCoords(geom, globalVertIndex, outMesh);
        globalVertIndex += geomVertCount;
    }
}
Also used : Geometry(com.jme3.scene.Geometry) VertexBuffer(com.jme3.scene.VertexBuffer) Mesh(com.jme3.scene.Mesh)

Example 9 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class TextureAtlas method applyCoords.

/**
     * Applies the texture coordinates to the given output mesh
     * if the DiffuseMap or ColorMap of the input geometry exist in the atlas.
     * @param geom The geometry to change the texture coordinate buffer on.
     * @param offset Target buffer offset.
     * @param outMesh The mesh to set the coords in (can be same as input).
     * @return true if texture has been found and coords have been changed, false otherwise.
     */
public boolean applyCoords(Geometry geom, int offset, Mesh outMesh) {
    Mesh inMesh = geom.getMesh();
    geom.computeWorldMatrix();
    VertexBuffer inBuf = inMesh.getBuffer(Type.TexCoord);
    VertexBuffer outBuf = outMesh.getBuffer(Type.TexCoord);
    if (inBuf == null || outBuf == null) {
        throw new IllegalStateException("Geometry mesh has no texture coordinate buffer.");
    }
    Texture tex = getMaterialTexture(geom, "DiffuseMap");
    if (tex == null) {
        tex = getMaterialTexture(geom, "ColorMap");
    }
    if (tex != null) {
        TextureAtlasTile tile = getAtlasTile(tex);
        if (tile != null) {
            FloatBuffer inPos = (FloatBuffer) inBuf.getData();
            FloatBuffer outPos = (FloatBuffer) outBuf.getData();
            tile.transformTextureCoords(inPos, offset, outPos);
            return true;
        } else {
            return false;
        }
    } else {
        throw new IllegalStateException("Geometry has no proper texture.");
    }
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer) Mesh(com.jme3.scene.Mesh) FloatBuffer(java.nio.FloatBuffer) MatParamTexture(com.jme3.material.MatParamTexture) Texture(com.jme3.texture.Texture)

Example 10 with Geometry

use of com.jme3.scene.Geometry in project jmonkeyengine by jMonkeyEngine.

the class TextureAtlas method makeAtlasBatch.

/**
     * Creates one geometry out of the given root spatial and merges all single
     * textures into one texture of the given size.
     * @param spat The root spatial of the scene to batch
     * @param mgr An assetmanager that can be used to create the material.
     * @param atlasSize A size for the atlas texture, it has to be large enough to hold all single textures.
     * @return A new geometry that uses the generated texture atlas and merges all meshes of the root spatial, null if the atlas cannot be created because not all textures fit.
     */
public static Geometry makeAtlasBatch(Spatial spat, AssetManager mgr, int atlasSize) {
    List<Geometry> geometries = new ArrayList<Geometry>();
    GeometryBatchFactory.gatherGeoms(spat, geometries);
    TextureAtlas atlas = createAtlas(spat, atlasSize);
    if (atlas == null) {
        return null;
    }
    Geometry geom = new Geometry();
    Mesh mesh = new Mesh();
    GeometryBatchFactory.mergeGeometries(geometries, mesh);
    applyAtlasCoords(geometries, mesh, atlas);
    mesh.updateCounts();
    mesh.updateBound();
    geom.setMesh(mesh);
    Material mat = new Material(mgr, "Common/MatDefs/Light/Lighting.j3md");
    Texture diffuseMap = atlas.getAtlasTexture("DiffuseMap");
    Texture normalMap = atlas.getAtlasTexture("NormalMap");
    Texture specularMap = atlas.getAtlasTexture("SpecularMap");
    if (diffuseMap != null) {
        mat.setTexture("DiffuseMap", diffuseMap);
    }
    if (normalMap != null) {
        mat.setTexture("NormalMap", normalMap);
    }
    if (specularMap != null) {
        mat.setTexture("SpecularMap", specularMap);
    }
    mat.setFloat("Shininess", 16.0f);
    geom.setMaterial(mat);
    return geom;
}
Also used : Geometry(com.jme3.scene.Geometry) ArrayList(java.util.ArrayList) Mesh(com.jme3.scene.Mesh) Material(com.jme3.material.Material) MatParamTexture(com.jme3.material.MatParamTexture) Texture(com.jme3.texture.Texture)

Aggregations

Geometry (com.jme3.scene.Geometry)246 Material (com.jme3.material.Material)175 Vector3f (com.jme3.math.Vector3f)116 Box (com.jme3.scene.shape.Box)92 DirectionalLight (com.jme3.light.DirectionalLight)56 Node (com.jme3.scene.Node)54 Sphere (com.jme3.scene.shape.Sphere)49 Spatial (com.jme3.scene.Spatial)41 Quaternion (com.jme3.math.Quaternion)39 Quad (com.jme3.scene.shape.Quad)33 Texture (com.jme3.texture.Texture)30 RigidBodyControl (com.jme3.bullet.control.RigidBodyControl)26 Mesh (com.jme3.scene.Mesh)25 KeyTrigger (com.jme3.input.controls.KeyTrigger)24 AmbientLight (com.jme3.light.AmbientLight)24 ColorRGBA (com.jme3.math.ColorRGBA)21 FilterPostProcessor (com.jme3.post.FilterPostProcessor)21 PointLight (com.jme3.light.PointLight)20 Vector2f (com.jme3.math.Vector2f)17 FloatBuffer (java.nio.FloatBuffer)17