C ++ OpenGL 게임에 모델을로드했습니다. 내가로드 한 COLLADA 파일 형식이며 파일의 믹서 아래에 애니메이션을 설정합니다. 문제는 모델에 애니메이션을 적용하는 방법을 모른다는 것입니다. Assimp 문서는 실제로 도움이되지 않았습니다. 소스 코드는 애니메이션을 사용하지 않았으며로드 된 모델에 애니메이션을 적용하는 방법을 누군가가 온라인에서 찾을 수없는 것 같습니다. 어쩌면 assimp로 애니메이션을 만드는 방법을 이해할 것입니다.
답변
면책 조항 : Assimp 가 사용 하는 객체 그래프는 변경되지 않으므로 플랫폼에 관계없이 프로세스가 동일하지만 Assimp를 관리하는 래퍼 인 AssimpNet을 사용합니다.
나는 개인적으로 Assimp 멋진 아이디어이며, 나에게 수많은 시간을 저장하지만 엔진에 자신의 그래프를 번역 한 생각 되는 수입을 작성하고 모든 학습 그렇게해야합니다.
블렌드 셰이프 또는 개별 노드가 아닌 골격 애니메이션을 참조한다고 가정합니다 (후자는 나중에 언급 할 것이지만).
아시다시피 Assimp는 소스 파일의 엔티티를 트리에서 수집합니다 nodes
. 이 노드에는 meshes
시각적 지오메트리를 식별하기 위해 부착 된 것과 같은 것이 있거나 조명과 사물의 경우 뼈와 같은 세계의 변형을 식별하기 위해 존재하는 ‘추상적 인’노드 일 수 있습니다. 많은 파일 형식이 계층 구조를 ‘평평하게’만들어 단일 수준의 하위 수준이있는 모델 (각각 메쉬가있는 모델)을 갖게됩니다. COLLADA는 그중 하나가 아니므로 가져온 모델이 올바르게 작동하려면 구조를 보존해야하기 때문에 조금 더 복잡합니다.
위 다이어그램을 보자. 점선 상자는 노드 오브젝트이며 일부는 메시를 갖지만 씬 오브젝트에서 찾은 루트 노드에서 나오는 그래프 내에 모두 존재합니다.
애니메이션 임포트
애니메이션 데이터 가져 오기는 프로세스에서 가장 간단한 부분입니다. aiScene
목적은 회원해야합니다 aiAnimations
의 목록입니다 aiAnimation
오브젝트. 각각 멤버 aiAnimation
에 aiNodeAnim
* 객체 목록이 있습니다 mChannels
. 기본적으로 각 채널은 단일 노드를 제어하며 특정 시점에서이 노드에 대한 스케일, 회전 및 변환 값이있는 키 프레임 목록을 포함합니다. 애니메이션 트랙은 이름을 통해 제어 할 노드를 식별합니다.
(이 시점에서 3DSMax와 같은 일부 익스포터는 애니메이션을 이상한 방식으로 결합하여 관련없는 노드에 대한 트랙을 포함하는 단일 애니메이션을 생성하므로 스키닝 된 메시에 애니메이션을 적용하지 않는 경우 모든 애니메이션 객체!)
“Box”를 애니메이션한다고 가정 해 봅시다. 이미 지오메트리와 함께 ‘Box’노드를 가져 왔으며 월드에 변형이있는 항목이 있습니다. 상자에 애니메이션을 적용하려면 mNodeName이 “Box”와 일치하는 것을 찾을 때까지 애니메이션을 가져와 aiAnimations
각 aiNodeAnim
(채널) 에서 반복 하십시오. 그리고, 위치의 각 반복하되는 스케일 및 회전은 키 프레임 mPositionKeys
, mScalingKeys
및 mRotationKeys
에 어떤 구조 애플리케이션 저장 애니메이션 데이터로 (오프셋 벡터 또는 쿼터니온, 시간) 값을 변환 부재.
그런 다음 평소와 같이 키 프레임 / 보간을 선택하고 프레임에 지정된 변환을 해당 노드에 로컬 변환을 적용하고 이동하는 것을보십시오!
뼈대 애니메이션 추출은 Assimp 뼈가 다른 노드에 불과하므로 동일한 프로세스입니다. 스키닝 데이터는 약간 까다 롭습니다. 스킨 모델을 애니메이션하려면 세 가지가 필요합니다.
-
애니메이션에서 각 본에 대한 변형 (위에서 볼 수 있음)
-
골격의 계층
-
스키닝은 메쉬 오브젝트에서 얻는 각 본 (일명 바인드 포즈 포즈 변환)에 대해 변환됩니다.
그러나 가장 먼저 할 일은 골격을 찾는 것입니다.
해골 찾기
위의 예제 다이어그램은 지금까지 본 모든 COLLADA DOM에서 찾을 수있는 것입니다. 즉, 스켈레톤은 루트 노드 바로 아래의 ‘시각적’지오메트리를 형제로하는 별도의 노드 트리로 존재합니다.
Assimp는 ‘bone node’와 ‘nodes’를 구분하지 않습니다. 즉, 수입자는 전체 트리에서 읽기 전에 올바른 시작 노드를 선택하기 위해 추측을해야합니다.
우리가 골격을 찾아야하는 이유는 다이어그램에서 볼 수 있듯이 각 뼈가 서로 뼈를 모으기 때문입니다. 애니메이션 트랙 / 채널에서 추출 된 변환을 정점을 올바르게 이동하려면 다른 트랙의 변환과 결합해야합니다.
내가하는 방식은 다음과 같습니다.
모든 메시를 살펴보고 그들이 사용하는 모든 본을 식별 한 다음 각 본에 대해 동일한 이름을 가진 루트 아래 오브젝트 그래프에서 노드를 찾습니다. 나는이 뼈가 뿌리에서 나무에서 얼마나 떨어져 있는지 확인합니다. 값이 가장 낮은 뼈 (분리 정도)는 골격의 근입니다.
이것을 가지고 나면,이 노드와 각 하위 노드를 읽고 노드의 변환 및 상위 노드의 이름을 저장하는 경우 입니다. 이 정보를 사용하여 각 뼈의 부모를 찾을 수 있습니다.
스키닝 데이터
각 메시에서 본과 가중치를 추출하는 가장 까다로운 비트입니다. 이번에 찾고 mBones
있는 회원이며의 회원이 aiMesh
됩니다. 여기에는 두 가지 관심사가 있습니다.
-
mOffsetMatrix
-이것은 스키닝 변환 또는 역 바인드 포즈 변환입니다-뼈 원래 변환 및 부모 이름과 함께 각 뼈에 대해 이것을 저장하려고합니다. -
mWeights
-이것은 정점 가중치입니다-그리고 그들은 거꾸로되어 있습니다!
각 aiVertexWeight 개체에는 정점을 식별하는 mVertexId 및 뼈의 가중치 인 mWeight가 포함됩니다. mVertexId는 메시를 제공하는 ‘vertex array’에서 꼭짓점의 인덱스입니다. 즉, 각 본에 번호를 할당하고 동일한 본을 일관되게 참조 할 수 있도록 본 이름의 ‘마스터 목록’을 정의해야합니다. 그런 다음 꼭짓점 가중치가 포함 된 aiBone 객체의 이름으로 해당 번호를 찾아야합니다. 이제 메쉬의 정점을 본 ID와 가중치로 업데이트 할 수 있습니다.
(내가 거꾸로 의미하는 것을 알면 가중치에는 정점 ID가 있고 부모에는 뼈가 포함되어 있지만 수입자를 작성하는 것이 더 쉬워집니다)
개요
이제 스킨되지 않은 항목의 경우 특정 시간에 노드의 이름 (이름으로 식별)의 변환을 정의하는 키 프레임 목록이 있어야합니다. 노드에 애니메이션을 적용하는 데 필요한 전부입니다 (로컬 변환 만 업데이트).
스키닝 된 메시가있는 경우 다음이 있어야합니다.
에이. 특정 순서의 뼈 목록
b. 메시의 각 꼭짓점에 대한 본 ID와 가중치 목록은 꼭짓점 데이터 배열로 압축 될 수 있습니다.
기음. (a)
d. 목록에있는 각 뼈마다 하나씩 스키닝 / 역 바인드 변환 목록 . (a)에서 각 뼈의 부모
e. (a)의 각 뼈에 대한 바인딩 포즈 변환 (당신이 얻은 동일한 장소 (d), 또는 스키닝 변환의 역수를 취함)
이것은 스켈 레탈 애니메이션에 대한 “표준 데이터 세트”이며 스켈 레탈 애니메이션에 대해 알고 있다면 필요한 것입니다! 그렇지 않다면 그것은 상당히 큰 영역이기 때문에 다른 질문이 될 것입니다.)
나는 그것이 혼란에 도움이되거나 최소한 추가되지 않기를 바랍니다. 행운을 빕니다!
(* 애니메이션에는 메시에 직접 애니메이션을 적용 할 수있는 mMeshAnim도 포함되어 있습니다.
답변
좀 더 경험이 풍부한 답변을 기다리고 있었지만 아무도 당신을 도울만한 일이없는 것 같습니다. 내가 찾은 정보를 알려 드리겠습니다.
분명히 Assimp 애니메이션에 대한 문서가 부족하며 Assimp 코드를 직접 파는 경우를 제외 하고는이 정확한 지점에 대한 사용 가능한 정보가없는 것 같습니다.
그러나 애니메이션을 가져오고 사용하기 위해 작성한 흥미로운 코드 부분을 볼 수있는 이 포럼 스레드를 찾았습니다 .
내가 찾은 잠재적으로 유용한 다른 정보는 이 블로그 항목 인데, 이 항목 은 모든 항목 에 대해 누구나 사용할 수있는 코드가 있는 Open Asset Import Library 애니메이션 로더 를 찾을 수 있습니다 (항목 끝에 쓰여진대로).
이것이 도움이되기를 바랍니다 …