libQGLViewer how to draw withouth clearing buffer - c++

I'm using libQGLViewer in my project to draw the trajectory of a robot. To this end, I started from the code of the simpleViewer provided in the examples.
To do my stuff, I put these lines of code in the draw function:
void Viewer::draw()
{
glPushMatrix();
for (auto pose : poses)
{
std::vector<float> m;
poseToVector(pose, m);
glPushMatrix();
multMatrix(m);
drawReferenceSystem();
glPopMatrix();
}
glPopMatrix();
}
where the poseToVector, multMatrix and drawReferenceSystem functions are OpenGL wrappers to implement the desired functionalities.
Now, my problem is that the poses vector is filled at each iteration of my code with a new pose. Thus, what I'm doing now is that at iteration 1 I'm drawing pose 1, at iteration 2 I'm drawing pose 1 and 2, at iteration 3 I'm drawing pose 1,2 and 3, and so on.
For this reason, I was wondering if there was a more efficient way to perform this operation. However, if I just get the back of the vector I will see at each time instant only the last pose. I guess that this is because every time the draw function is called the frame buffer is cleared.
Therefore, my question is: is it possible to avoid clearing the buffer or I'm just saying bullshit?

preDraw clears the screen and resets matrices.
You could subclass QGLViewer and override it to drop the clearing behavior.
The default implementation is:
void QGLViewer::preDraw() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // this line should be removed here or in a sublass.
// GL_PROJECTION matrix
camera()->loadProjectionMatrix();
// GL_MODELVIEW matrix
camera()->loadModelViewMatrix();
Q_EMIT drawNeeded();
}

Related

Plotting 2D map coordinates to OpenGL 3D projection

