opengl - 使用向量而不是glulookat在球体周围旋转

时间:2013-05-18 11:39:52

标签: opengl rotation linear-algebra

我在绘制模型并使用鼠标旋转模型时遇到问题, 我很确定数学有问题但不确定。 物体只是以一种奇怪的方式旋转。 我希望对象从当前位置开始旋转每次单击而不是因为重置而重置 矢量现在已经改变,计算又重新开始。

void DrawHandler::drawModel(Model * model){
unsigned int l_index;
glClear(GL_COLOR_BUFFER_BIT |  GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW); // Modeling transformation
glLoadIdentity();
Point tempCross;
crossProduct(tempCross,model->getBeginRotate(),model->getCurrRotate());
float tempInner= innerProduct(model->getBeginRotate(),model->getCurrRotate());
float tempNormA =normProduct(model->getBeginRotate());
float tempNormB=normProduct(model->getCurrRotate());
glTranslatef(0.0,0.0,-250.0);
glRotatef(acos (tempInner/(tempNormA*tempNormB)) * 180.0 / M_PI,tempCross.getX(),tempCross.getY(),tempCross.getZ());
glColor3d(1,1,1);

glBegin(GL_TRIANGLES); 
for (l_index=0;l_index < model->getTrianglesDequeSize() ;l_index++)
{

    Triangle t = model->getTriangleByPosition(l_index);
    Vertex a1 = model->getVertexByPosition(t.getA());
    Vertex a2 = model->getVertexByPosition(t.getB());
    Vertex a3 = model->getVertexByPosition(t.getC());
    glVertex3f( a1.getX(),a1.getY(),a1.getZ()); 
    glVertex3f( a2.getX(),a2.getY(),a2.getZ());
    glVertex3f( a3.getX(),a3.getY(),a3.getZ());

}
glEnd();


}

这是保存旋转公式

的起始矢量的鼠标功能
    void Controller::mouse(int btn, int state, int x, int y)
{
    x=x-WINSIZEX/2;
    y=y-WINSIZEY/2;
    if (btn==GLUT_LEFT_BUTTON){
        switch(state){
        case(GLUT_DOWN):
            if(!_rotating){
                _model->setBeginRotate(Point(float(x),float(y),
                    (-float(x)*x - y*y + SPHERERADIUS*SPHERERADIUS < 0)? 0:float(sqrt(-float(x)*x - y*y + SPHERERADIUS*SPHERERADIUS))));
                _rotating=true;
            }
            break;
        case(GLUT_UP):
            _rotating=false;
            break;
        }
    }
}

最后是保存当前向量的以下函数。 (开始向量是单击鼠标的位置 并且curr向量是当前鼠标位置的位置)

void Controller::getMousePosition(int x,int y){
    x=x-WINSIZEX/2;
    y=y-WINSIZEY/2;
    if(_rotating){
        _model->setCurrRotate(Point(float(x),float(y),
            (-float(x)*x - y*y + SPHERERADIUS*SPHERERADIUS < 0)? 0:float(sqrt(-float(x)*x - y*y + SPHERERADIUS*SPHERERADIUS))));
    }
}

其中sphereradius是70度的球半径O_O

有任何计算错误吗?似乎无法找到问题...... 感谢

2 个答案:

答案 0 :(得分:1)

为什么这么复杂?您可以更改视图矩阵,也可以更改焦点对象的模型矩阵。如果您选择更改模型矩阵并且您的对象位于世界坐标系的(0,0,0)中心,则计算围绕球体旋转的旋转是微不足道的 - 您只需旋转到相反的方向。如果要更改视图矩阵(实际上在更改摄像机位置时已完成),则必须近似所选球体上的曲面点。因此,您可以引入两个指定两个角度的参数。每次单击移动鼠标时,都会更新参数并计算球体上的新位置。 [http://en.wikipedia.org/wiki/Sphere]中有一些有用的公式。

答案 1 :(得分:1)

在不知道您正在使用哪些库(或库)的情况下,您的代码难以阅读。您似乎正在设置相机(0,0,-250),朝向原点,然后围绕原点旋转两个矢量model->getCurrRotate()model->getBeginRotate()之间的角度。

问题似乎是在“鼠标按下”事件中你明确地将BeginRotate设置为鼠标下球体上的点,然后在“鼠标移动”事件中将CurrRotate设置为鼠标下方的点,所以每次你单击其他位置,您将失去先前的旋转状态,因为BeginRotate和CurrRotate只是被覆盖。

在任意不同的轴周围组合多个旋转不是一项简单的任务。正确的方法是使用四元数。您可能会发现this primer on quaternions and other 3D math concepts有用。

您可能还需要一种更强大的算法,用于将屏幕坐标转换为球体上的模型坐标。您正在使用的是假设球体在屏幕上显示半径为70像素,并且投影矩阵是正交的。