Flipping Opengl drawing without scale by negative numbers - c++

I am trying to draw two 2D diamonds facing each other.
So I drew the first diamond then I drew the second diamond after using:
glTranslated(0, -150, 0);
so it can appear exactly under my first diamond .
However, I ran into a problem that I couldn't flip the second diamond so it could look like a mirror.
Here is what i am trying to do:
I searched online for solutions and they all mentioned that I should
use
glScalef(1.0f,-1.0f,1.0f);
but each time I use it the drawing disappears.
The function
glRotatef(angle,x,y,z);
caught my attention but i couldn't use it properly resulting in wrong direction.
Here is how my image looks like right now without glRotate():
So I think I need the proper technique to use any of these functions.
Note: I am using many line loops and vertices to draw.
#include <windows.h> // For MS Windows
#include <GL/glut.h> // (or others, depending on the system in use)
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0); // Set display-window color to
white.
glMatrixMode(GL_PROJECTION); // Set projection parameters.
gluOrtho2D(0.0, 400.0, 0.0, 400.0);
}
void drawDiamond()
{
glBegin(GL_LINE_LOOP);
glVertex2f(125, 350);
glVertex2f(245, 350);
glVertex2f(290, 300);
glVertex2f(182, 200);
glVertex2f(75, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(138, 350);
glVertex2f(159, 337);
glVertex2f(123, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(109, 333);
glVertex2f(123, 300);
glVertex2f(154, 225);
glVertex2f(92, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(290, 300);
glVertex2f(75, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(123, 300);
glVertex2f(159, 337);
glVertex2f(154, 300);
glVertex2f(171, 225);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(159, 337);
glVertex2f(181, 350);
glVertex2f(209, 337);
glVertex2f(181, 300);
glVertex2f(171, 225);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(181, 300);
glVertex2f(209, 337);
glVertex2f(219, 300);
glVertex2f(195, 225);
glVertex2f(181, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(243, 300);
glVertex2f(195, 225);
glVertex2f(219, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(209, 337);
glVertex2f(229, 350);
glVertex2f(260, 333);
glVertex2f(243, 300);
glVertex2f(209, 337);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(260, 333);
glVertex2f(278, 300);
glVertex2f(210, 225);
glVertex2f(243, 300);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(195, 225);
glVertex2f(182, 200);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex2f(171, 225);
glVertex2f(182, 200);
glEnd();
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT); // Clear display window.
glColor3f(0.0, 0.0, 0.0); // Set line segment color to blue.
// your code goes here
drawDiamond();
glTranslatef(0.0f, -150, 0.0f);
drawDiamond();
glFlush(); // Process all OpenGL routines as quickly as possible.
}
void main(int argc, char** argv)
{
glutInit(&argc, argv); // Initialize GLUT.
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Set display mode.
glutInitWindowPosition(50, 100); // Set top-left display-window
position.
glutInitWindowSize(400, 400); // Set display-window width and
height.
glutCreateWindow("Diamond Project"); // Create display window.
init(); // Execute initialization procedure.
glutDisplayFunc(display); // Send graphics to display window.
glutMainLoop(); // Display everything and wait.
}

What you want to do is to mirror (flip) the object around an axis, which is parallel to the X-axis, and goes through the bottom bounding of the object (diamond).
To do so, the bottom Y coordinate (bottomY) has to be found and the object has to be translated in the opposite direction. Note the bottom of the model coordinates (vertices) and not the bottom of final coordinates on the viewport:
float bottomY = 200.0f;
glTranslatef( 0.0f, -bottomY , 0.0f );
At next the object has to be flipped. This can either be done by
glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
or by
glScalef(1.0f, -1.0f, 0.0f)
Note, both operations result in the same transformation matrix, because cos(90°) = cos(-90°), sin(90°) = -sin(90°).
Then the bottomY translation has to be reversed:
glTranslatef( 0.0f, bottomY, 0.0f );
But note that the OpenGL fixed function pipeline stack operates in the the reverse order, because the current matrix is multiplied by the matrix which is specified by the new operation.
Translation: See the documentation of glTranslate:
glTranslate produces a translation by x y z . The current matrix (see glMatrixMode) is multiplied by this translation matrix, with the product replacing the current matrix.
Rotation: See the documentation of glRotate:
glRotate produces a rotation of angle degrees around the vector x y z . The current matrix (see glMatrixMode) is multiplied by a rotation matrix with the product replacing the current matrix.
Scaling: See the documentation of glScale:
glScaleproduces a nonuniform scaling along the x, y, and z axes. The three parameters indicate the desired scale factor along each of the three axes.
The current matrix (see glMatrixMode) is multiplied by this scale matrix.
This means the the following should do what you want:
float bottomY = 200.0f;
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
drawDiamond();
glTranslatef( 0.0f, bottomY , 0.0f );
glRotatef( 180.0f, 1.0f, 0.0f, 0.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );
drawDiamond();
and is the same as:
glTranslatef( 0.0f, bottomY , 0.0f );
glScalef( 1.0f, -1.0f, 1.0f );
glTranslatef( 0.0f, -bottomY , 0.0f );

Depending on how your vertices are setup and depending on if you have Back Face Culling enabled you might have to change your diamond or (model's) center point to be the bottom tip from there you can then simply rotate about the X axis provided that you declared that as the Horizontal Axis. To do so shouldn't be all that hard. It would look something like:
glRotatef( 180.0f, 1, 0, 0 );
provided you are rotating in degrees as opposed to radians.

For each vertex (I'm assuming that you use immediate mode for designating vertices), you can glVertex2i(myVertex.x, symmetryLine - myVertex.y, 0) where myVertex are the x and y values you previously used, and symmetryLine the value you wish to mirror against. Best way would be to use a negative glScale though. Your diamond is rotationally symmetric glRotate also works but you know, not a very elegant way to do it.

Related

How to create a "Concave/Convex Circle Illusion" in OpenGL

This semester, I am taking a Computer Graphics course at school, and our first assignment is to create a concave/convex illusion.
This is an example of what I am supposed to create:
Concave/Convex Circle Illusion
I've tried to work this problem out myself, however I keep getting stuck. I know how to create the gray background, and I know how to create a circle. What I dont know how to do is to make the circle look like the picture. I know how to fill it with a solid color, I just dont know how to fill it with multiple colors and fade it like in the picture.
So here is my C++ code which we run in Visual Studio 15.
#include <cstdlib>
#include <glut.h>
#include <math.h>
const double p = 3.14159/180;
void circle(float r){
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINE_LOOP);
for (int i=100; i <= 460; i++){
double degree = p*i;
double x = cos(degree) * r;
double y = sin(degree) * r;
glVertex2d(x,y);
}
glEnd();
}
/*
//This circle function was my attempt at creating the illusion shown in the picture above.
//I tried to break up the circle into separate pieces and make them each a different color,
//but unfortunately it didnt come out like the picture above.
void circle (float radius){
glColor3f(0.0,0.0,0.0); // black
glBegin(GL_POLYGON);
glVertex2i(21,21);
glVertex2i(25,19);
glVertex2i(28,17);
glVertex2i(32,16);
glVertex2i(36,17);
glVertex2i(40,19);
glVertex2i(43,21);
glEnd();
glColor3f(0.329412,0.329412,0.329412); // dim grey
glBegin(GL_POLYGON);
glVertex2i(21,21);
glVertex2i(19,25);
glVertex2i(17,30);
glVertex2i(48,30);
glVertex2i(46,25);
glVertex2i(43,21);
glEnd();
glColor3f(0.752941,0.752941,0.752941); // grey
glBegin(GL_POLYGON);
glVertex2i(17,30);
glVertex2i(16,35);
glVertex2i(15,40);
glVertex2i(50,40);
glVertex2i(49,35);
glVertex2i(48,30);
glEnd();
glColor3f(0.650024,0.650024,0.650024); // light grey
glBegin(GL_POLYGON);
glVertex2i(15,40);
glVertex2i(16,45);
glVertex2i(17,50);
glVertex2i(48,50);
glVertex2i(49,45);
glVertex2i(50,40);
glEnd();
glColor3f(0.8,0.8,0.8); // very light grey
glBegin(GL_POLYGON);
glVertex2i(17,50);
glVertex2i(20,55);
glVertex2i(45,55);
glVertex2i(48,50);
glEnd();
glColor3f(1.0,1.0,1.0); // white
glBegin(GL_POLYGON);
glVertex2i(20,55);
glVertex2i(23,58);
glVertex2i(25,60);
glVertex2i(28,62);
glVertex2i(32,63);
glVertex2i(36,62);
glVertex2i(40,60);
glVertex2i(43,58);
glVertex2i(45,55);
glEnd();
}
*/
void display(void){
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.658824,0.658824,0.658824);
glBegin(GL_POLYGON); //Creates the gray background
glVertex2i(10,10);
glVertex2i(390, 10);
glVertex2i(390,290);
glVertex2i(10,290);
glEnd();
circle(30);
glFlush();
}
void main(int argc, char** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400, 300);
glutInitWindowPosition(200,100);
glutCreateWindow("Project 1");
glClearColor(0.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,400.0,0.0,300.0);
glutDisplayFunc(display);
glutMainLoop();
}
So Ive got the majority of the code down, I just cant figure out the coloring of the circle.
Any advice/help that can make the outcome of my code look like the example picture above would be greatly appreciated.
Thanks!
Drawing by glBegin/glEnd sequences is deprecated since several years.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
But, the effect of the picture is achieved by a simple gray color gradient. The background is gray and inside the circle is a linear color gradient from white to black.
glClear, clear the framebuffer by the color which is set by glClearColor.
Set a gray clear color to create a gray background:
glClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
glClear(GL_COLOR_BUFFER_BIT);
To create a color gradient, you have to set the color attribute by glColor3d, before you set the vertex coordinate by glVertex2d. The color is interpolated between the vertices. Use the primitive type GL_TRIANGLE_FAN to create a filled polygon:
const double p = 3.14159/180;
void circle(float r, bool flip ){
glBegin(GL_TRIANGLE_FAN);
glColor3d( 0.5, 0.5, 0.5 );
glVertex2d( 0.0, 0.0 );
for (int i=0; i <= 360; i++)
{
double degree = p*i;
double c = cos( degree );
double s = sin( degree );
double col = s * 0.5 + 0.5;
if ( flip )
col = 1.0 - col;
glColor3d( col, col, col );
glVertex2d( c*r, s*r );
}
glEnd();
}
The draw function may look like this:
void display(void){
glClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
for ( int x = 0; x < 2; ++ x )
{
for ( int y = 0; y < 2; ++ y)
{
glPushMatrix();
glTranslated( 120.0 + 160.0*x, 100.0+100*y, 0.0f );
circle(30, x > 0);
glPopMatrix();
}
}
glFlush();
}
Preview:

Perspective projection (misunderstood gluPerspective)

I want to clarify things with gluPerspective near and far parameters, I know
that they define the range in z axis for all objects - so objects closer/away than near/far will be clipped by the clipping algorithms. And when lets say near = 0.1, and far = 100*winWid, we are not seeing anything because objects are behind of the viewer (and camera by default is at (0.0, 0.0, 0.0) plus openGL user coordinates system is right handed), so then we call (see code below) translate(0.0, 0.0, -winWid) to move back by -z axis objects to place them in front of the camera.
But if we set far = -100*winWid; everything works same as with positive far value.
So what's being changed when far is negative ??
Why in that case nothing is clipped too ??
#include <gl/glut.h>
#include <math.h>
const float winWid = 1000.0f;
const float winHei = 800.0f;
GLfloat cube_side = 200.0f;
GLfloat ALPHA = 0.7f;
void render();
void updateDisplay()
{
render(cubeAngle, rotx, roty, rotz);
}
void drawCube(const GLfloat& a)
{
glBegin(GL_QUADS);
// back face
glColor4f(0.0f, 1.0f, 0.0f, ALPHA);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, a, 0.0f);
glVertex3f(a, a, 0.0f);
glVertex3f(a, 0.0f, 0.0f);
// and other cube faces here ...
glEnd();
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
drawCube(cube_side);
glPopMatrix();
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_ALPHA);
glutInitWindowSize(winWid, winHei);
glutInitWindowPosition(100, 100);
glutCreateWindow("window");
glutDisplayFunc(updateDisplay);
glEnable(GL_DEPTH_TEST); // depth buffer setup
glEnable(GL_BLEND); // transparency setup
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(55.0f, winWid/winHei, 0.1f, 100*winWid);
glMatrixMode(GL_MODELVIEW);
glTranslatef(0.0f, 0.0f, -winWid); // move back to see drawing objects
glRotatef(75.0f, -1.0f, 0.0f, 0.0f); // make z+ axis point up to emphasize 3D (wihout this rotate z+ points towards the viewer)
glutMainLoop();
return 0;
}
Negative far-plane values are not supported by gluPerspective. The documentation states:
zFar: Specifies the distance from the viewer to the far clipping plane (always positive). (source)
By default, the camera in OpenGL looks along the negative z-axis. So the visible area is [-near, -far] in world coordinates. In your code example, the object is located at z=-1000, while the visible range is from [-0.01, -100*1000], which means that the object is clearly in view.
One additional thing to mention is the depth-buffer precision: This is mainly defined by the range given by nearPlane and farPlane. Assuming, that you have a precision of 16-bit (can be more or less depending on the setup), one can store 2^16 different depth values. This means with your setup, objects can be relative far away from each other and will still be treated as being at the same depth. You may think about whether this huge depth range is really necessary for the application.

How to rotate a computer drawing in 90 degrees

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

openGl / glut: seeing through blocks,

I am writing a Programm, trying to display some kind of sphere consisting of independent blocks. Unfortunately, from some angles I can see through the blocks, seeing the ones behind them.
good angle: http://i.imgur.com/6o120KF.png
bad angle: http://i.imgur.com/DbB9iVO.png
I was checking some posts, but nothing helped. I cared for depth buffer, zNear but now I have no ideas.May someone halp?
My Code
int main(int argc, char** argv) {
//init world
world.init();
//configure GLUT
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_DOUBLE); // Enable double buffered mode
glutInitWindowSize(WIDTH, HEIGHT); // Set the window's initial width & height
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
glutCreateWindow(title); // Create window with the given title
glutDisplayFunc(display); // Register callback handler for window re-paint event
glutKeyboardFunc(keyboard); // call keyboard() when key is hit
glutIdleFunc(display); // if no rendering to be, call display
glutReshapeFunc(reshape); // Register callback handler for window re-size event
initGL(); // Our own OpenGL initialization
glutMainLoop(); // Enter the infinite event-processing loop
return 0;
}
void initGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set background color to black and opaque
glClearDepth(1.0f); // Set background depth to farthest
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glDisable(GL_BLEND);
glDepthFunc(GL_LEQUAL); // Set the type of depth-test
glShadeModel(GL_SMOOTH); // Enable smooth shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Nice perspective corrections
glClear(GL_DEPTH_BUFFER_BIT);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear color and depth buffers
glMatrixMode(GL_MODELVIEW); // To operate on model-view matrix
glLoadIdentity(); // Reset the model-view matrix
//formulas for camera changes
glTranslatef(translatex, 2.0f, -7.0f); // Move right and into the screen
glRotated(rotAnglex, 1, 0, 0); // rotate by rotAngle about y-axis
glRotated(rotAngley, 0, 1, 0); // rotate by rotAngle about y-axis
glRotated(rotAnglez, 0, 0, 1); // rotate by rotAngle about y-axis
glScalef(zoom ,zoom ,zoom);
glBegin(GL_LINES);
// draw line for x axis
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0 - xmove, 0.0 - ymove, 0.0 - zmove);
glVertex3f(100.0 - xmove, 0.0 - ymove, 0.0 -zmove);
// draw line for y axis
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0 - xmove, 0.0 - ymove, 0.0 - zmove);
glVertex3f(0.0 - xmove, 100.0 - ymove, 0.0 -zmove);
// draw line for Z axis
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0 - xmove, 0.0 - ymove, 0.0 - zmove);
glVertex3f(0.0 - xmove, 0.0 - ymove, 100.0 -zmove);
glEnd();
glBegin(GL_QUADS);
//draw axes
if(it_counter++ < iterations){
//print world
BOOST_FOREACH(std::Cell* now_cell, world.cells){
BOOST_FOREACH(std::Voxel* now_voxel, now_cell->content){
addVoxel(*now_voxel);
}
}
}
glEnd(); // End of drawing color-cube
glLoadIdentity(); // Reset the model-view matrix
glTranslatef(-1.5f, 0.0f, -6.0f); // Move left and into the screen
glScalef(3.0f ,3.0f ,3.0f);
glutSwapBuffers(); // Swap the front and back frame buffers (double buffering)
}
Is the order of adding blocks (voxels in code) important for rendering?
It seams as if you created a window without a depth buffer. Enabling the depth-test will only work if your window has such a buffer.
To solve your problem, you have to change
glutInitDisplayMode(GLUT_DOUBLE);
to
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE);

