【问题标题】:Rendering independent bones渲染独立骨骼
【发布时间】:2021-12-18 16:38:36
【问题描述】:

我正在尝试根据给出的位置在 3D 空间中渲染手的模型 来自XR_EXT_hand_tracking 扩展的XrHandJointLocationEXT 数组。 我同时使用GTLF hand models from Valve,它们的骨骼数量正确 以匹配 XrHandJointEXT 枚举中 OpenXR 规范定义的关节。

我的渲染如下:

每一帧我都通过乘以当前变换来独立更新每个关节 使用从 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]);
}

然后bones 数组与view-proj 一起上传到顶点着色器 矩阵,为 HMD 的每个 eye 计算。

#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;
}

计算方法是否正确?我得到了不错但“有问题”的结果。如你看到的 在下面的屏幕截图中,我将两个独立的关节都渲染在了手的顶部 模型,你可以在拇指上看到一个小故障。

在计算骨骼变换时是否应该考虑父骨骼?

【问题讨论】:

  • glTF Skinning Tutorial 有一些额外的数学和着色器代码需要查看,如果您认为可能存在错误。

标签: opengl-es gltf skinning openxr


【解决方案1】:

终于找到了我的问题的答案:GTLF 模型的关节顺序与XrHandJointEXT 的顺序不匹配,导致将正确的变换应用于错误的关节。

在我的例子中,我的模型将 Wrist 节点定义为第一个节点,将 Palm 定义为最后一个节点,其中 OpenXR 将 XR_HAND_JOINT_PALM_EXT 定义为第一个关节,XR_HAND_JOINT_WRIST_EXT 定义为第二个关节。

这里是更新函数的代码

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;
}

【讨论】:

    猜你喜欢
    • 2019-05-14
    • 2020-09-22
    • 2011-10-13
    • 1970-01-01
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    相关资源
    最近更新 更多