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?
Related
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();
}
I have an interesting bug that has been "bugging" me for a few days now.
I am currently using OpenGL to draw text on a screen. I am utilizing the OGLFT library to assist the drawing. This library actually uses the freetype2 library. I am actually not doing anything special with the text. I am only looking for monochromatic text.
Anyways, after implementing the library, I noticed that the text is only drawn correct when I have glStipple enabled. I believe that there is some interference issue between the OGLFT library and what I am enabling.
I was wondering if there is anyone out there with some experience on using the OGLFT library. I am posting a minimalist example of my code to demonstrate what is going on:
(Please note that there are some variables that are used to st the zoom factor of my glCanvas and the position of the camera and that this is only for 2D)
double _zoomX = 1.0;
double _zoomY = 1.0;
double _cameraX = 0;
double _cameraY = 0;
/* This function gets called everytime a draw routine is needed */
void modelDefinition::onPaintCanvas(wxPaintEvent &event)
{
wxGLCanvas::SetCurrent(*_geometryContext);// This will make sure the the openGL commands are routed to the wxGLCanvas object
wxPaintDC dc(this);// This is required for drawing
glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT);
updateProjection();
OGLFT::Monochrome *testface = new OGLFT::Monochrome( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
testface->draw(0, 0, "test");
glEnable(GL_LINE_STIPPLE);// WHen I comment out this line, the text is unable to be drawn
glLineStipple(1, 0b0001100011000110);
glBegin(GL_LINES);
glVertex2d(_startPoint.x, _startPoint.y);
glVertex2d(_endPoint.x, _endPoint.y);
glEnd();
glDisable(GL_LINE_STIPPLE);
SwapBuffers();
}
void modelDefinition::updateProjection()
{
// First, load the projection matrix and reset the view to a default view
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-_zoomX, _zoomX, -_zoomY, _zoomY, -1.0, 1.0);
//Reset to modelview matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, (double)this->GetSize().GetWidth(), (double)this->GetSize().GetHeight());
/* This section will handle the translation (panning) and scaled (zooming).
* Needs to be called each time a draw occurs in order to update the placement of all the components */
if(_zoomX < 1e-9 || _zoomY < 1e-9)
{
_zoomX = 1e-9;
_zoomY = _zoomX;
}
if(_zoomX > 1e6 || _zoomY > 1e6)
{
_zoomX = 1e6;
_zoomY = _zoomX;
}
glTranslated(-_cameraX, -_cameraY, 0.0);
}
Also one thing to note is that the code below the glEnable(GL_LINE_STIPPLE); is required. It is as if the glStipple needs to be drawn correctly for the text to be displayed correctly.
Looking through your code, I believe that your intention is to render it as a greyscale? If so, then you can simply use the OGLFT::Grayscale *testface = new OGLFT::Grayscale( "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf", 8);
This will get what you need without having to worry about the issue that you posted. In fact, I recommend doing it this way too.
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.)
}
I have a program that monitors a text file for changes, and upon detecting one, the user has the option to redisplay the screen based on the contents of this text file. My problem is that when a new screen is requested, the contents of the previous screen stay, while the new contents overlaps it. I want the screen to be cleared before new data is put on the screen.
here is what I have:
void keyboard(unsigned char key, int x, int y){
if(key == 'c'){
c_pressed++;
cout<<"c pressed: "<<c_pressed<<"sound.txt cleared..."<<endl;
clear_file();
}
if(key=='v'){
v_pressed++;
cout<<"v pressed: "<<v_pressed<<"displaying new configuration..."<<endl;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glutPostRedisplay();
}
}
When the key 'c' is pressed, the text file is cleared. I have verified this works properly. Then after a separate program loads in new data into the text file, the user presses 'v' to load these new instructions. I've tried placing the clear function within the 'v' statement, and as well as in the display function...
void display(void){
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
read_in_sound();
cout<<"Number of sound events: "<<numLines<<endl;
for(int j=0; j<numLines; j++){
if(data[0+j*4]==1){
circle(0,0,200,50);
}
if(data[1+j*4]==1){
circle(0,400,200,50);
}
if(data[2+j*4]==1){
circle(400,400,200,50);
}
if(data[3+j*4]==1){
circle(400,0,200,50);
}
}
glFlush();
glutSwapBuffers();
}
But when I call redisplay, both the old and new screens are displayed.
As a general rule you should do OpenGL drawing calls (and clearing the scene is a drawing call) only from the display function. If something in a OpenGL scene changes the canonical way is to redraw the whole thing. So in reaction to any event you change your programs state and issue a redraw, which will ultimately redraw the scene using OpenGL.
If the scene is very complex any you want to only update the scene with only opaque geometry (anything that requires blending mandates a full redraw) you should use store the scene color and depth buffer to textures and use them to start from a well defined state. Ideally you use a framebuffer object for this.
This may not be the best method in the world, but I added a rectangle object that is the size of the window that matches the black background that gets called up each time I want to "redraw". It saves time from having to write in a framebuffer like the previous answer suggested.
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.