围绕错误的轴旋转

时间:2016-04-18 23:36:23

标签: c++ opengl rotation opengl-4 glm-math

我正在尝试围绕太空中的某个点旋转相机,如下所示:

Rotating around an object

红点通常会成为物体的中心。

用户可以用鼠标旋转相机,垂直移动应垂直旋转(x轴),水平旋转(y轴)。

我想要什么

到y轴的旋转始终是摄像机的明显 y轴,与x相同。例如,如果用户向上移动鼠标,它应该总是看起来像是在向上移动并超过相机所关注的对象。如果用户从左向右移动鼠标,它应该看起来像是在y轴上旋转(或者相机在y轴上移动)。

因此,如果用户将鼠标向左移动一点,然后开始向上移动,它应该仍然看起来像是从新视角越过对象的顶部,而不是沿着世界的实际x轴。

这在我使用过的大多数3D软件中都是标准的。例如。

我尝试了什么

在这里有很多问题的帮助下,我已经非常接近我想要的东西,但并不完全。

对于以下代码位:view_是4x4视图矩阵,origin_将是我们正在旋转的图片中的点,position_是蓝色线表示相机离原点(或任何相机平移,但尚未实现)的距离的图像,pitchyawroll是我们想要的数量旋转(在这种情况下,滚动始终为零)。

到目前为止,我最好的结果是:

// rotation_ is a vec3 here
rotation_ += glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll) );
glm::mat4 rot = glm::rotate( glm::mat4(1.0f), rotation_.x, glm::vec3(1.0f, 0.0f, 0.0f) );
rot = glm::rotate( rot, rotation_.y, glm::vec3(0.0f, 1.0f, 0.0f) );
rot = glm::rotate( rot, rotation_.z, glm::vec3(0.0f, 0.0f, 1.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot,  origin_);

关闭,但沿x轴旋转约90度会导致围绕y轴的进一步旋转出现绕z轴。我似乎无法用y轴到x轴复制这个,所以我很好奇这是否实际上是万向节锁或其他东西。

为了解决这个问题,我尝试将rotation_存储为四元数,然后像这样进行旋转:

// rotation_ is a quaternion here.
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
glm::vec3(1.0f, 0.0f, 0.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot,  origin_);

这实际上更糟糕。看起来我总是沿着世界的轴而不是相机的方向旋转,这不是我想要的。

当向上/向下移动鼠标时,如何使相机始终看起来像是垂直旋转,而当向左/向右移动时,总是看起来像是水平旋转?

1 个答案:

答案 0 :(得分:3)

我正在以错误的顺序组合我的四元数!

public class Ellipse {
    private double area;
    private double axis1;
    private double axis2;

    public Ellipse() {
        area = 0;
    }

    public Ellipse (double axis1, double axis2) {
        this.axis1 = axis1;
        this.axis2 = axis2;
    }

    public void calculateArea() {
        area += axis1 * axis2;
    }

    public double getArea() {
        return area;
    }
}

public class Circle extends Ellipse {
    private double radius;
    private double area;

    public Circle(){
        area = 0;
    }

    public Circle(double radius) {
        super(radius, radius);
    } 

    public double getArea() {
        return area;
    }
}

public class Driver {
    public static void main (String args[]) {
        Ellipse ellipse = new Ellipse(10, 20);
        ellipse.calculateArea();
        Circle circle = new Circle(50);
        circle.calculateArea();
        System.out.println("Area of Circle is : " + ellipse.getArea());
        System.out.println("Area of Circle is : " + circle.getArea());
    }
 }

该行

// rotation_ is a quaternion here.
rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));
glm::vec3(1.0f, 0.0f, 0.0f) );
view_ = glm::translate(glm::translate( glm::mat4(1.0f), position_ ) * rot,  origin_);

应该是

rotation_ *= glm::fquat(glm::vec3(glm::radians(pitch), glm::radians(yaw), glm::radians(roll)));

像这样,四元数解决方案就像我预期的那样工作。

如果我理解正确,这是因为我想首先旋转到新的增量旋转,然后将旧的旋转添加到它。这样我就可以先将新旋转应用到摄像机的轴上,然后再考虑其余的旋转。

反之这样做会让它旋转到旧的旋转,然后将新的旋转添加到该旋转,这会导致新的旋转不会按照我期望的方向应用。