OpenGL手臂旋转肩膀和肘部 [英] OpenGL Arm that rotates shoulder and elbow

查看:107
本文介绍了OpenGL手臂旋转肩膀和肘部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了以下代码:

  #include< math.h>#include< GL/gl.h>#include< GL/glu.h>#include< GL/glut.h>#定义宽度400#定义HEIGTH 400#定义ORIGIN_X 50#定义ORIGIN_Y 50#定义move(x,y)glTranslatef(x,y,0.0f);#定义delete(y)glScalef(1,y,1);#定义rotateX(角度)glRotatef(角度,1,0,0);#定义rotateY(角度)glRotatef(角度,0,1,0);#定义rotateZ(角度)glRotatef(角度,0,0,1);//变量变量定义输入变量(de hombro a mano)静态GLfloat肩膀X角度,肩膀Y角度,肩膀Z角度;//定义为sólolarotacióndel antebrazo(de codo a mano)的变量静态GLfloat elbow_Xangle,elbow_Yangle,elbow_Zangle;void keyboardHandler(unsigned char key,int x,int y){开关(键){案例'q':肩膀_角++;休息;案例'e':休息;情况'a':休息;案例``d'':休息;例'w':肩膀Xangle ++;休息;案例's:Shoulder_Xangle--;休息;案例'r':elbow_Zangle ++;休息;例'y':elbow_Zangle--;休息;案例'f':elbow_Yangle ++;休息;案例'h':elbow_Yangle--;休息;案例't':elbow_Xangle ++;休息;案例'g':elbow_Xangle--;休息;默认值:break;}glutPostRedisplay();//Avisa que la ventana ha de refrescarse}无效的init(){glutKeyboardFunc(keyboardHandler);//事件处理程序的事件处理程序del tecladoglClearColor(0.0,0.0,0.0,0.0);//从黑色到黑色格式的RGBA颜色}无效旋转(GLfloat Xangle,GLfloat Yangle,GLfloat Zangle){rotationX(Xangle);//Rotar Xangle Grados Sobre el eje XrotationY(Yangle);//Rotar Yangle Grados Sobre el eje YrotationZ(Zangle);//Rotar Zangle grados sobre el eje Z}void draw_sphere(GLdouble radius){GLint切片= 360;GLint堆栈= 360;glutWireSphere(半径,切片,堆栈);}void draw_cube(){glBegin(GL_QUADS);glColor3f(0.0,0.7,0.1);//前面的方:佛得角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:rojoglVertex3f(-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:布兰科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)最终版本旋转(elbow_Xangle,elbow_Yangle,elbow_Zangle);//2)Rotamiento del cododraw_sphere(0.5);//1)Dibujar 1 esfera(codo)}void draw_arm(){移动(0.0,-1.5);//3)总决赛放大(2.0);//2)Escalar el brazodraw_cube();//1)Dibujar 1 cubo(brazo)}void draw_forearm(){move(0.0,-3.0);//5)最终决赛旋转(elbow_Xangle,elbow_Yangle,elbow_Zangle);//4)Rotamiento del codo移动(0.0,-1.5);//3)Mover hacia abajo para que el radio derotación=tamañocodo放大(2.0);//2)Escalar el antebrazodraw_cube();//1)Dibujar 1 cubo(antebrazo)}void draw_hand(){move(0,-3.0);//4)最终决赛旋转(elbow_Xangle,elbow_Yangle,elbow_Zangle);//3)Rotamiento del codomove(0.0,-2.5)//2)移动器hacia abajo eltamañodel codo + antebrazo =(1.0 + 2.0)-0.5rotationX(90);//1)Poner la mano en su sitioglutSolidCone(0.5,1.5,360,360);}无效的display(){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//Borrado del FrameBufferglEnable(GL_DEPTH_TEST);glLoadIdentity();//卡尔加·拉·马特里斯(cargar la matriz)旋转(shoulder_Xangle,肩膀_Yangle,肩膀_Zangle);//Movimiento del hombrodraw_shoulder();//Dibujar el hombroglLoadIdentity();旋转(shoulder_Xangle,肩膀_Yangle,肩膀_Zangle);//Movimiento del hombrodraw_arm();//Dibujar el BrazoglLoadIdentity();旋转(shoulder_Xangle,肩膀_Yangle,肩膀_Zangle);//Movimiento del hombrodraw_elbow();//Dibujar el codoglLoadIdentity();旋转(shoulder_Xangle,肩膀_Yangle,肩膀_Zangle);//Movimiento del hombrodraw_forearm();//Dibujar el antebrazoglLoadIdentity();旋转(shoulder_Xangle,肩膀_Yangle,肩膀_Zangle);//Movimiento del hombrodraw_hand();//Dibujar la mano//Forzar renderizadoglutSwapBuffers();}void reshape(int w,int h){glViewport(0,0,(GLsizei)w,(GLsizei)h);glMatrixMode(GL_PROJECTION);//墨西哥的Activar las modificaciones en lacámaraglLoadIdentity();glOrtho(-8,8,-12,4,-8,8);glMatrixMode(GL_MODELVIEW);//模型活动}int main(int argc,char ** argv){glutInit(& argc,argv);//Cargar el teclado y elrátonglutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);//Búfferdoble,同色RGB和profundidadglutInitWindowSize(WIDTH,HEIGTH);//Tamañode la ventanaglutInitWindowPosition(ORIGIN_X,ORIGIN_Y);//Posicióndel extremo superior-izquierdo de la ventanaglutCreateWindow("Brazo Articulado");//Crear la ventana在里面();glutDisplayFunc(显示);//平塔多活动博物馆glutReshapeFunc(reshape);//活动电子报glutMainLoop();//OpenGL的Arrancar el bucle de返回0;} 

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

