3

Ok I have checked over and over, and so far I "think" i understand how opengl is drawing and how to specify what i want to draw, however i just cant seem to make it draw more than 1 line.

Using the template from Xcode 4.2 i can get the following code. It DOES draw my square skeleton using GLKIT, because im just ignoring the opengl es 2.0 method to not use shaders atm, but when i Touch the screen it should draw my own array, Which it doesnt....

So first the square format (just to show the type of variable they use in the template)

GLfloat gCubeVertexData[216] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, 0.5f,          1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,

    0.5f, 0.5f, -0.5f,         0.0f, 1.0f, 0.0f,
    -0.5f, 0.5f, -0.5f,        0.0f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f,          0.0f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f,          0.0f, 1.0f, 0.0f,
    -0.5f, 0.5f, -0.5f,        0.0f, 1.0f, 0.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 1.0f, 0.0f,

    -0.5f, 0.5f, -0.5f,        -1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,       -1.0f, 0.0f, 0.0f,
    -0.5f, 0.5f, 0.5f,         -1.0f, 0.0f, 0.0f,
    -0.5f, 0.5f, 0.5f,         -1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,       -1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, 0.5f,        -1.0f, 0.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,       0.0f, -1.0f, 0.0f,
    0.5f, -0.5f, -0.5f,        0.0f, -1.0f, 0.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, -1.0f, 0.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, -1.0f, 0.0f,
    0.5f, -0.5f, -0.5f,        0.0f, -1.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         0.0f, -1.0f, 0.0f,

    0.5f, 0.5f, 0.5f,          0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, 0.0f, 1.0f,

    0.5f, -0.5f, -0.5f,        0.0f, 0.0f, -1.0f,
    -0.5f, -0.5f, -0.5f,       0.0f, 0.0f, -.0f,
    0.5f, 0.5f, -0.5f,         0.0f, 0.0f, -1.0f,
    0.5f, 0.5f, -0.5f,         0.0f, 0.0f, -1.0f,
    -0.5f, -0.5f, -0.5f,       0.0f, 0.0f, -1.0f,
    -0.5f, 0.5f, -0.5f,        0.0f, 0.0f, -1.0f
};

Here is my SetupGL that I call Once in the "View did Load" function.

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];

    [self loadShaders];

    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE; //No Idea why it wont work without this


    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));

    glBindVertexArrayOES(0);
}

This is the update method (that is just making stuff rotate)

- (void)update
{
    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 10000.0f);

    self.effect.transform.projectionMatrix = projectionMatrix;

    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -10.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);

    // Compute the model view matrix for the object rendered with GLKit
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

    self.effect.transform.modelviewMatrix = modelViewMatrix;

    _rotation += self.timeSinceLastUpdate * 0.5f;
}

The Draw In Rect method (The render i think)

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArrayOES(_vertexArray);

    // Render the object with GLKit
    [self.effect prepareToDraw];

    glDrawArrays(GL_LINE_STRIP, 0, 36); //Probably have to change the 36

}

This is the Touch part:

On touches began i am just creating the NSMutableData

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *touch = [touches anyObject];
    startPoint = [touch locationInView:self.view];

    vertexData3 = [NSMutableData dataWithLength: sizeof(GLKVector2)]; //HERE

    if (!referenceAttitude)
        referenceAttitude = motionManager.deviceMotion.attitude;

    writtingON = YES;   

}

On Touches Ended I am trying to Draw with the new vertices i got. The vertices are obtained using a timer that triggers readings from the motion manager, doing some math + where the user touched the screen so values should be around the range of the screen coordinates.

HOWEVER to test the drawing i am just creating a temporal NSMUtableData variable with some values that i added by hand (the adding is horrible tho). I Am using NSMutableData because thats what they suggested in another tutorial. I am 90% sure it is saving the data correctly because when i retrieve it it IS there. (http://games.ianterrell.com/how-to-draw-2d-shapes-with-glkit/)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{


    ////////Test array


    tempVert = GLKVector2Make(10, -8);
    NSRange r = {0*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: r withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(2, -8);
    NSRange q = {1*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: q withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(4, 9);
    NSRange w = {2*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: w withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(1, -9);
    NSRange e = {3*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: e withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(2, -2);
    NSRange t = {4*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: t withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];


    //////////////////////

    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData3), [vertexData3 mutableBytes], GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

    glBindVertexArrayOES(0);

}

This Last part is the one driving me crazy!!! What i think it should do is, modify the buffer with my own array so that the autoupdate draws it.

Any suggestions will be really appreciated.

Thanks

Oh and if anyone knows how to set up the orthogonalmatrix because im really only interested in the 2d components atm, so that i cant replace it for that perspective matrix.

EDIT:

Ok i just tried sending a random array of GLfloats and it does change the shape, but why not with my array of NSMutableData? i thought i am doing the exact same proceadure as in the tutorial....

Pochi
  • 13,391
  • 3
  • 64
  • 104

1 Answers1

0

the last part should be only:

glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData3), [vertexData3 mutableBytes], GL_DYNAMIC_DRAW);
// bind buffer and specify it's new data (no need to glGenBuffers(), that was done in setupGL())
// also, it would be handy to save number of vertices so it could be used later for drawing (nVertices = sizeof(vertexData3) / sizeof(GLKVector2))

glBindVertexArrayOES(_vertexArray);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindVertexArrayOES(0);
// bind vertex array and setup the vertex attribute (although this could be done only once, in setupGL())

That way, you don't generate so many OpenGL objects, and the rendering should be faster (also, won't run out of memory).

Otherwise, the rendering seems to be ok. But you should really use the real number of vertices to do the drawing:

glDrawArrays(GL_LINE_STRIP, 0, nVertices);

There are almost certainly problems with scale (there should be no difference between GLfloats and GLKVector2). You generate some points by your method, but then only draw the first 36. It may be possible that there is a curve generated correclty, but you only see a short bit of the beginning of it, which naturally seems flat. Also, you seem not to be sure that your calculations of position generate coordinates inside the window, maybe it would be a good idea to a) post your source here b) multiply your coordinates by some small (but above zero) values in order for them to fit on the screen.

As for the ortho, you can use:

GLKMatrix4MakeOrtho(-1, 1, -1, 1, .1, 1000); // this sets normalized coordinates
GLKMatrix4MakeOrtho(0, widthPx, 0, heightPx, .1, 1000); // this sets pixel coordinates

The parameters of GLKMatrix4MakeOrtho are just desired coordinates at the corners of the screen (left, right, bottom, top) and depth range being drawn (near, far).

I hope this will give you at least some kind of insight ...

the swine
  • 10,713
  • 7
  • 58
  • 100
  • Yeah i kinda figured it out but really wasnt sure what was the problem. When i read ur post it confirmed that in fact i was drawing only the first points, i thought that number ment "number of objects" as in triangles, lines etc, but no haha. Also do you happen to know how to create and load vertices/Textures during runtime? If you do please let me know so i post a question. I just kinda gave up on asking about opengl here lol. – Pochi Jan 20 '12 at 10:53
  • Yes, the last argument of glDrawArrays() is number of vertices, not a number of primitives. As for the creation of vertices/textures at runtime, you *are*, in fact, now creating vertices at runtime so i'm not sure what more is there to know (but will provide answer if needed). About textures - there are many ways of creating textures (loading images, rendering to texture, procedural texturing) ... i don't know what you'd like to know. If creating a new question, please be specific about the effect you want to achieve. – the swine Jan 20 '12 at 11:11