I have a simple OpenGL object which has defined certain glScalef size. It needs glutMouseFunc to make it work as I imagined. So, this is what I've imagined:
On GLUT_LEFT_BUTTON object needs to go bigger for 0.1, so:
glScalef(scalesize+0.1,scalesize+0.1,0.0.);
polygon();
On GLUT_RIGHT_BUTTON object needs to go smaller for 0.1, so:
glScalef(scalesize-0.1,scalesize-0.1,0.0);
polygon();
This is my polygon function:
void polygon(void){
glBegin(GL_POLYGON);
glColor3f(1.0,0.0,0.0);
glVertex2f(-0.15, -0.15);
glColor3f(0.0,0.0,0.0);
glVertex2f(-0.15, 0.15);
glColor3f(0.0,0.0,1.0);
glVertex2f(0.15, 0.15);
glColor3f(0.0,1.0,0.0);
glVertex2f(0.15, -0.15);
glEnd();
glEnable (GL_LINE_STIPPLE);
glLineWidth(3.0);
glLineStipple (6, 0x1C47);
glBegin(GL_LINES);
glColor3f(0.0,0.0,0.0);
glVertex2f(-0.25, -0.25);
glVertex2f(-0.25, 0.25);
glVertex2f(0.25, 0.25);
glVertex2f(0.25, -0.25);
glVertex2f(-0.25, 0.25);
glVertex2f(0.25, 0.25);
glVertex2f(-0.25, -0.25);
glVertex2f(0.25, -0.25);
glEnd();
}
This is my scene function:
void scene(void){
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glScalef(scalesize,scalesize,0.0);
polygon();
glPopMatrix();
glFlush();
}
float scalesize = 1.0;
Now I'm not sure how to prevent scaling lower than 0.15, regarding to my object size. I've tried with if statement to check if scalesize is bigger than 1.0, but didn't worked. Any solutions?
Thanks
Ok, thanks to #radical7 I've figured it out. Already did everything what he said, but the real solution was to let scene function do its job, I didnt have to call glScalef in my mouse function.
Thanks again.
Related
Trying to make some effect on these 2D shapes
How do I make the quad shape change color automatically without user interactive. Like a constant cycle of color from red, yellow and green?
void changecolor() {
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_QUADS);
glVertex2f(0.0, 0.8);
glVertex2f(-0.2, 0.3);
glVertex2f(0.0, 0.0);
glVertex2f(0.2, 0.3);
glEnd();
}
Trying to make the quad to slow expansion animation as i run it. Currently it just shows the final expanded result as i run.
void q4() {
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glScalef(15, 15, 0);
glBegin(GL_QUADS);
glColor3f(1.0, 0, 0);
glVertex2f(0.1, 0.1);
glVertex2f(0.1, -0.1);
glVertex2f(-0.1, -0.1);
glVertex2f(-0.1, 0.1);
glEnd();
}
After reading a lot of guides about orbiting around camera and asking some additional question on SO I came up with SSCCE what I have so far. Maybe this way it will be easier for other to understand what I need and for me what is the answer.
So far it looks like this:
the code for drawing objects:
glPushMatrix();
glTranslatef(translate[0], translate[1], translate[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(0,0,0);
glColor3f(1.0,0.0,0.0);
fig.DrawBox(5.0f,5.0f,-5.0f,-5.0f,5.0f,-5.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(translate[0], translate[1], translate[2]);
glTranslatef(2,0,0);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(0,0,0);
glColor3f(0.0,1.0,1.0);
fig.DrawBox(1.5f,1.5f,-1.5f,-1.5f,1.5f,-1.5f);
glTranslatef(-4, 1.5, 0);
glColor3f(1.0,0.0,1.0);
fig.DrawBox(0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f);
glTranslatef(4-1, 1.5-0.5, 0);
glColor3f(0.0,0.0,1.0);
fig.DrawBox(0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f);
glPopMatrix();
translate is position updated during navigation and rot is rotation.
The red box is a main container and everything is inside it. 'Camera' can go outside of it, but during rotation it should rotate as well. As for the small boxes I'd like to be able to orbit around each one of them. So far I can orbit around this green one, but when I move to purple then it doesn't work.
In my final app I will have hundreds of objects so I am not sure if current method of using only one glPushMatrix() glPopMatrix() is the best idea (I am concerned about proper placing them), but when I am using push pop for every object then each one rotates by it's own pivot point.
EDIT:
I've been working on my code and I managed to achieve something more then before. Although it's still not exactly what I'm looking for.
My code:
glPushMatrix();
glTranslatef(translate[0], translate[1], translate[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(0,0,0);
glColor3f(1.0,0.0,0.0);
fig.DrawBox(5.0f,5.0f,-5.0f,-5.0f,5.0f,-5.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(translate[0], translate[1], translate[2]);
glRotatef(-rot, 0.0, 1.0, 0.0);
glTranslatef(4,0,0);
glPushMatrix();
glPushMatrix();
glTranslatef(2,0,0);
glColor3f(0.0,1.0,1.0);
fig.DrawBox(1.5f,1.5f,-1.5f,-1.5f,1.5f,-1.5f);
glPopMatrix();
glPushMatrix();
glTranslatef(-4, 1.5, 0);
glColor3f(1.0,0.0,1.0);
fig.DrawBox(0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f);
glPopMatrix();
glPushMatrix();
glTranslatef(-1, -0.5, 0);
glColor3f(0.0,0.0,1.0);
fig.DrawBox(0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f);
glPopMatrix();
glPopMatrix();
glPopMatrix();
And how it looks now:
so as you can see, I was able to move rotation point, but at the same time I've moved whole group inside box. And I don't want to do that.
After many changes and ideas I've finally figured out the proper way to achieve what I was looking for. It turned out that I needed to switch order of translations:
glPushMatrix();
glTranslatef(0, translate[1], translate[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(translate[0], 0,0);
glColor3f(1.0,0.0,0.0);
fig.DrawBox(5.0f,5.0f,-5.0f,-5.0f,5.0f,-5.0f);
glPopMatrix();
glPushMatrix();
glTranslatef(0, translate[1], translate[2]);
glRotatef(rot, 0.0, 1.0, 0.0);
glTranslatef(translate[0],0,0);
glPushMatrix();
glPushMatrix();
glTranslatef(2,0,0);
glColor3f(0.0,1.0,1.0);
fig.DrawBox(1.5f,1.5f,-1.5f,-1.5f,1.5f,-1.5f);
glPopMatrix();
glPushMatrix();
glTranslatef(-4, 1.5, 0);
glColor3f(1.0,0.0,1.0);
fig.DrawBox(0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f);
glPopMatrix();
glPushMatrix();
glTranslatef(-1, -0.5, 0);
glColor3f(0.0,0.0,1.0);
fig.DrawBox(0.5f,0.5f,-0.5f,-0.5f,0.5f,-0.5f);
glPopMatrix();
glPopMatrix();
glPopMatrix();
Now the rotation point is exactly in front of me no matter where the camera is.
OpenGL rotating a camera around a point Maybe that answer could help you. I think you have to: translate-rotate-translate.
I am trying to draw a sphere and a cube at the same time on my screen. But the colors of my cube(which gets drawn first) dissapear. I don't understand why.
the sphere on the right is fine. But my cube on the left isn't.
I added texture to both:
I can perfectly draw both of them seperately, but when I try to draw both of them on one widget something goes wrong.
I tought the popping and pushing would solve this issue, but it doesn't.
code:
void MyGLWidget::drawCube()
{
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glLoadIdentity();
gluLookAt(position,0.5,-0.1,-0.5,-0.5,0,0,0,1);
glTranslatef( 0.5, 0, 0.0);
glRotatef(getCubeAngle(), 1.0f, 0.0f, 0.0f);
glTranslatef(0, 0, 0);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
//back
glTexCoord2f(0.0, 1.0); glVertex3f(-0.1, 0.1,-0.1 );
glTexCoord2f(1.0, 1.0); glVertex3f(0.1, 0.1,-0.1);
glTexCoord2f(1.0, 0.0); glVertex3f(0.1,-0.1,-0.1);
glTexCoord2f(0.0, 0.0); glVertex3f(-0.1,-0.1,-0.1);
/*rest of cube gets drawn*/
glEnd();
glFlush();
glPopMatrix();
}
void MyGLWidget::drawSun()
{
glPushMatrix();
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, texturePlanet[0]);
glPushMatrix();
glScalef(1,1,1);
glLoadIdentity();
GLUquadricObj *quadric=gluNewQuadric();
gluQuadricTexture(quadric, GLU_TRUE);
gluQuadricNormals(quadric, GLU_SMOOTH);
glEnable(GL_TEXTURE_2D); //
glBindTexture(GL_TEXTURE_2D,texturePlanet[0]);//
gluSphere(quadric, 0.25, 360,360);
glDisable(GL_TEXTURE_2D);//
gluDeleteQuadric(quadric);
glPopMatrix();
}
void MyGLWidget::paintGL()
{
drawCube();
drawSun();
}
It is because In your cube drawing, you didn't enable texturing.
glEnable(GL_TEXTURE_2D); //ADD THIS TO ENABLE TEXTURING
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
//back
glTexCoord2f(0.0, 1.0); glVertex3f(-0.1, 0.1,-0.1 );
glTexCoord2f(1.0, 1.0); glVertex3f(0.1, 0.1,-0.1);
glTexCoord2f(1.0, 0.0); glVertex3f(0.1,-0.1,-0.1);
glTexCoord2f(0.0, 0.0); glVertex3f(-0.1,-0.1,-0.1);
/*rest of cube gets drawn*/
glEnd();
glFlush();
glPopMatrix();
glDisable(GL_TEXTURE_2D); // ADD THIS TO DISABLE TEXTURING
I'm trying to recognize a drawn object on a mousPressEvent in OpenGL in Qt with picking.
I did some research but wasn't able to find the problem.
Clearly it recognizes something (because the return value of glRenderMode(GL_RENDER) is often an integer > 0), but not necessarily when I click on an object.
I think gluPerspective is the problem right here, but i just don't know how to resolve it.
mousePressEvent:
void WorldView::mousePressEvent(QMouseEvent *e)
{
GLuint buff[256];
GLint hits;
GLint view[4];
//Buffer to store selection data
glSelectBuffer(256, buff);
//Viewport information
glGetIntegerv(GL_VIEWPORT, view);
//Switch to select mode
glRenderMode(GL_SELECT);
//Clear the name stack!
glInitNames();
//Restric viewing volume
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
//Restrict draw area
gluPickMatrix(e->x(), e->y(), 1.0, 1.0, view);
gluPerspective(40.0f, (GLfloat)view[2]/(GLfloat)view[3], 1.0, 100.0);
//Draw the objects onto the screen
glMatrixMode(GL_MODELVIEW);
//Draw only the names in the stack
paintGL();
//Back into projection mode to push the matrix
glMatrixMode(GL_PROJECTION);
glPopMatrix();
hits = glRenderMode(GL_RENDER);//number of recognized objects
printf("\n%d\n",hits);
//Back to modelview mode
glMatrixMode(GL_MODELVIEW);
}
Draw function:
void WorldView::paintGL ()
{
this->dayOfYear = (this->dayOfYear+1);
this->hourOfDay = (this->hourOfDay+1) % 24;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// store current matrix
glMatrixMode( GL_MODELVIEW );
glPushMatrix( );
gluLookAt(camPosx ,camPosy ,camPosz,
camViewx,camViewy,camViewz,
camUpx, camUpy, camUpz );
//Draw Axes
glDisable( GL_LIGHTING );
glBegin(GL_LINES);
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(10.0, 0.0, 0.0);
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 10.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 10.0);
glEnd();
//Draw objects we want to pick
glPushName(0);
glBegin(GL_TRIANGLES);
glVertex3d(1,1,1);
glVertex3d(2,3,2);
glVertex3d(5,2,2);
glEnd();
glPopName();
glPushName(1);
glBegin(GL_TRIANGLES);
glVertex3d(7,-5,1);
glVertex3d(10,3,2);
glVertex3d(10,2,2);
glEnd();
glPopName();
glPushName(2);
glBegin(GL_TRIANGLES);
glVertex3d(1,-5,7);
glVertex3d(2,3,9);
glVertex3d(5,2,9);
glEnd();
glPopName();
}
EDIT1: Maybe completing the code could help?
Initializer:
void WorldView::initializeGL ()
{
this->dayOfYear = 0;
this->hourOfDay = 0;
// Initialize QGLWidget (parent)
QGLWidget::initializeGL();
glShadeModel(GL_SMOOTH);
// Black canvas
glClearColor(0.0f,0.0f,0.0f,0.0f);
// Place light
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glEnable(GL_DEPTH_TEST);
GLfloat light0_position [] = {0.1f, 0.1f, 0.1f, 0.1f};
GLfloat light_diffuse []={ 1.0, 1.0, 1.0, 1.0 };
glLightfv ( GL_LIGHT0, GL_POSITION, light0_position );
glLightfv ( GL_LIGHT0, GL_DIFFUSE, light_diffuse );
}
resizer:
void WorldView::resizeGL ( int width, int height )
{
if ((width<=0) || (height<=0))
return;
//set viewport
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//set persepective
//change the next line order to have a different perspective
GLdouble aspect_ratio=(GLdouble)width/(GLdouble)height;
gluPerspective(40.0f, aspect_ratio, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
Use bullet raycast and not gl_Select which is way too slow and unwieldy. This will also make you get away from calling paintGL manually and other glCalls...in qt mousepressevent. Dont do this!
I am making a GUIon in Qt and I am using QGLWidgt to dispaly motion of an object.
For debugging puposes, I hard coded on matrix for try to display a teapot, but nothing is showing up on the screen. I have tried many things, I just dont know what is wrong.
EDIT
I figured out that it is showing the teapot, but the scaling is way off.. If i change the position was far from where it was. When I changed the position from -2.700, 2.000, 0.000 to -0.0270, 0.0200, 0.000, I could see it. I guess my question now is how to set the size of the screen to show what is being displayed??
The paintGL, resideGL and intializeGL are given below.
void GLWidget::initializeGL()
{
glClearColor(1.0,1.0,1.0,1.0);
GLUquadricObj *qobj = gluNewQuadric();
gluQuadricDrawStyle(qobj,GLU_FILL);
gluQuadricNormals(qobj,GLU_SMOOTH);
glClearDepth( 1.0f );
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
double eqn[] = {0.01f,0.0f,0.01f,-1.0f};
// enable clip plane
::glClipPlane(GL_CLIP_PLANE0,eqn);
setupLight();
}
void GLWidget::paintGL() {
double MOpenGLStack[16] = {0.4314, 0.875, 0.2181, 0.000,
0.0567, -0.267, 0.961, 0.000,
0.900, -0.402, -0.165, 0.000,
-2.700, 2.000, 0.000, 1.000};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);
glTranslated(xTrans / 16.0, yTrans/ 16.0, 0.0f);
::glPushMatrix();
::glMultMatrixd(MOpenGLStack);
glutSolidTeapot(0.15);
::glPopMatrix();
}
void GLWidget::resizeGL(int w, int h){
int side = qMin(w, h);
glViewport((w - side) / 2, (h - side) / 2, side, side);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0f, (double)w/(double)h, 0.1f, 1000.0f);
glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity ();
glTranslatef(0.0f, 0.0f, -10.0f);
}
There is a problem here:
gluPerspective(30.0f, (double)w/(double)h, 0.1f, 1000.0f);
glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
The first line is overriden by the second line - you cannot have both perspective and orthographic view at the same time. If you do not want to view the teapot in parallel view, you can comment the second line.