Search in sources :

Example 46 with VertexBuffer

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

the class TestLodGeneration method makeLod.

private void makeLod(final LodGenerator.TriangleReductionMethod method, final float value, final int ll) {
    exec.execute(new Runnable() {

        public void run() {
            for (final Geometry geometry : listGeoms) {
                LodGenerator lODGenerator = new LodGenerator(geometry);
                final VertexBuffer[] lods = lODGenerator.computeLods(method, value);
                enqueue(new Callable<Void>() {

                    public Void call() throws Exception {
                        geometry.getMesh().setLodLevels(lods);
                        lodLevel = 0;
                        if (geometry.getMesh().getNumLodLevels() > ll) {
                            lodLevel = ll;
                        }
                        geometry.setLodLevel(lodLevel);
                        hudText.setText(computeNbTri() + " tris");
                        return null;
                    }
                });
            }
        }
    });
}
Also used : Geometry(com.jme3.scene.Geometry) LodGenerator(jme3tools.optimize.LodGenerator) Callable(java.util.concurrent.Callable)

Example 47 with VertexBuffer

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

the class MeshLoader method pushTexCoord.

private void pushTexCoord(Attributes attribs) throws SAXException {
    if (texCoordIndex >= 8) {
        // More than 8 not supported by ogre.
        return;
    }
    Type type = TEXCOORD_TYPES[texCoordIndex];
    VertexBuffer tcvb = mesh.getBuffer(type);
    FloatBuffer buf = (FloatBuffer) tcvb.getData();
    buf.put(parseFloat(attribs.getValue("u")));
    if (tcvb.getNumComponents() >= 2) {
        buf.put(parseFloat(attribs.getValue("v")));
        if (tcvb.getNumComponents() >= 3) {
            buf.put(parseFloat(attribs.getValue("w")));
            if (tcvb.getNumComponents() == 4) {
                buf.put(parseFloat(attribs.getValue("x")));
            }
        }
    }
    texCoordIndex++;
}
Also used : Type(com.jme3.scene.VertexBuffer.Type)

Example 48 with VertexBuffer

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

the class FbxSkin method generateBoneData.

