Using C++ std::Vector in glVertexPointer OpenGL function - c++

I have a vector of floats, this vector describes a set of triangles each triangle is described using 18 floats, first 3 are the first vertex, next 3 decribes the normal of the last vertex, and so on 3 times until describe each triangle.
i am using
std::vector< GLfloat >
to store all numbers, and this is my code to render the triangles
void Visualizer::draw3dModel()
{
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glNormalPointer(GL_FLOAT, 6 * sizeof(GLfloat), this->vertexes->data() + 3);
glVertexPointer(3, GL_FLOAT, 6 * sizeof(GLfloat), this->vertexes->data());
glPushMatrix();
glScalef(0.05f, 0.05f, 0.05f);
glColor3f(1,1,1);
glDrawArrays(GL_TRIANGLES, 0, this->vertexes->size());
glPopMatrix();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
this code actually works, but in certain moments I recreate the vector of floats with new triangles, it can be more or less triangles
before creating new triangles I clear the vector of vertexes, using this functions
std::vector< GLfloat >* MarchingCubesThread::getTriangles(float minvalue_scale)
{
this->generateTriangles(minvalue_scale);
for(unsigned int i=0; i < this->num_triangles; i++)
{
for(int j=0; j < 3; j++)
{
this->vertexes.push_back(this->triangles[i].p[j].x);
this->vertexes.push_back(this->triangles[i].p[j].y);
this->vertexes.push_back(this->triangles[i].p[j].z);
this->vertexes.push_back(this->triangles[i].norm.x);
this->vertexes.push_back(this->triangles[i].norm.y);
this->vertexes.push_back(this->triangles[i].norm.z);
}
}
return &(this->vertexes);
}
void MarchingCubesThread::generateTriangles(float minvalue_scale)
{
this->vertexes.clear();
this->triangles.clear();
this->triangles = MarchingCubesDataset(this->dataset->getMaxVal() * minvalue_scale, *(this->dataset), LinearInterp, this->num_triangles);
}
After playing around creating a new set of new triangles, the OpenGL render updates the mesh well, but in certain moments, I get some garbage triangles, and/or triangles that are from last iteration, and they should be cleared by calling this:
this->vertexes.clear();
this->triangles.clear();
here some screenshots taken in consecutive times:
any clues about what is happening here?, thank you
PD: for a complete source code, this is the public git repository on github:
https://github.com/joecabezas/MemoriaJoeCabezasCode/tree/visualizer

glDrawArrays expects not count of floats in your buffer, but count of vertices.
So correct call should be:
glDrawArrays(GL_TRIANGLES, 0, this->vertexes->size() / 6);
By letting glDrawArrays to draw 6 times more vertices you were displaying garbage after end of valid vector data, and sometimes it was data from previous iteration.

Related

OpenGL indices Array

I have a class terrain which create a grid of Quads. I do it like this
for(int z=0; z<_length;z++){
for(int x=0; x<_width;x++){
vertices.push_back(vec3((float)x*250, 0.f, (float)z*250));
}
}
for(int z=0; z<(_length-1);++z){
for(int x=0; x<(_width-1);++x){
int index = z*_width+x;
Vertex _vertices[] = {
Vertex(vertices.at(index),vec3(0, 0, 0)),
Vertex(vertices.at(index+1),vec3(0, 0, 0)),
Vertex(vertices.at(index+_width),vec3(0, 0, 0)),
Vertex(vertices.at(index+1+_width),vec3(0,0,0))
};
unsigned short indices[]= {index,index + 1,index +
_width,index + 1,index + _width,index + _width + 1};
Quad quad(_vertices, 4, indices, 6);
squares.push_back(quad);
i++;
}
}
The vertices and the logic are correct, but the indices aren't, for some reason. here is the output for this code :
But when I change this indices to this :
unsigned short indices[]= {0,1,2,1,2,3};
It works great :
The problem is I don't understand why this line
unsigned short indices[]= {index,index + 1,index +
_width,index + 1,index + _width,index + _width + 1};
doesn't work. And if it worked, my grid would consume a lot less ressources. If someone could explain me why it doesn't work, It would be great, thanks you.
In case you need to know how I draw a Quad, here is the code :
class Quad{
public:
Quad(Vertex *_vertices, int _n, unsigned short * _indices, unsigned short _numIndices){
for(int i=0; i < _numIndices; i++){
indices.push_back(_indices[i]);
}
for(int i=0; i<_n; i++){
vec3 v = vec3(_vertices[i].position, _lengthPower);
position.push_back(v);
}
glGenVertexArrays(1, &mVertexArray);
glBindVertexArray(mVertexArray);
glGenBuffers(1, &mPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec3)*position.size(), position.data(), GL_STATIC_DRAW);
glGenBuffers(1, &mIndicesBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*indices.size(), indices.data(), GL_STATIC_DRAW);
}
void draw(){
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, mPositionBuffer);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(0);
}
~Quad(){
}
private:
std::vector<unsigned short> indices;
std::vector<vec3> position;
GLuint mVertexArray;
GLuint mPositionBuffer;
GLuint mIndicesBuffer;
};
I'm using, OpenGL, glm, glfw etc.
The posted code uses parts of two solutions to draw the terrain. Each one would work just fine by itself, but this is halfway between.
Separate Quads
Most of the code shown treats the terrain as a set of separate quads. In this case, you have length - 1 times width - 1 quad instances, each one with 4 vertices and 6 indices.
This is exactly what your Quad class implements. It stores 4 vertices and 6 indices in its own pair of VBOs, and sets up a VAO with the attribute state. Then you instantiate a Quad for each square in your terrain.
Since the vertices for each Quad are stored in its own buffers, the implication is that the indices reference vertices within this buffer. Which means that the indices are in the range 0 to 3, which is exactly what you found to be working.
The downside of this choice is that it will be inefficient for large terrains. You'll have a lot of objects (2 VBOs and 1 VBO for each quad), and need a separate draw call for rendering each quad. You're also not sharing vertices, having 4 copies of most vertices in your overall data structure.
You could actually drop the indices for this approach, and use a glDrawArrays(GL_TRIANGLE_STRIP, 4) call to draw the quad. But the other disadvantages remain.
Shared Vertices
A much more efficient approach is to store the entire terrain in a single VBO. Your code started doing that here:
for(int z=0; z<_length;z++){
for(int x=0; x<_width;x++){
vertices.push_back(vec3((float)x*250, 0.f, (float)z*250));
}
}
But then you do not follow through with it. What you need to do is store these vertices in a single VBO for the entire terrain.
Since the indices will then reference vertices by their position in this vertex buffer that contains all vertices in the terrain, the index calculations start to make much more sense:
int index = z*_width+x;
unsigned short indices[]= {index,index + 1,index +
_width,index + 1,index + _width,index + _width + 1};
This would be the indices for a quad within this overall VBO. You would want to change this to also build an index array for the entire terrain. This could look something like this:
for(int z = 0; z < _length - 1; ++z) {
for(int x = 0; x < _width; ++x) {
indices.push_back(z * width + x);
indices.push_back((z + 1) * width + x);
}
}
This can then be rendered using length - 1 triangle strips. with 2 * _width indices each. The common vertices are shared, which makes the whole thing much more efficient. You could reduce the rendering to a single draw call by using slightly more advanced features, like primitive restart.
The only downside is that it might seem less object oriented to not have objects for each quad. But that seems sort of artificial anyway. You have a terrain that consists of a grid of vertices. I see nothing wrong with having a terrain object containing this whole grid. And I like classes and objects as much as the next guy (some say too much...).

