Unexpected error for me. I wrote this code:
Eigen::Array <GLfloat, NumVertices, 2> vertices;
vertices(0, 0) = 0.90f; vertices(0, 1) = 0.90f;
vertices(1, 0) = 0.90f; vertices(1, 1) = -0.90f;
vertices(2, 0) = -0.90f; vertices(2, 1) = -0.90f;
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices),
vertices.data(), GL_STATIC_DRAW);
And I see this:
Why? How correctly use Eigen array for OpenGL?
What I think:
0,0 = x1 0,1 = y1
1,0 = x2 1,1 = y2
2,0 = x3 2,1 = y3
But drawed this:
1,1 = x1 2,1 = y1
2,0 = x2 0,1 = y2
0,0 = x3 1,0 = y3
By default the elements of an Eigen::Array are stored column major. So you have two options:
Use column 2D vectors:
Eigen::Array<float, 2, NumVertices> vertices;
or request for a row-major storage layout:
Eigen::Array<float, NumVertices, 2, Eigen::RowMajor> vertices;
Moreover, in general the number of vertices is not known at compile time, or it is rather large. In these cases, use Eigen::Dynamic instead of NumVertices:
Eigen::Array<float, 2, Eigen::Dynamic> vertices(2, num_vertices);
Related
I'm writing my own version of gluLookAt. I believe I have the correct implementation however, often the matrix that gets returned is full of nan's.
Here is my function:
mat4 look_at(vec4 eye, vec4 at, vec4 up)
{
vec4 vpn = vec4_sub(eye, at);
vec4 n = vec4_norm(vpn);
vec4 u = vec4_norm(vec4_cross(up, n));
vec4 v = vec4_norm(vec4_cross(n, u));
vec4 p = { eye.x, eye.y, eye.z, 1 };
mat4 m;
m.x.x = u.x; m.y.x = u.y; m.z.x = u.z; m.w.x = u.w;
m.x.y = v.x; m.y.y = v.y; m.z.y = v.z; m.w.y = v.w;
m.x.z = n.x; m.y.z = n.y; m.z.z = n.z; m.w.z = n.w;
m.x.w = p.x; m.y.w = p.y; m.z.w = p.z; m.w.w = p.w;
mat4 m_t = mat4_trans(m);
mat4 m_t_inv= mat4_inv(m_t);
return m_t_inv;
}
I am currently trying to look at the top of a cube I made. The cube is 1x1x1 and is centered at the origin. I am setting the model_view like so:
vec4 e = {0, 1, 0, 1};
vec4 a = {0, 0, 0, 0};
vec4 u = {0, 0, 1, 0};
model_view = look_at(e, a, u);
I believe I have the parameters correct. I want to look down at the origin from y=1.
Does the issue appear to be in my function? or have I misunderstood the parameters?
The fourth component of the axis vectors u, v and p has to be zero. In your case the fourth component of vpn is not zero, because eye is {0, 1, 0, 1}.
I recommend doing the computation of u, v and p with vec3 rather than vec4. However, you can fix the issue with setting vpn[3] = 0:
vec4 vpn = vec4_sub(eye, at);
vpn[3] = 0
Suppose that X, Y are the matrices of coordinates inside the given intervals
xc = 0, yc = 0
xl = linspace(xc - 10, xc + 10, 2);
yl = linspace(yc - 10, yc + 10, 2);
[X,Y] = meshgrid(xl,yl);
and fun is a handle to some function test(v)
fun = #(v)test(v);
How to combine both matrices X, Y so that they represent components x,y of the vector v
res = arrayfun(fun, [X,Y]); //First processed X and then Y
Unfortunately, this solution does not work....
There is another way when the function is modified so that two parameters x, y are passed
fun = #(x, y)test(x, y);
res = arrayfun(fun, X, Y); //This works well
However, I would like to preserve an intertace of the function if any solution exists.
Thanks for your help.
Redefine fun as fun = #(x, y)test([x,y]);
No need to modify function test()
xc = 0;
yc = 0;
xl = linspace(xc - 10, xc + 10, 2);
yl = linspace(yc - 10, yc + 10, 2);
[X,Y] = meshgrid(xl,yl);
% Given function test
test =#(v)v(1) + v(2);
% pass x, y as a vector
fun = #(x, y)test([x,y]);
res = arrayfun(fun, X, Y);
% X =
-10 10
-10 10
% Y =
-10 -10
10 10
% fun(x, y) = x + y
% res =
-20 0
0 20
From Matlab doc:
B = arrayfun(func,A) applies the function func to the elements of A, one element at a time
B = arrayfun(func,A1,...,An) applies func to the elements of the arrays A1,...,An, so that B(i) = func(A1(i),...,An(i))
So you are using arrayfun in the wrong way.
Use a for loop or two nested loops instead.
for i=1:size(X,1)
for j=1:size(X,2)
res(i,j)=fun([X(i,j),Y(i,j)])
end
end
What are you trying to do?
Also, in Matlab, you should use % instead of // for commenting
These are some related questions:
arrayfun when each row of the array is an input
Passing a vector as multiple inputs to a function
I try to switch my openGL code from using display list to using VBO.
In the code, I tried to draw a green-grid floor, which is composed by green lines in parallel with x-axis and green lines in parallel with z-axis.
But when the program runs, floor doesn't display. And I can't find where goes wrong.
Here is my code initialize VBO of floor:
//**********************************
//defined in head of my source code
struct BufferVBO1
{
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat r;
GLfloat g;
GLfloat b;
};
struct IdVBO
{
GLuint id;
size_t bufsiz;
};
IdVBO vboGround;
//**************************************
glGenBuffers(1, &vboGround.id);
int groundSiz1 = ( (floorEdge_x_max-floorEdge_x_min)/(5*LENGTH_UNIT)+1 )*2 ;
int groundSiz2 = ( (floorEdge_z_max-floorEdge_z_min)/(5*LENGTH_UNIT)+1 )*2 ;
vboGround.bufsiz = groundSiz1+groundSiz2 ;
BufferVBO1 *groundBuf = new BufferVBO1 [vboGround.bufsiz];
for(int i=0, idx=0; idx<groundSiz1; ++i)
{
groundBuf[idx].x = floorEdge_x_min+i*5*LENGTH_UNIT;
groundBuf[idx].y = 0;
groundBuf[idx].z = floorEdge_z_min;
groundBuf[idx].r = 75/255.0;
groundBuf[idx].g = 1.0;
groundBuf[idx].b = 63/255.0;
++idx;
groundBuf[idx].x = floorEdge_x_min+i*5*LENGTH_UNIT;
groundBuf[idx].y = 0;
groundBuf[idx].z = floorEdge_z_max;
groundBuf[idx].r = 75/255.0;
groundBuf[idx].g = 1.0;
groundBuf[idx].b = 63/255.0;
++idx;
}
for(int i=0, idx=groundSiz1; idx<vboGround.bufsiz; ++i)
{
groundBuf[idx].x = floorEdge_x_min;
groundBuf[idx].y = 0;
groundBuf[idx].z = floorEdge_z_min+i*5*LENGTH_UNIT;
groundBuf[idx].r = 75/255.0;
groundBuf[idx].g = 1.0;
groundBuf[idx].b = 63/255.0;
++idx;
groundBuf[idx].x = floorEdge_x_max;
groundBuf[idx].y = 0;
groundBuf[idx].z = floorEdge_z_min+i*5*LENGTH_UNIT;
groundBuf[idx].r = 75/255.0;
groundBuf[idx].g = 1.0;
groundBuf[idx].b = 63/255.0;
++idx;
}
glBindBuffer(GL_ARRAY_BUFFER, vboGround.id);
glBufferData(GL_ARRAY_BUFFER, sizeof(BufferVBO1)*vboGround.bufsiz, groundBuf, GL_STATIC_DRAW);
delete [] groundBuf ;
glBindBuffer(GL_ARRAY_BUFFER, 0);
Here is the code to display:
glDisable(GL_LIGHTING);
glBindBuffer(GL_ARRAY_BUFFER, vboGround.id);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(BufferVBO1), (void*)0);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer( 3, GL_FLOAT, sizeof(BufferVBO1), (void*)(sizeof(GLfloat)*3) );
for(int i=0; i<vboGround.bufsiz; i+=2)
glDrawArrays(GL_LINE, i, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnable(GL_LIGHTING);
I've tried to draw a simple GL_QUADS floor using VBO, and it works! But when I tried to draw green-grid floor, it doesn't display.
Tell me where is the problem.
The first argument to glDrawArrays() here is invalid:
glDrawArrays(GL_LINE, i, 2);
GL_LINE is not a valid primitive type. You need to use GL_LINES:
glDrawArrays(GL_LINES, i, 2);
GL_LINE may look very similar, but it's one of the possible arguments for glPolygonMode().
You should always call glGetError() when your OpenGL call does not behave as expected. In this case, it should have returned GL_INVALID_ENUM.
BTW, you can draw all the lines in a single glDrawArrays() call, instead of using a loop:
glDrawArrays(GL_LINES, 0, vboGround.bufsize);
So in my program, I'm using OpenGL/GLSL to construct a square and texturing it.
It's modern OpenGL 4.0+ so doesn't use glBegin/glEnd etc.
My square is made up of 2 triangles, constructed using glDrawArrays(GL_TRIANGLES, 0, 6);
As you can see with my function below, it creates 2 triangles. I'm using 18 vertices in an array when really I only need 12 to create a square because 6 of them are used in both triangles. Its the same with the 24 colours and 8 text coordinates.
void Ground::constructGeometry(Shader* myShader)
{
//Triangle 1 (x,y,z)
vert[0] =-dimY; vert[1] = dimX; vert[2] = dimZ; //Point 2
vert[3] =-dimY; vert[4] =-dimX; vert[5] = dimZ; //Point 1
vert[6] = dimY; vert[7] =-dimX; vert[8] = dimZ; //Point 4
//Triangle 2 (x,y,z)
vert[9] = dimY; vert[10] =-dimX; vert[11] = dimZ; //Point 4
vert[12] = dimY; vert[13] = dimX; vert[14] = dimZ; //Point 3
vert[15] =-dimY; vert[16] = dimX; vert[17] = dimZ; //Point 2
//Colours 1 (r,g,b,a)
col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 1.0f;
col[4] = 1.0f; col[5] = 0.0f; col[6] = 0.0f; col[7] = 1.0f;
col[8] = 1.0f; col[9] = 0.0f; col[10] = 0.0f; col[11] = 1.0f;
//Colours 2 (r,g,b,a)
col[12] = 1.0f; col[13] = 0.0f; col[14] = 0.0f; col[15] = 1.0f;
col[16] = 1.0f; col[17] = 0.0f; col[18] = 0.0f; col[19] = 1.0f;
col[20] = 1.0f; col[21] = 0.0f; col[22] = 0.0f; col[23] = 1.0f;
//(s,t) coords for Tri 1
tex[0] = 0.0; tex[1] = 1.0;
tex[2] = 0.0; tex[3] = 0.0;
tex[4] = 1.0; tex[5] = 0.0;
//(s,t) coords for Tri 2
tex[6] = 1.0; tex[7] = 0.0;
tex[8] = 1.0; tex[9] = 1.0;
tex[10] = 0.0; tex[11] = 1.0;
glGenVertexArrays(2, &m_vaoID[0]);
glBindVertexArray(m_vaoID[0]);
glGenBuffers(3, m_vboID);
GLint vertexLocation= glGetAttribLocation(myShader->handle(), "in_Position");
GLint colorLocation= glGetAttribLocation(myShader->handle(), "in_Color");
GLint texCoordLocation = glGetAttribLocation(myShader->handle(), "in_TexCoord");
glUniform1i(glGetUniformLocation(myShader->handle(), "DiffuseMap"), 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vboID[0]);
glBufferData(GL_ARRAY_BUFFER, totalVerts *sizeof(GLfloat), vert, GL_STATIC_DRAW);
glEnableVertexAttribArray(vertexLocation);
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vboID[1]);
glBufferData(GL_ARRAY_BUFFER, totalCols *sizeof(GLfloat), col, GL_STATIC_DRAW);
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, m_vboID[2]);
glBufferData(GL_ARRAY_BUFFER, totalTexs *sizeof(GLfloat), tex, GL_STATIC_DRAW);
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0,0);
glEnableVertexAttribArray(texCoordLocation);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
}
How can this be made more efficient so when making the second triangle I can use vert[x] that's already been used instead of declaring the same ones again (points 4 and 2)?
And the same with colours?
And how does this affect my rendering function below?
void Ground::render(GLuint texName, Shader* myShader)
{
glUseProgram(myShader->handle()); //find shader passed
glBindTexture(GL_TEXTURE_2D, texName); //blending needed to use alpha channel
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindVertexArray(m_vaoID[0]); //select first VAO
glDrawArrays(GL_TRIANGLES, 0, 6); //draw first object 0-3, then second 3-6
glDisable(GL_BLEND);
glUseProgram(0);
glBindVertexArray(0); //unbind the vertex array object
}
Obviously I guess it's OK to do it the way I have for only 2 triangles, but I wouldn't want to write out hundreds of vertices if, for some reason, I suddenly wanted a whole bunch of triangles...
Use glDrawElements() instead of glDrawArrays() if you would like to reuse vertices.
glDrawElements takes an index array argument, which allows you to specify the indices of vertices in the vertex array, making it possible to use them multiple times.
As an alternative to the (correct) answers using glDrawElements, you could use glDrawArrays with GL_TRIANGLE_FAN instead of GL_TRIANGLES. A fan uses the first three vertices to draw a triangle, then each subsequent vertex will generate a triangle using the new vertex, the last vertex and the first vertex. Now you only need four vertices (arranged counter-clockwise) in your array, and the call looks like:
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
What you asking for is called indexed rendering. The basic idea is to provide an index buffer those elements reference the vertex IDs in your vertex arrays. So for two triangles sharing one edge, you can define just the 4 corner vertices and can use and index array like {0,1,2, 2,1,3}. You will have to use glDrawElements() to do the drawing.
You might also want to have a look at this wiki page to get an overview of what drawing paths are available in modern GL.
Well question is similiar to my previous one about glOrtho variant
glOrtho OpenGL es 2.0 variant how fix blank screen?
Triangle below is draw perfectly at ortho projection (without projection it's squashed triangle, instead of the three equal sides triangle on rectangle viewport)
GLfloat triangle_vertices[] =
{
-0.5, -0.25, 0.0,
0.5, -0.25, 0.0,
0.0, 0.559016994, 0.0
};
Ortho matrix code:
typedef float[16] matrix;
void ortho_matrix(float right, float left, float bottom, float top, float near, float far, matrix result)
{
// First Column
result[0] = 2.0 / (right - left);
result[1] = 0.0;
result[2] = 0.0;
result[3] = 0.0;
// Second Column
result[4] = 0.0;
result[5] = 2.0 / (top - bottom);
result[6] = 0.0;
result[7] = 0.0;
// Third Column
result[8] = 0.0;
result[9] = 0.0;
result[10] = -2.0 / (far - near);
result[11] = 0.0;
// Fourth Column
result[12] = -(right + left) / (right - left);
result[13] = -(top + bottom) / (top - bottom);
result[14] = -(far + near) / (far - near);
result[15] = 1;
}
Setting my projection matrix to ortho, where aspect_ratio = screen_width/screen_heigth
ortho_matrix(-aspect_ratio, aspect_ratio, -1.0, 1.0, -1.0, 1.0, PROJECTION_MATRIX);
Task is to change ortho projection to perspective, so i write function for this
UPD: changed to col-major
void frustum_matrix(float right, float left, float bottom, float top, float near, float far, matrix result)
{
// First Column
result[0] = 2 * near / (right - left);
result[1] = 0.0;
result[2] = 0.0;
result[3] = 0.0;
// Second Column
result[4] = 0.0;
result[5] = 2 * near / (top - bottom);
result[6] = 0.0;
result[7] = 0.0;
// Third Column
result[8] = (right + left) / (right - left);
result[9] = (top + bottom) / (top - bottom);
result[10] = -(far + near) / (far - near);
result[11] = -1;
// Fourth Column
result[12] = 0.0;
result[13] = 0.0;
result[14] = -(2 * far * near) / (far - near);
result[15] = 0.0;
}
Setting my projection to frustum matrix, where aspect_ratio = screen_width/screen_heigth
frustum_matrix(-aspect_ratio, aspect_ratio, -1.0, 1.0, 0.1, 1.0, PROJECTION_MATRIX);
Well i peek matrix at glFrustrum page http://www.opengl.org/sdk/docs/man/xhtml/glFrustum.xml, but matrix for ortho func is from same source and works fine. Anyway i see similiar frustum matrix at various places like https://stackoverflow.com/a/5812983/1039175 frustum function.
All what i got is blank screen, viewport and other stuff related to drawning is set right.
It looks like your matrix indices are transposed from glFrustum's doc page. Do you transpose the matrix before uploading it? OpenGL typically refers to column vector matrices, so if you're copying the equations from glFrustum, the indices should look like this:
[0] [4] [ 8] [12]
[1] [5] [ 9] [13]
[2] [6] [10] [14]
[3] [7] [11] [15]
I have to admit that I'm too lazy to read your code, but... assuming your clear color is set to white, it could be that you didn't set the viewport :
Make sure you call this at least once before rendering:
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
GLsizei width = viewport[2];
GLsizei height = viewport[3];
glViewport(0, 0, width, height);
As for some general advice: don't try to reinvent the wheel with rewriting the matrix code (unless perhaps for some academic purpose). If you consider switching to c++ it's worth checking out the glm library : http://glm.g-truc.net/
It has replacements for exactly those matrix functions you are trying to implement and then some... I use it myself and it's a fantastic math lib to work with as it is specifically aimed towards opengl-es 2.0 and glsl.