1

ノード階層内のノードをカメラに向ける、つまりビルボードにする必要があります。すべてのノードについて、そのワールド マトリックスとワールドの回転をクォータニオンとして保存します。私がクォータニオンについて知っていることにより、私が望む操作は、カメラのクォータニオンとノードの回転クォータニオンの差を取得し、その差によってノードを単純に回転させることです。

私のカメラはオイラー角として保存されているので、最初に X 軸の回転を作成し、次に Z 軸の回転 (Y 軸の回転はありません) を作成し、それらを乗算してカメラのクォータニオンを作成します。

そこから、差を取得し、最終的にそこから回転マトリックスを作成し、それをノードのワールド マトリックスに乗算するための計算を行うだけです。

ただし、これにより、ノードが狂ったように回転し、カメラに面しなくなります。

関連する JavaScript コードは次のとおりです。

// If there is a parent, multiply both world matrix and rotation by it
// localMatrix here is the current local matrix of the node
// rotation here is the local rotation quaternion
if (node.parent) {
    math.Mat4.multMat(node.parent.worldMatrix, localMatrix, node.worldMatrix);
    math.Quaternion.concat(node.parent.worldRotation, rotation, node.worldRotation);
} else {
    node.worldMatrix = localMatrix;
    node.worldRotation = rotation.copy();
}

// And here the mess begins
if (node.billboarded) {
    var cameraX = [];
    var cameraZ = [];
    var camera = [];

    // transform.rotation is my camera's rotation stored as 3 euler angles,
    // but I am not using the Y-axis for now
    math.Quaternion.setFromAxisAngle([1, 0, 0], transform.rotation[0], cameraX);
    math.Quaternion.setFromAxisAngle([0, 0, 1], transform.rotation[2], cameraZ);
    math.Quaternion.concat(cameraX, cameraZ, camera);

    // The current rotation on the node
    var initial = node.worldRotation.copy();

    // Need to reverse it, since the difference is camera * -initial
    math.Quaternion.conjugate(initial, initial);

    var difference = [];

    math.Quaternion.concat(camera, initial, difference);

    var rotationMatrix = [];

    math.Quaternion.toRotationMatrix4(difference, rotationMatrix);

    var finalMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];

    // pivot is the node's position, need to keep the rotation in local space
    math.Mat4.translate(finalMatrix, pivot[0], pivot[1], pivot[2]);
    math.Mat4.multMat(finalMatrix, rotationMatrix, finalMatrix);
    math.Mat4.translate(finalMatrix, -pivot[0], -pivot[1], -pivot[2]);

    // And finally actually rotate the node
    math.Mat4.multMat(node.worldMatrix, finalMatrix, node.worldMatrix);
}

私が犯している明らかな間違いはありますか?

4

1 に答える 1

0

あなたの仮定は間違っています:

私が望む操作は、ノードのカメラ四元数と回転四元数の差を取得し、その差だけノードを回転させることです。

これを正しく行った場合、ノードはカメラが向いている方向と同じ方向を向くはずです。これは、実際にカメラを向いているのとはかなり異なります。

必要なのは、ワールド空間でカメラの位置に面する変換を見つけることです。gluLookAt()に関する簡単な調査が役立つ場合があります。

于 2013-06-24T14:36:39.030 に答える