How To Correctly Use glMultMatrix - iPhone - OpenGL ES - iphone

I wonder if anyone can help me learn how to correctly use glMultMatrix.
I have the following render code in my app, however it appears I cannot just feed a C struct with the matrix to glMultMatrix :
-(void)render
{
matrixStruct matrices[] = {1, 0, -0, -9.37988, 0, -0.651537, 0.758617, 1133.64, 0, 0.758617, 0.651537, 129730, 0, 0, 0, 1};
// clear the matrix
glPushMatrix();
glLoadIdentity();
//scale
glScalef(0.00001, 0.00001, 0.00001);
glMultMatrixf(matrices);
[mesh render];
//restore the matrix
glPopMatrix();
}
I understand from the documentation at http://www.opengl.org/sdk/docs/man/xhtml/glMultMatrix.xml that I need to provide :
void glMultMatrixd( const GLdouble * m);
void glMultMatrixf( const GLfloat * m);
m
Points to 16 consecutive values that are used as the elements of a 4 × 4 column-major matrix.
I am not sure how I should format my matrix and pass it to glMultMatrix. Also do I need to enable glMatrixMode before I call render ?
Thank you

Worked it out - I needed to pass an array of floats :
e.g
float matrices[] ={1,0,0,0,0,1,0,0,0,0,1,0,-578.556,7068.92,48.6953,1};
All working now - thanks.

Related

Matlab gradient equivalent in opencv

I am trying to migrate some code from Matlab to Opencv and need an exact replica of the gradient function. I have tried the cv::Sobel function but for some reason the values in the resulting cv::Mat are not the same as the values in the Matlab version. I need the X and Y gradient in separate matrices for further calculations.
Any workaround that could achieve this would be great
Sobel can only compute the second derivative of the image pixel which is not what we want.
(f(i+1,j) + f(i-1,j) - 2f(i,j)) / 2
What we want is
(f(i+i,j)-f(i-1,j)) / 2
So we need to apply
Mat kernelx = (Mat_<float>(1,3)<<-0.5, 0, 0.5);
Mat kernely = (Mat_<float>(3,1)<<-0.5, 0, 0.5);
filter2D(src, fx, -1, kernelx)
filter2D(src, fy, -1, kernely);
Matlab treats border pixels differently from inner pixels. So the code above is wrong at the border values. One can use BORDER_CONSTANT to extent the border value out with a constant number, unfortunately the constant number is -1 by OpenCV and can not be changed to 0 (which is what we want).
So as to border values, I do not have a very neat answer to it. Just try to compute the first derivative by hand...
You have to call Sobel 2 times, with arguments:
xorder = 1, yorder = 0
and
xorder = 0, yorder = 1
You have to select the appropriate kernel size.
See documentation
It might still be that the MatLab implementation was different, ideally you should retrieve which kernel was used there...
Edit:
If you need to specify your own kernel, you can use the more generic filter2D. Your destination depth will be CV_16S (16bit signed).
Matlab computes the gradient differently for interior rows and border rows (the same is true for the columns of course). At the borders, it is a simple forward difference gradY(1) = row(2) - row(1). The gradient for interior rows is computed by the central difference gradY(2) = (row(3) - row(1)) / 2.
I think you cannot achieve the same result with just running a single convolution filter over the whole matrix in OpenCV. Use cv::Sobel() with ksize = 1, then treat the borders (either manually or by applying a [ 1 -1 ] filter).
Pei's answer is partly correct. Matlab uses these calculations for the borders:
G(:,1) = A(:,2) - A(:,1);
G(:,N) = A(:,N) - A(:,N-1);
so used the following opencv code to complete the gradient:
static cv::Mat kernelx = (cv::Mat_<double>(1, 3) << -0.5, 0, 0.5);
static cv::Mat kernely = (cv::Mat_<double>(3, 1) << -0.5, 0, 0.5);
cv::Mat fx, fy;
cv::filter2D(Image, fx, -1, kernelx, cv::Point(-1, -1), 0, cv::BORDER_REPLICATE);
cv::filter2D(Image, fy, -1, kernely, cv::Point(-1, -1), 0, cv::BORDER_REPLICATE);
fx.col(fx.cols - 1) *= 2;
fx.col(0) *= 2;
fy.row(fy.rows - 1) *= 2;
fy.row(0) *= 2;
Jorrit's answer is partly correct.
In some cases, the value of the directional derivative may be negative, and MATLAB will retain these negative numbers, but OpenCV Mat will set the negative number to 0.