private int generateBoneData(Mesh mesh, FbxMesh fbxMesh) {
    // Create bone buffers
    FloatBuffer boneWeightData = BufferUtils.createFloatBuffer(fbxMesh.vCount * 4);
    ByteBuffer boneIndicesData = BufferUtils.createByteBuffer(fbxMesh.vCount * 4);
    mesh.setBuffer(VertexBuffer.Type.BoneWeight, 4, boneWeightData);
    mesh.setBuffer(VertexBuffer.Type.BoneIndex, 4, boneIndicesData);
    mesh.getBuffer(VertexBuffer.Type.BoneWeight).setUsage(Usage.CpuOnly);
    mesh.getBuffer(VertexBuffer.Type.BoneIndex).setUsage(Usage.CpuOnly);
    VertexBuffer weightsHW = new VertexBuffer(Type.HWBoneWeight);
    VertexBuffer indicesHW = new VertexBuffer(Type.HWBoneIndex);
    // Setting usage to CpuOnly so that the buffer is not send empty to the GPU
    indicesHW.setUsage(Usage.CpuOnly);
    weightsHW.setUsage(Usage.CpuOnly);
    mesh.setBuffer(weightsHW);
    mesh.setBuffer(indicesHW);
    int bonesLimitExceeded = 0;
    // Accumulate skin bones influence into mesh buffers
    for (FbxNode limb : bones) {
        FbxCluster cluster = limb.skinToCluster.get(id);
        if (cluster == null || cluster.indexes == null || cluster.weights == null || cluster.indexes.length != cluster.weights.length)
            continue;
        if (limb.boneIndex > 255)
            throw new AssetLoadException("Bone index can't be packed into byte");
        for (int i = 0; i < cluster.indexes.length; ++i) {
            int vertexIndex = cluster.indexes[i];
            if (vertexIndex >= fbxMesh.reverseVertexMap.size())
                throw new AssetLoadException("Invalid skinning vertex index. Unexpected index lookup " + vertexIndex + " from " + fbxMesh.reverseVertexMap.size());
            List<Integer> dstVertices = fbxMesh.reverseVertexMap.get(vertexIndex);
            for (int j = 0; j < dstVertices.size(); ++j) {
                int v = dstVertices.get(j);
                // Append bone index and weight to vertex
                int offset;
                int smalestOffset = 0;
                float w = 0;
                float smalestW = Float.MAX_VALUE;
                for (offset = v * 4; offset < v * 4 + 4; ++offset) {
                    w = boneWeightData.get(offset);
                    if (w == 0)
                        break;
                    if (w < smalestW) {
                        smalestW = w;
                        smalestOffset = offset;
                    }
                }
                if (w == 0) {
                    boneWeightData.put(offset, (float) cluster.weights[i]);
                    boneIndicesData.put(offset, (byte) limb.boneIndex);
                } else {
                    if ((float) cluster.weights[i] > smalestW) {
                        // If current weight more than smallest, discard smallest
                        boneWeightData.put(smalestOffset, (float) cluster.weights[i]);
                        boneIndicesData.put(smalestOffset, (byte) limb.boneIndex);
                    }
                    bonesLimitExceeded++;
                }
            }
        }
    }
    if (bonesLimitExceeded > 0)
        scene.warning("Skinning support max 4 bone per vertex. Exceeding data of " + bonesLimitExceeded + " weights in mesh bones will be discarded");
    // Postprocess bones weights
    int maxWeightsPerVert = 0;
    boneWeightData.rewind();
    for (int v = 0; v < fbxMesh.vCount; v++) {
        float w0 = boneWeightData.get();
        float w1 = boneWeightData.get();
        float w2 = boneWeightData.get();
        float w3 = boneWeightData.get();
        if (w3 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 4);
        } else if (w2 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 3);
        } else if (w1 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 2);
        } else if (w0 != 0) {
            maxWeightsPerVert = Math.max(maxWeightsPerVert, 1);
        }
        float sum = w0 + w1 + w2 + w3;
        if (sum != 1f) {
            // normalize weights
            float mult = (sum != 0) ? (1f / sum) : 0;
            boneWeightData.position(v * 4);
            boneWeightData.put(w0 * mult);
            boneWeightData.put(w1 * mult);
            boneWeightData.put(w2 * mult);
            boneWeightData.put(w3 * mult);
        }
    }
    return maxWeightsPerVert;
}
Also used : VertexBuffer(com.jme3.scene.VertexBuffer) FloatBuffer(java.nio.FloatBuffer) ByteBuffer(java.nio.ByteBuffer) AssetLoadException(com.jme3.asset.AssetLoadException)

Example 49 with VertexBuffer

use of com.jme3.scene.VertexBuffer 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 50 with VertexBuffer

use of com.jme3.scene.VertexBuffer 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

VertexBuffer (com.jme3.scene.VertexBuffer)45 FloatBuffer (java.nio.FloatBuffer)43 Vector3f (com.jme3.math.Vector3f)20 ByteBuffer (java.nio.ByteBuffer)12 IndexBuffer (com.jme3.scene.mesh.IndexBuffer)10 ShortBuffer (java.nio.ShortBuffer)9 IntBuffer (java.nio.IntBuffer)8 Mesh (com.jme3.scene.Mesh)7 Geometry (com.jme3.scene.Geometry)6 Buffer (java.nio.Buffer)6 ColorRGBA (com.jme3.math.ColorRGBA)5 Vector2f (com.jme3.math.Vector2f)5 ArrayList (java.util.ArrayList)5 Bone (com.jme3.animation.Bone)4 Material (com.jme3.material.Material)4 Matrix4f (com.jme3.math.Matrix4f)4 Type (com.jme3.scene.VertexBuffer.Type)3 Texture (com.jme3.texture.Texture)3 TempVars (com.jme3.util.TempVars)3 HashMap (java.util.HashMap)3