首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenGL中的旋转立方体

OpenGL中的旋转立方体
EN

Stack Overflow用户
提问于 2021-03-26 07:42:06
回答 2查看 548关注 0票数 2

我想要一个围绕中心旋转的立方体。这是我可以通过这个转变来做的事情:

代码语言:javascript
复制
model = glm::rotate(identity, glm::radians(-100.0f * time), glm::vec3(0.0, 1.0, 0.0)); //rotate around y-axis
model = glm::translate(model, glm::vec3(8.0, 0.0, 0.0));
model = glm::rotate(model, glm::radians(-100.0f * time), glm::vec3(1.0, 0.0, 0.0)); //self-rotation

现在我想要一个立方体,它围绕第一个立方体旋转,因为它是围绕y轴旋转的。假设第一个立方体是地球,第二个立方体是月球。我试过了,但没成功。

代码语言:javascript
复制
test = glm::rotate(test, glm::radians(-100.0f * time), glm::vec3(0.0, 1.0, 0.0));
test = glm::translate(test, glm::vec3(3.0, 0.0, 0.0));
test = glm::translate(test, glm::vec3(8.0, 0.0, 0.0));
test = glm::rotate(test, glm::radians(-100.0f * time), glm::vec3(0.0, 1.0, 0.0));
test = glm::translate(test, glm::vec3(-8.0, 0.0, 0.0));
test = glm::rotate(test, glm::radians(-100.0f * time), glm::vec3(1.0, 0.0, 0.0)); // self-rotation

知道我做错什么了吗?这是一张旋转的图片:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-03-27 10:19:01

您的评论建议您有以下操作顺序:

代码语言:javascript
复制
mvp = m_projection*m_view*m_model
vertex' = mvp*vertex

m_view是视图的逆矩阵,m_model是实际网格的直接矩阵。

因此,您应该设置m_projectionm_view一次,然后只更新m_model

我不使用GLM (有我自己的数学库),但是IIRC它们模仿旧的固定流水线矩阵数学。所以当我这么做的时候(C++/VCL/OpenGL/GLSL .我知道分数应该是VBO/VAO,我只是想要快速测试):

代码语言:javascript
复制
//---------------------------------------------------------------------------
//    ang   ,ang speed,body r,orbit r
//    [deg] ,[deg/s]   [unit],[unit]
float                  rs=1.0;          // star
float a0=0.0,da0= 50.0,r0=0.5,R0= 7.0;  // planet
float a1=0.0,da1=200.0,r1=0.2,R1= 1.0;  // moon
float a2=0.0,da2=250.0,r2=0.2,R2= 1.5;  // moon
float a3=0.0,da3= 20.0,r3=0.5,R3=10.0;  // planet
float a4=0.0,da4=150.0,r4=0.2,R4= 1.0;  // moon
float a5=0.0,da5=180.0,r5=0.2,R5= 1.5;  // moon
float b =0.0,db =50.0;                  // common self rotation
//---------------------------------------------------------------------------
void gl_draw()
    {
    GLint ix;
    GLfloat mp[16],mv[16],mm[16],m0[16];
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float aspect=float(xs)/float(ys);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0/aspect,aspect,0.1,100.0);
    glGetFloatv(GL_PROJECTION_MATRIX,mp);
    glMatrixMode(GL_TEXTURE);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0,0.0,-25.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mv);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glGetFloatv(GL_MODELVIEW_MATRIX,mm);

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_CULL_FACE);
//  glEnable(GL_CULL_FACE);

    // GLSL sphere shader
    glUseProgram(prog_id);
    ix=glGetUniformLocation(prog_id,"m_projection"); glUniformMatrix4fv(ix,1,false,mp);
    ix=glGetUniformLocation(prog_id,"m_view");       glUniformMatrix4fv(ix,1,false,mv);
    ix=glGetUniformLocation(prog_id,"m_model");

    // sun
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(1.0,1.0,0.0); glVertex4f(0.0,0.0,0.0,rs); glEnd();
    // planet
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRotatef(a0,0.0,0.0,1.0);
    glTranslatef(R0,0.0,0.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,m0);
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(0.0,0.7,1.0); glVertex4f(0.0,0.0,0.0,r0); glEnd();
    // moon
    glLoadMatrixf(m0);
    glRotatef(a1,0.0,0.0,1.0);
    glTranslatef(R1,0.0,0.0);
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(0.4,0.4,0.4); glVertex4f(0.0,0.0,0.0,r1); glEnd();
    // moon
    glLoadMatrixf(m0);
    glRotatef(a2,0.0,0.0,1.0);
    glTranslatef(R2,0.0,0.0);
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(0.4,0.4,0.4); glVertex4f(0.0,0.0,0.0,r2); glEnd();
    // planet
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glRotatef(a3,0.0,0.0,1.0);
    glTranslatef(R3,0.0,0.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,m0);
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(0.0,0.7,1.0); glVertex4f(0.0,0.0,0.0,r3); glEnd();
    // moon
    glLoadMatrixf(m0);
    glRotatef(a4,0.0,0.0,1.0);
    glTranslatef(R4,0.0,0.0);
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(0.4,0.4,0.4); glVertex4f(0.0,0.0,0.0,r4); glEnd();
    // moon
    glLoadMatrixf(m0);
    glRotatef(a5,0.0,0.0,1.0);
    glTranslatef(R5,0.0,0.0);
    glRotatef(b,0.0,0.0,1.0);
    glGetFloatv(GL_MODELVIEW_MATRIX,mm); glUniformMatrix4fv(ix,1,false,mm);
    glBegin(GL_POINTS); glColor3f(0.4,0.4,0.4); glVertex4f(0.0,0.0,0.0,r5); glEnd();

    glUseProgram(0);

    glFlush();
    SwapBuffers(hdc);
    }
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    // this is periodicaly called by timer
    gl_draw();
    float dt=0.001*float(Timer1->Interval); // timer period in seconds
    a0=fmod(a0+da0*dt,360.0);
    a1=fmod(a1+da1*dt,360.0);
    a3=fmod(a3+da3*dt,360.0);
    a4=fmod(a4+da4*dt,360.0);
    a5=fmod(a5+da5*dt,360.0);
    b =fmod(b +db *dt,360.0);
    }
