SkillAgentSearch skills...

Ikrigretarget

ik rig retarget

Install / Use

/learn @AndrewChan2022/Ikrigretarget
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

| Documentation | Linux | MacOS | Windows | PyPI | | :---: | :---: | :---: | :---: | :---: | | docs| rgl-ci | rgl-ci | rgl-ci | 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

  1. animation interpolation

    now generate every frame,

    should generate only frames containing in source animation

  2. python bind

    a. copy dll to package

  3. ik part not implement

  4. fbx sdk, replace assimp lib

    assimp import and export fbx not stable

  5. 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} $$

pose transform

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

.
View on GitHub
GitHub Stars16
CategoryDevelopment
Updated11d ago
Forks3

Languages

C++

Security Score

75/100

Audited on Mar 26, 2026

No findings