2015-10-17 228 views
1

我试图做的速度乘以帧之间的时间的等价物。我会想象这样做的四元数将通过提高他们的权力来完成。我有代码来旋转基于我的鼠标移动的对象。它具有以一个帧速率运行的主循环和以固定帧速率运行的物理循环。下面是主回路的相关部分:如何缩放四元数的旋转

glfwPollEvents(); 
Input::update(); 
window.clear(0,0,0,1); 

rigidBody.angularVelocity *= glm::angleAxis(0.001f * Input::deltaMouse().x, glm::vec3(0,1,0)); 
rigidBody.angularVelocity *= glm::angleAxis(0.001f * Input::deltaMouse().y, glm::vec3(1,0,0)); 

if(Input::getKey(Input::KEY_A)) 
{ 
    rigidBody.velocity -= float(Time::getDelta()) * glm::vec3(1,0,0); 
} 
if(Input::getKey(Input::KEY_D)) 
{ 
    rigidBody.velocity += float(Time::getDelta()) * glm::vec3(1,0,0); 
} 
if(Input::getKey(Input::KEY_W)) 
{ 
    rigidBody.velocity -= float(Time::getDelta()) * glm::vec3(0,0,1); 
} 
if(Input::getKey(Input::KEY_S)) 
{ 
    rigidBody.velocity += float(Time::getDelta()) * glm::vec3(0,0,1); 
} 
if(Input::getKey(Input::KEY_LCONTROL)) 
{ 
    rigidBody.velocity -= float(Time::getDelta()) * glm::vec3(0,1,0); 
} 
if(Input::getKey(Input::KEY_LSHIFT)) 
{ 
    rigidBody.velocity += float(Time::getDelta()) * glm::vec3(0,1,0); 
} 

这里是物理环路的相关部分:

for(int i = 0; i < *numRigidBodies; i++) 
{ 
    rigidBodies[i].transform->getPos() += rigidBodies[i].velocity; 
    rigidBodies[i].transform->getRot() *= rigidBodies[i].angularVelocity; 
} 
rigidBodies[0].angularVelocity = glm::quat(); 
rigidBodies[0].velocity = glm::vec3(); 

这工作得很好,但是当我尝试提高角速度与GLM电源:: pow,对象随机旋转,不跟随我的鼠标。我意识到我可以用一行代码来做到这一点,如

rigidBodies[i].transform->getRot() *= glm::angleAxis((float)Time::getFixedDelta() * glm::angle(rigidBodies[i].angularVelocity), glm::axis(rigidBodies[i].angularVelocity)); 

但这似乎是不必要的复杂的任务。是什么导致这个问题,我该如何解决它?

+0

没有四元数的唯一平方根,或者实际上是一个旋转。 10度的旋转可以是5度的两次旋转或185度的两次旋转。两者在组成时产生10度的旋转。一般来说,k度旋转的第n根是x从0到n-1的x 360/n + k/n。我不知道你的图书馆在做什么,我只是指出这个数学模糊不清。 – Yakk

回答

1

不确定如何使用你正在使用的API来做到这一点,但基本上,你会使用Quaternion :: Slerp()。斯勒普的意思是“球面线性插值”。

是这样的(伪)应该工作:

auto& rot = rigidBodies[i].transform->getRot(); 

auto goal = rigidBodies[i].angularVelocity * rot; 
rot = rot.slerp(rot, goal, Time::deltaTime); 


编辑:
我要指出,这不是我会如何解决这个问题。我只是将旋转周围的X和Y轴作为标量存储起来,并从它们的每一帧构建一个新的四元数。

请原谅稀松伪代码:

// previous x and y positions, could probably be set in MouseDown event 
float lastX = ...; 
float lastY = ...; 

float xRotation = 0; 
float yRotation = 0; 

float rotationSpeed = 1.0; 

void OnMouseMove(float x, float y) { 
    float dx = x - lastX; 
    float dy = y - lastY; 
    lastX = x; 
    lastY = y; 

    xRotation += dy * rotationSpeed * Time::deltaTime; 
    yRotation += dx * rotationSpeed * Time::deltaTime; 

    rigidBodies[i].transform->getRot() = eulerQuat(xRotation, yRotation, 0); 
} 
+0

我很抱歉没有说我使用的是什么API。时间是我实施的课程,变革也是。我正在使用GLM数学库,这对此非常重要。我想避免x和y旋转因为欧拉角度,因为这应该适用于所有物理对象。 – msik314

+0

所以使用第一个解决方案 – bitwise

+0

该解决方案可以达到某个点,但是当我达到某个角速度以上时,它就会变得不稳定以及 – msik314

0

原来角速度通常表示为三维矢量,其中矢量是轴,幅度角速度。这行代码:

rigidBodies[i].transform->getRot() *= rigidBodies[i].angularVelocity; 

与此:

if(rigidBodies[i].angularVelocity != glm::vec3()) 
    rigidBodies[i].transform->getRot() *= glm::quat(rigidBodies[i].angularVelocity * float(Time::getFixedDelta())); 

与物理系统的正常工作。 if检查确保角速度不为0.