Search in sources :

Example 21 with VertexBuffer

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

the class GLRenderer method setVertexAttrib.

public void setVertexAttrib(VertexBuffer vb, VertexBuffer idb) {
    if (vb.getBufferType() == VertexBuffer.Type.Index) {
        throw new IllegalArgumentException("Index buffers not allowed to be set to vertex attrib");
    }
    if (context.boundShaderProgram <= 0) {
        throw new IllegalStateException("Cannot render mesh without shader bound");
    }
    Attribute attrib = context.boundShader.getAttribute(vb.getBufferType());
    int loc = attrib.getLocation();
    if (loc == -1) {
        // not defined
        return;
    }
    if (loc == -2) {
        loc = gl.glGetAttribLocation(context.boundShaderProgram, "in" + vb.getBufferType().name());
        // the internal name of the enum (Position).
        if (loc < 0) {
            attrib.setLocation(-1);
            // not available in shader.
            return;
        } else {
            attrib.setLocation(loc);
        }
    }
    if (vb.isInstanced()) {
        if (!caps.contains(Caps.MeshInstancing)) {
            throw new RendererException("Instancing is required, " + "but not supported by the " + "graphics hardware");
        }
    }
    int slotsRequired = 1;
    if (vb.getNumComponents() > 4) {
        if (vb.getNumComponents() % 4 != 0) {
            throw new RendererException("Number of components in multi-slot " + "buffers must be divisible by 4");
        }
        slotsRequired = vb.getNumComponents() / 4;
    }
    if (vb.isUpdateNeeded() && idb == null) {
        updateBufferData(vb);
    }
    VertexBuffer[] attribs = context.boundAttribs;
    for (int i = 0; i < slotsRequired; i++) {
        if (!context.attribIndexList.moveToNew(loc + i)) {
            gl.glEnableVertexAttribArray(loc + i);
        }
    }
    if (attribs[loc] != vb) {
        // NOTE: Use id from interleaved buffer if specified
        int bufId = idb != null ? idb.getId() : vb.getId();
        assert bufId != -1;
        if (context.boundArrayVBO != bufId) {
            gl.glBindBuffer(GL.GL_ARRAY_BUFFER, bufId);
            context.boundArrayVBO = bufId;
        //statistics.onVertexBufferUse(vb, true);
        } else {
        //statistics.onVertexBufferUse(vb, false);
        }
        if (slotsRequired == 1) {
            gl.glVertexAttribPointer(loc, vb.getNumComponents(), convertFormat(vb.getFormat()), vb.isNormalized(), vb.getStride(), vb.getOffset());
        } else {
            for (int i = 0; i < slotsRequired; i++) {
                // The pointer maps the next 4 floats in the slot.
                // E.g.
                // P1: XXXX____________XXXX____________
                // P2: ____XXXX____________XXXX________
                // P3: ________XXXX____________XXXX____
                // P4: ____________XXXX____________XXXX
                // stride = 4 bytes in float * 4 floats in slot * num slots
                // offset = 4 bytes in float * 4 floats in slot * slot index
                gl.glVertexAttribPointer(loc + i, 4, convertFormat(vb.getFormat()), vb.isNormalized(), 4 * 4 * slotsRequired, 4 * 4 * i);
            }
        }
        for (int i = 0; i < slotsRequired; i++) {
            int slot = loc + i;
            if (vb.isInstanced() && (attribs[slot] == null || !attribs[slot].isInstanced())) {
                // non-instanced -> instanced
                glext.glVertexAttribDivisorARB(slot, vb.getInstanceSpan());
            } else if (!vb.isInstanced() && attribs[slot] != null && attribs[slot].isInstanced()) {
                // instanced -> non-instanced
                glext.glVertexAttribDivisorARB(slot, 0);
            }
            attribs[slot] = vb;
        }
    }
}
Also used : Attribute(com.jme3.shader.Attribute) VertexBuffer(com.jme3.scene.VertexBuffer)

Example 22 with VertexBuffer

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

the class IrUtils method convertIrMeshToJmeMesh.

/**
     * Convert IrMesh to jME3 mesh.
     */
