Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opengl 带养育问题的骨骼动画_Opengl_Animation_3d_Lua_Skeletal Animation - Fatal编程技术网

Opengl 带养育问题的骨骼动画

Opengl 带养育问题的骨骼动画,opengl,animation,3d,lua,skeletal-animation,Opengl,Animation,3d,Lua,Skeletal Animation,tl;dr:设置模型动画时,每个关节都会正确移动,但不会相对于其父关节移动。 我正在使用Lua中定制的IQE加载程序和渲染器开发骨骼动画系统。在这一点上,几乎所有的东西都在工作,除了在设置动画时骨架似乎是脱节的。每个关节都可以正确地平移、旋转和缩放,但没有考虑其父关节的位置,因此会产生一些可怕的问题 在参考IQM规范和演示时,我一辈子都无法找出哪里出了问题。我的LUA代码(与我所能说的)相同,与引用C++相同。 计算基本关节矩阵: local base = self.active_animat

tl;dr:设置模型动画时,每个关节都会正确移动,但不会相对于其父关节移动。

我正在使用Lua中定制的IQE加载程序和渲染器开发骨骼动画系统。在这一点上,几乎所有的东西都在工作,除了在设置动画时骨架似乎是脱节的。每个关节都可以正确地平移、旋转和缩放,但没有考虑其父关节的位置,因此会产生一些可怕的问题

在参考IQM规范和演示时,我一辈子都无法找出哪里出了问题。我的LUA代码(与我所能说的)相同,与引用C++相同。 计算基本关节矩阵:

local base = self.active_animation.base
local inverse_base = self.active_animation.inverse_base

for i, joint in ipairs(self.data.joint) do
    local pose = joint.pq

    local pos = { pose[1], pose[2], pose[3] }
    local rot = matrix.quaternion(pose[4], pose[5], pose[6], pose[7])
    local scale = { pose[8], pose[9], pose[10] }

    local m = matrix.matrix4x4()
    m = m:translate(pos)
    m = m:rotate(rot)
    m = m:scale(scale)

    local inv = m:invert()

    if joint.parent > 0 then
        base[i] = base[joint.parent] * m
        inverse_base[i] = inv * inverse_base[joint.parent]
    else
        base[i] = m
        inverse_base[i] = inv
    end
end
计算动画帧矩阵

local buffer = {}
local base = self.active_animation.base
local inverse_base = self.active_animation.inverse_base
for k, pq in ipairs(self.active_animation.frame[self.active_animation.current_frame].pq) do
    local joint = self.data.joint[k]
    local pose = pq

    local pos = { pose[1], pose[2], pose[3] }
    local rot = matrix.quaternion(pose[4], pose[5], pose[6], pose[7])
    local scale = { pose[8], pose[9], pose[10] }

    local m = matrix.matrix4x4()
    m = m:translate(pos)
    m = m:rotate(rot)
    m = m:scale(scale)

    local f = matrix.matrix4x4()

    if joint.parent > 0 then
        f = base[joint.parent] * m * inverse_base[k]
    else
        f = m * inverse_base[k]
    end

    table.insert(buffer, f:to_vec4s())
end
完整代码供进一步检查。相关代码位于/libs/iqe.lua中,在函数iqe:buffer()和iqe:send_frame()的底部附近。这段代码运行在一个自定义版本的爱情游戏框架上,其中包括一个Windows二进制文件(和批处理文件)


最后一点注意:我们的矩阵代码已经根据其他实现和一些测试进行了验证。

父骨骼的转换应该会影响其子骨骼的转换。事实上,这是通过在其父骨骼的框架中指定特定骨骼的变换来实现的。所以,通常骨骼的变换是在其局部坐标系中指定的,这取决于它的父对象。如果父母中的任何一个转变了,这种转变将影响所有的孩子,即使他们的局部转变没有改变

在本例中,您曾经缓存每个节点的所有绝对(精确地说,相对于根)变换。然后使用缓存更新每个节点的本地变换,而不更新缓存。那么,如果在更新子节点时使用缓存而不是实际的父节点变换,那么节点的局部变换的更改将如何影响它的子节点呢

还有一个问题。你为什么要做下面的事情

f = base[joint.parent] * m * inverse_base[k]
我的意思是,通常只是:

f = base[joint.parent] * m
我猜,动画中记录的变换是绝对的(精确地说,相对于根)。这很奇怪。通常每个转换都是局部的。检查此问题,因为这会给您带来很多问题

此外,我认为没有必要在您的案例中缓存某些内容(除了通常不需要的反向_基)

按如下方式更改IQE:send_frame()函数:

local buffer = {}
local transforms = {}
local inverse_base = self.active_animation.inverse_base
for k, pq in ipairs(self.active_animation.frame[self.active_animation.current_frame].pq) do
    local joint = self.data.joint[k]
    local pose = pq

    local pos = { pose[1], pose[2], pose[3] }
    local rot = matrix.quaternion(pose[4], pose[5], pose[6], pose[7])
    local scale = { pose[8], pose[9], pose[10] }

    local m = matrix.matrix4x4()
    m = m:translate(pos)
    m = m:rotate(rot)
    m = m:scale(scale)

    local f = matrix.matrix4x4()

    if joint.parent > 0 then
        transforms[k] = transforms[joint.parent] * m
        f = transforms[k] * inverse_base[k]
    else
        f = m  * inverse_base[k]
        transforms[k] = m
    end

    table.insert(buffer, f:to_vec4s())
end
这对我有好处。尝试去掉inverse_base,就可以从IQE:buffer()函数中删除所有与动画相关的代码


另外,通常通过遍历树来更新所有节点。但是,可以通过浏览列表来更新节点。您应该知道,您必须以某种方式保证,对于任何节点,它的子节点都会跟踪它。

首先,我要对您的帮助表示感谢!当我测试你的代码时,它几乎可以工作!无论如何,比我的代码要好得多!我在我的一个动画“blah”中发现了一个奇怪的bug,我想知道这是否是因为我解析列表的方式导致一些骨骼在被他们的孩子使用之前没有正确更新?我看了“废话”动画,似乎腿的最上面的父对象的变换是错误的。我不确定,但也许这个问题与这个奇怪的反向基础有关。尝试重写代码,但不要乘以逆_base[k],并调整您正在使用的导出工具的设置。您已经说过,某些骨骼在被其子代使用之前可能不会更新。如果是这样,它肯定会破坏动画。请参阅我之前编写的post scriptum。经过进一步研究,我发现IQM规范以线性方式写入骨骼,如果按列表顺序计算,子级永远不会比父级先计算。我将尝试重写一些代码以删除inverse_base,但我会注意到,正式IQM参考演示的代码与我编写的代码相同。以下是相关的IQM演示部分: