2014-10-29 133 views
2

總之,我被要求在OpenGL中製作這個草圖。我附上截至目前爲止我所做的一切。Opengl/Glut - 使傾斜平滑

我的問題是是如何使這些4水平棍棒傾斜。我寫這使得那些4 horizental行代碼旋轉(使用nm鍵繞中心四支),但有人問我,使得它傾斜旋轉同時

我想我需要使用模運算符,但是當角度通過某個點像10(例如角度%10)時,它會跳回到0導致棒突然移動。另外,如何讓棒子的底部保持在一個位置,並使棒子的末端傾斜(我的意思是上下移動),所以傾斜將是自然的,並不像旋轉。

任何提示使傾斜平滑?我在正確的軌道上嗎?

sketch screen-shot

#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; 
} 
+0

我可以建議看一下經典的glxgear [程序源代碼](https://code.google.com/p/oglshow/source/browse/trunk/cpp/glX/glxgears.c?r=23)靈感?如果您使用固定管道API,主要思想是使用矩陣堆棧移動到世界視圖的不同部分。 – didierc 2014-10-29 07:12:31

回答

1

最後,這是很多級聯矩陣在一起以實現不同的效果的。使用簡單的操作符是完全沒有必要的,並且是棍子不斷跳回到開始的源頭。當你想要產生一個重複模式時,使用簡單的運算符...就像旋轉10度,然後在0度重新開始,這就是它在那裏做的。

關鍵是使用正確的向量旋轉。圍繞矢量<旋轉0,1,0>圍繞垂直向上和向下的Y軸旋轉,這將導致圓柱體看起來像正在旋轉。圍繞<旋轉1,0,0>將圍繞平面的X軸旋轉。這樣做會導致氣缸向前或向後旋轉或傾斜。根據您應用矩陣變換的順序,可以使用圍繞X軸的旋轉來向前或向後傾斜您的圓柱體,然後繞Y軸進行另一次旋轉以將圓柱體旋轉到位。