I’m trying to convert a 2D map created in my map editor to a 3D plotting with OpenGL. This is my map generated in my map editor:
Those vertices are relative to my Cartesian origin world coordinate (top up of the picture) and I’m applying this formula to convert it to an OpenGL object coordinate:
World size: 800x600
x = (X / 800) -0.5
y = (Y / 600) -0.5
Getting this result:
(First object face)
−0.48625, 0.068333333
0.12625, 0.07
0.12875, −0.481666667
−0.4875, −0.486666667
Plotting this vertex buffer in OpenGL, I got a very weird result. So how can I get a 3D model from those vertex positions? Like this picture:
I’m rendering OpenGL in triangles mode and using this example as the start point: https://github.com/JoeyDeVries/LearnOpenGL/blob/master/src/1.getting_started/7.4.camera_class/camera_class.cpp
Using the conversion formula + the Earcut tessellation (https://github.com/mapbox/earcut.hpp), I've finally got this rectangle rendering correctly inside OpenGL. With two planes with just the Z-axis different, now the problem is how to render its laterals since Earcut just works with 2D coordinates...
If I get it right you got some planar 2D polygon and what to add some constant thickness to it (as a 3D mesh). That is doable fairly easily. As you correctly assumed you need to triangulate first. So you should have this input:
table of points pnt[pnts]
list of all points of your object.
polygon pol[pols] (circumference of your object)
just ordered list of points indexes referencing to table of points
triangulation result fac[facs]
ordered list of 3 point indexes representing all the triangles.
Now to make a mesh from it we need to do this:
copy all the points and extrude them by some translation.
all this new points will be added to current pnt[pnts] table. Do not forget to remember original table size pnts0 as it will be needed later.
copy/reverse the triangulation.
The opposite side of the triangulated polygon will be the same just in reverse polygon winding. So just copy it to fac[facs] as new triangles in reverse index order ... Do not forget to add the original point table size to all the new faces. This will use the new points ... From the images of yours you got to this point already.
create the missing side faces.
For this we can exploit the original polygon. As we just copied the points then we know that pnt[3*i] is opposite to pnt[pnts0+3*i]. So we just create triangle faces joining the opposite edges of the polygon.
Here small C++ example I busted for this right now:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include "gl_simple.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
const int N=128;
int pnts=6*3; // 3* number of points
float pnt[N]= // x,y per each point
{
-0.5,-0.5,0.0, // 6 ------ 9
-0.4, 0.0,0.0, // + +
-0.5,+0.5,0.0, // 3 12
+0.5,+0.5,0.0, // + +
+0.4, 0.0,0.0, // 0 ----- 15
+0.5,-0.5,0.0,
};
int pol[N]={ 0,3,6,9,12,15 }, pols=6; // original polygon (3*pnt index), number of its vertexes
int fac[N]= // triangulation result (3*pnt index)
{
0,3,15,
3,12,15,
3,6,12,
6,9,12,
}, facs=4*3; // number of triangles*3
//---------------------------------------------------------------------------
void extrude(float dz)
{
int i,i0,pnts0=pnts;
// copy and reverse triangulation
for (i=0;i<facs;i++)
fac[facs+facs-1-i]=fac[i]+pnts; facs+=facs;
// duplicate points
for (i=0;i<pnts;i++) pnt[pnts0+i]=pnt[i]; pnts+=pnts;
// extrude points
for (i= 2;i<pnts0;i+=3) pnt[i]-=dz;
for ( ;i<pnts ;i+=3) pnt[i]+=dz;
// side faces
for (i0=pols-1,i=0;i<pols;i0=i,i++)
{
fac[facs]=pol[i ]+pnts0; facs++;
fac[facs]=pol[i ]; facs++;
fac[facs]=pol[i0]; facs++;
fac[facs]=pol[i0]+pnts0; facs++;
fac[facs]=pol[i ]+pnts0; facs++;
fac[facs]=pol[i0]; facs++;
}
}
//---------------------------------------------------------------------------
void gl_draw()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glEnable(GL_COLOR_MATERIAL);
/*
glPolygonMode(GL_FRONT,GL_FILL);
glPolygonMode(GL_BACK,GL_LINE);
glDisable(GL_CULL_FACE);
*/
// set view
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0,0.0,-5.0);
static float ang=0.0;
glRotatef(ang,0.2,0.7,0.1); ang+=5.0; if (ang>=360.0) ang-=360.0;
// render mesh
float *p0,*p1,*p2,n[3],a[3],b[3],c;
glColor3f(0.7,0.7,0.7);
glBegin(GL_TRIANGLES);
for (int i=0;i+3<=facs;i+=3)
{
// points
p0=pnt+fac[i+0];
p1=pnt+fac[i+1];
p2=pnt+fac[i+2];
// compute normal
a[0]=p1[0]-p0[0]; a[1]=p1[1]-p0[1]; a[2]=p1[2]-p0[2];
b[0]=p2[0]-p1[0]; b[1]=p2[1]-p1[1]; b[2]=p2[2]-p1[2];
n[0]=(a[1]*b[2])-(a[2]*b[1]);
n[1]=(a[2]*b[0])-(a[0]*b[2]);
n[2]=(a[0]*b[1])-(a[1]*b[0]);
c=1.0/sqrt((n[0]*n[0])+(n[1]*n[1])+(n[2]*n[2]));
n[0]*=c; n[1]*=c; n[2]*=c;
// render
glNormal3fv(n);
glVertex3fv(p0);
glVertex3fv(p1);
glVertex3fv(p2);
}
glEnd();
// glFlush();
glFinish();
SwapBuffers(hdc);
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
// Init of program
gl_init(Handle); // init OpenGL
extrude(0.2);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
// Exit of program
gl_exit();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
// repaint
gl_draw();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
// resize
gl_resize(ClientWidth,ClientHeight);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::tim_redrawTimer(TObject *Sender)
{
gl_draw();
}
//---------------------------------------------------------------------------
It is VCL based so ignore all the VCL stuff and port the events you want/need and GL context stuff to your style of programing. The only important stuff here are:
the tables pnt,fac,pol which holds the input and latter also output. The extrude(dz) will create the mesh (call it just once!) and gl_draw will render the tables as mesh (Using the old style GL api for simplicity).
For the GL stuff I used my gl_simple.h which you can find in this related QA:
complete GL+GLSL+VAO/VBO C++ example
Here is preview of the code above:
the choppynes is due to my GIF capture the rendering is smooth. I used static allocation and on the run normal computation so the code is simple and easy to understand. Of coarse for the real deal you need to implement dynamic lists and VAO/VBO ... if you want good performance
It's hard to know for sure, but it seems your object has only thwo faces rendered because you didn't add the other faces to the index.
Because you have your vertices, but you also need to tell have a triangles for the sides. If they are triangles you should end up with 16 triangles to draw.
If you don't use an index, you need to duplicate your vertices, for each triangle and end up with 48 vertices to draw.
As to get the earing algorithm to work in 3D, if you know for sure that your polygon has all it's point in the same plan, you can take 3 vertices, deduce it's plan, and create a transformation matrix to bring all these points to (x,y,0) which is like 2D coordinates.