出于无知,要实现这一目标,我基本上为手臂的每个组件都放置了肩部旋转",为最后三个组件放置了肘部旋转",如您在显示功能和我的"draw_component"函数.

有人告诉我您可以通过添加2个旋转"语句(一个用于肩膀,一个用于肘部)来实现相同的功能,而不是像我对每个单个组件所做的那样.

有什么想法可以做到吗?

解决方案

请注意,从 glBegin / glEnd 序列开始绘制已过了几年.阅读有关


在这种情况下, glPushMatrix/glPupMatrix 仅用于 glScalef ( enlarge )操作.
除了推动和弹出矩阵,您还可以执行逆运算.这意味着 enlarge(2.0)可以通过 enlarge(0.5)反转:

 //旋转支架旋转(shoulder_Xangle,肩膀_Yangle,肩膀_Zangle);draw_sphere(0.5);//肩膀移动(0.0,-1.5);放大(2.0);draw_cube();//手臂放大(0.5);移动(0.0,-1.5)//旋转肘部旋转(elbow_Xangle,elbow_Yangle,elbow_Zangle);draw_sphere(0.5);//肘部移动(0.0,-1.5)放大(2.0);draw_cube();//前臂放大(0.5);移动(0.0,-1.0)rotationX(90);glutSolidCone(0.5,1.5,360,360);//手 

I've made the following code:

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

Basically, I have an arm made up of a shoulder, arm, elbow, forearm and hand. When the shoulder rotates, all those components have to rotate aswell. However, when the elbow rotates, only the elbow, the forearm and the hand are the ones that rotate.

From my ignorance, to achieve this, I've basically put a "shoulder rotate" for every single component of my arm, and an "elbow rotate" for my last 3 components, as you can see in my display function and my "draw_component" functions.

I've been told you can achieve the same functionality by just adding 2 "rotate" sentences (one for the shoulder and one for the elbow), and not like I did for every single component.

Any ideas how could this be made?

解决方案

Note, that 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 if you want to do it like this, then you can push and pop matrices to the matrix stack by glPushMatrix/glPupMatrix.
If you want to imagine how the matrix operations change the model, then you need to "read" the operations in the reverse order. This is, because the current matrix of the matrix stack is multiplied by the matrix which is specified by the new operation and the matrices are stored in column-major order (fixed function pipeline).
See also OpenGL translation before and after a rotation

If you add the following code to the display function, then you get a second arm, which behaves the same as the first:

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();                   
}

Preview:


In this case the glPushMatrix/glPupMatrix is needed for the glScalef (enlarge) operation only.
Instead of push and pop the matrix you can do the inverse operation too. This means enlarge(2.0) can be reversed by 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 

这篇关于OpenGL手臂旋转肩膀和肘部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