public static Mesh convertIrMeshToJmeMesh(IrMesh mesh) {
    Map<IrVertex, Integer> vertexToVertexIndex = new HashMap<IrVertex, Integer>();
    List<IrVertex> vertices = new ArrayList<IrVertex>();
    List<Integer> indexes = new ArrayList<Integer>();
    int vertexIndex = 0;
    for (IrPolygon polygon : mesh.polygons) {
        if (polygon.vertices.length != 3) {
            throw new UnsupportedOperationException("IrMesh must be triangulated first");
        }
        for (IrVertex vertex : polygon.vertices) {
            // Is this vertex already indexed?
            Integer existingIndex = vertexToVertexIndex.get(vertex);
            if (existingIndex == null) {
                // Not indexed yet, allocate index.
                indexes.add(vertexIndex);
                vertexToVertexIndex.put(vertex, vertexIndex);
                vertices.add(vertex);
                vertexIndex++;
            } else {
                // Index already allocated for this vertex, reuse it.
                indexes.add(existingIndex);
            }
        }
    }
    Mesh jmeMesh = new Mesh();
    jmeMesh.setMode(Mesh.Mode.Triangles);
    FloatBuffer posBuf = null;
    FloatBuffer normBuf = null;
    FloatBuffer tangBuf = null;
    FloatBuffer uv0Buf = null;
    FloatBuffer uv1Buf = null;
    ByteBuffer colorBuf = null;
    ByteBuffer boneIndices = null;
    FloatBuffer boneWeights = null;
    IndexBuffer indexBuf = null;
    IrVertex inspectionVertex = vertices.get(0);
    if (inspectionVertex.pos != null) {
        posBuf = BufferUtils.createVector3Buffer(vertices.size());
        jmeMesh.setBuffer(VertexBuffer.Type.Position, 3, posBuf);
    }
    if (inspectionVertex.norm != null) {
        normBuf = BufferUtils.createVector3Buffer(vertices.size());
        jmeMesh.setBuffer(VertexBuffer.Type.Normal, 3, normBuf);
    }
    if (inspectionVertex.tang4d != null) {
        tangBuf = BufferUtils.createFloatBuffer(vertices.size() * 4);
        jmeMesh.setBuffer(VertexBuffer.Type.Tangent, 4, tangBuf);
    }
    if (inspectionVertex.tang != null || inspectionVertex.bitang != null) {
        throw new IllegalStateException("Mesh is using 3D tangents, must be converted to 4D tangents first.");
    }
    if (inspectionVertex.uv0 != null) {
        uv0Buf = BufferUtils.createVector2Buffer(vertices.size());
        jmeMesh.setBuffer(VertexBuffer.Type.TexCoord, 2, uv0Buf);
    }
    if (inspectionVertex.uv1 != null) {
        uv1Buf = BufferUtils.createVector2Buffer(vertices.size());
        jmeMesh.setBuffer(VertexBuffer.Type.TexCoord2, 2, uv1Buf);
    }
    if (inspectionVertex.color != null) {
        colorBuf = BufferUtils.createByteBuffer(vertices.size() * 4);
        jmeMesh.setBuffer(VertexBuffer.Type.Color, 4, colorBuf);
        jmeMesh.getBuffer(VertexBuffer.Type.Color).setNormalized(true);
    }
    if (inspectionVertex.boneWeightsIndices != null) {
        boneIndices = BufferUtils.createByteBuffer(vertices.size() * 4);
        boneWeights = BufferUtils.createFloatBuffer(vertices.size() * 4);
        jmeMesh.setBuffer(VertexBuffer.Type.BoneIndex, 4, boneIndices);
        jmeMesh.setBuffer(VertexBuffer.Type.BoneWeight, 4, boneWeights);
        //creating empty buffers for HW skinning 
        //the buffers will be setup if ever used.
        VertexBuffer weightsHW = new VertexBuffer(VertexBuffer.Type.HWBoneWeight);
        VertexBuffer indicesHW = new VertexBuffer(VertexBuffer.Type.HWBoneIndex);
        //setting usage to cpuOnly so that the buffer is not send empty to the GPU
        indicesHW.setUsage(VertexBuffer.Usage.CpuOnly);
        weightsHW.setUsage(VertexBuffer.Usage.CpuOnly);
        jmeMesh.setBuffer(weightsHW);
        jmeMesh.setBuffer(indicesHW);
    }
    if (vertices.size() >= 65536) {
        // too many verticies: use intbuffer instead of shortbuffer
        IntBuffer ib = BufferUtils.createIntBuffer(indexes.size());
        jmeMesh.setBuffer(VertexBuffer.Type.Index, 3, ib);
        indexBuf = new IndexIntBuffer(ib);
    } else {
        ShortBuffer sb = BufferUtils.createShortBuffer(indexes.size());
        jmeMesh.setBuffer(VertexBuffer.Type.Index, 3, sb);
        indexBuf = new IndexShortBuffer(sb);
    }
    jmeMesh.setStatic();
    int maxBonesPerVertex = -1;
    for (IrVertex vertex : vertices) {
        if (posBuf != null) {
            posBuf.put(vertex.pos.x).put(vertex.pos.y).put(vertex.pos.z);
        }
        if (normBuf != null) {
            normBuf.put(vertex.norm.x).put(vertex.norm.y).put(vertex.norm.z);
        }
        if (tangBuf != null) {
            tangBuf.put(vertex.tang4d.x).put(vertex.tang4d.y).put(vertex.tang4d.z).put(vertex.tang4d.w);
        }
        if (uv0Buf != null) {
            uv0Buf.put(vertex.uv0.x).put(vertex.uv0.y);
        }
        if (uv1Buf != null) {
            uv1Buf.put(vertex.uv1.x).put(vertex.uv1.y);
        }
        if (colorBuf != null) {
            colorBuf.putInt(vertex.color.asIntABGR());
        }
        if (boneIndices != null) {
            if (vertex.boneWeightsIndices != null) {
                if (vertex.boneWeightsIndices.length > 4) {
                    throw new UnsupportedOperationException("Mesh uses more than 4 weights per bone. " + "Call trimBoneWeights() to allieviate this");
                }
                for (int i = 0; i < vertex.boneWeightsIndices.length; i++) {
                    boneIndices.put((byte) (vertex.boneWeightsIndices[i].boneIndex & 0xFF));
                    boneWeights.put(vertex.boneWeightsIndices[i].boneWeight);
                }
                for (int i = 0; i < 4 - vertex.boneWeightsIndices.length; i++) {
                    boneIndices.put((byte) 0);
                    boneWeights.put(0f);
                }
            } else {
                boneIndices.putInt(0);
                boneWeights.put(0f).put(0f).put(0f).put(0f);
            }
            maxBonesPerVertex = Math.max(maxBonesPerVertex, vertex.boneWeightsIndices.length);
        }
    }
    for (int i = 0; i < indexes.size(); i++) {
        indexBuf.put(i, indexes.get(i));
    }
    jmeMesh.updateCounts();
    jmeMesh.updateBound();
    if (boneIndices != null) {
        jmeMesh.setMaxNumWeights(maxBonesPerVertex);
        jmeMesh.prepareForAnim(true);
        jmeMesh.generateBindPose(true);
    }
    return jmeMesh;
}
Also used : HashMap(java.util.HashMap) VertexBuffer(com.jme3.scene.VertexBuffer) ArrayList(java.util.ArrayList) Mesh(com.jme3.scene.Mesh) FloatBuffer(java.nio.FloatBuffer) ByteBuffer(java.nio.ByteBuffer) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) IndexShortBuffer(com.jme3.scene.mesh.IndexShortBuffer) IndexIntBuffer(com.jme3.scene.mesh.IndexIntBuffer) IndexIntBuffer(com.jme3.scene.mesh.IndexIntBuffer) IntBuffer(java.nio.IntBuffer) IndexShortBuffer(com.jme3.scene.mesh.IndexShortBuffer) ShortBuffer(java.nio.ShortBuffer)

