Let's say that I want to translate a polygon.If before drawing it I use glTranslatef it gets translated, but if I want to draw two polygons and translate only one, how do I do?
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "utility.h"
void init()
{
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
}
void render()
{
glClearColor(APPLE_GRAY);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0.5, 0.0, 0.0);
glBegin(GL_POLYGON);
glColor4f(RED);
glVertex2f(0,0.5);
glVertex2f(-0.5,-0.5);
glVertex2f(0.5, -0.5);
glBegin(GL_POLYGON);
glColor4f(BLUE);
glVertex2f(0.5,0.5);
glVertex2f(-0.5,0.5);
glVertex2f(-0.5, -0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
}
I want to translate only the triangle, not the square.How to do that?
Before you translate, call:
glPushMatrix()
Then after drawing the first polygon, call:
glPopMatrix()
I've also noted you have no glEnd() call after your first polygon. Additionally, unless there is more code that's not listed, I notice that you don't switch from the modelview to the projection matrix when calling glOrtho(). This isn't strictly necessary if you are only using the modelview matrix for this example, but the traditional approach is to set up your projection like this:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1, 1, -1, 1, -1, 1);
Then, your render function sets up the modelview matrix for polygon rendering. Again, not a requirement and your example looks like it will do what you need since you are only using one matrix.
Reference: glPushMatrix() OpenGL Documentation
Related
I've started using OpenGL and I'm trying to create a wired sphere with colored longitude lines (like timezones) that rotates.
I'm trying to draw them using gluDisk-s and apply shifting in glRotatef func but I get following result (shown on images)
How can I fix it?
May be there is better way to do this?
The code I'm using:
void CreateDisk(int shift) {
quad = gluNewQuadric();
gluQuadricDrawStyle(quad, GLU_LINE);
glPushMatrix ();
glTranslatef (0., 0., 1.);
glRotatef(shift, 0, 1, 0);
glRotatef(count, 0, 1, 0);
gluDisk (quad, 0.5, .5, 50, 1);
glPopMatrix ();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30, aspect, .5, 50);
glMatrixMode(GL_MODELVIEW); //select the modelview matrix.
glLoadIdentity ();
gluLookAt(0,0,4,
0,0,0,
0,1,0);
glPushMatrix();
glColor3f(1, 0, 1);
CreateDisk(20);
glColor3f(1, 0, 0);
CreateDisk(60);
glPopMatrix();
glutSwapBuffers();
}
Currently it's creating two disks, that's for testing.
First screen Second screen
I've created a program in OpenGL that draws some shapes. I want the user to be able to zoom in on the shapes if they want to. This is the code that draws the shapes:
/*Initialise the required OpenGL functions*/
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, screenWidth, screenHeight, 0.0, -1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_CULL_FACE);
glClear(GL_DEPTH_BUFFER_BIT);
/*Draw a square*/
glColor3f(1, 0, 0);
glBegin(GL_QUADS);
glVertex2f(screenWidth * 0.75, screenHeight * 0.08333);
glVertex2f(screenWidth * 0.75, screenHeight * 0.16666);
glVertex2f(screenWidth * 0.86666, screenHeight * 0.16666);
glVertex2f(screenWidth * 0.86666, screenHeight * 0.08333);
glEnd();
glColor3f(0, 0, 0);
/*Let the user zoom*/
if (GetAsyncKeyState(VK_UP))
{
/*"zoom" is a global variable*/
zoom += 0.005;
}
glScaled(1 + zoom, 1 + zoom, 1);
/*Everything that is drawn from this point on (A sphere and a cube) should be scaled*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-0.3, 0, 0);
glutSolidSphere(3, 20, 20);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.55, 0.36, 0);
glutSolidCube(0.05);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glutSwapBuffers();
The code draws the shapes properly, but the shapes can't be scaled. I've used similar code in some other functions, so I believe that it may be because I am using 3D shapes or it may have something to do with me calling "glMatrixMode" multiple times. Either way, how should I change my code so that the cube and sphere are scaled based on user input, but the first square is not affected?
glScaled() changes the current matrix. So as soon as you call glLoadIdentity() you are undoing your scaling. You are doing lots of unnecessary calls to glMatrixMode() and glLoadIdentity() that should be eliminated. So try something more like this:
// You probably don't really need to do these, but if you do, do it once up top.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix(); // Save the current matrix
glScaled(1 + zoom, 1 + zoom, 1); // Scale it
/*Everything that is drawn from this point on (A sphere and a cube) should be scaled*/
glTranslatef(-0.3, 0, 0);
glutSolidSphere(3, 20, 20);
glTranslatef(0.55, 0.36, 0);
glutSolidCube(0.05);
glPopMatrix(); // Undo the glScaled() call above
glutSwapBuffers();
I'm having some problems translating an object I'm drawing. This is the entirety of my display function. I can't seem to find anything I'm doing wrong.
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, 720, 480, 0, -1.0, 1.0);
glTranslatef(-0.5f,0.0f,0.0f);
//drawing object here
glPopMatrix();
glutSwapBuffers();
You need to start modifying the modelview matrix stack after you've done glOrtho:
// ...
glOrtho(0, 720, 480, 0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glTranslatef(-0.5f,0.0f,0.0f);
// ...
But now your glPushMatrix and glPopMatrix are modifying different stacks, so the glPopMatrix will result in an error. You shouldn't need them for such a simple example anyway.
I have looked at some questions posted here on the matter and still cant work out why my 2d HUD appears but makes my 3d Rendered world disappear.
EDIT: It seems that the 2d scene is taking control of the entire screen so every now and then I can see the 3d scene glitching through the 2d scene. So even though I its only ment to be rendering a quad thats 10 x 10 pixels it renders this then blanks out the rest of the screen.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.5,20.0);
glMatrixMode(GL_MODELVIEW);
glViewport(0,0,x,y);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0,-0.5,-6.0);
glPushMatrix();
..Draw some 3d stuff...
glPopMatrix();
// Start 2d
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor3f(0.0f, 255.0f, 1.0f);
glBegin(GL_QUADS);
glVertex2f(0.0, 0.0);
glVertex2f(10.0, 0.0);
glVertex2f(10.0, 10.0);
glVertex2f(0.0, 10.0);
glEnd();
Then I swap buffers
Here is the order of my code. Its like it makes the 3d space then makes the 2d space which in turn cancels out the 3d space.
Took a little while to figure it out, so just in case others have the same issues:
...After Drawing 3d Stuff...
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
//glPushMatrix(); ----Not sure if I need this
glLoadIdentity();
glDisable(GL_CULL_FACE);
glClear(GL_DEPTH_BUFFER_BIT);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 0.0);
glVertex2f(0.0, 0.0);
glVertex2f(10.0, 0.0);
glVertex2f(10.0, 10.0);
glVertex2f(0.0, 10.0);
glEnd();
// Making sure we can render 3d again
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
//glPopMatrix(); ----and this?
...Then swap buffers...
:)
If you're overlaying a 2D ortho projection over 3D, you generally want to get the depth buffer out of the equation:
glDepthMask(GL_FALSE); // disable writes to Z-Buffer
glDisable(GL_DEPTH_TEST); // disable depth-testing
Of course, you'll want to reset these to their original values before doing your next 3D pass.
glViewport(0, 0, x, y); //You need to do this only once on viewport resize
//Setup for 3D
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(40.0, (GLdouble)x/(GLdouble)y, 0.5, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BIT);
// ... Render 3D ...
//Setup for 2D
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BIT);
// ... Render 2D ...
SwapBuffers;
Note that there's no need to handle Push/Pop of matrixes if you render 2D completely on top of 3D.
Is there a simple way to have isometric projection?
I mean the true isometric projection, not the general orthogonal projection.
(Isometric projection happens only when projections of unit X, Y and Z vectors are equally long and angles between them are exactly 120 degrees.)
Try using gluLookAt
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
/* use this length so that camera is 1 unit away from origin */
double dist = sqrt(1 / 3.0);
gluLookAt(dist, dist, dist, /* position of camera */
0.0, 0.0, 0.0, /* where camera is pointing at */
0.0, 1.0, 0.0); /* which direction is up */
glMatrixMode(GL_MODELVIEW);
glBegin(GL_LINES);
glColor3d(1.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(1.0, 0.0, 0.0);
glColor3d(0.0, 1.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 1.0, 0.0);
glColor3d(0.0, 0.0, 1.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 1.0);
glEnd();
glFlush();
Results in
We can draw a cube to check that parallel lines are indeed parallel
glPushMatrix();
glTranslated(0.5, 0.5, 0.5);
glColor3d(0.5, 0.5, 0.5);
glutWireCube(1);
glPopMatrix();
An isometric projection is just a matter of using an orthographic projection with a specific rotation angle.
You should be able to choose any of the 8 potential orientations, with a orthographic projection, and get a perfect isometric view of your model. Just follow the math in your referenced Wiki article for setting up the view matrix, and do an orthographic projection for your projection matrix, and you're all set.
Maybe I'm not quite grokking the math correctly, but couldn't you just position your camera as it explains in that Wikipedia link and use a standard orthogonal projection?
Even if it's not the same, the projection stack is entirely up to you.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// your isometric matrix here (see math on Wikipedia)
glMatrixMode(GL_MODELVIEW);
If you do not want to use GLU, here is bare bones using glOrtho
void gl_enter_2_5d_mode (void)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
double scale = 50;
glOrtho(-scale,
scale,
-scale * 0.7,
scale * 0.7,
-scale,
scale);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glRotatef(35.264f, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
}
void gl_leave_2_5d_mode (void)
{
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
}
then draw a cube in it
void cube (double size)
{
glBegin(GL_QUADS);
glVertex3f(size,size,size);
glVertex3f(-size,size,size);
glVertex3f(-size,-size,size);
glVertex3f(size,-size,size);
glVertex3f(size,size,-size);
glVertex3f(-size,size,-size);
glVertex3f(-size,-size,-size);
glVertex3f(size,-size,-size);
glVertex3f(size,size,size);
glVertex3f(size,-size,size);
glVertex3f(size,-size,-size);
glVertex3f(size,size,-size);
glVertex3f(-size,size,size);
glVertex3f(-size,-size,size);
glVertex3f(-size,-size,-size);
glVertex3f(-size,size,-size);
glVertex3f(size,size,size);
glVertex3f(-size,size,size);
glVertex3f(-size,size,-size);
glVertex3f(size,size,-size);
glVertex3f(size,-size,size);
glVertex3f(-size,-size,size);
glVertex3f(-size,-size,-size);
glVertex3f(size,-size,-size);
glEnd();
}
void test (void)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glBindTexture(GL_TEXTURE_2D, 0);
cube(1.0);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}
and call something like this
gl_enter_2_5d_mode()
test()
gl_leave_2_5d_mode()
should you want to toggle between 2d and 2.5d (so you can draw your UI) then I have similar functions to enter and leave 2d mode e.g.
void gl_init_2d_mode (void)
{
/*
* Enable Texture Mapping
*/
glEnable(GL_TEXTURE_2D);
/*
* Enable alpha blending for sprites
*/
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*
* Setup our viewport
*/
glViewport(0, 0, game.video_pix_width,
game.video_pix_height);
/*
* Make sure we're changing the model view and not the projection
*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
/*
* Reset the view
*/
glLoadIdentity();
gl_init_fbo();
}
void gl_enter_2d_mode (void)
{
/*
* Change to the projection matrix and set our viewing volume.
*/
glMatrixMode(GL_PROJECTION);
glPushMatrix();
/*
* Reset the view
*/
glLoadIdentity();
/*
* 2D projection
*/
glOrtho(0,
game.video_gl_width, game.video_gl_height,
0, -1200.0, 1200.0);
/*
* Make sure we're changing the model view and not the projection
*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
/*
* Reset the view
*/
glLoadIdentity();
}