### Complete THREE.IK Scene Setup and Animation Example
Source: https://github.com/whatisor/three.ik/blob/master/README.md
A comprehensive JavaScript example demonstrating the setup of a three.js scene with THREE.IK. It shows how to create an IK system, define chains and joints, set up a target effector, and animate the IK solution to make bones follow the target.
```javascript
// Set up scene, camera, renderer
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 100);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const ik = new THREE.IK();
const chain = new THREE.IKChain();
const constraints = [new THREE.IKBallConstraint(90)];
const bones = [];
// Create a target that the IK's effector will reach
// for.
const movingTarget = new THREE.Mesh(new THREE.SphereGeometry(0.1), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
movingTarget.position.z = 2;
const pivot = new THREE.Object3D();
pivot.add(movingTarget);
scene.add(pivot);
// Create a chain of THREE.Bone's, each wrapped as an IKJoint
// and added to the IKChain
for (let i = 0; i < 10; i++) {
const bone = new THREE.Bone();
bone.position.y = i === 0 ? 0 : 0.5;
if (bones[i - 1]) { bones[i - 1].add(bone); }
bones.push(bone);
// The last IKJoint must be added with a `target` as an end effector.
const target = i === 9 ? movingTarget : null;
chain.add(new THREE.IKJoint(bone, { constraints }), { target });
}
// Add the chain to the IK system
ik.add(chain);
// Ensure the root bone is added somewhere in the scene
scene.add(ik.getRootBone());
// Create a helper and add to the scene so we can visualize
// the bones
const helper = new THREE.IKHelper(ik);
scene.add(helper);
function animate() {
pivot.rotation.x += 0.01;
pivot.rotation.y += 0.01;
pivot.rotation.z += 0.01;
ik.solve();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
animate()
```
--------------------------------
### Dynamically Generate and Manage Example Links in JavaScript
Source: https://github.com/whatisor/three.ik/blob/master/examples/index.html
This JavaScript code dynamically creates navigation links for various examples based on a predefined 'files' object. It handles click events to select and load examples into an iframe, updates the URL hash for direct linking, and reveals a 'View source' button with the correct GitHub link for the selected example.
```javascript
var links = {};
var selected = null;
function createLink( file ) {
var link = document.createElement( 'a' );
link.className = 'link';
link.href = file + '.html';
link.textContent = getName( file );
link.setAttribute( 'target', 'viewer' );
link.addEventListener( 'click', function ( event ) {
if ( event.button === 0 ) {
selectFile( file );
}
} );
return link;
}
for ( var key in files ) {
var section = files[ key ];
var header = document.createElement( 'h2' );
header.textContent = key;
header.setAttribute( 'data-category', key );
container.appendChild( header );
for ( var i = 0; i < section.length; i ++ ) {
var file = section[ i ];
var link = createLink( file );
container.appendChild( link );
links[ file ] = link;
}
}
function loadFile( file ) {
selectFile( file );
viewer.src = file + '.html';
}
function selectFile( file ) {
if ( selected !== null ) links[ selected ].classList.remove( 'selected' );
links[ file ].classList.add( 'selected' );
window.location.hash = file;
viewer.focus();
panel.classList.add( 'collapsed' );
selected = file;
// Reveal "View source" button and set attributes to this example
viewSrcButton.style.display = '';
viewSrcButton.href = 'https://github.com/whatisor/THREE.IK/blob/master/examples/' + selected + '.html';
viewSrcButton.title = 'View source code for ' + getName(selected) + ' on GitHub';
}
if ( window.location.hash !== '' ) {
loadFile( window.location.hash.substring( 1 ) );
}
```
--------------------------------
### Run THREE.IK demo locally
Source: https://github.com/whatisor/three.ik/blob/master/README.md
Instructions to run the THREE.IK demo locally using http-server, assuming it's already installed globally.
```shell
http-server
```
--------------------------------
### Global and Layout CSS for THREE.IK Examples Viewer
Source: https://github.com/whatisor/three.ik/blob/master/examples/index.html
This CSS defines the foundational styles for the THREE.IK examples viewer, including body and panel layout, typography, link styling, and responsive design rules for different screen sizes. It sets up the visual structure and behavior of the example navigation and display areas.
```css
* { box-sizing: border-box; }
html { height: 100%; }
body { background-color: #ffffff; margin: 0px; height: 100%; color: #555; font-family: Roboto, sans-serif; font-size: 15px; line-height: 18px; overflow: hidden; }
h1 { margin-top: 30px; margin-bottom: 40px; margin-left: 20px; font-size: 25px; font-weight: normal; }
h2 { font-size: 20px; font-weight: normal; }
a { color: #2194CE; text-decoration: none; }
#panel { position: fixed; left: 0px; width: 310px; height: 100%; overflow: auto; background: #fafafa; }
#panel #content { padding: 0px 20px 20px 20px; }
#panel #content .link { color: #2194CE; text-decoration: none; cursor: pointer; display: block; }
#panel #content .selected { color: #ff0000; }
#panel #content .link:hover { text-decoration: underline; }
#viewer { position: absolute; border: 0px; left: 310px; width: calc(100% - 310px); height: 100%; overflow: auto; }
#viewSrcButton { position: fixed; bottom: 20px; right: 20px; padding: 8px; color: #fff; background-color: #555; opacity: 0.7; }
#viewSrcButton:hover { cursor: pointer; opacity: 1; }
.filterBlock{ margin: 20px; position: relative; }
.filterBlock p { margin: 0; }
#filterInput { width: 100%; padding: 5px; font-family: inherit; font-size: 15px; outline: none; border: 1px solid #dedede; }
#filterInput:focus{ border: 1px solid #2194CE; }
#clearFilterButton { position: absolute; right: 6px; top: 50%; margin-top: -8px; width: 16px; height: 16px; font-size: 14px; color: grey; text-align: center; line-height: 0; padding-top: 7px; opacity: .5; }
#clearFilterButton:hover { opacity: 1; }
.filtered { display: none !important; }
#panel li b { font-weight: bold; }
/* mobile */
#expandButton { display: none; position: absolute; right: 20px; top: 12px; width: 32px; height: 32px; }
#expandButton span { height: 2px; background-color: #2194CE; width: 16px; position: absolute; left: 8px; top: 10px; }
#expandButton span:nth-child(1) { top: 16px; }
#expandButton span:nth-child(2) { top: 22px; }
@media all and ( max-width: 640px ) {
h1{ margin-top: 20px; margin-bottom: 20px; }
#panel{ position: absolute; left: 0; top: 0; height: 480px; width: 100%; right: 0; z-index: 100; overflow: hidden; border-bottom: 1px solid #dedede; }
#content{ position: absolute; left: 0; top: 90px; right: 0; bottom: 0; font-size: 17px; line-height: 22px; overflow: auto; }
#viewer{ position: absolute; left: 0; top: 56px; width: 100%; height: calc(100% - 56px); }
#expandButton{ display: block; }
#panel.collapsed{ height: 56px; }
}
#title { color: #333; margin: 20px; }
#title img { vertical-align: middle; display: inline; width: 50px; }
#title h1 { vertical-align: middle;, font-weight: 300; margin: 5px 0px; display: inline; }
#title h1 a { text-decoration: none; color: #333; }
#title h1 span { font-weight: 400; }
```
--------------------------------
### Implement Client-Side Filtering for Example List in JavaScript
Source: https://github.com/whatisor/three.ik/blob/master/examples/index.html
This JavaScript code provides a real-time filtering mechanism for the list of examples. It updates the URL query parameter with the filter value, dynamically hides/shows example links based on the filter text, highlights matching text, and collapses/expands categories accordingly. It also includes a helper function for getting the example name.
```javascript
// filter
filterInput.addEventListener( 'input', function( e ) {
updateFilter();
} );
clearFilterButton.addEventListener( 'click', function( e ) {
filterInput.value = '';
updateFilter();
e.preventDefault();
} );
function updateFilter() {
var v = filterInput.value;
if( v !== '' ) {
window.history.replaceState( {} , '', '?q=' + v + window.location.hash );
} else {
window.history.replaceState( {} , '', window.location.pathname + window.location.hash );
}
var exp = new RegExp( v, 'gi' );
for ( var key in files ) {
var section = files[ key ];
for ( var i = 0; i < section.length; i ++ ) {
filterExample( section[ i ], exp );
}
}
layoutList();
}
function filterExample( file, exp ){
var link = links[ file ];
var name = getName( file );
var res = file.match( exp );
var text;
if ( res && res.length > 0 ) {
link.classList.remove( 'filtered' );
for( var i = 0; i < res.length; i++ ) {
text = name.replace( res[ i ], '' + res[ i ] + '' );
}
link.innerHTML = text;
} else {
link.classList.add( 'filtered' );
link.innerHTML = name;
}
}
function getName( file ) {
return file;
var name = file.split( '_' );
name.shift();
return name.join( ' / ' );
}
function layoutList() {
for ( var key in files ) {
var collapsed = true;
var section = files[ key ];
for ( var i = 0; i < section.length; i ++ ) {
var file = section[ i ];
if( !links[ file ].classList.contains( 'filtered' ) ){
collapsed = false;
break;
}
}
var element = document.querySelector( 'h2[data-category="' + key + '"]' );
if( collapsed ){
element.classList.add( 'filtered' );
} else {
element.classList.remove( 'filtered' );
}
}
}
filterInput.value = extractQuery();
updateFilter();
```
--------------------------------
### JavaScript THREE.IK Single Target Application Setup
Source: https://github.com/whatisor/three.ik/blob/master/examples/skinned-mesh.html
This class extends `IKApp` to demonstrate a single-target inverse kinematics setup. It handles loading an FBX model, adjusting bone orientations for the IK system, creating an IK chain with constraints, and adding a target object for the solver. The `update` method shows a simple animation of the target.
```JavaScript
class SingleTargetApp extends IKApp {
setupGUI() {
this.config.constraintType = 'ball';
this.config.constraintAngle = 90;
}
setupIK() {
var fbxLoader = new FBXLoader();
fbxLoader.load('assets/rigTest-02.fbx', (rigGroup) => {
this.scene.add(rigGroup)
rigGroup.updateMatrixWorld()
var rigMesh = rigGroup.children[0];
var rootBone = rigGroup.children[1].children[0]
/** This model's bind matrices are -Z forward, while the IK system operates in +Z Forward -- assuming the parent's +Z forward faces the child. This utility helps us recalculate the models bone matrices to be consistent with the IK system. **/
setZForward(rootBone);
//must rebind the skeleton to reset the bind matrix.
rigMesh.bind(rigMesh.skeleton)
rigMesh.material = new THREE.MeshPhysicalMaterial({
skinning: true,
wireframe: true
})
this.target = new THREE.Object3D()
this.target.position.set(0, 0, 5)
this.scene.add(this.target)
var boneGroup = rootBone;
var ik = new IK.IK();
const chain = new IK.IKChain();
var currentBone = boneGroup
for (let i = 0; i < 5; i++) {
var constraints = [new IK.IKBallConstraint(90)];
const target = i === 4 ? this.target : null;
chain.add(new IK.IKJoint(currentBone, { constraints }), { target });
currentBone = currentBone.children[0]
}
ik.add(chain);
const helper = new IK.IKHelper(ik);
this.scene.add(helper);
this.iks.push(ik)
}, console.log, console.log);
}
onChange() {
super.onChange();
}
update() {
if (this.target) {
this.target.position.y = 5 + Math.sin(0.005 * performance.now())
}
}
};
window.app = new SingleTargetApp();
```
--------------------------------
### Install THREE.IK via npm or script tag
Source: https://github.com/whatisor/three.ik/blob/master/README.md
Instructions for installing the THREE.IK library and its dependencies using npm, or by including the build file directly in an HTML script tag for browser usage.
```shell
$ npm install --save three three-ik
```
```html
```
--------------------------------
### GUI Setup for IK Constraints
Source: https://github.com/whatisor/three.ik/blob/master/examples/multi-effector.html
The `setupGUI` method initializes the dat.gui interface, allowing users to dynamically adjust IK constraint properties. It adds controls for 'constraintType' (none, ball) and 'constraintAngle', linking them to the application's configuration and triggering updates via the `onChange` handler.
```javascript
setupGUI() {
this.config.constraintType = 'ball';
this.config.constraintAngle = 360;
this.gui.add(this.config, 'constraintType', ['none', 'ball']).onChange(this.onChange);
this.gui.add(this.config, 'constraintAngle').min(0).max(360).step(1).onChange(this.onChange);
}
```
--------------------------------
### Initialize UI Elements and Handle Basic Interactions in JavaScript
Source: https://github.com/whatisor/three.ik/blob/master/examples/index.html
This snippet initializes various DOM elements, sets up event listeners for UI controls like expanding/collapsing a panel, and includes a specific workaround for iOS iframe resizing issues. It also defines a utility function to extract query parameters from the URL.
```javascript
var files = { "three.ik": [ "single-effector", "single-target", "multi-effector", "readme-example", "skinned-mesh" ] };
function extractQuery() {
var p = window.location.search.indexOf( '?q=' );
if( p !== -1 ) {
return window.location.search.substr( 3 );
}
return ''
}
var panel = document.getElementById( 'panel' );
var content = document.getElementById( 'content' );
var viewer = document.getElementById( 'viewer' );
var filterInput = document.getElementById( 'filterInput' );
var clearFilterButton = document.getElementById( 'clearFilterButton' );
var expandButton = document.getElementById( 'expandButton' );
expandButton.addEventListener( 'click', function ( event ) {
event.preventDefault();
panel.classList.toggle( 'collapsed' );
} );
// iOS iframe auto-resize workaround
if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
viewer.style.width = getComputedStyle( viewer ).width;
viewer.style.height = getComputedStyle( viewer ).height;
viewer.setAttribute( 'scrolling', 'no' );
}
var container = document.createElement( 'div' );
content.appendChild( container );
var viewSrcButton = document.createElement( 'a' );
viewSrcButton.id = 'viewSrcButton';
viewSrcButton.target = '_blank';
viewSrcButton.textContent = 'View source';
viewSrcButton.style.display = 'none';
document.body.appendChild( viewSrcButton );
```
--------------------------------
### Inverse Kinematics (IK) Chain Setup
Source: https://github.com/whatisor/three.ik/blob/master/examples/multi-effector.html
The `setupIK` method constructs the complex multi-effector IK structure. It initializes an `IK` solver, creates a root chain, and then iteratively builds multiple arm chains connected to the root. Each chain consists of `THREE.Bone` objects and `IK.IKJoint`s, with `IK.IKBallConstraint`s applied to control joint movement. Targets are created for the end effectors.
```javascript
setupIK() {
const ik = new IK.IK();
let rootChain = null;
for (let i = 0; i < 9; i++) {
const isRoot = i === 0;
const chain = new IK.IKChain();
const constraint = new IK.IKBallConstraint(this.config.constraintAngle);
const target = isRoot ? null : this.createTarget(new THREE.Vector3(
Math.cos(Math.PI * 0.5 * ((i - 1) % 4)),
ROOT_COUNT * DISTANCE * (i > 4 ? 1 : 0.5),
Math.sin(Math.PI * 0.5 * ((i - 1) % 4))
));
if (isRoot) {
rootChain = chain;
}
const bones = [];
const boneCount = isRoot ? ROOT_COUNT : ARM_COUNT;
for (let j = 0; j < boneCount; j++) {
const isBase = j === 0;
const isSubBase = !isRoot && isBase;
if (isSubBase) {
const joint = rootChain.joints[(ROOT_COUNT / (i > 4 ? 1 : 2)) - 1];
bones.push(joint.bone);
chain.add(joint);
continue;
}
const bone = new THREE.Bone();
bone.position.y = j === 0 ? 0 : DISTANCE;
bones[j] = bone;
if (bones[j - 1]) {
bones[j - 1].add(bones[j]);
}
const constraints = [constraint];
if (j === boneCount - 1 && !isRoot) {
chain.add(new IK.IKJoint(bone, { constraints }), { target });
} else {
chain.add(new IK.IKJoint(bone, { constraints }));
}
}
if (!isRoot) {
rootChain.connect(chain);
}
}
ik.add(rootChain);
this.iks.push(ik);
const pivot = new THREE.Object3D();
pivot.rotation.x = -Math.PI/ 2;
pivot.add(ik.getRootBone());
this.scene.add(pivot);
}
```
--------------------------------
### Configure JavaScript Module Imports
Source: https://github.com/whatisor/three.ik/blob/master/examples/readme-example.html
This JSON configuration defines an import map, mapping module names like 'three', 'dat.gui', and 'three-ik' to their respective file paths. This is a modern JavaScript feature used for managing dependencies and simplifying module imports in browser environments, pointing to local `node_modules` or build outputs.
```JSON
{ "imports": { "three": "./node_modules/three/build/three.module.js", "dat.gui": "./node_modules/dat.gui/build/dat.gui.module.js", "three-ik": "../build/three-ik.module.js" } }
```
--------------------------------
### APIDOC: THREE.IK Core Inverse Kinematics Components
Source: https://github.com/whatisor/three.ik/blob/master/examples/skinned-mesh.html
Documentation for key classes from the `three-ik` library used to construct and manage inverse kinematics chains. These components allow defining joints, constraints, and the overall IK structure.
```APIDOC
IK.IK():
- Constructor for the main Inverse Kinematics solver.
- Methods:
- add(chain: IK.IKChain): Adds an IK chain to the solver.
IK.IKChain():
- Constructor for an Inverse Kinematics chain.
- Methods:
- add(joint: IK.IKJoint, options?: { target?: THREE.Object3D }): Adds an IK joint to the chain.
- joint: The IKJoint instance to add.
- options.target: An optional THREE.Object3D that this joint will try to reach.
IK.IKJoint(bone: THREE.Bone, options?: { constraints?: IK.IKConstraint[] }):
- Constructor for an Inverse Kinematics joint, typically associated with a THREE.Bone.
- Parameters:
- bone: The THREE.Bone object that this joint controls.
- options.constraints: An array of IKConstraint instances to apply to this joint.
IK.IKBallConstraint(angle: number):
- Constructor for a ball joint constraint.
- Parameters:
- angle: The maximum angle (in degrees) the joint can rotate from its initial orientation.
IK.IKHelper(ik: IK.IK):
- Constructor for a visual helper that renders the IK chain and its components.
- Parameters:
- ik: The IK solver instance to visualize.
```
--------------------------------
### JavaScript Module Imports and Configuration for THREE.IK
Source: https://github.com/whatisor/three.ik/blob/master/examples/skinned-mesh.html
This snippet illustrates the module import structure for a Three.js project utilizing the 'three-ik' library. It includes standard Three.js modules, controls, loaders, and custom utility scripts, along with a 'jsconfig.json'-like import map.
```JavaScript
{ "imports": { "three": "./node_modules/three/build/three.module.js", "dat.gui": "./node_modules/dat.gui/build/dat.gui.module.js", "three-ik": "../build/three-ik.module.js" } }
import * as THREE from 'three';
import { TransformControls } from './node_modules/three/examples/jsm/controls/TransformControls.js';
import { OrbitControls } from './node_modules/three/examples/jsm/controls/OrbitControls.js';
import { FBXLoader } from './node_modules/three/examples/jsm/loaders/FBXLoader.js';
import { IKApp } from './scripts/IKApp.js';
import { getOriginalWorldPositions, getAlignmentQuaternion, updateTransformations, setZForward } from './scripts/AxisUtils.js';
import * as IK from 'three-ik';
import * as dat from 'dat.gui';
```
--------------------------------
### Apply Basic CSS Styling to Body
Source: https://github.com/whatisor/three.ik/blob/master/examples/readme-example.html
This CSS snippet sets the margin of the `body` element to 0 and hides any overflow. This is a common practice for web applications, especially those with full-screen canvases or interactive 3D scenes, to ensure no scrollbars appear and content fills the viewport.
```CSS
body { margin: 0px; overflow: hidden; }
```
--------------------------------
### IKJoint Class Constructor and Properties (JSDoc)
Source: https://github.com/whatisor/three.ik/blob/master/docs/IKJoint.html
Comprehensive JSDoc documentation for the `IKJoint` class, outlining its constructor signature, required parameters (`bone` of type `THREE.Bone`, and `config` of type `Object`), and the optional `constraints` property within the `config` object. This class is fundamental for defining joints in an Inverse Kinematics setup.
```APIDOC
Class: IKJoint
IKJoint(bone, config)
- Description: A class for a joint within an Inverse Kinematics (IK) system.
Constructor: new IKJoint(bone, config)
- Parameters:
- bone: THREE.Bone
- Description: The THREE.Bone object that this IKJoint is associated with.
- config: Object
- Description: A configuration object for the IK joint.
- Properties:
- constraints: Array. (optional)
- Description: An array of IKConstraint objects that apply to this joint, defining its movement limitations.
```
--------------------------------
### APIDOC: AxisUtils.js - setZForward
Source: https://github.com/whatisor/three.ik/blob/master/examples/skinned-mesh.html
A utility function designed to adjust the bind matrices of a bone hierarchy to align with a +Z forward convention, which is often required by IK systems like `three-ik`. This is crucial when a model's default bind pose is oriented differently (e.g., -Z forward).
```APIDOC
setZForward(rootBone: THREE.Bone):
- Recalculates the bone matrices within a skeleton hierarchy to ensure the +Z axis of each bone points towards its child, aligning with the 'three-ik' system's expectations.
- Parameters:
- rootBone: The root bone of the skeleton hierarchy to be adjusted.
- Usage:
- Must be called before binding the skeleton to the mesh if the model's default orientation is not +Z forward.
- Example: `setZForward(rootBone); rigMesh.bind(rigMesh.skeleton);`
```
--------------------------------
### IKChain._forward() method for FABRIK algorithm
Source: https://github.com/whatisor/three.ik/blob/master/docs/IKChain.js.html
This method implements the forward pass of the FABRIK (Forward And Backward Reaching Inverse Kinematics) algorithm. It calculates the new positions of the joints starting from the base towards the effector, adjusting them to reach the target position. It handles sub-base chains and updates world positions, ensuring the chain moves towards the target.
```javascript
// Copy the origin so the forward step can use before `_backward()`
// modifies it.
this.origin.copy(this.base._getWorldPosition());
// Set the effector's position to the target's position.
if (this.target) {
this._targetPosition.setFromMatrixPosition(this.target.matrixWorld);
this.effector._setWorldPosition(this._targetPosition);
}
else if (!this.joints[this.joints.length - 1]._isSubBase) {
// If this chain doesn't have additional chains or a target,
// not much to do here.
return;
}
// Apply sub base positions for all joints except the base,
// as we want to possibly write to the base's sub base positions,
// not read from it.
for (let i = 1; i < this.joints.length; i++) {
const joint = this.joints[i];
if (joint._isSubBase) {
joint._applySubBasePositions();
}
}
for (let i = this.joints.length - 1; i > 0; i--) {
const joint = this.joints[i];
const prevJoint = this.joints[i - 1];
const direction = prevJoint._getWorldDirection(joint);
const worldPosition = direction.multiplyScalar(joint.distance).add(joint._getWorldPosition());
// If this chain's base is a sub base, set it's position in
// `_subBaseValues` so that the forward step of the parent chain
// can calculate the centroid and clear the values.
// @TODO Could this have an issue if a subchain `x`'s base
// also had its own subchain `y`, rather than subchain `x`'s
// parent also being subchain `y`'s parent?
if (prevJoint === this.base && this.base._isSubBase) {
this.base._subBasePositions.push(worldPosition);
} else {
prevJoint._setWorldPosition(worldPosition);
}
}
```
--------------------------------
### Get World Position of Three.js Object
Source: https://github.com/whatisor/three.ik/blob/master/docs/utils.js.html
Retrieves the global position of a THREE.Object3D instance and assigns it to a target THREE.Vector3. This function is useful for obtaining an object's absolute position in the scene, independent of its parent transformations.
```javascript
export function getWorldPosition(object, target) {
return target.setFromMatrixPosition(object.matrixWorld);
}
```
--------------------------------
### IKHelper Class API Reference
Source: https://github.com/whatisor/three.ik/blob/master/docs/IKHelper.html
Detailed API documentation for the IKHelper class, including its constructor signature, parameters, and all public members (properties) with their types, descriptions, and default values. This class is designed to visualize an Inverse Kinematics (IK) system.
```APIDOC
Class: IKHelper
Extends: THREE.Object3d
Constructor: new IKHelper(ik, config)
Description: Creates a visualization for an IK system.
Parameters:
ik: [IK] - The IK instance to visualize.
config: Object - Configuration options for the helper.
Properties of config:
color: THREE.Color (optional) - The color for the visualization. Default: new THREE.Color(0xff0077)
showBones: boolean (optional) - Whether this IKHelper's bones are visible or not. Default: true
showAxes: boolean (optional) - Whether this IKHelper's axes are visible or not. Default: true
wireframe: boolean (optional) - Whether this IKHelper should be rendered as wireframes or not. Default: true
axesSize: number (optional) - The size of the axes. (No default specified in doc)
boneSize: number (optional) - The size of the bones. (No default specified in doc)
Members (Properties):
color: THREE.Color
Description: The color of this IKHelper's bones.
Default Value: new THREE.Color(0xff0077)
showAxes: boolean
Description: Whether this IKHelper's axes are visible or not.
Default Value: true
showBones: boolean
Description: Whether this IKHelper's bones are visible or not.
Default Value: true
wireframe: boolean
Description: Whether this IKHelper should be rendered as wireframes or not.
Default Value: true
```
--------------------------------
### IKBallConstraint Class API Reference
Source: https://github.com/whatisor/three.ik/blob/master/docs/IKBallConstraint.js.html
Comprehensive API documentation for the `IKBallConstraint` class, detailing its constructor and the private `_apply` method. This class is designed to enforce angular limits on `IKJoint` instances within a 3D inverse kinematics setup.
```APIDOC
class IKBallConstraint
A class for a constraint.
constructor(angle: number)
Pass in an angle value in degrees.
Parameters:
angle: The angle value in degrees.
_apply(joint: IKJoint): boolean
Applies a constraint to passed in IKJoint, updating its direction if necessary. Returns a boolean indicating if the constraint was applied or not.
Parameters:
joint: The IKJoint instance to apply the constraint to.
Returns:
boolean: True if the constraint was applied, false otherwise.
```
--------------------------------
### Calculate World Distance Between Two Three.js Objects
Source: https://github.com/whatisor/three.ik/blob/master/docs/utils.js.html
Computes the distance between the world positions of two THREE.Object3D instances. It internally uses `getWorldPosition` to get the global coordinates before calculating the Euclidean distance. Note: The original code contains a potential bug where 'a' and 'b' are undefined.
```javascript
export function getWorldDistance(obj1, obj2) {
getWorldPosition(obj1, t1);
getWorldPosition(obj2, t2);
return a.distanceTo(b);
}
```
--------------------------------
### Importing Core Libraries for THREE.IK Application
Source: https://github.com/whatisor/three.ik/blob/master/examples/multi-effector.html
This snippet demonstrates how to import necessary modules for a THREE.IK application. It includes 'three.js' for 3D rendering, 'TransformControls' and 'OrbitControls' for scene interaction, 'three-ik' for inverse kinematics functionalities, and 'dat.gui' for creating a graphical user interface.
```javascript
import * as THREE from 'three';
import { TransformControls } from './node_modules/three/examples/jsm/controls/TransformControls.js';
import { OrbitControls } from './node_modules/three/examples/jsm/controls/OrbitControls.js';
import { IKApp } from './scripts/IKApp.js';
import * as IK from 'three-ik';
import * as dat from 'dat.gui';
```
--------------------------------
### Application Instantiation
Source: https://github.com/whatisor/three.ik/blob/master/examples/multi-effector.html
This line instantiates the `MultiEffector` class and assigns it to `window.app`, making the application accessible globally in the browser's console for debugging or further interaction.
```javascript
window.app = new MultiEffector();
```
--------------------------------
### Build THREE.IK project
Source: https://github.com/whatisor/three.ik/blob/master/README.md
Command to build the THREE.IK project, typically used for generating distribution files.
```shell
$ npm run build
```
--------------------------------
### Project Module Imports Configuration
Source: https://github.com/whatisor/three.ik/blob/master/examples/multi-effector.html
This JSON snippet defines the module import paths for the project, mapping common library names like 'three', 'dat.gui', and 'three-ik' to their respective local file paths. This configuration is typically used in module bundlers or environments supporting import maps.
```json
{
"imports": {
"three": "./node_modules/three/build/three.module.js",
"dat.gui": "./node_modules/dat.gui/build/dat.gui.module.js",
"three-ik": "../build/three-ik.module.js"
}
}
```
--------------------------------
### IK Class API Reference
Source: https://github.com/whatisor/three.ik/blob/master/docs/IK.js.html
Comprehensive API documentation for the `IK` class, detailing its constructor, properties, and methods for managing and solving Inverse Kinematics chains. This includes how to add chains, trigger recalculations, and perform the IK solution.
```APIDOC
class IK {
constructor();
- Description: Creates an IK structure.
- Properties:
- chains: Array - Stores the IK chains added to the system.
- _needsRecalculated: boolean - Internal flag indicating if chain order needs recalculation.
- isIK: boolean - A boolean flag to identify IK instances.
- _orderedChains: Array> - Private, depth-sorted array of chains used for solving.
add(chain: IKChain);
- Description: Adds an IKChain to the IK system.
- Parameters:
- chain: IKChain - The IKChain instance to be added.
- Throws:
- Error: If the provided argument is not an instance of IKChain.
recalculate();
- Description: Internal method called when the IK structure has changed. It reorders the chains into a depth-sorted array (`_orderedChains`) to ensure correct processing during the solve operation.
- Throws:
- Error: If a recursive chain structure is detected within the system.
solve();
- Description: Performs the Inverse Kinematics solution and updates the positions and orientations of the bones within the managed IK chains. It iteratively runs forward and backward steps on the chains until a solution is found or iterations are exhausted.
- Process:
1. Ensures chains are ordered via `recalculate()` if not already.
2. Iterates through ordered sub-chains, performing `_updateJointWorldPositions()`, `_forward()`, and `_backward()` steps.
3. Checks for convergence based on `distanceFromTarget` and `tolerance`.
getRootBone(): THREE.Bone;
- Description: Returns the root bone of this IK structure. Currently, it only returns the bone of the first root chain added to the system.
- Returns:
- THREE.Bone: The root bone of the first IK chain.
```
--------------------------------
### three-ik Library API Reference
Source: https://github.com/whatisor/three.ik/blob/master/examples/multi-effector.html
This section details the core components of the `three-ik` library as used in the provided code, focusing on their instantiation and primary methods for building inverse kinematics structures.
```APIDOC
IK.IK()
- Description: The main Inverse Kinematics solver. Manages a collection of IK chains and solves them to reach their targets.
- Methods:
- add(chain: IKChain): Adds an IKChain to the solver.
- getRootBone(): Returns the root bone of the first chain added to the solver.
IK.IKChain()
- Description: Represents a sequence of connected joints and bones that form a kinematic chain.
- Methods:
- add(joint: IKJoint, options?: { target?: THREE.Object3D }): Adds an IKJoint to the chain. Optionally associates a target object with the joint (typically for the end effector).
- connect(childChain: IKChain): Connects another IKChain as a child to the current chain, forming a hierarchical structure.
IK.IKJoint(bone: THREE.Bone, options?: { constraints?: IKConstraint[] })
- Description: Represents a joint within an IKChain, associated with a THREE.Bone. It can have one or more constraints applied to limit its rotation.
- Parameters:
- bone: The THREE.Bone object associated with this joint.
- options.constraints: An array of IKConstraint objects that apply to this joint.
- Properties:
- constraints: An array of IKConstraint objects currently applied to the joint.
IK.IKBallConstraint(angle: number)
- Description: A type of IKConstraint that limits the rotation of a joint to a cone, defined by a maximum angle from its primary axis.
- Parameters:
- angle: The maximum angle (in degrees) for the ball constraint. A value of 360 means no effective constraint.
- Properties:
- angle: The current angle of the constraint. Can be dynamically updated.
```
--------------------------------
### Three.js IKHelper Class for IK System Visualization
Source: https://github.com/whatisor/three.ik/blob/master/docs/IKHelper.js.html
Implements `IKHelper`, a Three.js `Object3D` subclass designed to visualize an entire Inverse Kinematics (IK) system. It iterates through IK chains and joints to create visual representations using `BoneHelper` instances, providing configurable options for color, bone visibility, axes visibility, and wireframe rendering.
```javascript
import { Object3D, Color, Matrix4, AxesHelper, ArrowHelper, Mesh, ConeGeometry, MeshLambertMaterial, Vector3 } from 'three';
/**
* Class for visualizing an IK system.
* @extends {THREE.Object3d}
*/
class IKHelper extends Object3D {
/**
* Creates a visualization for an IK.
*
* @param {IK} ik
* @param {Object} config
* @param {THREE.Color} [config.color]
* @param {boolean} [config.showBones]
* @param {boolean} [config.showAxes]
* @param {boolean} [config.wireframe]
* @param {number} [config.axesSize]
* @param {number} [config.boneSize]
*/
constructor(ik, { color, showBones, boneSize, showAxes, axesSize, wireframe } = {}) {
super();
boneSize = boneSize || 0.1;
axesSize = axesSize || 0.2;
if (!ik.isIK) {
throw new Error('IKHelper must receive an IK instance.');
}
this.ik = ik;
this._meshes = new Map();
for (let rootChain of this.ik.chains) {
const chainsToMeshify = [rootChain];
while (chainsToMeshify.length) {
const chain = chainsToMeshify.shift();
for (let i = 0; i < chain.joints.length; i++) {
const joint = chain.joints[i];
const nextJoint = chain.joints[i+1];
const distance = nextJoint ? nextJoint.distance : 0;
// If a sub base, don't make another bone
if (chain.base === joint && chain !== rootChain) {
continue;
}
const mesh = new BoneHelper(distance, boneSize, axesSize);
mesh.matrixAutoUpdate = false;
this._meshes.set(joint, mesh);
this.add(mesh);
}
for (let subChains of chain.chains.values()) {
for (let subChain of subChains) {
chainsToMeshify.push(subChain);
}
}
}
}
/**
* Whether this IKHelper's bones are visible or not.
*
* @name IKHelper#showBones
* @type boolean
* @default true
*/
this.showBones = showBones !== undefined ? showBones : true;
/**
* Whether this IKHelper's axes are visible or not.
*
* @name IKHelper#showAxes
* @type boolean
* @default true
*/
this.showAxes = showAxes !== undefined ? showAxes : true;
/**
* Whether this IKHelper should be rendered as wireframes or not.
*
* @name IKHelper#wireframe
* @type boolean
* @default true
*/
this.wireframe = wireframe !== undefined ? wireframe : true;
/**
* The color of this IKHelper's bones.
*
* @name IKHelper#color
* @type THREE.Color
* @default new THREE.Color(0xff0077)
*/
this.color = color || new Color(0xff0077);
}
get showBones() { return this._showBones; }
set showBones(showBones) {
if (showBones === this._showBones) {
return;
}
for (let [joint, mesh] of this._meshes) {
if (showBones) {
mesh.add(mesh.boneMesh);
} else {
mesh.remove(mesh.boneMesh);
}
}
this._showBones = showBones;
}
get showAxes() { return this._showAxes; }
set showAxes(showAxes) {
if (showAxes === this._showAxes) {
return;
}
for (let [joint, mesh] of this._meshes) {
```
--------------------------------
### JavaScript Module Imports for Three.js IK Application
Source: https://github.com/whatisor/three.ik/blob/master/examples/single-target.html
Imports essential modules required for the Three.js inverse kinematics demonstration. This includes the core Three.js library, camera controls (TransformControls, OrbitControls), the `three-ik` library, `dat.gui` for UI, and a custom `IKApp` base class.
```javascript
import * as THREE from 'three';
import { TransformControls } from './node_modules/three/examples/jsm/controls/TransformControls.js';
import { OrbitControls } from './node_modules/three/examples/jsm/controls/OrbitControls.js';
import { IKApp } from './scripts/IKApp.js';
import * as IK from 'three-ik';
import * as dat from 'dat.gui';
```