我有一个非常基本的相机生成3个矢量用于gluLookAt(...)
问题是我不确定这是否正确,我改编自我的讲师向我们展示的代码(我认为他是从某处)。
这实际上有效,直到你将鼠标旋转成圆圈而不是相机开始围绕z轴旋转。这不应该发生,因为鼠标坐标仅连接到俯仰和偏航而不是滚动。
相机
// Camera.hpp
#ifndef MOOT_CAMERA_INCLUDE_HPP
#define MOOT_CAMERA_INCLUDE_HPP
#include <GL/gl.h>
#include <GL/glu.h>
#include <boost/utility.hpp>
#include <Moot/Platform.hpp>
#include <Moot/Vector3D.hpp>
namespace Moot
{
class Camera : public boost::noncopyable
{
protected:
Vec3f m_position, m_up, m_right, m_forward, m_viewPoint;
uint16_t m_height, m_width;
public:
Camera()
{
m_forward = Vec3f(0.0f, 0.0f, -1.0f);
m_right = Vec3f(1.0f, 0.0f, 0.0f);
m_up = Vec3f(0.0f, 1.0f, 0.0f);
}
void setup(uint16_t setHeight, uint16_t setWidth)
{
m_height = setHeight;
m_width = setWidth;
}
void move(float distance)
{
m_position += (m_forward * distance);
}
void addPitch(float setPitch)
{
m_forward = (m_forward * cos(setPitch) + (m_up * sin(setPitch)));
m_forward.setNormal();
// Cross Product
m_up = (m_forward / m_right) * -1;
}
void addYaw(float setYaw)
{
m_forward = ((m_forward * cos(setYaw)) - (m_right * sin(setYaw)));
m_forward.setNormal();
// Cross Product
m_right = m_forward / m_up;
}
void addRoll(float setRoll)
{
m_right = (m_right * cos(setRoll) + (m_up * sin(setRoll)));
m_right.setNormal();
// Cross Product
m_up = (m_forward / m_right) * -1;
}
virtual void apply() = 0;
}; // Camera
} // Moot
#endif
更新周期的片段
// Mouse movement
m_camera.addPitch((float)input().mouseDeltaY() * 0.001);
m_camera.addYaw((float)input().mouseDeltaX() * 0.001);
摄像机类中的apply()是在一个继承的类中定义的,该类是从游戏循环的draw函数调用的。
void apply()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(40.0,(GLdouble)m_width/(GLdouble)m_height,0.5,20.0);
m_viewPoint = m_position + m_forward;
gluLookAt( m_position.getX(), m_position.getY(), m_position.getZ(),
m_viewPoint.getX(), m_viewPoint.getY(), m_viewPoint.getZ(),
m_up.getX(), m_up.getY(), m_up.getZ());
}
答案 0 :(得分:1)
不要在矢量中累积变换,存储角度并动态生成矢量。
编辑:浮点稳定性。比较a
和b
的输出:
#include <iostream>
using namespace std;
int main()
{
const float small = 0.00001;
const unsigned int times = 100000;
float a = 0.0f;
for( unsigned int i = 0; i < times; ++i )
{
a += small;
}
cout << a << endl;
float b = 0.0f;
b = small * times;
cout << b << endl;
return 0;
}
输出:
1.00099
1
答案 1 :(得分:0)
我不知道从哪里开始,因为您只发布小片段,不足以完全重现问题。
在您的方法中,您更新所有参数,您的参数取决于以前的值。我不确定你到底打的是什么,因为你发布的是你只打电话给这两个人:
m_camera.addPitch((float)input().mouseDeltaY() * 0.001);
m_camera.addYaw((float)input().mouseDeltaX() * 0.001);
你应该以某种方式通过添加新参数来打破那个圆圈,输出应该取决于输入(例如,m_position不应该依赖于m_forward)。
你还应该初始化构造函数中的所有变量,我看到你只是初始化m_forward,m_right和m_up(顺便说一下,使用初始化列表)。
答案 2 :(得分:0)
您可能需要重新考虑您的方法,转而使用quaternion rotations中所述的this paper。这样做的好处是可以将所有累积的旋转表示为围绕单个矢量的单个旋转(仅需要跟踪单个四元数),您可以将其应用于描述摄像机方向的规范方向向量(向上,向范围和向右) 。此外,由于您使用的是C ++,因此可以使用Boost quaternion class来管理大部分数学。