diff --git a/java/libraries/opengl2/src/processing/opengl2/PGraphicsOpenGL2.java b/java/libraries/opengl2/src/processing/opengl2/PGraphicsOpenGL2.java index d8025c4a9..cbed039cf 100644 --- a/java/libraries/opengl2/src/processing/opengl2/PGraphicsOpenGL2.java +++ b/java/libraries/opengl2/src/processing/opengl2/PGraphicsOpenGL2.java @@ -378,13 +378,14 @@ public class PGraphicsOpenGL2 extends PGraphics { protected PImage[][] faceTextures = new PImage[DEFAULT_FACES][MAX_TEXTURES]; // Testing geometry buffer for now (but it already rocks) ... - public boolean USE_GBUFFER = false; - public boolean GBUFFER_MERGE_ALL = true; - public boolean GBUFFER_UPDATE_STACK = true; - public GeometryBuffer gbuffer; - public int GBUFFER_COUNT; - public float GBUFFER_SIZE; - public int GBUFFER_MAXSIZE = 10000000; + public GeometryBuffer geoBuffer; + public boolean USE_GEO_BUFFER = false; + public boolean GEO_BUFFER_ACCUM_ALL = true; + public boolean UPDATE_GEO_BUFFER_MATRIX_STACK = true; + + public int GEO_BUFFER_COUNT; + public float GEO_BUFFER_SIZE; + public int GEO_BUFFER_MAXSIZE = 10000000; // ........................................................ @@ -490,7 +491,7 @@ public class PGraphicsOpenGL2 extends PGraphics { // Shape recording: protected boolean recordingShape; - protected int numRecordedTextures = 0; + protected int recTexturesCount = 0; protected boolean mergeRecShapes = false; protected String recShapeName; // Used to set name of shape during recording. protected PShape3D recordedShape = null; @@ -498,8 +499,9 @@ public class PGraphicsOpenGL2 extends PGraphics { protected ArrayList recordedColors = null; protected ArrayList recordedNormals = null; protected ArrayList[] recordedTexCoords = null; - protected ArrayList recordedChildren = null; - + protected ArrayList recordedChildren = null; + protected ArrayList recordedIndices = null; + // ........................................................ // Drawing surface: @@ -923,15 +925,15 @@ public class PGraphicsOpenGL2 extends PGraphics { texCoordBuffer[t].rewind(); } - if (USE_GBUFFER) { - if (gbuffer == null) gbuffer = new GeometryBuffer(); - if (GBUFFER_MERGE_ALL) { - gbuffer.init(TRIANGLES); - GBUFFER_COUNT = 1; + if (USE_GEO_BUFFER) { + if (geoBuffer == null) geoBuffer = new GeometryBuffer(); + if (GEO_BUFFER_ACCUM_ALL) { + geoBuffer.init(TRIANGLES); + GEO_BUFFER_COUNT = 1; } else{ - GBUFFER_COUNT = 0; + GEO_BUFFER_COUNT = 0; } - GBUFFER_SIZE = 0; + GEO_BUFFER_SIZE = 0; } // Each frame starts with textures disabled. @@ -1007,11 +1009,11 @@ public class PGraphicsOpenGL2 extends PGraphics { public void endDraw() { report("top endDraw()"); - if (USE_GBUFFER) { - if (GBUFFER_MERGE_ALL && gbuffer != null && 0 < gbuffer.vertCount) { - gbuffer.pre(); - gbuffer.render(); - gbuffer.post(); + if (USE_GEO_BUFFER) { + if (GEO_BUFFER_ACCUM_ALL && geoBuffer != null && 0 < geoBuffer.vertCount) { + geoBuffer.pre(); + geoBuffer.render(); + geoBuffer.post(); } } @@ -1285,12 +1287,13 @@ public class PGraphicsOpenGL2 extends PGraphics { System.err.println("OPENGL2: Already recording."); return recordedShape; } else { - if (USE_GBUFFER) { - if (gbuffer != null && 0 < gbuffer.vertCount) { - gbuffer.pre(); - gbuffer.render(); - gbuffer.post(); - } + if (USE_GEO_BUFFER) { + if (geoBuffer != null && 0 < geoBuffer.vertCount) { + geoBuffer.pre(); + geoBuffer.render(); + geoBuffer.post(); + } + if (geoBuffer == null) geoBuffer = new GeometryBuffer(); } recordedShape = new PShape3D(parent); @@ -1360,7 +1363,17 @@ public class PGraphicsOpenGL2 extends PGraphics { } } - numRecordedTextures = 0; + if (USE_GEO_BUFFER) { + if (recordedIndices == null) { + recordedIndices = new ArrayList(vertexBuffer.capacity() / 3); + } else { + recordedIndices.ensureCapacity(vertexBuffer.capacity() / 3); + } + } else{ + recordedIndices = null; + } + + recTexturesCount = 0; recordedChildren = new ArrayList(PApplet.max(DEFAULT_PATHS, DEFAULT_FACES)); } @@ -1494,6 +1507,10 @@ public class PGraphicsOpenGL2 extends PGraphics { } public void vertex(float x, float y, float u0, float v0, float u1, float v1) { + //public void vertex(float x, float y, float texcoords...) { + //for (float tc : texcoords) + // + if (2 <= maxTextureUnits) { vertexTexture(u0, v0, 0); vertexTexture(u1, v1, 1); @@ -1965,9 +1982,16 @@ public class PGraphicsOpenGL2 extends PGraphics { public void endRecord() { if (recordingShape) { + if (USE_GEO_BUFFER && 0 < geoBuffer.vertCount) { + // Recording remaining geometry. + geoBuffer.record(); + geoBuffer.init(TRIANGLES); // To set counters to zero. + } + if (0 < recordedVertices.size()) { recordedShape.initShape(recordedVertices.size()); } + endShapeRecorderImpl(recordedShape); recordedShape = null; } else { @@ -2011,12 +2035,17 @@ public class PGraphicsOpenGL2 extends PGraphics { shape.setColors(recordedColors); shape.setNormals(recordedNormals); + if (recordedIndices != null) { + shape.initIndices(recordedIndices.size()); + shape.setIndices(recordedIndices); + } + // We set children first because they contain the textures... shape.optimizeChildren(recordedChildren); // (we make sure that there are not superfluous shapes) shape.setChildren(recordedChildren); // ... and then the texture coordinates. - for (int t = 0; t < numRecordedTextures; t++) { + for (int t = 0; t < recTexturesCount; t++) { shape.setTexcoords(t, recordedTexCoords[t]); } @@ -2027,6 +2056,9 @@ public class PGraphicsOpenGL2 extends PGraphics { for (int t = 0; t < maxTextureUnits; t++) { recordedTexCoords[t].clear(); } + if (recordedIndices != null) { + recordedIndices.clear(); + } recordedChildren.clear(); } } @@ -2465,39 +2497,81 @@ public class PGraphicsOpenGL2 extends PGraphics { } } - if (USE_GBUFFER) { - if (GBUFFER_MERGE_ALL) { - if (gbuffer.newTextures(renderTextures, tcount)) { + if (USE_GEO_BUFFER) { + + if (recordingShape) { + recTexturesCount = PApplet.max(recTexturesCount, tcount); + + int i0 = recordedIndices.size() + geoBuffer.idxCount; + int i1 = i0 + 3 * faceLength[j] - 1; + + int n0 = recordedVertices.size() + geoBuffer.vertCount; + int n1 = n0 + faceMaxIndex[j] - faceMinIndex[j]; + + String name = "shape"; + if (mergeRecShapes) { + name = "shape"; + } else { + name = recShapeName.equals("") ? "shape:" + recordedChildren.size() : recShapeName; + } + + PShape3D child = (PShape3D)PShape3D.createChild(name, n0, n1, i0, i1, TRIANGLES, 0, images); + recordedChildren.add(child); + } + + if (GEO_BUFFER_ACCUM_ALL) { + if (geoBuffer.newTextures(renderTextures, tcount)) { // Accumulation, but texture changed. - if (0 < gbuffer.vertCount) { + if (0 < geoBuffer.vertCount) { // Rendering accumulated so far and reinitializing buffer. - gbuffer.render(); - GBUFFER_COUNT++; - gbuffer.init(TRIANGLES, renderTextures, tcount); + + if (recordingShape) { + geoBuffer.record(); + } else { + geoBuffer.render(); + } + + GEO_BUFFER_COUNT++; + geoBuffer.init(TRIANGLES, renderTextures, tcount); } else { // No geometry accumulated yet, setting textures just in case. - gbuffer.setTextures(renderTextures, tcount); + geoBuffer.setTextures(renderTextures, tcount); } } } else { // No accumulation, each shape is sent in a separate buffer. - gbuffer.init(TRIANGLES, renderTextures, tcount); + geoBuffer.init(TRIANGLES, renderTextures, tcount); } - gbuffer.add(triangles, i, i + faceLength[j] - 1, vertices, faceMinIndex[j], faceMaxIndex[j]); - if (GBUFFER_MERGE_ALL) { - if (GBUFFER_MAXSIZE < gbuffer.vertCount) { + + geoBuffer.add(triangles, i, i + faceLength[j] - 1, vertices, faceMinIndex[j], faceMaxIndex[j]); + + if (GEO_BUFFER_ACCUM_ALL) { + if (GEO_BUFFER_MAXSIZE < geoBuffer.vertCount) { // Accumulation, but maximum buffer size reached. - gbuffer.render(); - GBUFFER_COUNT++; - gbuffer.init(TRIANGLES, renderTextures, tcount); + + if (recordingShape) { + geoBuffer.record(); + } else { + geoBuffer.render(); + } + + GEO_BUFFER_COUNT++; + geoBuffer.init(TRIANGLES, renderTextures, tcount); } } else { - gbuffer.render(); - GBUFFER_COUNT++; + + if (recordingShape) { + geoBuffer.record(); + } else { + geoBuffer.render(); + } + + GEO_BUFFER_COUNT++; + geoBuffer.init(TRIANGLES); } } else { if (recordingShape) { - numRecordedTextures = PApplet.max(numRecordedTextures, tcount); + recTexturesCount = PApplet.max(recTexturesCount, tcount); int n0 = recordedVertices.size(); int n1 = n0 + 3 * faceLength[j] - 1; @@ -2510,8 +2584,8 @@ public class PGraphicsOpenGL2 extends PGraphics { } PShape3D child = (PShape3D)PShape3D.createChild(name, n0, n1, TRIANGLES, 0, images); recordedChildren.add(child); - } - + } + // Division by three needed because each int element in the buffer is used // to store three coordinates. int size = 3 * faceLength[j]; @@ -3572,8 +3646,8 @@ public class PGraphicsOpenGL2 extends PGraphics { // MATRIX STACK public void pushMatrix() { - if (USE_GBUFFER && GBUFFER_MERGE_ALL && GBUFFER_UPDATE_STACK) { - gbuffer.stack.push(); + if (USE_GEO_BUFFER && GEO_BUFFER_ACCUM_ALL && UPDATE_GEO_BUFFER_MATRIX_STACK) { + geoBuffer.stack.push(); return; } @@ -3589,8 +3663,8 @@ public class PGraphicsOpenGL2 extends PGraphics { public void popMatrix() { - if (USE_GBUFFER && GBUFFER_MERGE_ALL && GBUFFER_UPDATE_STACK) { - gbuffer.stack.pop(); + if (USE_GEO_BUFFER && GEO_BUFFER_ACCUM_ALL && UPDATE_GEO_BUFFER_MATRIX_STACK) { + geoBuffer.stack.pop(); return; } @@ -3615,8 +3689,8 @@ public class PGraphicsOpenGL2 extends PGraphics { } public void translate(float tx, float ty, float tz) { - if (USE_GBUFFER && GBUFFER_MERGE_ALL && GBUFFER_UPDATE_STACK) { - gbuffer.stack.translate(tx, ty, tz); + if (USE_GEO_BUFFER && GEO_BUFFER_ACCUM_ALL && UPDATE_GEO_BUFFER_MATRIX_STACK) { + geoBuffer.stack.translate(tx, ty, tz); return; } @@ -3659,8 +3733,8 @@ public class PGraphicsOpenGL2 extends PGraphics { * takes radians (instead of degrees). */ public void rotate(float angle, float v0, float v1, float v2) { - if (USE_GBUFFER && GBUFFER_MERGE_ALL && GBUFFER_UPDATE_STACK) { - gbuffer.stack.rotate(angle, v0, v1, v2); + if (USE_GEO_BUFFER && GEO_BUFFER_ACCUM_ALL && UPDATE_GEO_BUFFER_MATRIX_STACK) { + geoBuffer.stack.rotate(angle, v0, v1, v2); return; } @@ -3694,8 +3768,8 @@ public class PGraphicsOpenGL2 extends PGraphics { * Scale in three dimensions. */ public void scale(float sx, float sy, float sz) { - if (USE_GBUFFER && GBUFFER_MERGE_ALL && GBUFFER_UPDATE_STACK) { - gbuffer.stack.scale(sx, sy, sz); + if (USE_GEO_BUFFER && GEO_BUFFER_ACCUM_ALL && UPDATE_GEO_BUFFER_MATRIX_STACK) { + geoBuffer.stack.scale(sx, sy, sz); return; } @@ -6980,35 +7054,56 @@ public class PGraphicsOpenGL2 extends PGraphics { int gcount = i1 - i0 + 1; int vcount = v1 - v0 + 1; + int k = 0; + IntBuffer indicesBuffer0 = indicesBuffer; while (indicesBuffer.capacity() < idxCount + 3 * gcount) { int newSize = indicesBuffer.capacity() << 1; - + ByteBuffer ibb = ByteBuffer.allocateDirect(newSize * SIZEOF_INT); ibb.order(ByteOrder.nativeOrder()); indicesBuffer = ibb.asIntBuffer(); indicesArray = new int[newSize]; + k++; + } + if (0 < k) { + indicesBuffer0.position(0); + indicesBuffer.position(0); + indicesBuffer.put(indicesBuffer0); + indicesBuffer.position(idxCount); + indicesBuffer0 = null; } + + k = 0; + FloatBuffer verticesBuffer0 = verticesBuffer; + FloatBuffer colorsBuffer0 = colorsBuffer; + FloatBuffer normalsBuffer0 = normalsBuffer; + FloatBuffer[] texcoordsBuffer0 = new FloatBuffer[texCount]; + for (int t = 0; t < texCount; t++) { + texcoordsBuffer0[t] = texcoordsBuffer[t]; + } while (verticesBuffer.capacity() / 3 < vertCount + vcount) { int newSize = verticesBuffer.capacity() / 3 << 1; + // The data already in the buffers cannot be discarded, copy it back to the new resized buffers!!!!!! ByteBuffer vbb = ByteBuffer.allocateDirect(newSize * 3 * SIZEOF_FLOAT); vbb.order(ByteOrder.nativeOrder()); verticesBuffer = vbb.asFloatBuffer(); - + ByteBuffer cbb = ByteBuffer.allocateDirect(newSize * 4 * SIZEOF_FLOAT); cbb.order(ByteOrder.nativeOrder()); colorsBuffer = cbb.asFloatBuffer(); - + ByteBuffer nbb = ByteBuffer.allocateDirect(newSize * 3 * SIZEOF_FLOAT); nbb.order(ByteOrder.nativeOrder()); normalsBuffer = nbb.asFloatBuffer(); - - for (int t = 0; t < texCount; t++) { + + for (int t = 0; t < texCount; t++) { + ByteBuffer tbb = ByteBuffer.allocateDirect(newSize * 2 * SIZEOF_FLOAT); tbb.order(ByteOrder.nativeOrder()); - texcoordsBuffer[t] = tbb.asFloatBuffer(); + texcoordsBuffer[t] = tbb.asFloatBuffer(); } verticesArray = new float[newSize * 3]; @@ -7016,9 +7111,41 @@ public class PGraphicsOpenGL2 extends PGraphics { normalsArray = new float[newSize * 3]; for (int t = 0; t < texCount; t++) { texcoordsArray[t] = new float[newSize * 2]; - } + } + + k++; } + if (0 < k) { + // To avoid moving the buffer position to far forward when increasing + // the size several consecutive times. + verticesBuffer0.position(0); + verticesBuffer.position(0); + verticesBuffer.put(verticesBuffer0); + verticesBuffer0 = null; + verticesBuffer.position(3 * vertCount); + + colorsBuffer0.position(0); + colorsBuffer.position(0); + colorsBuffer.put(colorsBuffer0); + colorsBuffer0 = null; + colorsBuffer.position(4 * vertCount); + + normalsBuffer0.position(0); + normalsBuffer.position(0); + normalsBuffer.put(normalsBuffer0); + normalsBuffer0 = null; + normalsBuffer.position(3 * vertCount); + + for (int t = 0; t < texCount; t++) { + texcoordsBuffer0[t].position(0); + texcoordsBuffer[t].position(0); + texcoordsBuffer[t].put(texcoordsBuffer0[t]); + texcoordsBuffer0[t] = null; + texcoordsBuffer[t].position(3 * vertCount); + } + } + int ni = 0; for (int i = i0; i <= i1; i++) { indicesArray[ni++] = vertCount + indices[i][VERTEX1] - v0; @@ -7111,7 +7238,7 @@ public class PGraphicsOpenGL2 extends PGraphics { idxCount += 3 * gcount; vertCount += vcount; - GBUFFER_SIZE += vcount; + GEO_BUFFER_SIZE += vcount; } void pre() { @@ -7150,6 +7277,13 @@ public class PGraphicsOpenGL2 extends PGraphics { } void render() { + // Note for my future self: Since this geometry already contains the + // geometric transformations that were applied at the moment of drawing, + // the current modelview should be reset to the camera state. + // In this way, the transformations can be stored in the matrix stack of + // the buffer but also being applied in order to affect other geometry + // that is not accumulated (PShape3D, for instance). + indicesBuffer.position(0); verticesBuffer.position(0); colorsBuffer.position(0); @@ -7166,13 +7300,49 @@ public class PGraphicsOpenGL2 extends PGraphics { gl2f.glTexCoordPointer(2, GL.GL_FLOAT, 0, texcoordsBuffer[t]); } - gl2f.glDrawElements(GL.GL_TRIANGLES, idxCount, GL2.GL_UNSIGNED_INT, indicesBuffer); // Using glDrawRangeElements doesn't make any difference: //gl2x.glDrawRangeElements(GL.GL_TRIANGLES, minVertIndex, maxVertIndex, idxCount, GL2.GL_UNSIGNED_INT, indicesBuffer); } + void record() { + indicesBuffer.position(0); + verticesBuffer.position(0); + colorsBuffer.position(0); + normalsBuffer.position(0); + for (int t = 0; t < texCount; t++) { + texcoordsBuffer[t].position(0); + } + + int v0 = recordedVertices.size(); + Integer idx; + for (int i = 0; i < idxCount; i++) { + idx = new Integer(v0 + indicesBuffer.get()); + recordedIndices.add(idx); + //System.out.println(idx); + } + + PVector v; + float[] c; + for (int i = 0; i < vertCount; i++) { + v = new PVector(verticesBuffer.get(), verticesBuffer.get(), verticesBuffer.get()); + recordedVertices.add(v); + + v = new PVector(normalsBuffer.get(), normalsBuffer.get(), normalsBuffer.get()); + recordedNormals.add(v); + + c = new float[4]; + c[0] = colorsBuffer.get(); c[1] = colorsBuffer.get(); + c[2] = colorsBuffer.get(); c[3] = colorsBuffer.get(); + recordedColors.add(c); + + for (int t = 0; t < texCount; t++) { + v = new PVector(texcoordsBuffer[t].get(), texcoordsBuffer[t].get(), 0); + recordedTexCoords[t].add(v); + } + } + } } /** diff --git a/java/libraries/opengl2/src/processing/opengl2/PShape3D.java b/java/libraries/opengl2/src/processing/opengl2/PShape3D.java index 6bb54bdb3..a22363b87 100644 --- a/java/libraries/opengl2/src/processing/opengl2/PShape3D.java +++ b/java/libraries/opengl2/src/processing/opengl2/PShape3D.java @@ -31,6 +31,7 @@ import processing.core.PImage; import processing.core.PShape; import processing.core.PVector; import java.nio.FloatBuffer; +import java.nio.IntBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -75,7 +76,7 @@ public class PShape3D extends PShape { protected FloatBuffer vertexBuffer; protected FloatBuffer colorBuffer; protected FloatBuffer normalBuffer; - protected FloatBuffer texCoordBuffer; + protected FloatBuffer texCoordBuffer; // Public arrays for setting/getting vertices, colors, normals, and // texture coordinates when using loadVertices/updateVertices, @@ -87,6 +88,12 @@ public class PShape3D extends PShape { public float[] normals; public float[] texcoords; + // Indexed mode, testing: + protected int glIndexBufferID = 0; + protected IntBuffer indexBuffer = null; + protected int indexCount = 0; + protected int[] indices; + // To put the texture coordinate values adjusted according to texture // flipping mode, max UV range, etc. protected float[] convTexcoords; @@ -139,6 +146,9 @@ public class PShape3D extends PShape { protected int firstVertex; protected int lastVertex; + protected int firstIndex; + protected int lastIndex; + // Bounding box (defined for all shapes, group and geometry): public float xmin, xmax; public float ymin, ymax; @@ -155,7 +165,9 @@ public class PShape3D extends PShape { glVertexBufferID = 0; glColorBufferID = 0; glNormalBufferID = 0; - glTexCoordBufferID = null; + glTexCoordBufferID = null; + + updateElement = -1; } public PShape3D(PApplet parent) { @@ -164,7 +176,7 @@ public class PShape3D extends PShape { pgl = (PGraphicsOpenGL2)parent.g; this.family = PShape.GROUP; this.name = "root"; - this.root = this; + this.root = this; } public PShape3D(PApplet parent, int numVert) { @@ -183,6 +195,8 @@ public class PShape3D extends PShape { glNormalBufferID = 0; glTexCoordBufferID = null; + updateElement = -1; + initShapeOBJ(filename, params); } @@ -199,6 +213,8 @@ public class PShape3D extends PShape { glNormalBufferID = 0; glTexCoordBufferID = null; + updateElement = -1; + initShape(size, params); } @@ -209,7 +225,8 @@ public class PShape3D extends PShape { deleteVertexBuffer(); deleteColorBuffer(); deleteTexCoordBuffer(); - deleteNormalBuffer(); + deleteNormalBuffer(); + deleteIndexBuffer(); } //////////////////////////////////////////////////////////// @@ -677,6 +694,13 @@ public class PShape3D extends PShape { } + static public PShape createChild(String name, int n0, int n1, int i0, int i1, int mode, float weight, PImage[] tex) { + PShape3D child = (PShape3D)createChild(name, n0, n1, mode, weight, tex); + child.firstIndex = i0; + child.lastIndex = i1; + return child; + } + static public PShape createChild(String name, int n0, int n1, int mode, float weight, PImage[] tex) { PShape3D child = new PShape3D(); child.family = PShape.GEOMETRY; @@ -744,6 +768,7 @@ public class PShape3D extends PShape { who3d.glColorBufferID = root.glColorBufferID; who3d.glNormalBufferID = root.glNormalBufferID; who3d.glTexCoordBufferID = root.glTexCoordBufferID; + who3d.glIndexBufferID = root.glIndexBufferID; who3d.vertexBuffer = root.vertexBuffer; who3d.colorBuffer = root.colorBuffer; @@ -1445,6 +1470,7 @@ public class PShape3D extends PShape { child1 = (PShape3D)childList.get(i); if (child0.equalTo(child1, false)) { child0.lastVertex = child1.lastVertex; // Extending child0. + child0.lastIndex = child1.lastIndex; // Updating the vertex data: for (int n = child0.firstVertex; n <= child0.lastVertex; n++) { vertexChild[n] = child0; @@ -1850,6 +1876,35 @@ public class PShape3D extends PShape { } + //////////////////////////////////////////////////////////// + + // INDEXED MODE: TESTING + + public void initIndices(int n) { + indexCount = n; + + glIndexBufferID = pgl.createGLResource(PGraphicsOpenGL2.GL_VERTEX_BUFFER); + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, glIndexBufferID); + final int bufferSize = indexCount * PGraphicsOpenGL2.SIZEOF_INT; + gl.glBufferData(GL.GL_ARRAY_BUFFER, bufferSize, null, GL.GL_STATIC_DRAW); + gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + + indices = new int[indexCount]; + } + + public void setIndices(ArrayList recordedIndices) { + gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, glIndexBufferID); + indexBuffer = gl.glMapBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, GL.GL_WRITE_ONLY).asIntBuffer(); + + for (int i = 0; i < indexCount; i++) { + indices[i] = (Integer)recordedIndices.get(i); + } + indexBuffer.put(indices); + + gl.glUnmapBuffer(GL.GL_ELEMENT_ARRAY_BUFFER); + gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); + } + //////////////////////////////////////////////////////////// // Data allocation, deletion. @@ -2089,6 +2144,13 @@ public class PShape3D extends PShape { } + protected void deleteIndexBuffer() { + if (glIndexBufferID != 0) { + pgl.deleteGLResource(glIndexBufferID, PGraphicsOpenGL2.GL_VERTEX_BUFFER); + glIndexBufferID = 0; + } + } + protected void deleteTexCoordBuffer() { for (int i = 0; i < numTexBuffers; i++) { deleteTexCoordBuffer(i); @@ -2206,7 +2268,6 @@ public class PShape3D extends PShape { } if (family == GROUP) { - init(); for (int i = 0; i < childCount; i++) { ((PShape3D)children[i]).draw(g); @@ -2363,7 +2424,16 @@ public class PShape3D extends PShape { } } - gl.glDrawArrays(glMode, firstVertex, lastVertex - firstVertex + 1); + if (glIndexBufferID != 0) { + gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, glIndexBufferID); + // Here the vertex indices are understood as the range of indices. + int last = lastIndex; + int first = firstIndex; + gl.glDrawElements(glMode, last - first + 1, GL.GL_UNSIGNED_INT, first * PGraphicsOpenGL2.SIZEOF_INT); + gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); + } else { + gl.glDrawArrays(glMode, firstVertex, lastVertex - firstVertex + 1); + } if (0 < numTextures) { for (int t = 0; t < numTextures; t++) {