【问题标题】:Getting a node in a node hierarchy to face the camera (billboard)让节点层次结构中的节点面向相机(广告牌)
【发布时间】:2013-06-19 22:24:12
【问题描述】:

我需要使节点层次结构中的一个节点面向相机,或者换句话说,成为一个广告牌。 对于每个节点,我将其世界矩阵和世界旋转存储为四元数。 根据我对四元数的了解,我想要的操作是获取相机四元数和节点旋转四元数之间的差异,并通过所述差异简单地旋转节点。

我的相机存储为欧拉角,所以我通过首先创建 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);
}

我犯了什么明显的错误吗?

【问题讨论】:

    标签: javascript quaternions rotational-matrices euler-angles


    【解决方案1】:

    你的假设是错误的:

    我想要的操作是获取相机之间的差异 四元数和节点的旋转四元数,并简单地旋转 所述差异的节点。

    如果您正确地执行此操作,它应该会导致您的节点朝向与相机朝向相同的方向。这与实际面对相机完全不同。

    您需要的是在世界空间中找到面向相机位置的变换。您可能会受益于对gluLookAt() 的一些快速研究。

    【讨论】:

    • 我不敢相信我竟然忽略了这一点。关于查看矩阵,我不能在这里使用它们,因为节点受节点层次结构的其余部分影响,我不能只用查看矩阵替换它们的转换,否则它们将无法工作,因为它们工作基于您有一些固定的轴对齐方向这一事实。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多