VBO Generate Verts for Chunks (Voxel Engine, Cpp)

I'm working on a Voxel Engine and I'm using VBO.
My problem is that I don't know how to generate Vertices.
I need to generate vertices for a chunk, So create a Chunk of cubes (With one VBO) from X,Y,Z coords.
How Can I do this?
First you will need to create/load the data for the voxels. Something like the following could be used to generate a 10x10x10 field of binary voxels:
Note: All code is untested and probably not optimal.
class Field {
bool data[10*10*10];
public:
bool& at(int i, int j, int k) { return data[i*10*10 + j*10 + k]; }
};
Field aField;
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
for (int k = 0; k < 10; ++k) {
aField.at(i, j, k) = !(rand() % 2);
}
}
}
I'm assuming you are after Minecraft style voxels, otherwise you probably want to use something like Marching Cubes to process the binary voxel field and pass the result to the vertex buffer code.
The next step is for each occupied voxel in the field, draw the faces associated with the cube. For this we need to create a list of all vertices and (in this case) triangle indices.
std::vector< std::array<GLfloat, 3> > vecVerts;
std::vector< std::array<GLuint, 3> > vecTris;
for (int i,j,k from 0 to 10) {
if (aField.at(i,j,k)) {
// Add vertices for eight corners of cube
vecVerts.emplace_back(dWidth*(i ), dWidth*(j ), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j ), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i ), dWidth*(j+1), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j+1), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i ), dWidth*(j ), dWidth*(k+1));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j ), dWidth*(k+1));
vecVerts.emplace_back(dWidth*(i ), dWidth*(j+1), dWidth*(k+1));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j+1), dWidth*(k+1));
// Add triangle coordinates for each triangle
vecTris.emplace_back(0, 1, 3); vecTris.emplace_back(0, 2, 3);
vecTris.emplace_back(4, 5, 7); vecTris.emplace_back(4, 6, 7);
/* todo: add remaining triangles, should be 8 more */
}
}
The above code will create two arrays in memory storing your vertex locations and the indices for the triangles. You'll notice that the code always draws 12 triangles for each voxel, it would be better to do a check if there is an adjacent occupied voxel and remove faces between such voxels, but I'll leave that for you. I also recommend you consider using glm::vec3 for storing vertex data rather then just a array.
We can now pass our arrays to OpenGL:
GLuint unVertexArray;
glGenVertexArrays(1, &unVertexArray);
glBindVertexArray(unVertexArray);
GLuint unVertexBuffer;
glGenBuffers(1, &unVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, unVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 3*vecVerts.size()*sizeof(GLfloat),
&vecVerts[0][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
GLuint unIndiciesBuffer;
glGenBuffers(1, &unIndicesBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, unIndicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3*vecTris.size()*sizeof(GLuint),
&vecTris[0][0], GL_STATIC_DRAW);
glBindVertexArray(0);
Then finally, to draw our arrays:
glBindVertexArray(unVertexArray);
glDrawElements(GL_TRIANGLES, 3*vecTris.size(), GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
I might (am almost certain I) have forgotten a few things here, but this should give you a general outline of what you will need to do. For a proper explanation of most of the gl calls used above there are many online references, such as http://arcsynthesis.org/gltut/index.html

glDrawArrays doesn't draw

I use vectors to store vertex and normal data
vector<float> vertex;
vector<float> normal;
For example:
normal.push_back(-1);
normal.push_back(0);
normal.push_back(0);
vertex.push_back(BARRIER_RADIUS);
vertex.push_back(POLE_HEIGHT);
vertex.push_back(-POLE_RADIUS);
for (int i = POLE_POINTS, i >= 0; i--)
{
//add more vertex
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, &vertex[0]);
glNormalPointer(GL_FLOAT, 0, &normal[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertex.size());
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
//Add some more + Draw some thing else the same way
What I've got from this is nothing. it doesn't draw anything onto the screen.
The previous version, which works, is as follow:
glNormal3f(-1, 0, 0);
glBegin(GL_TRIANGLE_FAN);
glVertex3f(BARRIER_RADIUS, POLE_HEIGHT, -POLE_RADIUS);
for ()
{
//add more vertex
glVertex3f(........);
}
glEnd();
//draw more the same way
Point me to where I've gone wrong.
You have defined vertex as a vector of float, but a geometric vertex consists of 3 floats, so that's a recipe for confusion. The number of vertices is not vertex.size(), but rather one third of that. I'm not sure if that's your only problem, but it's a problem.
You should have the same number of normals as vertices.

OpenGL: glDrawElements doesn't draw

I'm trying out the Vertex Arrays stuff but for some reason the glDrawElements command doesn't draw anything for me. I can draw using glBegin/glEnd and glDrawElements in between, but glDrawElements doesn't work. Here's a code snippet:
These arrays get set up in the constructor:
double points[100];
GLint indices[50];
for (int i=0; i < 50; i++){
points[2*i] = radius * cos(i*2*PI/50);
points[2*i + 1] = radius * sin(i*2*PI/50);
indices[i] = i;
}
Working code using only the points array with glArrayElement:
void GLCircle::draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, points);
glBegin(GL_POLYGON);
for (int i=0; i < 50; i++){
glArrayElement(i);
}
glEnd();
}
Also working code, using points array, specific indices accessed via indices array:
void GLCircle::draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, points);
glBegin(GL_POLYGON);
for (int i=0; i < 50; i++){
glArrayElement(indices[i]);
}
glEnd();
}
NON-working code, attempting to use glDrawElements:
void GLCircle::draw()
{
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_DOUBLE, 0, points);
glDrawElements(GL_POLYGON, 4, GL_INT, indices);
}
Any advice? It's not entirely necessary for me to use it at this point, but it's disturbing that it doesn't work...
The 2nd parameter of glDrawElements is count, so shouldn't 4 be the numbers of indices (50)?
The parameters for
glDrawElements()
are as follows.. :
1st [mode] parameter is what kind of primitive to render.
2nd [count] parameter should be the number of elements to render. ie. the number of vertices
3rd [type] parameter should be the type of the value in the 4th parameter.. can ONLY be either
GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT or GL_UNSIGNED_INT
4th [indices] parameter is a pointer to where the indices are stored.
You can read more on this here..
I just faced the same problem.
Try GL_UNSIGNED_INT
glDrawElements(GL_POLYGON, 4, GL_UNSIGNED_INT, indices);

