New Coordinates of the vertices after appliying glTranslatef and glRotatef (OpenGL, C++) - c++

First of all, let me tell i am quite new using OpenGL and C++. However, i want to get involved with this two topics.
So let me explain my case, ive been searching how to get the new coordinates of an object after glTrasnlatef and glRotatef were applied. However, i did not find the find info, actually i found some info about java but i am not getting it, as i told you i am working with C++.
I read there is something to deal with the glPushMatrix(); function but idont know how to handle it.
I know that after applying some trnaslation and rotation i am doing changes into the actual matrix.
Finally, the main purpose of this is because ill use those vertices from the rombohedrom and do a lot of translations and rotations, those are going to be needed as well.
So far this is my code (BTW i am working with lines and the vertices of course because i only need those).
i will really appreciate if someone can address me through the right path.
Thanks in advance
Alberto
#include <GL/glut.h>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
// Global variables
double rotate_y=0;
double rotate_x=0;
int width = 640;
int height = 640;
#define PI 3.14159265
float theta = 60;
float edgeLength = 1;
float sinThetaOverHypotenuse = (sin((theta*PI)/180))/edgeLength;
vector<vector<float>> coordinates{{0.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.0, 0.0, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{1.5, sinThetaOverHypotenuse, 0.0},
{0.5, sinThetaOverHypotenuse, 0},
{0.5, sinThetaOverHypotenuse, 0},
{0.0, 0.0, 0.0}};
void rhombohedrom()
{
vector<vector<float>> rotated {};
// glClearColor(1,1,0,0)
// Clear screen and Z-buffer
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH ) / 300.0;
double h = glutGet( GLUT_WINDOW_HEIGHT ) / 300.0;
glOrtho( -1 * w, 1 * w, -1 * h, 1 * h, 10, -10);
glMatrixMode( GL_MODELVIEW );
// Reset transformations
glLoadIdentity();
// Rotate when user changes rotate_x and rotate_y
glRotatef( rotate_x, 1.0, 0.0, 0.0 );
glRotatef( rotate_y, 0.0, 1.0, 0.0 );
/*
FACE 0
FACE 0
FACE 0
FACE 0
*/
// random color side - front
glBegin(GL_LINE_LOOP);
glColor3f( 0.7, 0.3, 0.8 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
/*
FACE 1
FACE 1
FACE 1
FACE 1
*/
glPushMatrix();
glTranslatef(0.0,0.0,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 1.0, 1.0, 1.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 2
FACE 2
FACE 2
FACE 2
*/
glPushMatrix();
glTranslatef(0.5,0.0,sinThetaOverHypotenuse);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.5, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
/*
FACE 3
FACE 3
FACE 3
FACE 3
*/
glPushMatrix();
glTranslatef(0.5,sinThetaOverHypotenuse,0.0);
glRotatef(90.0, 1.0, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
glColor3f( 0.5, 0.0, 0.0 );
for (int i = 0; i < 8; ++i)
{
glVertex3f(coordinates[i][0], coordinates[i][1], coordinates[i][2]);
}
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
void specialKeys(int key, int x, int y)
{
// Right arrow - increase rotation by 5 degree
if (key == GLUT_KEY_RIGHT)
rotate_y += 5;
// Left arrow - decrease rotation by 5 degree
else if (key == GLUT_KEY_LEFT)
rotate_y -= 5;
else if (key == GLUT_KEY_UP)
rotate_x += 5;
else if (key == GLUT_KEY_DOWN)
rotate_x -= 5;
// Request display update
glutPostRedisplay();
}
int main(int argc, char *argv[])
{
// Initialize GLUT and process user parameters
glutInit(&argc,argv);
glutInitWindowSize(width,height);
// Position of the window
glutInitWindowPosition(10,10);
// Request double buffered true color window with Z-buffer
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
// Create window
glutCreateWindow("rhombohedrom");
// Enable Z-buffer depth test
glEnable(GL_DEPTH_TEST);
// Callback functions
glutDisplayFunc(rhombohedrom);
glutSpecialFunc(specialKeys);
//
glutMainLoop();
return 0;
}

First, I want to address some remarks such as:
glPushMatrix() is an old way, try to use the MVP technique which will help you solving your problem. So, you have to write your Vertex Shader and pass the Matrices through what called uniform in OpenGL. Obviously, you have to use new Routines.
glPopMatrix() is also an old routine.
I'm happy to answer your further questions if you want to know more about those remarks.
Use Vertex Shader instead of simple calculus using the CPU!
you can change glTranslatef() and glRotatef() by lookAt so you can change the scale, rotation and translation.
Use Vertex Shader instead of using or stressing the CPU by graphic calculus. Even if you have an Intel integrated GPU

Related

How to glutDisplayFunc, glutMainLoop in glfw?

I have a small program using glut and i need for many reasons to use glfw now. Since I have never used glfw I have a lot of problems.
The main ones are the functions : glutDisplayFunc, glutReshapeFunc, glutIdleFunc and glutMainLoop. I have just found out that there are no equivalent functions in glfw. How should I modify my program ?
My program is about a cone rotating in 3 dimensions
I have a function displaycone:
void displayCone(void){
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT); //
// set matrix mode
glMatrixMode(GL_MODELVIEW);
// clear model view matrix
glLoadIdentity();
// multiply view matrix to current matrix
gluLookAt(3.0, 3.0, 3.0-4.5, 0.0, 0.0,-4.5,0,1,0);
// ******
glPushMatrix();
glTranslatef(0.0, 0.0, -4.5);
glBegin(GL_LINES);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(2.0, 0.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 2.0, 0.0);
glColor3f (1.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 2.0);
glEnd();
glPopMatrix();
// clear the drawing buffer.
// traslate the draw by z = -4.0
// Note this when you decrease z like -8.0 the drawing will looks far , or smaller.
glTranslatef(0.0,0.0,-4.5);
// Red color used to draw.
glColor3f(0.8, 0.2, 0.1);
// changing in transformation matrix.
// rotation about X axis
glRotatef(xRotated,1.0,0.0,0.0);
// rotation about Y axis
glRotatef(yRotated,0.0,1.0,0.0);
// rotation about Z axis
glRotatef(zRotated,0.0,0.0,1.0);
// scaling transfomation
glScalef(1.0,1.0,1.0);
// built-in (glut library) function , draw you a Cone.
// move the peak of the cone to the origin
glTranslatef(0.0, 0.0, -height);
glutSolidCone(base,height,slices,stacks);
// Flush buffers to screen
// gluLookAt(3,3,3,0,0,-4.5,0,1,0); <----------------------- delete
glFlush();
// sawp buffers called because we are using double buffering
// glutSwapBuffers();
}
a function reshapecone:
void reshapeCone(int x, int y)
{
if (y == 0 || x == 0) return; //Nothing is visible then, so return
//Set a new projection matrix
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//Angle of view:40 degrees
//Near clipping plane distance: 0.5
//Far clipping plane distance: 20.0
gluPerspective(35.0,(GLdouble)x/(GLdouble)y,0.5,20.0);
glViewport(0,0,x,y); //Use the whole window for rendering
}
and a function idleCone:
void idleCone(void)
{
for(int j = 1; j<10000 ; j++){
double i = dati[j+1][0];
int win = glfwGetWindow();
if(i == 0.) break;
xRotated = 180/M_PI*(dati[j][0]);
yRotated = 180/M_PI*(dati[j][1]);
zRotated = 180/M_PI*(dati[j][2]);
displayCone();
xRotated += 0.;
yRotated += 0.;
zRotated += 0.;
displayCone();
}
}
In my previous program i had in main:
glfwInit(&argc, argv);
//double buffering used to avoid flickering problem in animation
glutInitDisplayMode(GLUT_SINGLE | GL_RGB);
//glfwInitWindowSize(800,700);
glfwCreateWindow(800,700,"Rotation of the top",NULL,NULL);
glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
xRotated = yRotated = zRotated = 0.0;
xRotated=0.0;
yRotated=0.0;
glClearColor(0.0,0.0,0.0,0.0);
glutDisplayFunc(displayCone);
glutReshapeFunc(reshapeCone);
glutIdleFunc(idleCone);
glutMainLoop();
When using glfw, then you've to create your own application loop. Note, it is important to to make the OpenGL context current, before calling any OpenGL instruction, by glfwMakeContextCurrent. e.g.:
GLFWwindow *wnd = glfwCreateWindow(800,700,"Rotation of the top",NULL,NULL);
glfwMakeContextCurrent(wnd);
// do the OpenGL initialization
// [...]
while (!glfwWindowShouldClose(wnd))
{
// do the drawing
displayCone();
glfwSwapBuffers(wnd);
glfwPollEvents();
}
Instead of glutReshapeFunc you can set the size callback by glfwSetWindowSizeCallback: e.g.:
glfwSetWindowSizeCallback(wnd, reshapeCone);
void reshapeCone(GLFWwindow* window, int x, int y)
{
// [...]
}

openGL fixing camera?

This code makes cube. Code works correctly.
But, if I increase the vertex values, it does not show in the display. I want bigger cube, but bigger cube does not show in display. How can I fix it??
Thanks for answers...
#define A glVertex3f (-0.5, 0.5, -0.5)
#define B glVertex3f (-0.5, -0.5, -0.5)
#define C glVertex3f ( 0.5, -0.5, -0.5)
#define D glVertex3f ( 0.5, 0.5, -0.5)
#define E glVertex3f (-0.5, 0.5, 0.5)
#define F glVertex3f (-0.5, -0.5, 0.5)
#define G glVertex3f ( 0.5, -0.5, 0.5)
#define H glVertex3f ( 0.5, 0.5, 0.5)
#define _USE_MATH_DEFINES
#include <cmath>
#include <stdlib.h>
#include <math.h>
#include <glut.h>
float distance = 5.0;
int longitude = 0, latitude = 0, ainc = 5;
int lastx = -1, lasty = -1;
void display (void)
{
float xc, yc, zc;
int type = GL_POLYGON; // or GL_LINE_LOOP
xc = distance * cos (latitude /180.0*M_PI) * cos (longitude/180.0*M_PI);
yc = distance * sin (latitude /180.0*M_PI);
zc = distance * cos (latitude /180.0*M_PI) * sin (longitude/180.0*M_PI);
glLoadIdentity ();
gluLookAt (xc, yc, zc, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Sides of the cube as loops or polygons, in anti-clockwise order.
glColor3f (1.0, 0.0, 0.0);
glBegin (type); A; B; C; D; glEnd(); // front
glColor3f (0.0, 1.0, 0.0);
glBegin (type); H; E; F; G; glEnd(); // back
glColor3f (0.0, 0.0, 1.0);
glBegin (type); B; C; G; F; glEnd(); // bottom
glColor3f (1.0, 0.0, 1.0);
glBegin (type); A; D; H; E; glEnd(); // top
glColor3f (0.0, 1.0, 1.0);
glBegin (type); A; E; F; B; glEnd(); // left
glColor3f (1.0, 1.0, 0.0);
glBegin (type); D; C; G; H; glEnd(); // right
glutSwapBuffers ();
}
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case 27: case 'q': case 'Q':
exit (EXIT_SUCCESS);
break;
}
}
void special (int key, int x, int y)
{
switch (key) {
case GLUT_KEY_UP:
distance *= 1.1;
break;
case GLUT_KEY_DOWN:
distance /= 1.1;
break;
}
glutPostRedisplay ();
}
void click (int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
lastx = x;
lasty = y;
}
}
void mouse (int x, int y)
{
if (x > lastx) {
longitude = (longitude + ainc) % 360;
} else if (x < lastx) {
longitude = (longitude - ainc) % 360;
}
if (y > lasty) {
latitude = (latitude + ainc) % 360;
} else if (y < lasty) {
latitude = (latitude - ainc) % 360;
}
lastx = x;
lasty = y;
glutPostRedisplay ();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (65.0, (GLfloat) w / (GLfloat) h, 1.0, 20.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0.0, 0.0, -5.0);
}
int main (int argc, char *argv[])
{
glutInit (&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutCreateWindow (argv[0]);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(50.0, 1.0, 3.0, 7.0);
glMatrixMode (GL_MODELVIEW);
glutDisplayFunc (display);
glutKeyboardFunc (keyboard);
glutSpecialFunc (special);
glutMouseFunc (click);
glutMotionFunc (mouse);
glutReshapeFunc (reshape);
glEnable (GL_DEPTH_TEST);
glutMainLoop ();
return EXIT_SUCCESS;
}
I suspect it's you perspective that's broken.
Your near and far planes are 3.0 and 7.0 units. If you move your points outside these planes they will be removed. You also use 1.0 and 20.0 when you reshape the window, but they won't be used unless there's a reshape event.
I don't know what values you use for your cube but I think you move outside of your defined range. Try increasing the difference between the near and far places and make sure your cube falls between them.
For more info on gluPerspective see the documentation.
To scale an object's vertices, you only have to multiply them by the same number. For example if you want to make a cube twice as large, multiply all vertices by 2.0.
If the cube becomes so large that it's front side goes behind the "camera" then it will not render, and if your settings do not render the "back side" of faces, then your cube will not render at all (because the camera will be inside it).
You can also use glScalef(float x, float y, float z)

opengl rotate an object around fixed axes

Hi I'm trying to implement a opengl program with rotation&translation. But I got this problem that, the world axes will rotating along with my object(a cube). It's like, first I rotate cube along Z-axis, it works fine, then I middle-click the mouse and want to rotate the cube along the original Y-axis. At the moment I click, the cube will stop rotating along Z and start to rotate along Y. But it turns out it will rotate along a "new and invisible" Y-axis. I figure out that's because when I rotate the cube along Z with glRotatef(), the other two axis:X,Y also rotate. How can I fix the axes when I'm rotating the cube. I know the glRotatef() will multiply all matrix in screen with a rotation axis, so I tried added a glLoadIdentity() in each rotation but it still not work. can anyone give me the solution?
the code is here for reference:
#include <stdlib.h>
#include <GL/glut.h>
#include <iostream>
GLfloat vertices[8][3] =
{ { -1.0, -1.0, -1.0 }, { 1.0, -1.0, -1.0 },
{ 1.0, 1.0, -1.0 }, { -1.0, 1.0, -1.0 }, { -1.0, -1.0, 1.0 },
{ 1.0, -1.0, 1.0 }, { 1.0, 1.0, 1.0 }, { -1.0, 1.0, 1.0 } };
GLuint listName;
GLfloat theta[3] = { 0.0, 0.0, 0.0 };
GLint axis = 2;
GLfloat delta = 0.02;
GLint stop = 0;
GLfloat distance = 0;
void face(int a, int b, int c, int d)
{
glBegin(GL_POLYGON);
//glColor3fv(colors[a]);
glVertex3fv(vertices[a]);
//glColor3fv(colors[b]);
glVertex3fv(vertices[b]);
//glColor3fv(colors[c]);
glVertex3fv(vertices[c]);
//glColor3fv(colors[d]);
glVertex3fv(vertices[d]);
glEnd();
}
void cube(void)
{
glColor3f(1.0f,1.0f,1.0f);
face(0, 3, 2, 1);
face(2, 3, 7, 6);
face(0, 4, 7, 3);
face(1, 2, 6, 5);
face(4, 5, 6, 7);
face(0, 1, 5, 4);
glutWireCube(2.5f);
glutPostRedisplay();
}
void drawAxis(void){
// save previous matrix
glPushMatrix();
// clear matrix
glLoadIdentity();
// draw our axes
glRotatef(45.0, 1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, -1.0, 0.0);
glBegin(GL_LINES);
// draw line for x axis
glColor3f(1.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(10.0, 0.0, 0.0);
// draw line for y axis
glColor3f(0.0, 1.0, 0.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 10.0, 0.0);
// draw line for Z axis
glColor3f(0.0, 0.0, 1.0);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.0, 0.0, 10.0);
glEnd();
// load the previous matrix
glPopMatrix();
glutPostRedisplay();
}
void spinCube()
{
theta[axis] += delta;
if (theta[axis] > 360.0) theta[axis] -= 360.0;
glutPostRedisplay();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(45.0, 1.0, 0.0, 0.0);
glRotatef(45.0, 0.0, -1.0, 0.0);
drawAxis();
glPushMatrix();
glRotatef(theta[0], 1.0, 0.0, 0.0);
glRotatef(theta[1], 0.0, 1.0, 0.0);
glRotatef(theta[2], 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.0, distance + 2.0);
glCallList(listName);
glPopMatrix();
glutSwapBuffers();
}
void myReshape(int w, int h)
{
GLfloat aspect = (GLfloat) w / (GLfloat) h;
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (w <= h)
glOrtho(-10.0, 10.0, -10.0 / aspect, 10.0 / aspect, -50.0, 50.0);
else
glOrtho(-10.0*aspect, 10.0*aspect, -10.0, 10.0, -50.0, 50.0);
glMatrixMode(GL_MODELVIEW);
}
void mouse(int btn, int state, int x, int y)
{
if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { axis = 0;
}
if (btn == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) { axis = 1;
}
if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { axis = 2;
}
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 'q' || key == 'Q') exit(0);
if (key == ' ') { stop = !stop; }
if (stop)
glutIdleFunc(NULL);
else
glutIdleFunc(spinCube);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
glutInitWindowSize(600, 600);
glutCreateWindow("cube");
glutReshapeFunc(myReshape);
glutDisplayFunc(display);
glutIdleFunc(spinCube);
glutMouseFunc(mouse);
glutKeyboardFunc(keyboard);
//creating a display list:
listName = glGenLists(1);
glNewList(listName, GL_COMPILE);
cube();
glEndList();
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
What you're after might be accumulating arbitrary rotations. This can't be done with euler angles, which gimbal lock. It's pretty common to have euler angle rotations and in most cases the issue is simply to do with the order they're applied in. The first thing I'd suggest is to reverse the order of your x/y/z rotations.
Next, if you want to accumulate rotations you'll really want to get into quaternions. This can be done with matrices but can easily become numerically unstable. Quaternions can be normalized which solves this issue.
If you rotate around X, the first call is of course, glRotatef(a, 1, 0, 0); draw(). Then you want to rotate the object and its current rotation around y. Note that the object and current rotation are grouped in this line of thinking. So you glRotatef(b, 0, 1, 0); glRotatef(a, 1, 0, 0); draw();. Each time you rotate, you add the rotation behind the existing list of transforms. If you added in front, it'd transform the object in its local space and not global. What you could do is this (near-pseudo-code with an imaginary matrix implementation):
Keep a current object transform matrix M
In spinCube, M = rotationMatrix(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * M (note it's rotation * M and not M * rotation.
Before you draw the cube, glMultMatrixf(M.data)
The problem is floating point error will build up over time and the matrix will start to skew/scale your object in weird ways. Instead, you'll want a quaternion implementation (again near-pseudo-code):
Q = rotationQuaternion(delta, axis==0?1:0, axis==1?1:0, axis==2?1:0) * Q
Q.normalize()
...
glMultMatrixf(Q.toMatrix().data)

Calculating gluLookAt, glOrtho and glFrustum

I am working on an assignment to draw wire frame GLUT standard objects. This seems simple but we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate. How to you project the object without using these functions in glMatrixMode(GL_PROJECTION)?
This is what I have so far:
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity(); /* clear the matrix */
/* viewing transformation */
glTranslatef(0.0, 0.0, -5.0);
glScalef(1.0, 2.0, 1.0); /* modeling transformation */
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//glTranslatef(0.0, 0.0, -5.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
Can someone please help with this?
we are told we cannot use gluAtLook(), glOrtho(), glFrustrum but we must use glTranslate(), glScale() and glRotate
gluLookAt sets up the world to view space transformation, glOrtho does view to orthographic projection space transformation and glFrustum does view to perspective projection space transformation. When you say your tutor hasn't allowed to use it, it clearly means that the intention is to understand how these functions work in the first place.
There're many resources on the internet which teach you that. Here's one by a renowned UC Berkeley professor Dr. Ravi Ramamoorthi. SongHo has good articles which will help you do the same thing.
I can demonstrate a simple case in 2D. Say we've a world defined with objects (for simplicity we take a point P); we want the camera to be at (3, 3) with its X and Y axes pointing in directions opposite to world's X and Y axes. For simplicity we'll assume both frames have the same scaling factor i.e. 1 unit in both X and Y directions measure the same distance (magnitude) for both systems. So the two frames differ only by orientation and origin location (W0 and V0 are the symbols denoting them).
We need to derive Mworld->view i.e. the matrix which maps points in world space to view space. This is what the now-deprecated gluLookAt function calculates and multiplies with GL_MODELVIEW matrix stack. This matrix will be used to get a view of the world from the camera's viewpoint.
We know that Mworld->view = Tview->world. The matrix which maps points of frame A to frame B will also be the matrix which transforms B's frame into A's frame. The derivation goes like this
The point P in world has (1, 2) = Pw as coordinates, we're effectively finding a matrix, which when multiplied with Pw will give Pv i.e. the same point's coordinates in view frame. The point is written as a 3D point since homogeneous extension of a 2D point would be a 3D point; the homogeneous coordinate would be 1 since it's a point; had it been a vector, it'd be 0.
Step one is rotation; rotating view's frame by -180° (right-handed system where +ve rotation is counter-clockwise); now the axes are along the same direction for both frames. We've to tackle the origin difference, this is done by translation, which is step 2. Multiplying both will give the required matrix. Note that each step transforms the view's frame more closer into world's frame by post-multiplying. Also each transformation is based on that current local frame we're in and not based on the starting global (world) frame.
The same idea can be extended to 3D too, with some more effort. In the above derivation all I needed were just rotation matrix, translation matrix and matrix multiplication; no gluLookat.The links I gave you should help in calculating the same for 3D. The projection matrix derivation is a bit more involved. However, you can still achieve the result without using glOrtho; the links I gave above has the formula for the final matrix; you can compose a matrix using that and multiply that to the GL_PROJECTION matrix stack.
Note: The above derivation assumes column vectors and thus transformation matrices (like rotation) and multiplication order are done based on that. If you assume row vector convention then transpose all the matrices and reverse the order of multplication since
(AB)^T = B^T A^T
What you need to do is compute your own projection matrix and model-view matrix. After that you can load them using glLoadMatrix right after you call glLoadIdentity.
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <math.h> // for sqrt()
#include <glut.h>
static GLfloat Xvalue = 0.0f;
static GLfloat Yvalue = 0.0f;
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
static GLfloat zRot = 0.0f;
static GLfloat xScale = 1.0f;
static GLfloat yScale = 1.0f;
static GLfloat zScale = 1.0f;
void init(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glShadeModel(GL_FLAT);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0, 0.0, 0.0);
glLoadIdentity(); //clear the matrix
glTranslatef(Xvalue, Yvalue, -3.0); // viewing transformation
glScalef(xScale, yScale, zScale); // modeling transformation
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
glRotatef(zRot, 0.0f, 0.0f, 1.0f);
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
GLfloat identity[16] = { 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 };
if (h == 0) // don't want a divide by zero
{
h = 1;
}
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(identity);
GLfloat fovy = 52.0f; // in degrees
GLfloat c = 1.0 / (GLfloat)tan(fovy / 4.0), a = (GLfloat)w / (GLfloat)h, n = 1.0f, f = 1000.0f;
GLfloat projection[16] = { c / a, 0.0, 0.0, 0.0,
0.0, c, 0.0, 0.0,
0.0, 0.0, -(f + n) / (f - n), -1.0,
0.0, 0.0, -2.0*f*n / (f - n), 0.0 };
glMultMatrixf(projection);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void keyInput(unsigned char key, int x, int y)
{ // Keyboard input processing routine.
switch (key)
{
case 'b': // move left
Xvalue -= 0.1;
glutPostRedisplay();
break;
case 'B': // move right
Xvalue += 0.1;
glutPostRedisplay();
break;
case 'c': // move down
Yvalue -= 0.1;
glutPostRedisplay();
break;
case 'C': // move up
Yvalue += 0.1;
glutPostRedisplay();
break;
case 'e': // scale down
zScale -= 0.1;
xScale -= 0.1;
yScale -= 0.1;
glutPostRedisplay();
break;
case 'E': // scale up
zScale += 0.1;
xScale += 0.1;
yScale += 0.1;
glutPostRedisplay();
break;
case 'f': // rotate x axis CW
xRot -= 5.0f;
glutPostRedisplay();
break;
case 'F': // rotate x axis CCW
xRot += 5.0f;
glutPostRedisplay();
break;
case 'g': // rotate y axis CW
yRot -= 5.0f;
glutPostRedisplay();
break;
case 'G': // rotate y axis CCW
yRot += 5.0f;
glutPostRedisplay();
break;
case 'h': // rotate z axis CW
zRot -= 5.0f;
glutPostRedisplay();
break;
case 'H': // rotate z axis CCW
zRot += 5.0f;
glutPostRedisplay();
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyInput);
glutMainLoop();
return 0;
}

opengl sphere clipping

I've been experimenting with programs from my text book that involved clipping 2-D polygons using glOrtho and then creating glutWireSpheres in gluPerspective. My goal is to clip half the sphere with a plane, however, I am having trouble clipping 3-D objects. I created a toggle button to show the sphere clipped and unclipped, however, the button instead shows the sphere moving in a ellipse motion I believe.
Here is my drawscene for creating the sphere
double eqn0[4] = {1, 0, 0.0, -60}; // Data for clipping plane 0.
// Choose window.
glutSetWindow(id2);
gluLookAt(0.0, 3.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn0); // Specify clipping plane 0.
if (isClip0) glEnable(GL_CLIP_PLANE0); // Clip points s.t. z > 0.25.
else glDisable(GL_CLIP_PLANE0);
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glutWireSphere(1.0, 10, 10);
glPopMatrix();
glFlush();
And here is my toggle
case '0':
if (isClip0 == 0) isClip0 = 1;
else isClip0 = 0;
glutPostRedisplay();
break;
Can someone help me get in the right direction for clipping 3-D objects? Because this will work on 2-D polygons, yet when I try to apply it to spheres, the toggle button doesn't even act like a toggle.
EDIT: Full code:
#include <cmath>
#include <iostream>
#ifdef __APPLE__
# include <GLUT/glut.h>
#else
# include <GL/glut.h>
#endif
#define PI 3.14159265
using namespace std;
// Globals.
static int id1, id2; // Window identifiers.
static int isClip0 = 0; // Is clipping plane 0 enabled?
static int isClip1 = 0; // Is clipping plane 1 enabled?
static int isClip3 = 0; // Is clipping plane 0 enabled?
static int isClip4 = 0; // Is clipping plane 1 enabled?
// Drawing routine for first window.
void drawScene1(void)
{
// Choose window.
glutSetWindow(id1);
glClear(GL_COLOR_BUFFER_BIT);
// A red square.
glColor3f(1.0, 0.0, 0.0);
glBegin(GL_POLYGON);
glVertex3f(10.0, 10.0, 0.0);
glVertex3f(40.0, 10.0, 0.0);
glVertex3f(40.0, 40.0, 0.0);
glVertex3f(10.0, 40.0, 0.0);
glEnd();
glFlush();
}
// Drawing routine for second window.
void drawScene2(void)
{
double eqn0[4] = {1, 0, 0.0, -1000}; // Data for clipping plane 0.
// Choose window.
glutSetWindow(id2);
gluLookAt(0.0, 3.0, 12.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClipPlane(GL_CLIP_PLANE0, eqn0); // Specify clipping plane 0.
if (isClip0) glEnable(GL_CLIP_PLANE0); // Clip points s.t. z > 0.25.
else glDisable(GL_CLIP_PLANE0);
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glutWireSphere(1.0, 10, 10);
glPopMatrix();
glFlush();
}
// Initialization routine for first window.
void setup1(void)
{
// Black background.
glClearColor(0.0, 0.0, 0.0, 0.0);
}
// Initialization routine for second window.
void setup2(void)
{
// Green background.
glClearColor(1.0, 1.0, 1.0, 0.0);
}
// Reshape routine for first window.
void resize1(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Non-square aspect ratio squashes the square.
glOrtho(0.0, 50.0, 0.0, 100.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Reshape routine for second window.
void resize2(int w, int h)
{
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (float)w/(float)h, 1.0, 50.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
// Keyboard input processing routine shared by both windows.
void keyInput(unsigned char key, int x, int y)
{
switch(key)
{
case 27:
exit(0);
break;
case '0':
if (isClip0 == 0) isClip0 = 1;
else isClip0 = 0;
glutPostRedisplay();
break;
default:
break;
}
}
// Main routine.
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
// First top-level window definition.
glutInitWindowSize(250, 500);
glutInitWindowPosition(100, 100);
// Create the first window and return id.
id1 = glutCreateWindow("windows.cpp - window 1");
// Initialization, display, and other routines of the first window.
setup1();
glutDisplayFunc(drawScene1);
glutReshapeFunc(resize1);
glutKeyboardFunc(keyInput); // Routine is shared by both windows.
// Second top-level window definition.
glutInitWindowSize(250, 500);
glutInitWindowPosition(400, 100);
// Create the second window and return id.
id2 = glutCreateWindow("windows.cpp - window 2");
// Initialization, display, and other routines of the second window.
setup2();
glutDisplayFunc(drawScene2);
glutReshapeFunc(resize2);
glutKeyboardFunc(keyInput); // Routine is shared by both windows.
glutMainLoop();
return 0;
}
Sphere is dealt with in drawScene2
So, after adding a glLoadIdentity() right before the gluLookAt(), the movements will go away (as I already had suggested...). And when one sets a useful clip plane equation, the clipping works as expected, too. As you define a sphere with radius 1 around the object space center, setting
GLdouble eqn0[4] = {1, 0, 0.0, 0.5};
will result in the sphere being clipped at x=-0.5, so 3/4 of it is still visible, as one would expect.