1

XR_EXT_hand_tracking拡張XrHandJointLocationEXTからの配列によって指定された位置に基づいて、3D 空間で手のモデルをレンダリングしようとしています。XrHandJointEXT列挙型の OpenXR 仕様で定義されたジョイントに一致する正しい量のボーンを持つ Valve の両方のGTLF ハンド モデルを使用しています。

私は次のようにレンダリングを行います:

フレームごとに、現在の変換に GLTF モデルから取得した逆バインド マトリックスを乗算することで、各ジョイントを個別に更新します。はXrPosef、3D 空間の中心に相対的です。すべての行列計算を処理するためにcglmを使用しています。

for (size_t i = 0; i < XR_HAND_JOINT_COUNT_EXT; ++i) {
    const XrHandJointLocationEXT *joint = &locations->jointLocations[i];
    const XrPosef *pose = &joint->pose;

    glm_mat4_identity(model->bones[i]);

    vec3 position;
    wxrc_xr_vector3f_to_cglm(&pose->position, position);
    glm_translate(model->bones[i], position);

    versor orientation;
    wxrc_xr_quaternion_to_cglm(&pose->orientation, orientation);
    glm_quat_rotate(model->bones[i], orientation, model->bones[i]);

    glm_mat4_mul(model->bones[i], model->inv_bind[i], model->bones[i]);
}

次に、HMD ごとに計算されbonesた行列と共に、配列が頂点シェーダーにアップロードされます。view-projeye

#version 320 es"

uniform mat4 vp;
uniform mat4 bones[26];

layout (location = 0) in vec3 pos;
layout (location = 1) in vec2 tex_coord;
layout (location = 2) in uvec4 joint;
layout (location = 3) in vec4 weight;

out vec2 vert_tex_coord;

void main() {
    mat4 skin =
        bones[joint.x] * weight.x +
        bones[joint.y] * weight.y +
        bones[joint.z] * weight.z +
        bones[joint.w] * weight.w;
    gl_Position = vp * skin * vec4(pos, 1.0);
    vert_tex_coord = tex_coord;
}

計算方法は正しいですか?まともな結果が得られますが、「グリッチ」があります。次のスクリーンショットでわかるように、手のモデルの上に両方の独立したジョイントをレンダリングしました。親指に不具合が見られます。

スクリーンショット

ボーン トランスフォームを計算するとき、親ボーンを考慮する必要がありますか?

4

1 に答える 1

0

最終的に私の問題に対する答えが見つかりました: GTLF モデルからのジョイントの順序がXrHandJointEXTの順序と一致しないため、正しい変換が間違ったジョイントに適用されます。

私の場合、私のモデルはWristノードを最初のものとして定義し、ノードをPalm最後のものとして定義しました。ここで、OpenXR はXR_HAND_JOINT_PALM_EXT最初のジョイントとして定義しXR_HAND_JOINT_WRIST_EXT、2 番目のものとして定義します。

update 関数のコードは次のとおりです。

bool
wxrc_hand_model_update(struct wxrc_hand_model *model,
                const XrHandJointLocationEXT *locations)
{
        /*
         * OpenXR defines joint 0 as XR_HAND_JOINT_PALM_EXT, but the valve hand
         * model defines Palm as the last joint
         * TODO: handle this dynamically for other models
         */
        static const size_t convert[26] = {
                1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0
        };

        for (size_t i = 0; i < XR_HAND_JOINT_COUNT_EXT; ++i) {
                const XrHandJointLocationEXT *joint = &locations[convert[i]];
                const XrPosef *pose = &joint->pose;

                mat4 transform = GLM_MAT4_IDENTITY_INIT;

                vec3 position;
                wxrc_xr_vector3f_to_cglm(&pose->position, position);
                glm_translate(transform, position);

                versor orientation;
                wxrc_xr_quaternion_to_cglm(&pose->orientation, orientation);
                glm_quat_rotate(transform, orientation, transform);

                glm_mat4_mul(transform, model->inv_bind[i], model->bones[i]);
        }
        return true;
}
于 2021-11-12T19:06:43.490 に答える