I am getting the following errors:
QWidget::repaint: Recursive repaint detected.
QPainter::begin: A paint device can only be painted by one painter at a` time.
QPainter::beginNativePainting: Painter not active.
QPainter::setRenderHint: Painter must be active to set rendering hints.
QPainter::translate: Painter not active.
void Graficador::paintEvent(QPaintEvent *event){
QPainter painter;
painter.begin(this);
painter.beginNativePainting();
painter.setRenderHint(QPainter::Antialiasing);
painter.translate(250, 250);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.2,0.4,0.3,1);
glClear(GL_COLOR_BUFFER_BIT);
std::vector<unsigned short> nodosaux;
glPushMatrix();
for (unsigned i=1;i<=automata->Dimension();i++)
{
nodosaux=(automata->operator [](i))->Nodos();
if((automata->operator [](i))->Estado()==0)
glColor3f(0.3,0.3,0.3);
else if((automata->operator [](i))->Estado()==1.0)
glColor3f(1.0,1.0,1.0);
else if((automata->operator [](i))->Estado()==2.0)
glColor3f(0.7,0.7,0.7);
glBegin(GL_POLYGON);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINE_LOOP);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
}
glPopMatrix();
glPushMatrix();
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINES);
glVertex2f(-500.0,0.0);
glVertex2f(500.0,0.0);
glVertex2f(0.0,-500.0);
glVertex2f(0.0,500.0);
glEnd();
glPopMatrix();
painter.endNativePainting();
painter.end();
}
(Sorry for the use of operator, I know that its not the proper use but I need to solve this problem first).
This is the paintEvent() of a QGLWidget. I had no problem until I started using a pointer of my class "automata". This class only have some vectors with the coordinates (x,y) of the vertices, so I have no idea why I have this problem.
The complete program has a big class System that has inside: a user interface, an automata and some other classes that are used for other tasks. The user interface has this QGLWidget inside, and the automata that I'm trying to use here is a pointer that points to the automata in the system class.
I'm passing that pointer like this:
void Cargar_automata(Automata_Celular* ac)
{
automata = new Automata_Celular();
automata =ac;
}
I have some other widgets but they are only buttons to manage files and timers.
When using an OpenGL widget in Qt all painting should be done in a member called paintGL(). You are using the paintEvent which is what is causing the error messages you are seeing.
So your code should look something like this:
void Graficador::paintGL(){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.2,0.4,0.3,1);
glClear(GL_COLOR_BUFFER_BIT);
std::vector<unsigned short> nodosaux;
glPushMatrix();
for (unsigned i=1;i<=automata->Dimension();i++)
{
nodosaux=(automata->operator [](i))->Nodos();
if((automata->operator [](i))->Estado()==0)
glColor3f(0.3,0.3,0.3);
else if((automata->operator [](i))->Estado()==1.0)
glColor3f(1.0,1.0,1.0);
else if((automata->operator [](i))->Estado()==2.0)
glColor3f(0.7,0.7,0.7);
glBegin(GL_POLYGON);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
glColor3f(0.0,0.0,0.0);
glBegin(GL_LINE_LOOP);
for(unsigned j=1;j<=nodosaux.size();j++)
{
glVertex2f(automata->Nodo(nodosaux[j-1]).first,
automata->Nodo(nodosaux[j-1]).second);
}
glEnd();
}
glPopMatrix();
glPushMatrix();
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINES);
glVertex2f(-500.0,0.0);
glVertex2f(500.0,0.0);
glVertex2f(0.0,-500.0);
glVertex2f(0.0,500.0);
glEnd();
glPopMatrix();
}
Related
I wanna select point on object by click
It successfully realized
this->camera()->convertClickToLine(point, orig, dir);
bool found;
selectedPoint = this->camera()->pointUnderPixel(point, found);
if (selectedName() >= 0) {
glColor3f(0.9f, 0.2f, 0.1f);
glBegin(GL_POINTS);
glVertex3f(selectedPoint.x, selectedPoint.y, selectedPoint.z);
glEnd();
}
example of selectable object:
glBegin(GL_TRIANGLES);
glColor3f(0.5,0,0);
glVertex3f(xmin,ymin,zmin);
glVertex3f(xmin + (xmax-xmin)/2,ymin+(ymax-ymin)/2, zmin+(zmax-zmin)/2);
glVertex3f(xmax,ymin,zmin);
glEnd();
But if i start using QPainter, selectedPoint change coords to smth wrong
QPainter painter(this);
painter.setPen(Qt::black);
painter.setFont(QFont("Helvetica", 8));
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.drawText(textPosX + 10, textPosY, text);
painter.setBrush(QBrush(Qt::black, Qt::SolidPattern));
painter.drawEllipse(QPoint(textPosX, textPosY), 2, 2);
painter.end();
what should i do?
my steps:
I draw box and object by OpenGl
I draw objects names by Qpainter
I draw point on object by click (doesn't work due to previous item, if i comment item 2, all work fine)
solved
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
/QPainter/
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
I need to rotate the rectangular object upon pressing the left arrow key.
I am not able to rotate it, or maybe it is. There may be a problem playing with the buffer.
Weather the rotatef() function is placed correctly or where the problem lies.
#include<stdlib.h>
#include<glut.h>
#include<stdio.h>
#include<math.h>
#include<time.h>
void rot()
{ glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
glRotatef(30,0.0,0.0,1.0);
glBegin(GL_POLYGON);
glVertex2i(50,50);
glVertex2i(170,50);
glVertex2i(170,100);
glVertex2i(50,100);
glEnd();
glPopMatrix();
}
void shape()
{
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex2i(50,50);
glVertex2i(170,50);
glVertex2i(170,100);
glVertex2i(50,100);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
shape();
glutSwapBuffers();
glFlush();
}
void init()
{
glClearColor(1.0,1.0,1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0,700,0,700,-1,1);
glMatrixMode(GL_MODELVIEW);
}
void Keys(int key,int x,int y)
{
if(key==GLUT_KEY_LEFT)
rot();
glutPostRedisplay();
}
void main(int argc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(700,700);
glutCreateWindow("tetris");
glutDisplayFunc(display);
glutSpecialFunc(Keys);
init();
glutMainLoop();
}
You post a redisplay immediately after drawing your rotated vertices.
So right after drawing the rotated vertices, in your display callback function, you clear the window and then draw your vertices without rotation. So that is what you'll see (without rotation), until the next update.
One way to proceed is:
Do all your drawing in your display function
As reaction to a keypress, just update the angle ( I guess you want to rotate incrementally) and post a redisplay. Don't draw anything, your display function will use the updated angle.
I have created a bunny and a duck image in my blank window. My plan was to display it twice: once by itself and another image like it rotated at a 90 degrees. I've tried creating the image a second time and turning the image by changing values, but was difficult and couldn't work at all. Which axes needs to be used to rotate an image in a plane and the right way to accomplish it.
void myInit(void){
glClearColor(1.0, 1.0, 1.0, 0); // the background is white
glColor3f(0.0f, 0.0f, 0.0f); // set drawing color
gluOrtho2D(0.0, (GLdouble) screenWidth, 0.0, (GLdouble) screenHeight);
}
void drawBunny(){
glClear(GL_COLOR_BUFFER_BIT);
// draw the outline of box (bunny)
glLineWidth(2);
glBegin(GL_LINE_LOOP);
glVertex2i(50,50);
glVertex2i(150,50);
glVertex2i(150,100);
glVertex2i(50,100);
glEnd();
//draw bunny tail
glLineWidth(1);
glBegin(GL_LINE_STRIP);
glVertex2i(50,50);
glVertex2i(50,35);//2nd wider top/bottom
glVertex2i(70,35);//1st- shrink tail left/right
glVertex2i(70,50);//1st- shrink tail left/right
glEnd();
// draw first ear
glBegin(GL_LINE_LOOP);
glVertex2i(175,85);
glVertex2i(175,100);
glVertex2i(150,100);
glVertex2i(150,85);
glEnd();
//draw second ear
glBegin(GL_LINE_LOOP);
glVertex2i(175,70);
glVertex2i(175,100);
glVertex2i(150,100);
glVertex2i(150,70);
glEnd();
// draw the head
glBegin(GL_LINE_LOOP);
glVertex2i(150,100);
glVertex2i(150,110);
glVertex2i(125,110);
glVertex2i(125,100);
glEnd();
// draw first feet
glBegin(GL_LINE_LOOP);
glVertex2i(110,60);
glVertex2i(110,75);
glVertex2i(30,75); //decrease value increase feet
glVertex2i(30,60);
glEnd();
//draw second feet
glBegin(GL_LINE_LOOP);
glVertex2i(50,100);
glVertex2i(50,85);
glVertex2i(30,85); //decrease value increase feet
glVertex2i(30,100);
glEnd();
//* draw eyes
glBegin(GL_LINE_LOOP);
glVertex2i(140,100);
glVertex2i(140,105);
glVertex2i(135,105);
glVertex2i(135,100);
glEnd();
glFlush();
}
int main (int argc, char** argv){
glutInit(&argc, argv); // initialize the toolkit
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // set display mode
glutInitWindowPosition(100,150); // set window position
glutInitWindowSize(screenWidth,screenHeight); // set window size
glutCreateWindow("House"); // create & open window
glutDisplayFunc(drawBunny); // register redraw function
myInit();
glutMainLoop(); // loop forever
}
write a display function which consist of 2 bunnies and rotate them :
void display()
{
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
drawBunny();
glPushMatrix();
glRotatef(degreetoreturn,x,y,z); // Adjust parameters according to what you need
drawBunny();
glPopMatrix();
glutSwapBuffers();
}
Delete glClear() function and glFlush() functions from your drawBunny function. And finally in your main function change this line :
glutDisplayFunc(drawBunny); // register redraw function
to
glutDisplayFunc(display); // register redraw function
I have written the following program to display a teapot on a table in a room with 2side walls and a floor.
#include <stdio.h>
#include <glut.h>
void wall1(float thickness)
{
glPushMatrix();
glTranslatef(100,100,0);
glRotatef(90,1,0,0);
glScalef(thickness,1,1);
glutSolidCube(100);
glPopMatrix();
}
void wall2(float thickness)
{
glPushMatrix();
glTranslatef(150,100,-50);
glScalef(1,1,thickness);
glutSolidCube(100);
glPopMatrix();
}
void floor(float thickness)
{
glPushMatrix();
glTranslatef(150,50,0);
glScalef(1,thickness,1);
glutSolidCube(100);
glPopMatrix();
}
void leg(float thickness)
{
glPushMatrix();
glScalef(thickness,.5,thickness);
glutSolidCube(100);
glPopMatrix();
}
void tableTop(float thickess)
{
glPushMatrix();
glTranslatef(150,100,0);
glScalef(.5,thickess,.5);
glutSolidCube(100);
glPopMatrix();
}
void table()
{
tableTop(.05);
glPushMatrix();
glTranslatef(125,75,-25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(175,75,-25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(175,75,25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(125,75,25);
leg(.05);
glPopMatrix();
glPushMatrix();
glTranslatef(150,110,0);
glScalef(.1,.1,.1);
glutSolidTeapot(100);
glPopMatrix();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
float pos[] = {200,200,0};
float dif[] = {.3,.3,.3,3};
float spe[] = {1,1,1,1};
float amb[] = {1,1,1,0};
glLightfv(GL_LIGHT0,GL_POSITION,pos);
glLightfv(GL_LIGHT0,GL_DIFFUSE,dif);
glLightfv(GL_LIGHT0,GL_AMBIENT,amb);
glLightfv(GL_LIGHT0,GL_SPECULAR,spe);
glTranslatef(50,50,0);
glRotatef(30,1,0,0);
glRotatef(-30,0,1,0);
wall1(.05);
wall2(.05);
floor(0.05);
table();
glFlush();
}
void reshape(int w,int h)
{
glViewport(0,0,w,h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0,400,0,400,-400,400);
glMatrixMode(GL_MODELVIEW);
}
void main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("woot");
glClearColor(1,1,1,1);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glShadeModel(GL_SMOOTH);
glutReshapeFunc(reshape);
glutDisplayFunc(display);
glutMainLoop();
}
The problem with this is my lighting part is not working as expected. Its not illuminating evenly all my objects... What am i missing? This making even the teapot hard to sea.
My lighting part is in display function.
I was missing
glEnable(GL_NORMALIZE);
in the main function, and thus opengl was not rendering it properly! Alse #Christian's answer of using ambient only worked.
:)
OpenGL fixed function pipeline lighting is evaluated at the vertices only. glutSolidCube just creates vertices at the corners and nowhere else. So your lighting is calculated only very coarse. You could either switch to per fragment lighting by using a shader, or tesselate your objects. The latter requires you don't use glutSolidCube and instead load objects modelled in a 3D modeller or write your own primitive generators that offer a higher tesselation. I strongly recommend the first option.
glutSolidCube is just a very crude stand in function BTW.
If you want to evenly light all objects, only use ambient lighting.
I have put all the necessary files[temp link removed] if you need to have a look.
mavStar.exe is my program.
The function currently I‘m trying to debug is :
void drawOG()
{
int curr,right,back,bottom;
//Does NOT draw the right most,back most,bottom most layer at the moment
//Does NOT draw face between state 1 & 2
for(int z=0;z+1 < occupancyGrid->Nz; z++){
glPushMatrix();
for(int y=0;y+1 < occupancyGrid->Ny; y++){
glPushMatrix();
for(int x=0;x+1 < occupancyGrid->Nx; x++){
curr = occupancyGrid->M[x][y][z];
right = occupancyGrid->M[x+1][y][z];
back = occupancyGrid->M[x][y][z+1];
bottom = occupancyGrid->M[x][y+1][z];
drawCube(RIGHT_FACE,colorBetween(curr,right));
drawCube(BACK_FACE,colorBetween(curr,back));
drawCube(BOTTOM_FACE,colorBetween(curr,bottom));
glTranslatef (HALF_VOXEL_SIZE*2, 0.0, 0.0);
}
glPopMatrix();
glTranslatef (0.0, -HALF_VOXEL_SIZE*2, 0.0);
}
glPopMatrix();
glTranslatef (0.0, 0.0, -HALF_VOXEL_SIZE*2);
}
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//mouse tracking
glRotatef(fYDiff, 1,0,0);
glRotatef(fXDiff, 0,1,0);
glRotatef(fZDiff, 0,0,1);
glScalef(fScale, fScale, fScale);
//draw model
glMatrixMode(GL_MODELVIEW);
drawOG();
printOpenGLError(); // Check for OpenGL errors
glutSwapBuffers();
}
There is a much easier way to draw the faces you want by using:
glPushMatrix();
glBegin(GL_QUADS);
//Draw the 16 vertices with their normals.
glEnd();
glPopMatrix();
For example if you want the front:
glPushMatrix();
glBegin(GL_QUADS);
glColor3f(1.0f,1.0f,1.0f);
glNormal3f(0.0,0.0,1.0);
glVertex3f( position[0], position[1], position[2]);
glNormal3f(0.0,0.0,1.0);
glVertex3f( position1[0], position1[1], position1[2]);
glNormal3f(0.0,0.0,1.0);
glVertex3f(position2[0], position2[1], position2[2]);
glNormal3f(0.0,0.0,1.0);
glVertex3f(position3[0], position3[1], position3[2]);
glEnd();
glPopMatrix();
Draw the faces on a piece of paper to figure out what values you need for position,position1,position2,position3,etc. Named them so for general purpose, it should be fairly easy to determine their coordinates.
If you want to give it a touch of flexibility you can create a Cube class and render only the faces for witch you have set a flag to be on. By using a class you gain lots of control on how you want your render-able object to be displayed (color,position,scale, etc).