Ikrigretarget
ik rig retarget
Install / Use
/learn @AndrewChan2022/IkrigretargetREADME
| Documentation | Linux | MacOS | Windows | PyPI |
| :---: | :---: | :---: | :---: | :---: |
| |
|
|
|
|
<small><i><a href='http://ecotrust-canada.github.io/markdown-toc/'>Table of contents generated with markdown-toc</a></i></small>
todo and issues
-
animation interpolation
now generate every frame,
should generate only frames containing in source animation
-
python bind
a. copy dll to package
-
ik part not implement
-
fbx sdk, replace assimp lib
assimp import and export fbx not stable
-
render part not implement
cross platform
RHI of d3d12/vulkan/metal, no OpenGL
build
platform
1. mac
2. linux
3. windows
compiler:
1. clang 17
2. msvc 17
3. gcc 17
prerequisite
linux:
sudo apt-get install zlib1g-dev
python
pip install .
python python/test.py
cmake option
// with assimp project embedded
-DEMBED_ASSIMP=ON
// assimp as static lib
-DBUILD_SHARED_LIBS=OFF
// release
--DCMAKE_BUILD_TYPE=Release
general build
rm -rf build
cmake . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j 16
build/test/Release/testikrigretarget.exe
linux
// linux will force -DEMBED_ASSIMP=ON -DBUILD_SHARED_LIBS=ON
// here use gcc
sudo apt-get install zlib1g-dev
rm -rf build
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DEMBED_ASSIMP=ON
make -j16
macos
rm -rf build
mkdir build && cd build
// for xcode project
cmake .. -GXcode
// without xcode
cmake .. --DCMAKE_BUILD_TYPE=Release
make -j16
windows
rm -rf build
mkdir build && cd build
cmake ..
// with visual studio
open ikrigretarget.sln with visual studio
set testikrigretarget as start project
// without visual studio
cmake --build .
test/Debug/testikrigretarget.exe
build release
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RELEASE
make VERBOSE=1
algorithm
coordinate hand
all the coodinate system is right hand.
transform represent
https://fgiesen.wordpress.com/2012/02/12/row-major-vs-column-major-row-vectors-vs-column-vectors/
reference: Game Engine Architexture chapter 5.3.2
Points and vectors can be represented as row matrices (1× n) or column matrices (n × 1)
row represent:
$$v1=\begin{bmatrix}x & y & z\end{bmatrix}$$
col represent:
$$ v2=\begin{bmatrix} x \ y \ z \ \end{bmatrix} = v1^T $$
the choice between column and row vectors affect the order of matrix multiply
apply matrix to vector:
row vector: $$v1_{1 \times n} = v1_{1 \times n} \times M_{n \times n}$$
col vector: $$v2_{n \times 1} = M_{n \times n} \times v2_{n \times 1}$$
multiple matrix concatenate, apply M1 first, then M2:
$$v1 = v1 \times M1 \times M2$$
$$v2 = M2 \times M1 \times v2$$
the represent also affect the element order of matrix.
example of translation matrix for homogeneous coordinate:
row vector:
$$M_{translation}= \begin{bmatrix} 1 & 0 & 0 & 0 \ 0 & 1 & 0 & 0 \ 0 & 0 & 1 & 0 \ tx & ty & tz & 1 \ \end{bmatrix}$$
col vector:
$$M_{translation}= \begin{bmatrix} 1 & 0 & 0 & tx \ 0 & 1 & 0 & ty \ 0 & 0 & 1 & tz \ 0 & 0 & 0 & 1 \ \end{bmatrix}$$
storage order
the matrix can store in row major or col major.
the store order does not affect the represent, but it affect the element order in memory
to access element:
row major: m[row][col]
col major: m[col][row]
transform in our code
SoulScene.h
glm::mat4/glm::dmat4:
hand : right hand
represent : col vector
store order : col major
SoulFTransform SoulRetargeter.h SoulIKRetargetProcessor.h
https://docs.unrealengine.com/4.27/en-US/API/Runtime/Core/Math/FTransform/
Here we keep Unreal represent, but use right hand
Unreal FTransform
hand : right hand
represent : row vector
store order : row major
lib ASSIMP
aiMatrix4x4:
hand : right hand
represent : col vector
store order : row major
quaternion order
order of all quat: right is first
quaternion interpolation
slerp is linear interpolation on arc of 4d unit sphere.
fastlerp is linear interpolation on chord of 4d unit sphere.
because chord and arc mapping not uniform, so fastlerp will lead to unequall speed of each time step.
<img src="./img/slerp.jpg" width="500"/>
skeleton pose transform
reference: game engine architecture chapter 12.3.3
joint local space: the space of joint
global space: in world space or model space, because we does not care about transform outside model, so we choose model space.
to transform local pose to global pose(model space), only walking the skeleton hierarchy from current joint all the way to root.
denote transform from joint j local space to its parent space:
$$P_{j->p(j)}$$
row represent:
$$P_{5->M} = P_{5->4} \times P_{4->3} \times P_{3->0} \times P_{0->M}$$
col represent:
$$P_{5->M} = P_{0->M} \times P_{3->0} \times P_{4->3} \times P_{5->4} $$

root retarget
root retarget: retarget position by height ratio
init:
source.InitialHeightInverse = 1/ root.z
target.initialHeight = root.z
retarget:
target.root.translation = source.root.translation * target.initialHeight * source.InitialHeightInverse
chain FK retarget
chain FK retarget: copy global rotation delta
init:
foreach chain:
foreach joint:
record initialPoseGlobal, initialPoseLocal
reset currentPoseGlobal
retarget(inputPoseGlobal, outposeGlobal):
foreach chain:
foreach joint:
// apply parent transform to child to get position
currentPositionGlobal = apply parrent.currentPoseGlobal to initialPoseLocal
// copy global rotation delta
deltaRotationGlobal = inputPoseGlobal.currentRotationGlboal / source.initalRotationGlboal
currentRotationGlboal = initialRotationGlobal * deltaRotationGlobal
// copy global scale delta
currentScaleGlobal = TargetInitialScaleGlobal + (SourceCurrentScaleGlobal - SourceInitialScaleGlobal);
// pose from position and rotation
currentPoseGlobal = (currentPositionGlobal, currentRotationGlboal)
outposeGlobal[boneIndex] = currentPoseGlobal
chain IK retarget
// chain IK retarget
todo
Pole Match retarget
// pole match retarget
todo
render of joint pose animation
Here we use column vector represent
https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_020_Skins.md
jointMat and pose animation:
jointMatrix(j) = globalTransformOfJointNode(j) * inverseBindPoseMatrixForJoint(j);
currentpose.position = globalTransformOfJointNode * inverseBindPoseMatrixForJoint * bindpose.position
bindpose.position: bind pose vertex world position
currentpose.position: current pose vertex world position
inverseBindPoseMatrixForJoint: world space to joint local space of bind pose
globalTransformOfJointNode: joint local space to world space of current pose
global transform:
for joint from root to leaf:
globalTransformOfJointNode = parentGlobal * childLocal
skin shader: average position of several joint
.