Example 23 with VertexBuffer

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

the class TangentBinormalGenerator method genTangentLines.

private static Mesh genTangentLines(Mesh mesh, float scale) {
    FloatBuffer vertexBuffer = (FloatBuffer) mesh.getBuffer(Type.Position).getData();
    FloatBuffer normalBuffer = (FloatBuffer) mesh.getBuffer(Type.Normal).getData();
    FloatBuffer tangentBuffer = (FloatBuffer) mesh.getBuffer(Type.Tangent).getData();
    FloatBuffer binormalBuffer = null;
    if (mesh.getBuffer(Type.Binormal) != null) {
        binormalBuffer = (FloatBuffer) mesh.getBuffer(Type.Binormal).getData();
    }
    ColorRGBA originColor = ColorRGBA.White;
    ColorRGBA tangentColor = ColorRGBA.Red;
    ColorRGBA binormalColor = ColorRGBA.Green;
    ColorRGBA normalColor = ColorRGBA.Blue;
    Mesh lineMesh = new Mesh();
    lineMesh.setMode(Mesh.Mode.Lines);
    Vector3f origin = new Vector3f();
    Vector3f point = new Vector3f();
    Vector3f tangent = new Vector3f();
    Vector3f normal = new Vector3f();
    IntBuffer lineIndex = BufferUtils.createIntBuffer(vertexBuffer.limit() / 3 * 6);
    FloatBuffer lineVertex = BufferUtils.createFloatBuffer(vertexBuffer.limit() * 4);
    FloatBuffer lineColor = BufferUtils.createFloatBuffer(vertexBuffer.limit() / 3 * 4 * 4);
    boolean hasParity = mesh.getBuffer(Type.Tangent).getNumComponents() == 4;
    float tangentW = 1;
    for (int i = 0; i < vertexBuffer.limit() / 3; i++) {
        populateFromBuffer(origin, vertexBuffer, i);
        populateFromBuffer(normal, normalBuffer, i);
        if (hasParity) {
            tangent.x = tangentBuffer.get(i * 4);
            tangent.y = tangentBuffer.get(i * 4 + 1);
            tangent.z = tangentBuffer.get(i * 4 + 2);
            tangentW = tangentBuffer.get(i * 4 + 3);
        } else {
            populateFromBuffer(tangent, tangentBuffer, i);
        }
        int index = i * 4;
        int id = i * 6;
        lineIndex.put(id, index);
        lineIndex.put(id + 1, index + 1);
        lineIndex.put(id + 2, index);
        lineIndex.put(id + 3, index + 2);
        lineIndex.put(id + 4, index);
        lineIndex.put(id + 5, index + 3);
        setInBuffer(origin, lineVertex, index);
        setInBuffer(originColor, lineColor, index);
        point.set(tangent);
        point.multLocal(scale);
        point.addLocal(origin);
        setInBuffer(point, lineVertex, index + 1);
        setInBuffer(tangentColor, lineColor, index + 1);
        if (binormalBuffer == null) {
            normal.cross(tangent, point);
            point.multLocal(-tangentW);
            point.normalizeLocal();
        } else {
            populateFromBuffer(point, binormalBuffer, i);
        }
        point.multLocal(scale);
        point.addLocal(origin);
        setInBuffer(point, lineVertex, index + 2);
        setInBuffer(binormalColor, lineColor, index + 2);
        point.set(normal);
        point.multLocal(scale);
        point.addLocal(origin);
        setInBuffer(point, lineVertex, index + 3);
        setInBuffer(normalColor, lineColor, index + 3);
    }
    lineMesh.setBuffer(Type.Index, 1, lineIndex);
    lineMesh.setBuffer(Type.Position, 3, lineVertex);
    lineMesh.setBuffer(Type.Color, 4, lineColor);
    lineMesh.setStatic();
    //lineMesh.setInterleaved();
    return lineMesh;
}
Also used : ColorRGBA(com.jme3.math.ColorRGBA) Vector3f(com.jme3.math.Vector3f) IntBuffer(java.nio.IntBuffer) FloatBuffer(java.nio.FloatBuffer)

