PDA

View Full Version : Vertex Array drawing random points and colors



Beiufin
06-29-2012, 10:11 AM
The issue is when I try to render my list of Vertices using the code below, the points are not rendered properly The first point in the deque is always correctly rendered. The rest of the points sometimes shouw up for a frame or two but then disapear (causing them to look like their flickering). Furthermore, additional points that I have not created are drawn in random locations with random colors, they flicker as well. Without further ado...

...the code:


struct VertArray
{
float position[3];
unsigned char color[3];
};

deque <VertArray *> vertList;

GLvoid DrawPoints()
{
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_COLOR_ARRAY);

if(!vertList.empty())
{

glVertexPointer (3, GL_FLOAT, sizeof (VertArray), (vertList[0]->position));
glColorPointer (3, GL_UNSIGNED_BYTE, sizeof (VertArray), (vertList[0]->color));

glDrawArrays (GL_POINTS, 0, vertList.size());
}

glDisableClientState (GL_VERTEX_ARRAY);
glDisableClientState (GL_COLOR_ARRAY);


I generate these points elsewhere (obviously) and I am positive that the error is NOT in the generation code. I have a version of this program that is identical expect it uses immediates to render vertList. Why is it not rendering properly with VertexArray's?

Ill attach my initialization code as well in case that may be the cause.
NOTE: its not in order and there are some parts left out because I deemed them highly likely not to be the cause.


PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;

ppfd = &pfd;

ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | // Draw to window
PFD_SUPPORT_OPENGL | // use OpenGL
PFD_DOUBLEBUFFER; // use Double Buffer
ppfd->dwLayerMask = PFD_MAIN_PLANE;
ppfd->iPixelType = PFD_TYPE_RGBA; // Use RGBA format
ppfd->cColorBits = 32; // color bits
ppfd->cDepthBits = 32;
-----------------------------------------------------------------------------

glEnable(GL_LINE_SMOOTH); // Line AA
glEnable(GL_POINT_SMOOTH); // Point AA
glEnable(GL_BLEND); // Allow Transparency
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); // how transparency acts
glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT,GL_FASTEST);

glPolygonMode(GL_BACK, GL_LINE); //Draw back, and draw boundries
glLineWidth(LINEWIDTH); //Width of lines in OpenGl
glPointSize(POINTSIZE); //Size of Points in OpenGL

thokra
06-29-2012, 12:16 PM
glVertexPointer() expects as its 4th argument a pointer to an array of all vertices you try to submit with a call to glDrawArrays(). Currently glVertexPointer() only receives a pointer to an array of size 3 * sizeof(float). What you intend to draw, however, are vertList.size() vertices. The first vertex will be fine, the second won't be and in fact may be undefined since the GPU doesn't access the correct part client memory. Also, a stride is only necessary if you have an interleaved array of vertex attributes. In your case you have two distinct arrays for positions and colors.

In conclusion: You either need to pack all your points and colors into an interleaved array = [v1, c1, v2, c2, v3, c3, ... , vn, cn] and pass the pointer to glVertexPointer() and glColorPointer() with an appropriate stride or have seperate arrays with a stride of 0:




// seperate arrays
GLfloat positions[NUM_VERTS * 3];
GLuchar colors[NUM_VERTS * 3];

glVertexPointer (3, GL_FLOAT, 0, positions);
glColorPointer (3, GL_UNSIGNED_BYTE, 0, colors);

// interleaved array

const GLsizei stride = 3 * sizeof(float);

GLfloat interleaves[] = {v1_x, v1_y, v1_z, c1_r, c1_g, c1_b};

glVertexPointer (3, GL_FLOAT, stride, positions);
glColorPointer (3, GL_FLOAT, stride, positions + 1);



One thing you may notice is that with an interleaved array the type of all attributes must be the same since they're all interleaved into a single array. Disclaimer: Untested legacy code! That's never a good thing. ;)

Edit: In my madness I forgot to mention that you can also pack the data like this:




// assume you have n positions and n colors
GLfloat packedAttribs = {v1_x, v1_y, v1_z, v2_x, v2_y, v2_z, ... , vn_x, vn_y, vn_z, c1_r, c1_g, c1_b, c2_r, c2_g, c2_b, ..., cn_r, cn_g, cn_b};

// address of first position is simply &packedAttribs[0]
glVertexPointer(3, GL_FLOAT, 0, packedAttribs)

// address of first color is &packedAttribs[0] + n
glColorPointer(3, GL_FLOAT, 0, packedAttribs + n)

Beiufin
06-29-2012, 12:35 PM
If I were to pack my arrays of positions into a vector, i.e vector<float[3]*> would VertexPointer be able to iterate through it properly? If not, would it be able to read a vector<float> similar to the array you sugested {v1_x, v1_y, v1_z, v2_x, etc...}? It would be quite a hassle to try and manage an array of vertices in my case as I am constantly adding and removing items from the vertList. And I cant see creating one

thokra
06-29-2012, 02:16 PM
std::vector uses an array as its internal data structure which you can access by std::vector<T>::data() which returns a pointer to T (or T*). Using a std::vector<float> which contains every component of every vertex is fine.

std::vector<float[3]*> is not a legal declaration, so it's right out of the question.


It would be quite a hassle to try and manage an array of vertices in my case as I am constantly adding and removing items from the vertList.

You're not getting around passing a pointer and additional information to determine which memory locations to access. What do you want to do, what's the concrete problem you're facing?

Edit: BTW, you cannot use std::vector<float[3]> either! You generally can't use arrays as template arguments of STL containers since types designated by the arguments must be copy constructible and assignable.

Beiufin
06-29-2012, 02:33 PM
Millions of points with new ones being added rapidly. I cant really afford to manually iterate through them every frame due to cost. I would prefer to store them in a struct for easy sorting. Whats my best option?(OpenGL 1.4)

rakeshthp
10-04-2012, 12:25 AM
Millions of points with new ones being added rapidly. I cant really afford to manually iterate through them every frame due to cost. I would prefer to store them in a struct for easy sorting. Whats my best option?(OpenGL 1.4)

Hi,

Did you able to manage to implement "Millions of points with new ones being added rapidly." ? If so, can you guide me how did you do that? Also did you try dynamic deleting the points?

Thanks

Beiufin
10-04-2012, 09:09 AM
If you can, using a VBO is most efficient (see my other noob thread here (http://www.opengl.org/discussion_boards/showthread.php/178061-Buffer-vs-immediate)). In my case I has to have this program perform on older machines so I ended up using a Vertex array. My issue with the vertex array was that I had improperly synchronized my threads.

In the end I had other threads working on receiving new points and then storing them in a queue, when the drawing thread was ready to draw, it would fetch all the new points and store them in a vertex. I would then pass the vertex(by reference of course) to a draw points function similar to this one.

GLvoid DrawPoints(vector<float> vertArray, vector<float> colorArray)
{
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_COLOR_ARRAY);

glVertexPointer (2, GL_FLOAT, sizeof (vertArray), vertArray);
glColorPointer (3, GL_FLOAT, sizeof (colorArray), colorArray);

glDrawArrays (GL_POINTS, 0, vertArray.size() / 2; // the vertArray is ordered (X,Y,X,Y,X,Y,...)

glDisableClientState (GL_VERTEX_ARRAY);
glDisableClientState (GL_COLOR_ARRAY);
}



I did originally have it dynamically deleting points, but OpenGL does it more efficiently every draw.