代码之家  ›  专栏  ›  技术社区  ›  deko

旋转肩膀和肘部的OpenGL手臂

  •  1
  • deko  · 技术社区  · 6 年前

    我编写了以下代码:

    #include <math.h>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <GL/glut.h>
    
    #define WIDTH 400
    #define HEIGTH 400
    #define ORIGIN_X 50
    #define ORIGIN_Y 50
    
    #define move(x,y) glTranslatef(x, y, 0.0f);
    #define enlarge(y) glScalef(1, y, 1);
    
    #define rotateX(angle) glRotatef(angle, 1,0,0);
    #define rotateY(angle) glRotatef(angle, 0,1,0);
    #define rotateZ(angle) glRotatef(angle, 0,0,1);
    
    // Variables que definen la rotación del brazo entero (de hombro a mano)
    static GLfloat shoulder_Xangle, shoulder_Yangle, shoulder_Zangle;
    // Variables que definen sólo la rotación del antebrazo (de codo a mano)
    static GLfloat elbow_Xangle, elbow_Yangle, elbow_Zangle;
    
    void keyboardHandler(unsigned char key, int x, int y ){
    
        switch(key){
            case 'q': shoulder_Zangle++; break;
            case 'e': shoulder_Zangle--; break;
            case 'a': shoulder_Yangle++; break;
            case 'd': shoulder_Yangle--; break;
            case 'w': shoulder_Xangle++; break;
            case 's': shoulder_Xangle--; break;
            case 'r':    elbow_Zangle++; break;
            case 'y':    elbow_Zangle--; break;
            case 'f':    elbow_Yangle++; break;
            case 'h':    elbow_Yangle--; break;
            case 't':    elbow_Xangle++; break;
            case 'g':    elbow_Xangle--; break;
            default:                     break;
        }
    
        glutPostRedisplay();                // Avisa que la ventana ha de refrescarse
    }
    
    void init() {
        glutKeyboardFunc(keyboardHandler);  // Asociar handler a eventos procedentes del teclado
        glClearColor(0.0,0.0,0.0,0.0);  // Fijar el color por defecto a negro en el formato RGBA
    }
    
    void rotate(GLfloat Xangle, GLfloat Yangle, GLfloat Zangle) {
        rotateX(Xangle);        // Rotar Xangle grados sobre el eje X
        rotateY(Yangle);        // Rotar Yangle grados sobre el eje Y
        rotateZ(Zangle);        // Rotar Zangle grados sobre el eje Z
    }
    
    void draw_sphere(GLdouble radius) {
        GLint slices = 360;
        GLint stacks = 360;
        glutWireSphere(radius, slices, stacks);
    }
    
    void draw_cube() {
    
        glBegin(GL_QUADS);
    
          glColor3f ( 0.0,  0.7,  0.1);     // Parte anterior: verde        
          glVertex3f(-0.5,  0.5,  0.5);
          glVertex3f( 0.5,  0.5,  0.5);
          glVertex3f( 0.5, -0.5,  0.5);
          glVertex3f(-0.5, -0.5,  0.5);
    
          glColor3f ( 1.0,  0.0,  0.0);     // Parte posterior: rojo 
          glVertex3f(-0.5,  0.5, -0.5);     
          glVertex3f( 0.5,  0.5, -0.5);
          glVertex3f( 0.5, -0.5, -0.5);
          glVertex3f(-0.5, -0.5, -0.5);
    
          glColor3f ( 1.0,  1.0,  1.0);     // Resto: blanco
          glVertex3f(-0.5,  0.5,  0.5);
          glVertex3f( 0.5,  0.5,  0.5);
          glVertex3f( 0.5,  0.5, -0.5);
          glVertex3f(-0.5,  0.5, -0.5);
    
          glVertex3f(-0.5, -0.5,  0.5);
          glVertex3f( 0.5, -0.5,  0.5);
          glVertex3f( 0.5, -0.5, -0.5);
          glVertex3f(-0.5, -0.5, -0.5);
    
        glEnd();
    }
    
    void draw_shoulder() { draw_sphere(0.5); }
    
    void draw_elbow() {
        move(0, -3.0)                                              // 3) Colocar en su posición final
        rotate(elbow_Xangle, elbow_Yangle, elbow_Zangle);          // 2) Rotamiento del codo
        draw_sphere(0.5);                                          // 1) Dibujar 1 esfera (codo) 
    }
    
    void draw_arm() {
        move(0.0, -1.5);                                           // 3) Colocar en su posición final
        enlarge(2.0);                                              // 2) Escalar el brazo
        draw_cube();                                               // 1) Dibujar 1 cubo (brazo)
    }
    
    void draw_forearm() {
        move(0.0, -3.0);                                           // 5) Colocar en su posición final
        rotate(elbow_Xangle, elbow_Yangle, elbow_Zangle);          // 4) Rotamiento del codo
        move(0.0, -1.5);                                           // 3) Mover hacia abajo para que el radio de rotación = tamaño codo
        enlarge(2.0);                                              // 2) Escalar el antebrazo
        draw_cube();                                               // 1) Dibujar 1 cubo (antebrazo)
    }
    
    void draw_hand() {
        move(0, -3.0);                                             // 4) Colocar en su posición final
        rotate(elbow_Xangle, elbow_Yangle, elbow_Zangle);          // 3) Rotamiento del codo
        move(0.0, -2.5)                                            // 2) Mover hacia abajo el tamaño del codo+antebrazo = (1.0+2.0)-0.5
        rotateX(90);                                               // 1) Poner la mano en su sitio
        glutSolidCone(0.5, 1.5, 360, 360);
    }
    
    void display() {
    
    
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         // Borrado del FrameBuffer
        glEnable(GL_DEPTH_TEST);
    
        glLoadIdentity();                                           // Cargar la matriz identidad en la matriz de proyección            
    
        rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);  // Movimiento del hombro          
        draw_shoulder();                                            // Dibujar el hombro                          
    
        glLoadIdentity();
    
        rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);  // Movimiento del hombro
        draw_arm();                                                 // Dibujar el brazo
    
        glLoadIdentity();
    
        rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);  // Movimiento del hombro
        draw_elbow();                                               // Dibujar el codo
    
        glLoadIdentity();
    
        rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);  // Movimiento del hombro
        draw_forearm();                                             // Dibujar el antebrazo
    
        glLoadIdentity();
    
        rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);  // Movimiento del hombro
        draw_hand();                                                // Dibujar la mano
    
    
        // Forzar renderizado
        glutSwapBuffers();                   
    }
    
    void reshape(int w, int h) {
    
        glViewport(0, 0, (GLsizei)w, (GLsizei)h);
        glMatrixMode(GL_PROJECTION);                              // Activar las modificaciones en la cámara
        glLoadIdentity();                            
        glOrtho(-8, 8, -12, 4, -8, 8);
        glMatrixMode(GL_MODELVIEW);                               // Activar las modificaciones en el modelo
    }
    
    int main(int argc, char** argv) {
    
        glutInit(&argc, argv);                                    // Cargar el teclado y el ráton
    
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // Búffer doble, con color RGB y profundidad
    
        glutInitWindowSize(WIDTH, HEIGTH);                        // Tamaño de la ventana
        glutInitWindowPosition(ORIGIN_X, ORIGIN_Y);               // Posición del extremo superior-izquierdo de la ventana
    
        glutCreateWindow("Brazo Articulado");                     // Crear la ventana
        init();
        glutDisplayFunc(display);                                 // Activar la función de pintado
        glutReshapeFunc(reshape);                                 // Activar la función de escalado
        glutMainLoop();                                           // Arrancar el bucle de OpenGL
    
        return 0;
    }
    

    enter image description here

    基本上,我的手臂由肩、臂、肘、前臂和手组成。当肩部旋转时,所有这些组件也必须旋转。但是,当肘部旋转时,只有肘部、前臂和手是旋转的。

    有人告诉我,只需添加两个“旋转”句子(一个用于肩膀,一个用于肘部),就可以实现相同的功能,而不是像我对每个组件所做的那样。

    你知道怎么做吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Rabbid76    6 年前

    注意,该图纸 glBegin / glEnd 从几年前开始,序列就被弃用了。 了解 Fixed Function Pipeline Vertex Specification Shader 以最先进的方式呈现。


    但是如果你想这样做,那么你可以通过 glPushMatrix/glPupMatrix

    另请参见 OpenGL translation before and after a rotation

    如果将以下代码添加到 display

    void display() {
    
        // your original code
        ....  
    
        glLoadIdentity();
    
        move( 3.0, 0.0 )
    
        // rotate sholder
        rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);
    
        draw_sphere(0.5); // shoulder
        move(0.0, -1.5); 
        glPushMatrix();
        enlarge(2.0);                                     
        draw_cube(); //arm
        glPopMatrix();
    
        move(0.0, -1.5)
    
        // rotate elbow
        rotate(elbow_Xangle, elbow_Yangle, elbow_Zangle);
    
        draw_sphere(0.5); // elbow
        move(0.0, -1.5)  
        glPushMatrix();
        enlarge(2.0);  
        draw_cube();  // forearm
        glPopMatrix();
        move(0.0, -1.0)   
        rotateX(90);                  
        glutSolidCone(0.5, 1.5, 360, 360); // hand
    
        // Forzar renderizado
        glutSwapBuffers();                   
    }
    

    预览:


    在这种情况下 是需要的 glScalef enlarge )仅限操作。
    enlarge(2.0) 可以通过 enlarge(0.5) :

    // rotate sholder
    rotate(shoulder_Xangle, shoulder_Yangle, shoulder_Zangle);
    
    draw_sphere(0.5); // shoulder
    
    move(0.0, -1.5); 
    enlarge(2.0);                                     
    draw_cube(); //arm
    enlarge(0.5);
    
    move(0.0, -1.5)
    
    // rotate elbow
    rotate(elbow_Xangle, elbow_Yangle, elbow_Zangle);
    
    draw_sphere(0.5); // elbow
    
    move(0.0, -1.5)  
    enlarge(2.0);  
    draw_cube();  // forearm
    enlarge(0.5);
    
    move(0.0, -1.0)   
    rotateX(90);                  
    glutSolidCone(0.5, 1.5, 360, 360); // hand