OpenGL transformation with keyboard input not working

I'm trying to apply transformation to a specific part of my drawing that will only come in effect when a key is pressed.
I'm using glPushMatrix() then I do my transformation, then glPopMatrix().
What happens when I press my key is that the transformation is done only once, then no matter how many times I press the key again nothing happens.
Here's a snippet from my code:
void drawShapes(){
glClear(GL_COLOR_BUFFER_BIT);
//setting my variables
glPushMatrix();
if (translateFlag) //this is set to true in the keyboard function
{
x += 10;
glTranslated(x, 0, 0);
translateFlag = false;
}
drawCircle();
glPopMatrix();
//more drawings
}
when I remove the pushMatrix and popMatrix it works but it applies the transformation to all of my shapes, which is not what I want.
Any help would be appreciated..
[Update]
I've tried to run my code on 4 other computers (one macbook Air, one macbook Pro -an exact copy of mine- and 2 iMacs and) and it doesn't even run on any of them, could this mean the problem lies in my own macbook?!
Also I copied code that runs perfectly fine on the macbook air, rotating parts and everything and when I run it on mine I got the same disappointing result as my own code.
Here's the heypasteit code for my code 31JL
possible problems:
void drawShapes(){
glClear(GL_COLOR_BUFFER_BIT);
//setting my variables
// maybe you have forgot to set matrix mode correctly. make the projection and modelview
matrices correct.
glPushMatrix();
if (translateFlag) //this is set to true in the keyboard function
//probably your key hit function is not working properly (I can't say without looking at full code)
{
x += 10;
glTranslated(x, 0, 0);
translateFlag = false;
}
drawCircle();
glPopMatrix();
//more drawings
// you are using glFlush() ????? try swapbuffers. exact function depends
on the API you are using (GLUT \ GLFW etc.)
}

JOGL GL_SELECT picking fails

