-1

I'm trying to render an array of VBOs but the results are not right. I am saving them into an array when I draw them the first time using the GLPaint (OpenGLES v2) setup. Here is the sample project I have if you want to help me out. https://drive.google.com/file/d/0B0pG5vRVzBTzUTZPYWNoenhkcWs/edit?usp=sharing

////// Store VBOs when drawing this is done in renderLineFromPoint (from GLPaint)
- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end
{

static GLfloat*     vertexBuffer = NULL;
static NSUInteger   vertexMax = 64;
NSUInteger          vertexCount = 0,
count,
i;

[EAGLContext setCurrentContext:context];
glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);

// Convert locations from Points to Pixels
CGFloat scale = self.contentScaleFactor;
start.x *= scale;
start.y *= scale;
end.x *= scale;
end.y *= scale;

// Allocate vertex array buffer
if(vertexBuffer == NULL)
    vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat));

// Add points to the buffer so there are drawing points every X pixels
count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);

for(i = 0; i < count; ++i)
{
    if(vertexCount == vertexMax)
    {
        vertexMax = 2 * vertexMax;
        vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat));
    }

    vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);
    vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);
    vertexCount += 1;
}

glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, vertexCount*2*sizeof(GLfloat), vertexBuffer, GL_DYNAMIC_DRAW);

glEnableVertexAttribArray(ATTRIB_VERTEX);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0);

// Render the vertex array
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_POINTS, 0, vertexCount);

// Display the buffer
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];

// Store VBO for undo
VBOHolder *vboHolder = [[VBOHolder alloc]init];
vboHolder.vertexCount = vertexCount;
vboHolder.vbo = vertexBuffer;
[vboHolderArray addObject:vboHolder];

}

////// Here is the problem: I clear the screen and then try to re-render the VBOs
-(void)renderSavedVertexBufferes
{

  for (VBOHolderModel *vboh in vboHolderArray)
  {
    if (vboh.vertexCount == 0)
    {
        continue;
    }

    NSUInteger vertexCount = vboh.vertexCount;

    glBindBuffer(GL_ARRAY_BUFFER, vboId);
    glBufferData(GL_ARRAY_BUFFER, vertexCount*2*sizeof(GLfloat), vboh.vbo, GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(ATTRIB_VERTEX);
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, 0);

    // Render the vertex array
    glVertexPointer(2, GL_FLOAT, 0, vboh.vbo);
    glDrawArrays(GL_POINTS, 0, vertexCount);

    // Display the buffer
    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER];

  }
}


////// VBOHolderModel looks like this, it wraps the vbo so it can be put in NSMutableArray
@interface VBOHolderModel : NSObject
{
   GLfloat *vbo;
   NSUInteger vertexCount;

}

It's basically an undo... when pressing undo it should remove only the 3 because it was the last stroke, but it erases it all and draws the dots shown in the second image.

enter image description here

enter image description here

The Way
  • 594
  • 5
  • 15
  • Undo should be handled using intelligent design patterns, not any API specific features. I would look into the memento design pattern if I were you, this will allow you to store your document as a sequence of commands where each command stores the previous state. When it comes time to render your document you can do it as simply as a replay of all the commands. When it comes time to undo a command you can either use a copy of the prior state (fast, but memory hungry) or you can replay the commands in-order. – Andon M. Coleman Nov 22 '13 at 00:12
  • That was in response to your prior question; regarding *this* question, I have to wonder why a function called `SavedVertexBufferes` sends new data to the VBO each time it is called? It really is not saving anything if this is the case. I would consider using Vertex Array Objects, since this is iOS specific - not all GL ES 2.0 implementations support them, but iOS does. – Andon M. Coleman Nov 22 '13 at 00:19
  • Are you referring to the renderSavedVertexBufferes function? If so, that is where I am trying to redraw the vertex buffers that were already drawn and stored in an Array. I then create a flag in that Array to let me know when the last line was drawn, I can then remove the vertex buffers up to that point and redraw the remaining buffers, which is basically an "undo". But I'm still not a pro in how the VBOs work or OpenGL ES. I need a nice graphical diagram to explain the relationship between all the parts. – The Way Nov 22 '13 at 00:33
  • Right, but you are not actually re-drawing those VBOs. You are actually re-allocating them and giving them new data because you are calling `glBufferData (...)` on them. If you really want to re-use them, then eliminate the call to `glBufferData (...)`. If you use a Vertex Array Object you can actually remove 99% of those API calls and just bind a VAO and call `glDrawArrays (...)`. – Andon M. Coleman Nov 22 '13 at 00:38
  • This is how I see it... The vertex buffers store the drawing info and are passed in with glBufferData(). Then, calling glDrawArrays() will render that data. The way I have it now seems to be on the right track, but when it redraws it just seems that some of the data is missing, or I am only drawing some of the buffers. As you can see in the second image the points are in the right places, its just that most are missing. – The Way Nov 22 '13 at 00:39
  • Ok, let me try removing that call real quick, if that doesn't work then i'll look into the VAO. (thanks for the feedback) – The Way Nov 22 '13 at 00:41
  • Do you have a separate function where you initialize the VBOs with data? That is how this needs to function, one function to give it data (`glBufferData (...)`) and one to draw with (`glDrawArrays (...)`); since you draw with a VBO far more often than you give or change its data. This way you can literally re-use the VBOs instead of sending them new data every time you draw with them. VAOs will reduce the number of calls necessary to draw (e.g. `glVertexPointer (...)`, `glEnableVertexAttribArray (...)`, etc.) as well; you can move that setup into your init function and bind a VAO to draw. – Andon M. Coleman Nov 22 '13 at 00:46
  • I update the question to show the full function where i am initializing the VBOs with data, its the first one... `- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end` Its from the GLPaint app. So what your saying is I can clear the canvas with `glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT);` then just call `glDrawArrays()` again and it should redraw from the data already set? – The Way Nov 22 '13 at 00:53
  • No, you still have to bind the VBOs and draw them individually. But what you do **not** want to do is call `glBufferData (...)` over and over. – Andon M. Coleman Nov 22 '13 at 01:07
  • Ok, I'm trying all kinds of stuff, but if you have time maybe you can grab the sample project from the link above and see what you can do. I'm still getting results that are only rendering some of the points/lines. And I don't know why. Thanks a lot for your time thus far. Let me know if you want to open a chat and solve this. :) – The Way Nov 22 '13 at 01:19

1 Answers1

1

I found the answer to this question in the lines below

// Allocate vertex array buffer
if(vertexBuffer == NULL)
vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat));

The problems is that the stored Vertex Arrays are all the same! It was only allocating memory once on init when vertexBuffer is null. Some of the other code has change a bit to, if you want the updates, let me know.

The Way
  • 594
  • 5
  • 15
  • Can you please help me on how to use VBOHolder in GLPaint. Am still struggling with the undo action in GLPaint app. – Madhavan Dec 07 '17 at 11:34