0

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

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

最后是保存当前向量的以下函数。(起始向量是鼠标点击的位置,当前向量是鼠标当前的位置)

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

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

4

2 回答 2

1

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

于 2013-05-18T16:53:07.100 回答
1

如果不知道您正在使用什么库(或库),您的代码很难阅读。看来您将相机设置在 (0, 0, -250),朝向原点,然后围绕原点旋转两个向量之间的角度,model->getCurrRotate()然后model->getBeginRotate().

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

围绕任意不同的轴组合多次旋转并不是一项简单的任务。正确的方法是使用四元数。您可能会发现这本关于四元数和其他 3D 数学概念的入门非常有用。

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

于 2013-05-18T17:26:21.847 回答