I am using the GL_SELECT method to achieve mouse selection in OpenGL using JOGL Java Library.
I know the method is deprecated and such, but it is a simple school assignment and this should do it.
However I am having some trouble: even though something is rendered in GL_SELECT mode, glRenderMode(GL_RENDER) returns zero hits. The problem is deterministic, but I don't see a kind of pattern; for example, if I have a sphere in the center, it works if I click on its upper part, but not on its lower part. For a cube, it only won't work on one specific face. For a rectangle it works alright.
I have tested commenting out the glRenderMode(GL_SELECT) to check if something was indeed being rendered and yes, I could see the shape, but even so glRenderMode(GL_RENDER) gave me zero.
EDIT: I have also tested removing the call to gluPickMatrix() and the glRenderMode(GL_SELECT), which gave me exactly the same as the normal (non-picking) render, so the projection and model view matrixes are set up correctly I think.
So, I don't think I am rendering incorrectly in select mode. What can be going on?
EDIT: maybe this could be a hardware problem, as the method is deprecated. Is that possible?
Thanks in advance.
// Get required information
point.y = getHeight() - point.y;
gl.glGetIntegerv(GL2.GL_VIEWPORT, view, 0);
// Setup OpenGL for selection
gl.glSelectBuffer(64, buffer);
gl.glRenderMode(GL2.GL_SELECT);
gl.glInitNames();
// Setup projection matrix
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
Util.glu.gluPickMatrix( point.x, point.y, 5.0, 5.0, view, 0 );
Util.glu.gluPerspective(camera.getFieldOfView(), getWidth() * 1.0 / getHeight(),
camera.getCloseDistance(), camera.getFarDistance() );
// Setup model view matrix for rendering
gl.glMatrixMode(GL2.GL_MODELVIEW);
camera.setView(gl); // Set to model view and use glLookAt
gl.glClear( GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT );
// Render objects
for(int i = 0; i < shapeList.size(); i++) {
gl.glPushName(i);
// Execute transformations for translation/rotation/scale and render shape
shapeList.get(i).display(gl, false);
gl.glPopName();
}
// Process hits
hits = gl.glRenderMode(GL2.GL_RENDER);
System.out.println("Hits = " + hits);
// ... Process hits here ...
// Reset matrixes
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
camera.setView function:
public void setView( GL2 gl ) {
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
Util.glu.gluLookAt( eye[Axis.X], eye[Axis.Y], eye[Axis.Z],
target[Axis.X], target[Axis.Y], target[Axis.Z],
up[Axis.X], up[Axis.Y], up[Axis.Z] );
}

opengl glutWireTorus artifact

I am working on a small animation of a sinewave being generated by a moving circle similar to this gif.
However I'm having a weird issue with using glutWireTorus for the circle. Even when I comment out all the other drawing code and leave the torus moving along the z axis alone, I get flashing lines on the inside of it:
This is the display function where everything is drawn. I use the display function as my idle function, also, I checked if that was the issue by creating an idle function and putting my update code there but it still persisted.
void display(void)
{
glClearColor(0.f,0.f,0.f,0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the color buffer
and the depth buffer
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f); //Push everything back 5 units into the scene,
otherwise we won't see the primitive
camera();
//yPrev = myCircle.y;
glPushMatrix();
glTranslatef(0.0f,0.0f,t);
glutWireTorus(0.02,1,100,100);
glPopMatrix();
DrawAxes();
glutSwapBuffers(); //swap the buffers
glFlush();//Flush the OpenGL buffers to the window
t-=0.002;
if (t < -T)
{
t = 0;
}
}
Uh, interesting, I run into the same problem.
Here is the picture using parameter
glutWireTorus(/*innerRadius*/0.3, /*outerRadius*/0.5, /*nsides*/32, /*rings*/32);
another picture using parameter
glutWireTorus(/*innerRadius*/0.3, /*outerRadius*/0.5, /*nsides*/64, /*rings*/128);
We don't know why without glutWireTorus function implementation, but we can implements our own torus, or maybe someone can explain it?

Windows OpenGL implementation bug?

