Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - markandre13/makehuman.js: A MakeHuman variant with different features. · GitHub
Skip to content

Repository files navigation

makehuman.js

A Makehuman variant with different features.

currently writing a tool to create morph targets for face animation from the blend shapes in ARKit / ICT FaceKit

Currently Working On

Animation!

  • Face animation with MediaPipe/Live Link Face App

    • data is provided as Apple ARKit Blendshape parameters
    • MH's default face rig is not expressive enough to mimic the ARKit blendshapes
    • current approach is to create morph targets by mapping ARKit and ICT FaceKit meshes to the MH mesh (see screenshot above)
    • if that isn't good enough, i'll try to use MH's rigigy face rig
  • Body animation with MediaPipe/FreeMoCap

(also worth looking into: OpenPose, Apple VisionFramework, ...)

This needs the makehuman.js backend to be running locally.

Once that is working, the next step will be to record animations and export them to Blender.

Notes on MediaPipe:

  • better go through something like freemocap
  • on live preview
    • older versions of MediaPipe had filters to reduce jitter, now we need to do it on our own
      • Kalman seems to be a favourite
      • Simple Moving Average (SMA)
      • Savitzky-Golay filter needs lookahead
      • EMA
    • z-axis is not good when using world coordinates
      • use pose_world_landmarks with translating with the root of pose_landmarks?
    • the holistic task lacks good neck, hand and foot orientation

Current Status

  • Have a look at build 2023-10-31
  • Edit, load and save morph
  • Pose and load pose
  • Select one of 32 pre-defined facial expressions and/org edit facial pose units
  • Render various proxy meshes instead of the basemesh
  • Export the mesh with rig and texture coordinates as Collada for Blender
  • Nothing else... 😅

How to build

  • npm install
  • npm run dev:prepare
  • npm run dev:build
  • npm run dev:serve (in another terminal)

Why?

  • I've been using MakeHuman for more than a decade but often struggled with the UI and the source code.
  • I'm up to something with Blender and Chordata and in need for full artistic control of the toolchain. 😎

Animation

Capturing

  • MediaPipe

    Contains image recognition for facial landmarks, fingers and body.

  • Chordata

    Body pose capturing using 15 or 17 MARGS (accelerometer + gyroscope + magnetometer) attached to the body.

  • The FreeMoCap Project

    Not used in makehuman.js (yet): Python project which bundles and extends various free motion capture tools.

Face

Body

TBD

How does Makehuman work?

Morph

Data

  • data/3dobjs/base.obj contains a 3d model of a human body, called the base mesh.

    It is completely made of quads, which well give good results when applying a Catmul and Clark subdivision to it.

    Further reading: Mesh Topology.

  • data/target/ contains 1258 morph targets, which can deform the base mesh's shape, gender, age and ethnicity.

    The morph targets are handmade by editing the basemesh in a 3d editor and extracting the changes with MakeTarget.

  • data/modifiers/ bundles those morph targets into 249 more user friendly modifiers

Code

// render's the morphed base meshfunctionrender(canvas: HTMLCanvasElement,scene: HumanMesh)// the morphed base meshclassHumanMesh{// input
obj: Mesh// the base mesh from the Wavefront Object
human: Human// the morph targets// processingupdate()// calculate vertex from obj and human// output
vertex: number[]// the morphed obj.vertex}// aggregates all the modifiers and creates a list of morph targetsclassHuman{// inputmodifiers: Map<string,Modifier>modifierGroups: Map<string,Modifier[]>// output targetsDetailStack: Map<string,number>// morph targets// for posing and skinning (see below)meshData!: WavefrontObj__skeleton!: Skeleton}// creates a list of ui elements (sliders, text fields) to edit the modifier valuesfunctionloadSliders(filename: string)

Pose

The skeleton aggregates bones and weights. Bones can be rotated.

Posing the skeleton directly, especially those in the face, can be a bit tedious. Hence there are pre-defined pose units, e.g. "LipsKiss" or "HandBendOutLeft", which can control multiple bones at once while also restricting bone movement.

Data

  • Skeleton

    • data/rigs/default.mhskel the bones making up the skeleton

      For the actual bone positions little cubes within the mesh are referenced, so when the mesh is morphed, the skeleton is morphed along with it.

      Further reading: Base Mesh and Rig.

    • data/rigs/default_weights.mhw the weights each bone has on each vertex

  • Pose Units

    • data/poseunits/body-poseunits.json defines 63 pose units for the body.

    • data/poseunits/face-poseunits.bvh and face-poseunits.json defines 60 pose units for the face.

    • data/expressions/*.mhpose defines 32 face expressions based upon pose units, e.g. like "laugh01" or "fear02".

Code

// aggregates the bone tree and weight listclassSkeleton{}// a single boneclassBone{parent?: Bonechildren: Bone[]=[]name: stringyvector4?: vec4// direction vector of this bone (along y-axis)matRestGlobal?: mat4// bone relative to world
...
// user defined rotationmatPose: mat4}// weightsclassVertexBoneWeights{// bone name -> [[vertex numbers, ...], [weight for vertex, ...]]_data: Map<string,Array<Array<number>>>}

Proxy

Proxies provide additional meshes, e.g. teeth, tounge, eyes, alternative body meshes and cloth.

The proxy files contain data which is used to transform the morphed/posed basemesh into a proxy mesh. These files are created with MakeClothes.

classProxy{// return proxy mesh vertices, adjusted to basemesh morph/posegetCoords(baseMeshVertices: number[]): number[]}

Development

# install packages
npm install
# populate data directory
npm run dev:prepare
# run (in separate terminals)
npm run dev:build
npm run dev:serve

Run single test

 npm run dev:test --file=build/test/skeleton/Skeleton.spec.js

About

A MakeHuman variant with different features.

Resources

Stars

9 stars

Watchers

1 watching

Forks

Contributors

Languages