Rendering visually perfect squares in OpenGL?

In OpenGL's fixed pipeline, by default, specifying vertex coordinates using glVertex3f is equivalent to specifying a location between -1.0 and +1.0 in screen space. Therefore, given a set of 4 perfectly adjacent screen-space vertices using GL_TRIANGLE_STRIP (or even GL_QUADS), and unless your window is already perfectly square, you will always render a rectangle instead of a perfect square...
Knowing the width, height and aspect ratio of a window, is there some way to correct this?
I have tried multiplying the vertex coordinates by the aspect ratio, which unfortunately seemed to achieve the same visual effect.
Here's the full source code I'm currently using:
#include "main.h"
#pragma comment(lib, "glut32.lib")
int g_width = 800;
int g_height = 600;
int g_aspectRatio = double(g_width) / double(g_height);
bool g_bInitialized = false;
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(0, 0);
glutInitWindowSize(g_width, g_height);
glutCreateWindow("OpenGL Test App");
glutDisplayFunc(onRender);
glutReshapeFunc(onSize);
glutIdleFunc(onRender);
glutMainLoop();
return 0;
}
void onInit()
{
glFrontFace(GL_CW);
}
void onRender()
{
if(!g_bInitialized)
onInit();
static float angle = 0.0f;
const float p = 0.5f * g_aspectRatio;
glLoadIdentity();
gluLookAt(
0.0f, 0.0f, 10.0f,
0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glScalef(1, -1, 1); // Flip the Y-axis
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glBegin(GL_TRIANGLE_STRIP);
{
glColor4f(1.0, 0.0, 0.0, 1.0); // Red
glVertex3f(-p, -p, 0.0); // Top-Left
glColor4f(0.0, 1.0, 0.0, 1.0); // Green
glVertex3f(p, -p, 0.0); // Top-Right
glColor4f(0.0, 0.0, 1.0, 1.0); // Blue
glVertex3f(-p, p, 0.0); // Bottom-Left
glColor4f(1.0, 1.0, 0.0, 1.0); // Yellow
glVertex3f(p, p, 0.0); // Bottom-Left
}
glEnd();
angle += 0.6f;
glutSwapBuffers();
}
void onSize(int w, int h)
{
g_width = max(w, 1);
g_height = max(h, 1);
g_aspectRatio = double(g_width) / double(g_height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, w, h);
gluPerspective(45, g_aspectRatio, 1, 1000);
glMatrixMode(GL_MODELVIEW);
}
EDIT:
This has been solved... In the above code, I had defined g_aspectRatio as an int instead of a floating-point value. Therefore, it's value was always 1...
In my (old) experience, that's just why you have an aspect ratio argument to gluPerspective().
The manual page says:
In general, the aspect ratio in gluPerspective should match
the aspect ratio of the associated viewport. For example, aspect = 2.0
means the viewer's angle of view is twice as wide in x as it is in y.
If the viewport is twice as wide as it is tall, it displays the image
without distortion.
Check your g_aspectRatio value.
by default, specifying vertex coordinates using glVertex3f is equivalent to specifying a location between -1.0 and +1.0 in screen space
Wrong. Coordinates passed to OpenGL through glVertex or a glVertexPointer vertex array are in model space. The transformation to screen space happens by transforming into view space by the modelview matrix and from view space to clip space by the projection matrix. Then clipping is applied and the perspective divide applied to reach normalized coordinate space.
Hence the value range for glVertex can be whatever you like it to be. By applying the right projection matrix you get your view space to be in [-aspect; aspect]×[-1, 1] if you like that.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-aspect, aspect, -1, 1, -1, 1);