I am having a very tough time sorting out this strange clipping bug in my app.
Basically, for some reason, OpenGL is clipping (using the scissor test) my call to glClear(), but not the rendering I do afterwards.
The real problem, however, is that the problem goes away when I resize my window. I can guarantee that resizing the window doesn't change anything in my app or run any code. It is very stange. Worse still, simply putting
glDisable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
where I need to disable the scissor test, instead of having just one call to glDisable() solves the problem. So does removing the code all together (the scissor test is already disabled in this test case, but the code is there for when it wasn't left to disabled in previous code). It even solves the problem to put:
glEnable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
There are only two explanations I can think of. Either I am somehow calling UB (which I doubt, because opengl doesn't have UB AFAIK), or there is an implementation bug, because calling glDisable() twice with the same parameter consecutively SHOULD be the same as calling it once... if I'm not mistaken.
JUST incase it is of interest, here is the function for which the problem is happening:
void gle::Renderer::setup3DCamera(gle::CameraNode& cam, gle::Colour bkcol,
int clrmask, int skymode, gle::Texture* skytex, bool uselight) {
// Viewport
Rectangle wr(cam.getViewport()?*cam.getViewport():Rectangle(0,0,1,1));
if (cam.isRatioViewport()||(!cam.getViewport())) {
if (i_frameBind==NULL)
wr.scale(selectedWindow->getWidth(),selectedWindow->getHeight());
else wr.scale(i_frameBind->getWidth(),i_frameBind->getHeight());
}
gle::Rectangle_t<int> iport; iport.set(wr);
int winHei;
if (i_frameBind==NULL)
winHei = selectedWindow->getHeight();
else
winHei = i_frameBind->getHeight();
glViewport(iport.x1(),winHei-iport.y2(),iport.wid(),iport.hei());
// Viewport Clipping
if (cam.isClipping()) {
/* This is never executed in the test case */
glEnable(GL_SCISSOR_TEST);
glScissor(iport.x1(),winHei-iport.y2(),iport.wid(),iport.hei());
} else {
/* This is where I disable the scissor test */
glDisable(GL_SCISSOR_TEST);
glDisable(GL_SCISSOR_TEST);
}
float w=wr.wid()/2, h=wr.hei()/2;
// Projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
Projection proj = cam.getProjection();
gluPerspective(proj.fov,proj.aspect*(w/h),proj.cnear,proj.cfar);
// Camera
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float m[] = { 1,0,0,0, 0,0,-1,0, 0,1,0,0, 0,0,0,1 };
glMultMatrixf(m);
static gle::Mesh *skyBox = NULL;
// Screen Clearing
switch (clrmask&GLE_CLR_COLOUR&0x00F?skymode:GLE_SKYNONE) {
case GLE_SKYNONE:
clear(clrmask&(~GLE_CLR_COLOUR)); break;
case GLE_SKYCOLOUR:
clearColour(clrmask,bkcol); break;
case GLE_SKYBOX:
glDisable(GL_DEPTH_TEST);
if (!(clrmask&GLE_CLR_DEPTH&0x00F)) glDepthMask(0);
float m = (cam.getProjection().cnear+cam.getProjection().cfar)/2.0f;
if (skyBox==NULL) skyBox = gle::createStockMesh(GLE_MESHSKYBOX,GLE_WHITE,0,m);
glEnable(GL_TEXTURE_2D);
glDisable(GL_CULL_FACE);
skytex->flush();
glBindTexture(GL_TEXTURE_2D,skytex->getID());
glDisable(GL_LIGHTING);
glPushMatrix();
float m3[16];
Orientation::matrixSet(m3,cam.pos().getMatrix(GLE_ROTMATRIX));
Orientation::matrixTranspose(m3);
glMultMatrixf(m3);
if (i_reflectionOn) glMultMatrixf(Orientation::matrixGet3x3(i_reflectionTransform));
renderMesh(*skyBox,NULL,1);
glPopMatrix();
glDisable(GL_TEXTURE_2D);
if (clrmask&GLE_CLR_DEPTH) glClear(GL_DEPTH_BUFFER_BIT);
else glDepthMask(1);
glAble(GL_DEPTH_TEST,depthmode!=GLE_ALWAYS);
break;
}
// Camera
glMultMatrixf(cam.getAbsInverseMatrix());
if (i_reflectionOn) glMultMatrixf(i_reflectionTransform);
// Lighting
i_lightOn = uselight;
glAble(GL_LIGHTING,i_lightOn);
}
This looks like a driver bug to me. However, there are two cases where this may actually be a bug in your code.
First, you might be in the middle of the glBegin() / glEnd() block when calling that glDisable(), causing some error and also ending the block, effectively making the second call to glDisable() legit and effective. Note that this is a dumb example with glBegin() / glEnd(), it could be pretty much any case of OpenGL error being caught. Insert glGetError() calls throughout your code to be sure. My guess is the first call to glDisable() generates GL_INVALID_OPERATION.
Second, you are not scissor testing, but you are still calling glViewport() with the same values. This would have the opposite effect (not clip glClear() and clip drawing) on NVIDIA, but it might very well be it does the opposite on some other driver / GL implementation.