Example 24 with VertexBuffer

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

the class TangentBinormalGenerator method splitVertices.

//Don't remove splitmirorred boolean,It's not used right now, but i intend to
//make this method also split vertice with rotated tangent space and I'll
//add another splitRotated boolean 
private static List<VertexData> splitVertices(Mesh mesh, List<VertexData> vertexData, boolean splitMirorred) {
    int nbVertices = mesh.getBuffer(Type.Position).getNumElements();
    List<VertexData> newVertices = new ArrayList<VertexData>();
    Map<Integer, Integer> indiceMap = new HashMap<Integer, Integer>();
    FloatBuffer normalBuffer = mesh.getFloatBuffer(Type.Normal);
    for (int i = 0; i < vertexData.size(); i++) {
        ArrayList<TriangleData> triangles = vertexData.get(i).triangles;
        Vector3f givenNormal = new Vector3f();
        populateFromBuffer(givenNormal, normalBuffer, i);
        ArrayList<TriangleData> trianglesUp = new ArrayList<TriangleData>();
        ArrayList<TriangleData> trianglesDown = new ArrayList<TriangleData>();
        for (int j = 0; j < triangles.size(); j++) {
            TriangleData triangleData = triangles.get(j);
            if (parity(givenNormal, triangleData.normal) > 0) {
                trianglesUp.add(triangleData);
            } else {
                trianglesDown.add(triangleData);
            }
        }
        //if the vertex has triangles with opposite parity it has to be split
        if (!trianglesUp.isEmpty() && !trianglesDown.isEmpty()) {
            log.log(Level.FINE, "Splitting vertex {0}", i);
            //assigning triangle with the same parity to the original vertex
            vertexData.get(i).triangles.clear();
            vertexData.get(i).triangles.addAll(trianglesUp);
            //creating a new vertex
            VertexData newVert = new VertexData();
            //assigning triangles with opposite parity to it
            newVert.triangles.addAll(trianglesDown);
            newVertices.add(newVert);
            //keep vertex index to fix the index buffers later
            indiceMap.put(nbVertices, i);
            for (TriangleData tri : newVert.triangles) {
                for (int j = 0; j < tri.index.length; j++) {
                    if (tri.index[j] == i) {
                        tri.index[j] = nbVertices;
                    }
                }
            }
            nbVertices++;
        }
    }
    if (!newVertices.isEmpty()) {
        //we have new vertices, we need to update the mesh's buffers.
        for (Type type : VertexBuffer.Type.values()) {
            //skip tangent buffer as we're gonna overwrite it later
            if (type == Type.Tangent || type == Type.BindPoseTangent)
                continue;
            VertexBuffer vb = mesh.getBuffer(type);
            //They'll be initialized when Hardware Skinning is engaged
            if (vb == null || vb.getNumComponents() == 0)
                continue;
            Buffer buffer = vb.getData();
            //IndexBuffer has special treatement, only swapping the vertex indices is needed                
            if (type == Type.Index) {
                boolean isShortBuffer = vb.getFormat() == VertexBuffer.Format.UnsignedShort;
                for (VertexData vertex : newVertices) {
                    for (TriangleData tri : vertex.triangles) {
                        for (int i = 0; i < tri.index.length; i++) {
                            if (isShortBuffer) {
                                ((ShortBuffer) buffer).put(tri.triangleOffset + i, (short) tri.index[i]);
                            } else {
                                ((IntBuffer) buffer).put(tri.triangleOffset + i, tri.index[i]);
                            }
                        }
                    }
                }
                vb.setUpdateNeeded();
            } else {
                //copy the buffer in a bigger one and append nex vertices to the end
                Buffer newVerts = VertexBuffer.createBuffer(vb.getFormat(), vb.getNumComponents(), nbVertices);
                if (buffer != null) {
                    buffer.rewind();
                    bulkPut(vb.getFormat(), newVerts, buffer);
                    int index = vertexData.size();
                    newVerts.position(vertexData.size() * vb.getNumComponents());
                    for (int j = 0; j < newVertices.size(); j++) {
                        int oldInd = indiceMap.get(index);
                        for (int i = 0; i < vb.getNumComponents(); i++) {
                            putValue(vb.getFormat(), newVerts, buffer, oldInd * vb.getNumComponents() + i);
                        }
                        index++;
                    }
                    vb.updateData(newVerts);
                    //destroy previous buffer as it's no longer needed
                    destroyDirectBuffer(buffer);
                }
            }
        }
        vertexData.addAll(newVertices);
        mesh.updateCounts();
    }
    return vertexData;
}
Also used : FloatBuffer(java.nio.FloatBuffer) ShortBuffer(java.nio.ShortBuffer) IndexBuffer(com.jme3.scene.mesh.IndexBuffer) ByteBuffer(java.nio.ByteBuffer) IntBuffer(java.nio.IntBuffer) Buffer(java.nio.Buffer) DoubleBuffer(java.nio.DoubleBuffer) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) FloatBuffer(java.nio.FloatBuffer) Type(com.jme3.scene.VertexBuffer.Type) Vector3f(com.jme3.math.Vector3f) IntBuffer(java.nio.IntBuffer) ShortBuffer(java.nio.ShortBuffer)

