1

glm :: quaternionsを使用して、特定の軸を中心にベクトルを回転させています。ただし、ベクトルは呼び出されるたびに軸を反転します。

オブジェクトを横軸を中心に回転させるコードは次のとおりです。

void PlayerController::rotateForward(float angle) {
    angle = (angle*M_PI) / 180.0f;
    fquat rot = fquat(angle, playerObject->getVecSide());
    normalize(rot);
    vec4 newUpVec = rot * vec4(playerObject->getVecUp(), 1.0f);
    normalize(newUpVec);
    vec3 upVec3 = normalize(vec3(newUpVec.x ,newUpVec.y, newUpVec.z));

    playerObject->setVecUp(upVec3);
    playerObject->setVecForward(-normalize(cross(playerObject->getVecUp(), playerObject->getVecSide())));
    vec3 newPlayerPos = currentPlanet->getPosition() + (playerObject->getVecUp() * radius);
    playerObject->setPosition(newPlayerPos);
}

このメソッドを呼び出すたびに、上向きのベクトルが軸を中心に回転しますが、反転します。これを回避するには、次を使用します。

    vec4 newUpVec = rot * -vec4(playerObject->getVecUp(), 1.0f);

しかし、これは原因を見つけるのではなく、症状を治療するようなものです。たぶん、このあたりの誰かが、クォータニオンがここで何をしているのかを理解するのを手伝ってくれるでしょう。

4

1 に答える 1

1

ここに答えがあります。クォータニオンの初期化が間違っていました...

これらの行がありませんでした:

rotateAround = rotateAround * sinf(angle/2.0f);
angle = cosf(angle/2.0f);

メソッドの正しいバージョンは次のようになります。

vec3 GameObjectRotator::rotateVector(float angle, vec3 toRotate, vec3 rotateAround) {
    angle = (angle*M_PI) / 180.0f;

    rotateAround = rotateAround * sinf(angle/2.0f);
    angle = cosf(angle/2.0f);

    fquat rot = fquat(angle, rotateAround);
    normalize(rot);
    vec4 rotated =  rot * vec4(toRotate, 1.0f);
    normalize(rotated);
    return normalize(vec3(rotated));
}

(クラスは最初のバージョンからかなりのリファクタリングを経てきましたが、アイデアはとにかく明確なはずです)

于 2012-06-06T00:35:50.527 に答える