围绕绝对轴旋转 3d 模型

Posted

技术标签:

【中文标题】围绕绝对轴旋转 3d 模型【英文标题】:rotate 3d model around absolute axes 【发布时间】:2013-03-11 09:46:26 【问题描述】:

我不知道如何将鼠标拖动转换为围绕图像平面的 Ox 和 Oy 旋转。 我遵循here 的第一个答案,并将模型视图矩阵存储在一个数组中,并在每次鼠标移动时更新它。 alphabeta 与鼠标从前一个位置的增量成正比。

此代码在鼠标移动时更新旋转:

glLoadMatrixf(currentModelViewMatrix);
glRotatef(beta,0,1,0);
glRotatef(alpha,1,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);

我尝试了this 解释末尾的解决方案,但没有任何区别。

只有beta 给出的旋转是绝对的,alpha 给出的旋转是围绕模型中的一个轴,当围绕第一个轴旋转时它会转动。我不知道如何使第二次旋转是绝对的。现在的方式对用户来说似乎并不直观。


编辑: 增量代码:

GLfloat currentModelViewMatrix[16];
GLfloat whole[16];
void glob()
 
  glLoadIdentity();
  glRotatef(beta,0,1,0);
  glRotatef(alpha,1,0,0);
  glMultMatrixf(currentModelViewMatrix);
  glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix); 

  glLoadIdentity();
  glTranslatef(0,0,-20);
  glMultMatrixf(currentModelViewMatrix);
  glGetFloatv(GL_MODELVIEW_MATRIX,whole); 

  alpha=beta=0;

在每个模型之前,都会加载矩阵:

glLoadMatrixf(whole);

完整代码:

#include "math.h"
#include "string.h"
#include "stdio.h"
#include "GL/freeglut.h"
#include "GL/gl.h"
#include "GL/glu.h"
float alpha,beta;

void key(int key, int x, int y)
   printf("%d",key);
    switch(key)
       case GLUT_KEY_RIGHT:
            printf("right\n");
            break;
        case GLUT_KEY_LEFT:
            printf("left\n");
            break;
        case GLUT_KEY_UP:
            printf("top\n");
            break;
        case GLUT_KEY_DOWN:
            printf("bottom\n");
            break;
    
    glutPostRedisplay();
    fflush(stdout); 


void otherkeys(unsigned char key,int x,int y)
   printf("%c\n",key);
    fflush(stdout);
    switch(key)
       case '+':
            printf("plus\n");
            break;
        case '-':
            printf("minus\n");
            break;
        case 'w':
                alpha+=10;
            break;
        case 's':
                alpha-=10;
            break;
        case 'd':
                beta+=10;
            break;
        case 'a':
                beta-=10;
            break;
    
    glutPostRedisplay();

void drawCube()
   int i,j,d;
    glBegin(GL_LINES);
        for(i=0;i<8;i++)
           for(j=i+1;j<8;j++)
               d=j^i;
                if(d==1||d==2||d==4)
                   glVertex3i(i%2,i/2%2,i/4%2 );   
                    glVertex3i(j%2,j/2%2,j/4%2 );   
                                   
            
        
    glEnd();


GLfloat currentModelViewMatrix[16];
GLfloat whole[16];
void glob()
   
    glLoadIdentity();
    glRotatef(beta,0,1,0);
    glRotatef(alpha,1,0,0);
    glMultMatrixf(currentModelViewMatrix);
    glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);   

    glLoadIdentity();
    glTranslatef(0,0,-20);
    glMultMatrixf(currentModelViewMatrix);
    glGetFloatv(GL_MODELVIEW_MATRIX,whole); 

    alpha=beta=0;

void renderFunction()
   int i;
    glClearColor(0.0,0.0,0.0,0.0);
    glClear(GL_COLOR_BUFFER_BIT);   
    glColor3f(1.0,1.0,1.0); 
    glMatrixMode(GL_PROJECTION); 
        glLoadIdentity();
//              glRotatef(angle2,0.0,0.0,1.0);
        gluPerspective(60, 1.333, 0.1, 100);

    glMatrixMode(GL_MODELVIEW);

    glColor3f(1.0,0.0,0.0); 
    for(i=1;i<8;i++)
       
        glLoadMatrixf(whole);   
        glTranslatef(i*2.0,0,0);
        drawCube();
    

    glColor3f(0.0,1.0,0.0); 
    for(i=1;i<6;i++)
    
        glLoadMatrixf(whole);   
        glTranslatef(0,i*2.0,0);
        drawCube();
    

    glColor3f(0.0,0.0,1.0); 
    for(i=0;i<5;i++)
    
        glLoadMatrixf(whole);   
        glTranslatef(0,0,i*2.0);
        drawCube();
    

    glFlush();


/*mouse*/
int prevx,prevy,dx,dy;
void rotate(int dx,int dy)
   printf("%f %f\n",dy/10.0,dy/10.0);
    alpha=dy/2.0;
    beta=dx/2.0;
    glob();


void passive(int x,int y)
   prevx=x;prevy=y;

void active(int x,int y)
   dx=x-prevx;
    prevx=x;
    dy=y-prevy;
    prevy=y;
    rotate(dx,dy);


void globinit()

    glLoadIdentity();
    glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);   

    glLoadIdentity();
    glTranslatef(0,0,-20);
    glGetFloatv(GL_MODELVIEW_MATRIX, whole);    

int main (int argc, char* argv[])
       
    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE);
    glutInitWindowSize(800,600);
    glutInitWindowPosition(100,100);
    glutCreateWindow("Open GL bla bla");
    glutDisplayFunc(renderFunction);
    glutIdleFunc(renderFunction);
    glutSpecialFunc(key);
    glutKeyboardFunc(otherkeys);
    glutMotionFunc(active);
    glutPassiveMotionFunc(passive);
    globinit();
    glutMainLoop(); 
    return 0;

【问题讨论】:

【参考方案1】:

尝试以下方法:

glLoadIdentity();
glRotatef(beta,0,1,0);
glRotatef(alpha,1,0,0);
glMultMatrixf(currentModelViewMatrix);
glGetFloatv(GL_MODELVIEW_MATRIX, currentModelViewMatrix);

由于顺序改变,旋转是在全局坐标系而不是局部坐标系中执行的。

【讨论】:

谢谢,翻译效果很好,不会绕原点旋转

以上是关于围绕绝对轴旋转 3d 模型的主要内容,如果未能解决你的问题,请参考以下文章

围绕特定轴动画qt3d旋转

three.js 在它的中心围绕 Y 轴旋转 Object3d

仅在绘图中围绕 z 轴旋转

如何使用 3D 中的变换矩阵围绕 Z 轴旋转?

围绕绝对世界轴检索四元数角度

如何围绕节点的 Y 轴旋转 SKSpriteNode?