2014-10-11 3 views
3

tl; dr : 모델에 애니메이션을 적용 할 때 각 관절은 올바르게 움직이지만 모 모 관절을 기준으로 이동하지 않습니다.육아 문제가있는 골격 애니메이션

enter image description here

나는 루아에서 IQE 로더와 렌더러 내장 사용자 정의를 사용하여 골격 애니메이션 시스템에서 일하고 있습니다. 거의 모든 것이이 시점에서 작동하고 있습니다. 단, 애니메이션 작업을 할 때 골격의 연결이 끊어지는 것처럼 보입니다. 각 조인트는 정확하게 병진 이동, 회전 및 크기 조정을 수행하지만 부모 위치를 고려하지 않으므로 약간의 끔찍한 문제가 발생합니다.

IQM 사양과 데모를 언급 할 때, 내가 잘못하면 무엇이 잘못 될지 알 수 없습니다. 내 루아 코드는 (내가 말할 수있는 한) 참조 용 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 

전체 코드는 추가 심사 here입니다. 관련 코드는 /libs/iqe.lua에 있으며 IQE 함수의 맨 아래에 있습니다 : buffer() 및 IQE : send_frame(). 이 코드는 LOVE 게임 프레임 워크의 사용자 정의 버전에서 실행되며 Windows 바이너리 (및 배치 파일)가 포함됩니다.

최종주의 사항 : 매트릭스 코드는 다른 구현 및 여러 테스트와 비교하여 검증되었습니다.

답변

3

부모 본 변환은 자녀의 변형에 영향을 주어야합니다. 사실, 이것은 부모의 프레임에서 특정 뼈의 변형을 지정함으로써 달성됩니다. 따라서 보통 뼈의 변형은 부모에 따라 달라지는 로컬 좌표계에서 지정됩니다. 부모 중 하나라도 변형 된 경우이 변환은 로컬 변환이 변경되지 않은 경우에도 모든 자식에게 적용됩니다.

경우에 따라 각 노드의 모든 절대 (루트와 정확히 일치하는) 변환을 캐시합니다. 그런 다음 캐시를 사용하여 각 노드의 로컬 변환을 업데이트하고 캐시를 업데이트하지 마십시오. 그래서 노드의 로컬 변환을 변경하면 자식이 어떻게 변경 될까요? 실제 부모 변환 대신 캐시를 사용하는 자식을 업데이트하면 어떻게됩니까?

문제가 하나 더 있습니다. 왜 다음과 같은 일을합니까?

내 말은
f = base[joint.parent] * m * inverse_base[k] 

, 보통은 다음과 같습니다

f = base[joint.parent] * m 

나는 (정확히 말하면, 루트에 상대적으로) 애니메이션에 기록 된 변환은 절대 것을 생각한다. 그것은 매우 이상합니다. 일반적으로 모든 변환은 로컬입니다. 이 문제는 많은 문제를 추가하기 때문에 확인하십시오.

이상의 내용을 더 이상 캐시하지 않아도됩니다 (보통 inverse_base 제외).

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 

이 나를 위해 좋은 작동합니다.() 기능을

P.S.을 버퍼 : inverse_base 제거하는 시도하고 당신은 당신의 IQE에서 모든 애니메이션 관련 코드를 제거 할 수있을 것입니다 일반적으로 모든 노드는 트리를 따라 이동하여 업데이트됩니다. 그러나 목록을 이동하여 노드를 업데이트합니다. 당신은 어떤 노드에 대해서 그것이 자식 노드 일 것이라고 보장해야한다는 것을 알아야한다.

+0

먼저 도움을 주셔서 감사드립니다. 귀하의 코드를 테스트 할 때, 그것은 거의 작동합니다! 어쨌든 제 코드보다 훨씬 낫습니다! 나는 나의 애니메이션 중 하나 인 "blah"로이 이상한 버그를 얻었고, 이것이 내가 뼈를 올바르게 해석하지 못하게하는 목록을 파싱하는 방식 때문에 아이들이 사용하기에 적절하지 않은지 궁금합니다. https://dl.dropboxusercontent.com/u/12958391/misc/mk2.png – Karai17

+0

"ㅋㅋ"애니메이션을 보았습니다. 다리의 맨 위에있는 부모의 변형이 잘못된 것처럼 보입니다. 확실하지는 않지만 아마도이 이상한 * inverse_base *와 관련된이 문제. * inverse_base [k] * 을 곱하지 않고 코드를 다시 작성하고 사용중인 내보내기 도구의 설정을 조정하십시오. – Podgorskiy

+0

일부 뼈는 자녀가 사용하기 전에 업데이트되지 않을 수도 있습니다. 그렇다면 분명히 애니메이션이 깨질 것입니다. 앞서 작성한 포스트 스크립트를 참조하십시오. – Podgorskiy