Example 25 with VertexBuffer

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

the class TangentBinormalGenerator method linkVertices.

private static ArrayList<VertexInfo> linkVertices(Mesh mesh, boolean splitMirrored) {
    ArrayList<VertexInfo> vertexMap = new ArrayList<VertexInfo>();
    FloatBuffer vertexBuffer = mesh.getFloatBuffer(Type.Position);
    FloatBuffer normalBuffer = mesh.getFloatBuffer(Type.Normal);
    FloatBuffer texcoordBuffer = mesh.getFloatBuffer(Type.TexCoord);
    Vector3f position = new Vector3f();
    Vector3f normal = new Vector3f();
    Vector2f texCoord = new Vector2f();
    final int size = vertexBuffer.limit() / 3;
    for (int i = 0; i < size; i++) {
        populateFromBuffer(position, vertexBuffer, i);
        populateFromBuffer(normal, normalBuffer, i);
        populateFromBuffer(texCoord, texcoordBuffer, i);
        boolean found = false;
        //separate vertice should have separate tangent space   
        if (!splitMirrored) {
            for (int j = 0; j < vertexMap.size(); j++) {
                VertexInfo vertexInfo = vertexMap.get(j);
                if (approxEqual(vertexInfo.position, position) && approxEqual(vertexInfo.normal, normal) && approxEqual(vertexInfo.texCoord, texCoord)) {
                    vertexInfo.indices.add(i);
                    found = true;
                    break;
                }
            }
        }
        if (!found) {
            VertexInfo vertexInfo = new VertexInfo(position.clone(), normal.clone(), texCoord.clone());
            vertexInfo.indices.add(i);
            vertexMap.add(vertexInfo);
        }
    }
    return vertexMap;
}
Also used : Vector2f(com.jme3.math.Vector2f) Vector3f(com.jme3.math.Vector3f) ArrayList(java.util.ArrayList) FloatBuffer(java.nio.FloatBuffer)

Aggregations

FloatBuffer (java.nio.FloatBuffer)42 VertexBuffer (com.jme3.scene.VertexBuffer)40 Vector3f (com.jme3.math.Vector3f)17 ByteBuffer (java.nio.ByteBuffer)12 IndexBuffer (com.jme3.scene.mesh.IndexBuffer)9 ShortBuffer (java.nio.ShortBuffer)9 IntBuffer (java.nio.IntBuffer)8 Buffer (java.nio.Buffer)6 Geometry (com.jme3.scene.Geometry)5 Mesh (com.jme3.scene.Mesh)5 Bone (com.jme3.animation.Bone)4 Matrix4f (com.jme3.math.Matrix4f)4 Vector2f (com.jme3.math.Vector2f)4 ArrayList (java.util.ArrayList)4 Material (com.jme3.material.Material)3 ColorRGBA (com.jme3.math.ColorRGBA)3 Type (com.jme3.scene.VertexBuffer.Type)3 TempVars (com.jme3.util.TempVars)3 HashMap (java.util.HashMap)3 BoundingBox (com.jme3.bounding.BoundingBox)2