From e8f344a0dbcef7578544a57757fdd3439c3cf4c5 Mon Sep 17 00:00:00 2001 From: Kirill Vainer Date: Fri, 21 Aug 2015 21:21:31 -0400 Subject: [PATCH] GLRenderer: remaining portion of VAO support --- .../java/com/jme3/font/BitmapTextPage.java | 5 + .../main/java/com/jme3/renderer/Renderer.java | 6 + .../src/main/java/com/jme3/scene/Mesh.java | 199 ++++++------------ .../java/com/jme3/scene/VertexBuffer.java | 17 +- .../src/main/java/com/jme3/shader/Shader.java | 10 + .../java/com/jme3/system/NullRenderer.java | 3 + .../main/java/com/jme3/util/NativeObject.java | 3 +- 7 files changed, 108 insertions(+), 135 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java b/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java index 1edac967c..d0d2e6969 100644 --- a/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java +++ b/jme3-core/src/main/java/com/jme3/font/BitmapTextPage.java @@ -137,6 +137,11 @@ class BitmapTextPage extends Geometry { Mesh m = getMesh(); int vertCount = pageQuads.size() * 4; int triCount = pageQuads.size() * 2; + + if (vertCount > m.getVertexCount() || + triCount > m.getTriangleCount()) { + m.setUpdateNeeded(); + } VertexBuffer pb = m.getBuffer(Type.Position); VertexBuffer tb = m.getBuffer(Type.TexCoord); diff --git a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java index edfd380b4..1784eb7f5 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Renderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Renderer.java @@ -283,6 +283,12 @@ public interface Renderer { * the per-instance attributes. */ public void renderMesh(Mesh mesh, int lod, int count, VertexBuffer[] instanceData); + + /** + * Delete a Mesh (or Vertex Array Object in GL terms) from the GPU. + * @param mesh The mesh to delete. + */ + public void deleteMesh(Mesh mesh); /** * Resets all previously used {@link NativeObject Native Objects} on this Renderer. diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index a0f8e1fe6..fbe5d7794 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -42,6 +42,7 @@ import com.jme3.math.Matrix4f; import com.jme3.math.Triangle; import com.jme3.math.Vector2f; import com.jme3.math.Vector3f; +import com.jme3.renderer.Renderer; import com.jme3.scene.VertexBuffer.Format; import com.jme3.scene.VertexBuffer.Type; import com.jme3.scene.VertexBuffer.Usage; @@ -49,6 +50,7 @@ import com.jme3.scene.mesh.*; import com.jme3.util.BufferUtils; import com.jme3.util.IntMap; import com.jme3.util.IntMap.Entry; +import com.jme3.util.NativeObject; import com.jme3.util.SafeArrayList; import java.io.IOException; import java.nio.*; @@ -71,7 +73,7 @@ import java.util.ArrayList; * * @author Kirill Vainer */ -public class Mesh implements Savable, Cloneable { +public class Mesh extends NativeObject implements Savable { /** * The mode of the Mesh specifies both the type of primitive represented @@ -127,19 +129,14 @@ public class Mesh implements Savable, Cloneable { */ TriangleFan(false), - /** - * A combination of various triangle modes. It is best to avoid - * using this mode as it may not be supported by all renderers. - * The {@link Mesh#setModeStart(int[]) mode start points} and - * {@link Mesh#setElementLengths(int[]) element lengths} must - * be specified for this mode. - */ - Hybrid(false), + Reserved(false), + /** * Used for Tesselation only. Requires to set the number of vertices * for each patch (default is 3 for triangle tesselation) */ Patch(true); + private boolean listMode = false; private Mode(boolean listMode){ @@ -182,9 +179,6 @@ public class Mesh implements Savable, Cloneable { private int patchVertexCount=3; //only used for tesselation private int maxNumWeights = -1; // only if using skeletal animation - private int[] elementLengths; - private int[] modeStart; - private Mode mode = Mode.Triangles; /** @@ -193,6 +187,10 @@ public class Mesh implements Savable, Cloneable { public Mesh(){ } + protected Mesh(int id) { + super(id); + } + /** * Create a shallow clone of this Mesh. The {@link VertexBuffer vertex * buffers} are shared between this and the clone mesh, the rest @@ -202,23 +200,12 @@ public class Mesh implements Savable, Cloneable { */ @Override public Mesh clone() { - try { - Mesh clone = (Mesh) super.clone(); - clone.meshBound = meshBound.clone(); - clone.collisionTree = collisionTree != null ? collisionTree : null; - clone.buffers = buffers.clone(); - clone.buffersList = new SafeArrayList(VertexBuffer.class,buffersList); - clone.vertexArrayID = -1; - if (elementLengths != null) { - clone.elementLengths = elementLengths.clone(); - } - if (modeStart != null) { - clone.modeStart = modeStart.clone(); - } - return clone; - } catch (CloneNotSupportedException ex) { - throw new AssertionError(); - } + Mesh clone = (Mesh) super.clone(); + clone.meshBound = meshBound.clone(); + clone.collisionTree = collisionTree != null ? collisionTree : null; + clone.buffers = buffers.clone(); + clone.buffersList = new SafeArrayList(VertexBuffer.class,buffersList); + return clone; } /** @@ -229,37 +216,30 @@ public class Mesh implements Savable, Cloneable { * @return a deep clone of this mesh. */ public Mesh deepClone(){ - try{ - Mesh clone = (Mesh) super.clone(); - clone.meshBound = meshBound != null ? meshBound.clone() : null; - - // TODO: Collision tree cloning - //clone.collisionTree = collisionTree != null ? collisionTree : null; - clone.collisionTree = null; // it will get re-generated in any case - - clone.buffers = new IntMap(); - clone.buffersList = new SafeArrayList(VertexBuffer.class); - for (VertexBuffer vb : buffersList.getArray()){ - VertexBuffer bufClone = vb.clone(); - clone.buffers.put(vb.getBufferType().ordinal(), bufClone); - clone.buffersList.add(bufClone); - } - - clone.vertexArrayID = -1; - clone.vertCount = vertCount; - clone.elementCount = elementCount; - clone.instanceCount = instanceCount; - - // although this could change - // if the bone weight/index buffers are modified - clone.maxNumWeights = maxNumWeights; - - clone.elementLengths = elementLengths != null ? elementLengths.clone() : null; - clone.modeStart = modeStart != null ? modeStart.clone() : null; - return clone; - }catch (CloneNotSupportedException ex){ - throw new AssertionError(); + Mesh clone = (Mesh) super.clone(); + clone.meshBound = meshBound != null ? meshBound.clone() : null; + + // TODO: Collision tree cloning + //clone.collisionTree = collisionTree != null ? collisionTree : null; + clone.collisionTree = null; // it will get re-generated in any case + + clone.buffers = new IntMap(); + clone.buffersList = new SafeArrayList(VertexBuffer.class); + for (VertexBuffer vb : buffersList.getArray()){ + VertexBuffer bufClone = vb.clone(); + clone.buffers.put(vb.getBufferType().ordinal(), bufClone); + clone.buffersList.add(bufClone); } + + clone.vertCount = vertCount; + clone.elementCount = elementCount; + clone.instanceCount = instanceCount; + + // although this could change + // if the bone weight/index buffers are modified + clone.maxNumWeights = maxNumWeights; + + return clone; } /** @@ -475,40 +455,6 @@ public class Mesh implements Savable, Cloneable { return lodLevels[lod]; } - /** - * Get the element lengths for {@link Mode#Hybrid} mesh mode. - * - * @return element lengths - */ - public int[] getElementLengths() { - return elementLengths; - } - - /** - * Set the element lengths for {@link Mode#Hybrid} mesh mode. - * - * @param elementLengths The element lengths to set - */ - public void setElementLengths(int[] elementLengths) { - this.elementLengths = elementLengths; - } - - /** - * Set the mode start indices for {@link Mode#Hybrid} mesh mode. - * - * @return mode start indices - */ - public int[] getModeStart() { - return modeStart; - } - - /** - * Get the mode start indices for {@link Mode#Hybrid} mesh mode. - */ - public void setModeStart(int[] modeStart) { - this.modeStart = modeStart; - } - /** * Returns the mesh mode * @@ -899,23 +845,6 @@ public class Mesh implements Savable, Cloneable { indices[2] = ib.get(vertIndex+2); } - /** - * Returns the mesh's VAO ID. Internal use only. - */ - public int getId(){ - return vertexArrayID; - } - - /** - * Sets the mesh's VAO ID. Internal use only. - */ - public void setId(int id){ - if (vertexArrayID != -1) - throw new IllegalStateException("ID has already been set."); - - vertexArrayID = id; - } - /** * Generates a collision tree for the mesh. * Called automatically by {@link #collideWith(com.jme3.collision.Collidable, @@ -1109,20 +1038,17 @@ public class Mesh implements Savable, Cloneable { * @return A virtual or wrapped index buffer to read the data as a list */ public IndexBuffer getIndicesAsList(){ - if (mode == Mode.Hybrid) - throw new UnsupportedOperationException("Hybrid mode not supported"); - IndexBuffer ib = getIndexBuffer(); - if (ib != null){ - if (mode.isListMode()){ + if (ib != null) { + if (mode.isListMode()) { // already in list mode - return ib; - }else{ + return ib; + } else { // not in list mode but it does have an index buffer // wrap it so the data is converted to list format return new WrappedIndexBuffer(this); } - }else{ + } else { // return a virtual index buffer that will supply // "fake" indices in list format return new VirtualIndexBuffer(vertCount, mode); @@ -1385,16 +1311,30 @@ public class Mesh implements Savable, Cloneable { return patchVertexCount; } + @Override + public void resetObject() { + id = -1; + setUpdateNeeded(); + } + + @Override + public void deleteObject(Object rendererObject) { + ((Renderer)rendererObject).deleteMesh(this); + } + + @Override + public NativeObject createDestructableClone() { + return new Mesh(id); + } + + @Override + public long getUniqueId() { + return ((long)OBJTYPE_MESH << 32) | ((long)id); + } + public void write(JmeExporter ex) throws IOException { OutputCapsule out = ex.getCapsule(this); -// HashMap map = new HashMap(); -// for (Entry buf : buffers){ -// if (buf.getValue() != null) -// map.put(buf.getKey()+"a", buf.getValue()); -// } -// out.writeStringSavableMap(map, "buffers", null); - out.write(meshBound, "modelBound", null); out.write(vertCount, "vertCount", -1); out.write(elementCount, "elementCount", -1); @@ -1402,8 +1342,6 @@ public class Mesh implements Savable, Cloneable { out.write(maxNumWeights, "max_num_weights", -1); out.write(mode, "mode", Mode.Triangles); out.write(collisionTree, "collisionTree", null); - out.write(elementLengths, "elementLengths", null); - out.write(modeStart, "modeStart", null); out.write(pointSize, "pointSize", 1f); //Removing HW skinning buffers to not save them @@ -1439,21 +1377,16 @@ public class Mesh implements Savable, Cloneable { instanceCount = in.readInt("instanceCount", -1); maxNumWeights = in.readInt("max_num_weights", -1); mode = in.readEnum("mode", Mode.class, Mode.Triangles); - elementLengths = in.readIntArray("elementLengths", null); - modeStart = in.readIntArray("modeStart", null); collisionTree = (BIHTree) in.readSavable("collisionTree", null); - elementLengths = in.readIntArray("elementLengths", null); - modeStart = in.readIntArray("modeStart", null); pointSize = in.readFloat("pointSize", 1f); -// in.readStringSavableMap("buffers", null); buffers = (IntMap) in.readIntSavableMap("buffers", null); for (Entry entry : buffers){ buffersList.add(entry.getValue()); } //creating hw animation buffers empty so that they are put in the cache - if(isAnimated()){ + if (isAnimated()) { VertexBuffer hwBoneIndex = new VertexBuffer(Type.HWBoneIndex); hwBoneIndex.setUsage(Usage.CpuOnly); setBuffer(hwBoneIndex); diff --git a/jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java b/jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java index c67435b78..3fe8e5cad 100644 --- a/jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java +++ b/jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java @@ -524,6 +524,17 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { this.usage = usage; } + /** + * The size of an element in bytes. + * + * The number of components multiplied by the size of a component. + * + * @return size of an element in bytes. + */ + public int getElementSize() { + return componentsLength; + } + /** * @param normalized Set to true if integer components should be converted * from their maximal range into the range 0.0 - 1.0 when converted to @@ -976,6 +987,10 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { * of the parameters. The buffer will be of the type specified by * {@link Format format} and would be able to contain the given number * of elements with the given number of components in each element. + * @param format The format of the buffer to create + * @param components The number of components (aka dimensions) + * @param numElements Capacity of the buffer in number of elements. + * @return A buffer satisfying the given requirements. */ public static Buffer createBuffer(Format format, int components, int numElements){ if (components < 1 || components > 4) @@ -1010,7 +1025,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable { * @return Deep clone of this buffer */ @Override - public VertexBuffer clone(){ + public VertexBuffer clone() { // NOTE: Superclass GLObject automatically creates shallow clone // e.g re-use ID. VertexBuffer vb = (VertexBuffer) super.clone(); diff --git a/jme3-core/src/main/java/com/jme3/shader/Shader.java b/jme3-core/src/main/java/com/jme3/shader/Shader.java index eb084f178..cfe915ad8 100644 --- a/jme3-core/src/main/java/com/jme3/shader/Shader.java +++ b/jme3-core/src/main/java/com/jme3/shader/Shader.java @@ -274,6 +274,16 @@ public final class Shader extends NativeObject { return attrib; } + public boolean isAttributeDefined(VertexBuffer.Type attribType) { + int ordinal = attribType.ordinal(); + Attribute attrib = attribs.get(ordinal); + if (attrib == null){ + return false; + } else { + return attrib.location != -1 && attrib.location != 2; + } + } + public ListMap getUniformMap(){ return uniforms; } diff --git a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java index f2e029af4..7ac0b3495 100644 --- a/jme3-core/src/main/java/com/jme3/system/NullRenderer.java +++ b/jme3-core/src/main/java/com/jme3/system/NullRenderer.java @@ -164,4 +164,7 @@ public class NullRenderer implements Renderer { public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { } + @Override + public void deleteMesh(Mesh mesh) { + } } diff --git a/jme3-core/src/main/java/com/jme3/util/NativeObject.java b/jme3-core/src/main/java/com/jme3/util/NativeObject.java index 508e6623d..34114ebd2 100644 --- a/jme3-core/src/main/java/com/jme3/util/NativeObject.java +++ b/jme3-core/src/main/java/com/jme3/util/NativeObject.java @@ -52,7 +52,8 @@ public abstract class NativeObject implements Cloneable { OBJTYPE_SHADERSOURCE = 5, OBJTYPE_AUDIOBUFFER = 6, OBJTYPE_AUDIOSTREAM = 7, - OBJTYPE_FILTER = 8; + OBJTYPE_FILTER = 8, + OBJTYPE_MESH = 9; /** * The object manager to which this NativeObject is registered to.