How do you implement glOrtho for opengles 2.0? With or without tx,ty,tz values from the glOrtho spec?

Im trying to implement my own glOtho function from the opengles docs http://www.khronos.org/opengles/documentation/opengles1_0/html/glOrtho.html
to modify a Projection matrix in my vertex shader. It's currently not working properly as I see my simple triangles vertices out of place. Can you please check the code below and see if i'm doing things wrong.
I've tried setting tx,ty and tz to 0 and that seems to make it render properly. Any ideas why would this be so?
void ES2Renderer::_applyOrtho(float left, float right,float bottom, float top,float near, float far) const{
float a = 2.0f / (right - left);
float b = 2.0f / (top - bottom);
float c = -2.0f / (far - near);
float tx = - (right + left)/(right - left);
float ty = - (top + bottom)/(top - bottom);
float tz = - (far + near)/(far - near);
float ortho[16] = {
a, 0, 0, tx,
0, b, 0, ty,
0, 0, c, tz,
0, 0, 0, 1
};
GLint projectionUniform = glGetUniformLocation(_shaderProgram, "Projection");
glUniformMatrix4fv(projectionUniform, 1, 0, &ortho[0]);
}
void ES2Renderer::_renderScene()const{
GLfloat vVertices[] = {
0.0f, 5.0f, 0.0f,
-5.0f, -5.0f, 0.0f,
5.0f, -5.0f, 0.0f};
GLuint positionAttribute = glGetAttribLocation(_shaderProgram, "Position");
glEnableVertexAttribArray(positionAttribute);
glVertexAttribPointer(positionAttribute, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(positionAttribute);
}
Vert shader
attribute vec4 Position;
uniform mat4 Projection;
void main(void){
gl_Position = Projection*Position;
}
Solution
From Nicols answer below I modifed my matrix as so and it seemed render properly
float ortho[16] = {
a, 0, 0, 0,
0, b, 0, 0,
0, 0, c, 0,
tx, ty, tz, 1
};
Important note
You cannot use GL_TRUE for transpose argument for glUniform as below. opengles does not support it. it must be GL_FALSE
glUniformMatrix4fv(projectionUniform, 1, GL_TRUE, &ortho[0]);
From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml
transpose
Specifies whether to transpose the matrix as the values are loaded into the uniform variable. Must be GL_FALSE.
Matrices in OpenGL are column major. Unless you pass GL_TRUE as the third parameter to glUniformMatrix4fv, the matrix will effectively be transposed relative to what you would intend.

How to batch render sprites in OpenGL ES (iPhone)

I have a game that renders a bunch of sprites (several hundred), almost all of which are using the same texture. Currently, I'm calling glDrawArrays(...) for each one, which I recently discovered was very inefficient. After doing some research, I've learned that I need to put all my vertices for every sprite into one big vertex buffer, and call glDrawArrays(...) just once using that. However, when I do so it only draws the first sprite, and the other 200 are blank.
blueSpriteVertices[blueBatchNum * 4] = Vertex3DMake(xloc, yloc, zloc);
blueSpriteVertices[blueBatchNum * 4 + 1] = Vertex3DMake(xloc + size, yloc, zloc);
blueSpriteVertices[blueBatchNum * 4 + 2] = Vertex3DMake(xloc, yloc + size, zloc);
blueSpriteVertices[blueBatchNum * 4 + 3] = Vertex3DMake(xloc + size, yloc + size, zloc);
blueBatchNum++;
//^^This block of code^^ is called iteratively, adding data for various sprites
//(around 200) to the vertex array. "xloc", "yloc", etc. are private members of
//this sprite class
//Draw the whole batch
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1, 1, 1, 1);
//This code is actually in the Texture2D class implementation, hence "_name"
//and "coordinates"
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, blueSpriteVertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_VERTEX_ARRAY);
I finally solved this problem by using GL_TRIANGLES instead of GL_TRIANGLE_STRIP, and handled the triangle strips manually. By doing so I was able to eliminate all the "strips" that it was interpreting in between my sprites. Works like a charm now, and the batching definitely improved my game's performance astronomically.
Using (GL_TRIANGLES instead of GL_TRIANGLE_STRIP works for me (on Android)
glDrawElements(GL_TRIANGLES, 6 * mSpriteCounter, GL_UNSIGNED_SHORT, (char*) NULL);
The glDrawArrays() last parameter should contain the number of vertices (in your case you have only 4). Also you must have the same number of texture coordinates to match the drawn vertices!

Why does this Drawing glitch happen with GL_TRIANGLE_STRIP in OpenGL ES 1.1

So I'm starting to work with openGL, been following the tutorials over at Jeff LaMarche's blog and I've run into a problem when trying to draw a square using the GL_TRIANGLE_STRIP mode with glDrawArrays.
It works, by that I mean that I can draw a square, but I get this weird drawing glitch. You can see it here:
Drawing glitch http://img10.imageshack.us/img10/1631/picture1io.png
I'm using the xcode template that's provided by Jeff, so I assume the setup is all proper. The code I'm using in the drawView function is as follows:
Square2D *square = malloc(sizeof(Square2D));
Square2DSet(square, -0.25, -0.25, -20.0, 0.5, 0.5);
glLoadIdentity();
glClearColor(0.7, 0.7, 0.7, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glColor4f(1.0, 0.0, 0.0, 1.0);
glVertexPointer(3, GL_FLOAT, 0, square);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 12);
glDisableClientState(GL_VERTEX_ARRAY);
if(square != NULL)
free(square);
here's the code for Square2d and Square2DSet:
typedef struct {
Vertex3D tl;
Vertex3D bl;
Vertex3D tr;
Vertex3D br;
} Square2D;
static inline void Square2DSet(Square2D *sq, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
{
sq->tl = Vertex3DMake(x, y, z);
sq->bl = Vertex3DMake(x, y + height, z);
sq->tr = Vertex3DMake(x + width, y, z);
sq->br = Vertex3DMake(x + width, y + height, z);
}
I'm sure I'm doing something wrong, just not sure what. Eventually the glitch will go away after the program has run for a little bit.
Any ideas?
Cheers
glDrawArrays(GL_TRIANGLE_STRIP, 0, 12);
is drawing 12 vertices. You want 4. Its asking how many indices, not how many values to look at. It will multiply the index by the number of values at each index.
The reason why its going crazy is because its drawing junk, then it disappears because I assume that junk gets filled with 0s or something and it just goes away.

OpenGL to OpenGL-ES - glRectf()

I am trying to learn OpenGL on the iPhone using the "Super Bible" but am having trouble porting from OpenGLto OpenGL ES. My understanding is that the glRectf() function is not available in the latter. What is the substitute approach? Any relevant conceptual information would be appreciated as well.
The substitute approach is to draw a triangle strip:
GLfloat texture[] =
{
0, 0,
0, 1,
1, 0,
1, 1
};
GLfloat model[] =
{
0, 0, // lower left
0, h, // upper left
w, 0, // lower right
w, h // upper right
};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, model);
glTexCoordPointer(2, GL_FLOAT, 0, texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
This draws a textured rectangle with width w and height h.
Rather than doing a rect, you just do two triangles.
This is really irrelevant though since GL-ES on the iPhone does not support immediate mode. You need to define all your vertices in an array and use one of the vertex array rendering functions to draw them rather than using the immediate mode functions.