Reputation: 1570
In short, I am asked to make this sketch in OpenGL. I attached a screenshot of what I have done so far.
My questions is that how to make those 4 horizontal sticks to tilt. I wrote the code that makes those 4 horizental lines to rotate (use n
and m
key to rotate the four sticks around center) but I am asked to make it both tilt and rotate at the same time.
I think I need to use modulus operator but when angle passes certain point like 10 (e.g angle % 10) it jumps back to 0 causes the sticks to suddenly move. Also, how to make the stick's base to stay in one position and make the end of the sticks to tilt (I mean move up and down), so tilting would be natural and not like rotating.
Any hint to make a tilting smooth? am I on a right track?
#include <GL/glut.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define PI 3.14159265
static GLfloat lpos[] = { 0.0, 5.0, 4.0, 1.0 };
static GLfloat black[] = { 0.0, 0.0, 0.0, 1.0 };
static GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
static GLfloat gray[] = { 0.5, 0.5, 0.5, 1.0 };
static GLfloat red[] = { 1.0, 0.0, 0.0, 1.0 };
static GLfloat green[] = { 0.0, 1.0, 0.0, 1.0 };
static GLfloat blue[] = { 0.0, 0.0, 1.0, 1.0 };
static GLfloat yellow[] = { 1.0, 1.0, 0.0, 1.0 };
static GLfloat magenta[] = { 1.0, 0.0, 1.0, 1.0 };
static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
static GLfloat darkcyan[] = { 0.0, 0.4, 0.4, 1.0 };
static GLfloat lightgreen[] = { 0.5,1.0,0.5,1.0 };
static float alpha = 0.0;
static float beta = PI / 6.0;
static float zoom = 15.0;
static bool lightSource = true;
float numberOfTriangles = 1;
static GLdouble cpos[3];
bool showNormalVectors = false;
static double xPointer, yPointer, zPointer;
static double fenceHeight = -0.5;
static int angle = 0;
void writemessage()
{
printf("HW-3 - Computer Graphics - Professor Suzuki\n");
printf("Seyedamirhossein Hesamian\n\n");
printf(" X => x++ <= Move light source in direction of +X\n");
printf(" Y => y++ <= Move light source in direction of +Y\n");
printf(" Z => z++ <= Move light source in direction of +Z\n");
printf("\n");
printf("^X => x-- <= Move light source in direction of -X\n");
printf("^Y => y-- <= Move light source in direction of -Y\n");
printf("^Z => z-- <= Move light source in direction of -Z\n");
printf("\n");
printf(" ^ => Move camera up\n");
printf(" > => Move camera right\n");
printf(" < => Move camera left\n");
printf(" down arrow => Move camera down\n");
printf("\n");
printf(" t => More Twist\n");
printf(" f => Less Twist\n");
printf("\n");
printf(" q => More Propeller\n");
printf(" f => Less Propeller\n");
printf("\n");
printf(" e => More Triangles\n");
printf(" d => Less Triangles\n");
printf("\n");
printf(" 0 => Toggling light source\n");
printf("\n");
printf(" r => Rotates Propeller\n");
printf("\n");
printf(" n => Toggle to show Normal Vectors\n");
printf("\n");
printf(" s => Toggle to show Inside Triangles\n");
printf("\n");
printf(" w => Toggle to show wire frame mode\n");
printf("\n");
printf(" You can not move the light source when the light source is off !!!");
}
void doGlTranslatef(){
glTranslatef(xPointer, yPointer, zPointer);
}
void releaseGlTranslatef(){
glTranslatef(-xPointer, -yPointer, -zPointer);
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLfloat)w / (GLfloat)h, 0.01, 20.0);
glMatrixMode(GL_MODELVIEW);
}
void DrawSticksArroundYard(){
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, black);
GLUquadricObj *quadObj;
// Right-Line
xPointer = 4.8;
yPointer = 1.0 + fenceHeight;
zPointer = -5.0;
doGlTranslatef();
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 10, 10, 10);
releaseGlTranslatef();
// Left-Line
xPointer = -4.8;
yPointer = 1.0 + fenceHeight;
zPointer = -5.0;
doGlTranslatef();
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 10, 10, 10);
releaseGlTranslatef();
// Back-Line
xPointer = -4.8;
yPointer = 1.0 + fenceHeight;
zPointer = -5.0;
doGlTranslatef();
glRotatef(90, 0, 1, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 9.6, 10, 10);
glRotatef(-90, 0, 1, 0);
releaseGlTranslatef();
// Front-Line
xPointer = 4.8;
yPointer = 1.0 + fenceHeight;
zPointer = 5.0;
doGlTranslatef();
glRotatef(-90, 0, 1, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 9.6, 10, 10);
glRotatef(90, 0, 1, 0);
releaseGlTranslatef();
// Pin-Front-Right
xPointer = 4.8;
yPointer = 0.0;
zPointer = 5.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Front-Left
xPointer = -4.8;
yPointer = 0.0;
zPointer = 5.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Back-Left
xPointer = -4.8;
yPointer = 0.0;
zPointer = -5.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Back-Right
xPointer = 4.8;
yPointer = 0.0;
zPointer = -5.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Back-Center
xPointer = 0.0;
yPointer = 0.0;
zPointer = -5.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Front-Center
xPointer = 0.0;
yPointer = 0.0;
zPointer = 5.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Right-Center
xPointer = 4.8;
yPointer = 0.0;
zPointer = 0.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
// Pin-Left-Center
xPointer = -4.8;
yPointer = 0.0;
zPointer = 0.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.1, 1.3 + fenceHeight, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
}
void DrawYardFloor(){
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lightgreen);
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, lightgreen);
glBegin(GL_POLYGON);
glNormal3f(0, 1, 0);
glVertex3f(-5.3, -0.005, -5.3);
glVertex3f(-5.3, -0.005, 5.3);
glVertex3f(5.3, -0.005, 5.3);
glVertex3f(5.3, -0.005, -5.3);
glEnd();
}
void DrawCenterPin(){
xPointer = 0.0;
yPointer = 0.0;
zPointer = 0.0;
doGlTranslatef();
glRotatef(-90, 1, 0, 0);
GLUquadricObj *quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.2, 0.2, 3, 10, 10);
glRotatef(90, 1, 0, 0);
releaseGlTranslatef();
}
void DrawHorizontalStickNum(){
xPointer = 0.0;
yPointer = 2.9;
zPointer = -3.0;
doGlTranslatef();
GLUquadricObj *quadObj = gluNewQuadric();
gluCylinder(quadObj, 0.1, 0.1, 3, 10, 10);
releaseGlTranslatef();
glEnd();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
cpos[0] = zoom * cos(beta) * sin(alpha);
cpos[1] = zoom * sin(beta);
cpos[2] = zoom * cos(beta) * cos(alpha);
gluLookAt(cpos[0], cpos[1], cpos[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
if (lightSource == true){
glLightfv(GL_LIGHT0, GL_POSITION, lpos);
glMaterialfv(GL_FRONT, GL_EMISSION, white);
glPushMatrix();
glTranslatef(lpos[0], lpos[1], lpos[2]);
glutSolidSphere(0.1, 10, 8);
glPopMatrix();
glMaterialfv(GL_FRONT, GL_EMISSION, black);
}
DrawYardFloor();
DrawSticksArroundYard();
DrawCenterPin();
// We can use N and M to rotate the sticks arround the center pin
glRotatef(angle, 0, 1, 0);
for (int i = 0; i < 4; i++){
glPushMatrix();
glRotatef(i * 360 / 4, 0, 1, 0);
// For tilting the sticks
//glRotatef(angle % 10, 1, 1, 0);
DrawHorizontalStickNum();
//glRotatef(angle % 10, 1, 1, 0);
glPopMatrix();
}
glRotatef(angle, 0, 1, 0);
glutSwapBuffers();
glFlush();
}
void keyboard(unsigned char key, int x, int y)
{
static int polygonmode[2];
switch (key) {
case 27:
exit(0);
break;
case 'x':
if (lightSource == true)
lpos[0] = lpos[0] + 0.2;
glutPostRedisplay();
break;
case 'X':
if (lightSource == true)
lpos[0] = lpos[0] - 0.2;
glutPostRedisplay();
break;
case 'y':
if (lightSource == true)
lpos[1] = lpos[1] + 0.2;
glutPostRedisplay();
break;
case 'Y':
if (lightSource == true)
lpos[1] = lpos[1] - 0.2;
glutPostRedisplay();
break;
case 'z':
if (lightSource == true)
lpos[2] = lpos[2] + 0.2;
glutPostRedisplay();
break;
case 'Z':
if (lightSource == true)
lpos[2] = lpos[2] - 0.2;
glutPostRedisplay();
break;
case '+':
if (zoom != 1.5)zoom = zoom - 0.5;
glutPostRedisplay();
break;
case '-':
if (zoom != 17)zoom = zoom + 0.5;
glutPostRedisplay();
break;
case '0':
if (lightSource == true){
glDisable(GL_LIGHT0);
lightSource = false;
}
else{
glEnable(GL_LIGHT0);
lightSource = true;
}
glutPostRedisplay();
break;
case 'e':
if(fenceHeight<2)
fenceHeight += 0.5;
glutPostRedisplay();
break;
case 'd':
if (fenceHeight > -0.5)
fenceHeight -= 0.5;
glutPostRedisplay();
break;
case 'w':
glGetIntegerv(GL_POLYGON_MODE, polygonmode);
if (polygonmode[0] == GL_FILL)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glutPostRedisplay();
break;
case 'n':
angle++;
glutPostRedisplay();
break;
case 'm':
angle--;
glutPostRedisplay();
break;
default:
break;
}
}
void specialkey(GLint key, int x, int y)
{
switch (key) {
case GLUT_KEY_RIGHT:
alpha = alpha + PI / 180;
if (alpha > 2 * PI) alpha = alpha - 2 * PI;
glutPostRedisplay();
break;
case GLUT_KEY_LEFT:
alpha = alpha - PI / 180;
if (alpha < 0) alpha = alpha + 2 * PI;
glutPostRedisplay();
break;
case GLUT_KEY_UP:
if (beta < 0.45*PI) beta = beta + PI / 180;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
if (beta > -0.05*PI) beta = beta - PI / 180;
glutPostRedisplay();
break;
default:
break;
}
}
int main(int argc, char** argv)
{
writemessage();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(1200, 800);
glutInitWindowPosition(0, 0);
glutCreateWindow(argv[0]);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
/* initially GL_FILL mode (default), later GL_LINE to show wireframe */
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_LIGHTING);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glEnable(GL_LIGHT0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 5.0, 10.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutSpecialFunc(specialkey);
glutMainLoop();
return 0;
}
Upvotes: 1
Views: 372
Reputation: 510
In the end, this is a lot of concatenating matrices together to achieve different effects. Using the modulous operator is entirely unnecessary, and is the source of the sticks constantly jumping back to the start. The modulous operator is used when you want to generate a repeating pattern... like rotating 10 degrees and the restarting back at 0 degrees, which is what it's doing there.
The key is rotating using the right vector. Rotating around the vector <0, 1, 0> is rotating around the Y axis which is straight up and down, which will result in the cylinder looking like it's rotating in place. Rotating around <1, 0, 0> would be rotating around the X axis, which is flat. Doing this will result in the cylinder rotating forward or backward, or tilting. Depending on what order you apply the matrix transformations, you can use a rotation around the X axis to tilt your cylinder forward or backward, following by another rotation around the Y axis to spin the cylinder into place.
Upvotes: 1