Rendering mesh polygons in OpenGL - very slow

I recently switched from intermediate mode and have a new rendering process. There must be something I am not understanding. I think it has something to do with the indices.
Here is my diagram: Region->Mesh->Polygon Array->3 vertex indices which references the master list of vertices.
Here my render code:
// Render the mesh
void WLD::render(GLuint* textures, long curRegion, CFrustum cfrustum)
{
int num = 0;
// Set up rendering states
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Set up my indices
GLuint indices[3];
// Cycle through the PVS
while(num < regions[curRegion].visibility.size())
{
int i = regions[curRegion].visibility[num];
// Make sure the region is not "dead"
if(!regions[i].dead && regions[i].meshptr != NULL)
{
// Check to see if the mesh is in the frustum
if(cfrustum.BoxInFrustum(regions[i].meshptr->min[0], regions[i].meshptr->min[2], regions[i].meshptr->min[1], regions[i].meshptr->max[0], regions[i].meshptr->max[2], regions[i].meshptr->max[1]))
{
// Cycle through every polygon in the mesh and render it
for(int j = 0; j < regions[i].meshptr->polygonCount; j++)
{
// Assign the index for the polygon to the index in the huge vertex array
// This I think, is redundant
indices[0] = regions[i].meshptr->poly[j].vertIndex[0];
indices[1] = regions[i].meshptr->poly[j].vertIndex[1];
indices[2] = regions[i].meshptr->poly[j].vertIndex[2];
// Enable texturing and bind the appropriate texture
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textures[regions[i].meshptr->poly[j].tex]);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].x);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].u);
// Draw
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
}
}
}
num++;
}
// End of rendering - disable states
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Sorry if I left anything out. And I really appreciate feedback and help with this. I would even consider paying someone who is good with OpenGL and optimization to help me with this.
There is no point in using array rendering if you're only rendering 3 vertices at a time. The idea is to send thousands through with a single call. That is, you render a single "Polygon Array" or "Mesh" with one call.