//---------------------------------------------------------------------------

我得到了这个输出(使用我的球体着色器):

该着色器只将点x,y,z,r作为球体的三维中心和半径,发出BBOX四角和渲染内接球面的法线阴影。它还使用颜色和你的3个矩阵。

所以,如果我看得对,你应该这样做:

代码语言:javascript
复制
model = identity; 
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render star
model = identity; 
model = glm::rotate(model, glm::radians(a0), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(model, glm::vec3(R0, 0.0, 0.0));
model0= model;
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render planet
model = model0;
model = glm::rotate(model, glm::radians(a1), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(model, glm::vec3(R1, 0.0, 0.0));
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render moon
model = model0;
model = glm::rotate(model, glm::radians(a2), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(model, glm::vec3(R2, 0.0, 0.0));
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render moon
model = identity; 
model = glm::rotate(model, glm::radians(a3), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(model, glm::vec3(R3, 0.0, 0.0));
model0= model;
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render planet
model = model0;
model = glm::rotate(model, glm::radians(a4), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(model, glm::vec3(R4, 0.0, 0.0));
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render moon
model = model0;
model = glm::rotate(model, glm::radians(a5), glm::vec3(0.0, 1.0, 0.0));
model = glm::translate(model, glm::vec3(R5, 0.0, 0.0));
model = glm::rotate(model, glm::radians(b), glm::vec3(0.0, 1.0, 0.0));
// render moon

如果这是不起作用的,那么你得到的矩阵顺序和使用的数学或GLM之间的其他不匹配行为与我预期的不同。我用普通的角度来做自我旋转,所以你只需要为你的身体添加索引.

另外,请注意老的GL旋转使用[deg],所以如果GLM想要[rad],您需要转换角度和角速度常数。

如果您想拥有更精确的/与真实世界相关的东西,或者更好地直观地看到以下内容:

票数 2
EN

Stack Overflow用户

发布于 2021-03-26 21:53:29

对象A围绕B级旋转:A的自旋转,A到B的偏移,B的旋转,B的位置平移。因为B是太阳,我假设它在你们的世界起源,而且所有东西都在xz平面上(笛卡尔而不是OpenGL弦),这就是:

代码语言:javascript
复制
model = glm::rotate(identity, glm::radians(-100.0f * time), glm::vec3(1.0, 0.0, 0.0)); //self-rotation
model = glm::translate(model, glm::vec3(8.0, 0.0, 0.0)); // earth is 8 away from sun, where unrotated about sun is 8 units east
model = glm::rotate(model, glm::radians(-100.0f * time), glm::vec3(0.0, 1.0, 0.0)); //rotate about sun
// no need for another translation since sun is at origin

然后,对于父为地球的对象,在解决父对象与世界的关系之前,首先解决该关系:

代码语言:javascript
复制
model = glm::rotate(identity, glm::radians(-100.0f * time), glm::vec3(1.0, 0.0, 0.0)); //self-rotation of moon
model = glm::translate(model, glm::vec3(-4.0, 0.0, 0.0)); // moon is 4 away from Earth, where unrotated about Earth is 4 units west
model = glm::rotate(model, glm::radians(-100.0f * time), glm::vec3(0.0, 1.0, 0.0)); //rotate about Earth
// translate to Earth origin, which is calculate from above code block

免责声明,我不使用glm-数学,这只是几何转换的顺序,我不知道它是否直接翻译成glm::x

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66812765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档