提交 949f971e 编写于 作者: G Greg Tatum

Skinning docs

上级 b7f7cb2a
......@@ -102,12 +102,29 @@
<h3>[property:Array skinWeights]</h3>
<div>
Array of skinning weights, matching number and order of vertices.
Array of [page:Vector4 Vector4s] representing the skinning weights as used in a [page:SkinnedMesh],
The weights match the number and order of vertices in the geometry. The weighted values
are typically between the values of 0 and 1 and affect the amount that the individuals bones affect
a given vertex.
</div>
<h3>[property:Array skinIndices]</h3>
<div>
Array of skinning indices, matching number and order of vertices.
Array of [page:Vector4 Vector4s] representing the indices of individual bones in the [page:Skeleton.bones] array,
The indices match the number and order of vertices in the geometry.
<code>
geometry.skinIndices[15] = new THREE.Vector4( 0, 5, 9, 0 );
geometry.skinWeights[15] = new THREE.Vector4( 0.2, 0.5, 0.3, 0 );
// corresponds with the following vertex
geometry.vertices[15]
// these bones will be used like so:
skeleton.bones[0]; // weight of 0.2
skeleton.bones[5]; // weight of 0.5
skeleton.bones[9]; // weight of 0.3
skeleton.bones[0]; // weight of 0
</code>
</div>
<h3>[property:Object boundingBox]</h3>
......
......@@ -11,25 +11,34 @@
<h1>[name]</h1>
<div class="desc">A bone which is part of a [page:SkinnedMesh].</div>
<div class="desc">
A bone which is part of a [page:Skeleton]. The skeleton in turn is used by the [page:SkinnedMesh].
Bones are almost identical to a blank [page:Object3D].
</div>
<h3>Example</h3>
<code>
var root = new THREE.Bone();
var child = new THREE.Bone();
root.add( child );
child.position.y = 5;
</code>
<h2>Constructor</h2>
<h3>[name]([page:SkinnedMesh belongsToSkin])</h3>
<div>
belongsToSkin -- An instance of [page:SkinnedMesh].
</div>
<h3>[name]([page:SkinnedMesh skin])</h3>
<div>
This creates a new instance of a bone from the skin.
skin — (optional) The [page:SkinnedMesh] to which the bone belongs.
</div>
<h2>Properties</h2>
<h3>[property:SkinnedMesh skin]</h3>
<div>
The skin that contains this bone.
An optional reference to the [page:SkinnedMesh].
</div>
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="../../list.js"></script>
<script src="../../page.js"></script>
<link type="text/css" rel="stylesheet" href="../../page.css" />
</head>
<body>
<h1>[name]</h1>
<div class="desc">
Use an array of [page:Bone bones] to create a skeleton that can be used by a [page:SkinnedMesh].
WebGL only.
</div>
<h2>Example</h2>
<code>
// Create a simple "arm"
var bones = [];
var shoulder = new THREE.Bone();
var elbow = new THREE.Bone();
var hand = new THREE.Bone();
shoulder.add( elbow );
elbow.add( hand );
bones.push( shoulder );
bones.push( elbow );
bones.push( hand );
shoulder.position.y = -5;
elbow.position.y = 0;
hand.position.y = 5;
var armSkeleton = THREE.Skeleton( bones );
// See THREE.SkinnedMesh for an example of usage with a mesh
</code>
<h2>Constructor</h2>
<h3>[name]( [page:Array bones], [page:Array boneInverses], [page:Boolean useVertexTexture] )</h3>
<div>
bones — The array of [page:bone bones]<br/>
boneInverses — (optional) An array of [page:Matrix4 Matrix4s]<br/>
useVertexTexture — (optional) Whether or not to use a vertex texture in the shader.
</div>
<div>
The constructor automatically sets up all of the properties below.
</div>
<h2>Properties</h2>
<h3>[property:Array bones]</h3>
<div>
The array of [page:bone bones]
</div>
<h3>[property:Boolean useVertexTexture]</h3>
<div>
Whether or not to use a vertex texture in the shader, set in the constructor. Not all devices
support floating point pixel textures. If this option is set then the bone matrices will be packed into
a texture and sent to the shader. This method allows a much larger set of bones to be used. Otherwise
the vertex shader will use uniforms, which do not allow for as many bones to be used. The exact
numbers vary between devices.
</div>
<h3>[property:Array boneInverses]</h3>
<div>
An array of [page:Matrix4 Matrix4s] that represent the inverse of the matrixWorld of the individual bones.
</div>
<h3>[property:Integer boneTextureWidth]</h3>
<div>
The width of the vertex data texture.
</div>
<h3>[property:Integer boneTextureHeight]</h3>
<div>
The height of the vertex data texture.
</div>
<h3>[property:Float32Array boneMatrices]</h3>
<div>
The array buffer holding the bone data when using a vertex texture.
</div>
<h3>[property:DataTexture boneTexture]</h3>
<div>
The [page:DataTexture] holding the bone data when using a vertex texture.
</div>
<h2>Methods</h2>
<h3>[method:null calculateInverses]()</h3>
<div>Generates the boneInverses.</div>
<h3>[method:null pose]()</h3>
<div>Returns the skeleton to the base pose.</div>
<h3>[method:null update]()</h3>
<div>
Updates the [page:Float32Array boneMatrices] and [page:DataTexture boneTexture] after changing the bones.
This is called automatically by the [page:WebGLRenderer] if the skeleton is used with a [page:SkinnedMesh].
</div>
<h2>Source</h2>
[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
</body>
</html>
......@@ -11,20 +11,53 @@
<h1>[name]</h1>
<div class="desc">An 3d object that has bones data. These Bones can then be used to animate the vertices of the object.</div>
<div class="desc">A mesh that has a [page:Skeleton] with [page:Bone bones] that can then be used to animate the vertices of the geometry.</div>
<h2>Example</h2>
<iframe src='../../scenes/bones-browser.html'></iframe>
<code>
var geometry = new THREE.CylinderGeometry( 5, 5, 5, 5, 15, 5, 30 );
//Create the skin indices and skin weights
for( var i=0; i < geometry.vertices.length; i++ ) {
// Imaginary functions to calculate the indices and weights
var skinIndex = calculateSkinIndex( geometry.vertices, i );
var skinWeight = calculateSkinWeight( geometry.vertices, i );
// Ease between each bone
geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex+1, 0, 0 ) );
geometry.skinWeights.push( new THREE.Vector4( 1-skinWeight, skinWeight, 0, 0 ) );
}
var mesh = THREE.SkinnedMesh( geometry, material );
// See example from THREE.Skeleton for the armSkeleton
mesh.bind( armSkeleton );
// Add the root bone, then recalculate the skeleton inverses
mesh.add( armSkeleton.bones[0] );
mesh.updateMatrixWorld( true ); // ensure the bones matrices are already recomputed
skeleton.calculateInverses();
// Move the bones and manipulate the model
armSkeleton.bones[0].rotation.x = -0.1;
armSkeleton.bones[1].rotation.x = 0.2;
</code>
<h2>Constructor</h2>
<h3>[name]([page:Geometry geometry], [page:Material material], [page:boolean useVertexTexture])</h3>
<div>
geometry — An instance of [page:Geometry].<br />
material — An instance of [page:Material] (optional).<br />
useVertexTexture -- Defines wether a vertex texture can be used (optional).
</div>
<div>
This Creates a new instance of skinnedMesh.
geometry —- An instance of [page:Geometry]. [page:Geometry.skinIndices] and [page:Geometry.skinWeights] should be set.<br />
material —- An instance of [page:Material] (optional).<br />
useVertexTexture -- Defines whether a vertex texture can be used (optional).
</div>
......
......@@ -116,6 +116,7 @@ var list = {
[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
[ "PointCloud", "api/objects/PointCloud" ],
[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
[ "Skeleton", "api/objects/Skeleton" ],
[ "Sprite", "api/objects/Sprite" ]
],
......
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Three.js Bones Browser</title>
<style>
@font-face {
font-family: 'inconsolata';
src: url('../files/inconsolata.woff') format('woff');
font-weight: normal;
font-style: normal;
}
body {
margin:0;
font-family: 'inconsolata';
font-size: 15px;
line-height: 18px;
overflow: hidden;
}
canvas { width: 100%; height: 100% }
#newWindow {
display: block;
position: absolute;
bottom: 0.3em;
left: 0.5em;
color: #fff;
}
</style>
</head>
<body>
<a id='newWindow' href='./bones-browser.html' target='_blank'>Open in New Window</a>
<script src="../../build/three.min.js"></script>
<script src='../../examples/js/libs/dat.gui.min.js'></script>
<script src="../../examples/js/controls/OrbitControls.js"></script>
<script>
var gui, scene, camera, renderer, orbit, ambientLight, lights, mesh, bones, skeletonHelper;
var state = {
animateBones : false
};
function initScene () {
gui = new dat.GUI();
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 200 );
camera.position.z = 30;
camera.position.y = 30;
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
orbit = new THREE.OrbitControls( camera, renderer.domElement );
orbit.noZoom = true;
ambientLight = new THREE.AmbientLight( 0x000000 );
scene.add( ambientLight );
lights = [];
lights[0] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[1] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[2] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[0].position.set( 0, 200, 0 );
lights[1].position.set( 100, 200, 100 );
lights[2].position.set( -100, -200, -100 );
scene.add( lights[0] );
scene.add( lights[1] );
scene.add( lights[2] );
window.addEventListener( 'resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
initBones();
setupDatGui();
}
function createGeometry ( sizing ) {
var geometry = new THREE.CylinderGeometry(
5, // radiusTop
5, // radiusBottom
sizing.height, // height
8, // radiusSegments
sizing.segmentCount * 3, // heightSegments
true // openEnded
);
for( var i=0; i < geometry.vertices.length; i++ ) {
var vertex = geometry.vertices[i];
var y = (vertex.y + sizing.halfHeight);
var skinIndex = Math.floor( y / sizing.segmentHeight );
var skinWeight = (y % sizing.segmentHeight) / sizing.segmentHeight;
geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex+1, 0, 0 ) );
geometry.skinWeights.push( new THREE.Vector4( 1-skinWeight, skinWeight, 0, 0 ) );
}
return geometry;
};
function createBones ( sizing ) {
bones = [];
var prevBone = new THREE.Bone();
bones.push( prevBone );
prevBone.position.y = -sizing.halfHeight;
for( var i=0; i < sizing.segmentCount; i++ ) {
var bone = new THREE.Bone();
bone.position.y = sizing.segmentHeight;
bones.push( bone );
prevBone.add( bone );
prevBone = bone;
}
return bones;
};
function createMesh ( geometry, bones ) {
var material = new THREE.MeshPhongMaterial({
skinning : true,
color: 0x156289,
emissive: 0x072534,
side: THREE.DoubleSide,
shading: THREE.FlatShading
});
var mesh = new THREE.SkinnedMesh(
geometry,
material
);
var skeleton = new THREE.Skeleton( bones );
mesh.bind( skeleton );
mesh.add( bones[0] );
mesh.updateMatrixWorld( true );
skeleton.calculateInverses();
skeletonHelper = new THREE.SkeletonHelper( mesh );
skeletonHelper.material.linewidth = 2;
scene.add( skeletonHelper );
return mesh;
};
function setupDatGui () {
var folder = gui.addFolder( "General Options" );
folder.add( state, "animateBones" );
folder.__controllers[0].name("Animate Bones")
folder.add( mesh, "pose" );
folder.__controllers[1].name(".pose()");
var bones = mesh.skeleton.bones;
for( var i=0; i < bones.length; i++ ) {
var bone = bones[i]
folder = gui.addFolder( "Bone " + i );
folder.add( bone.position, 'x', -10 + bone.position.x, 10 + bone.position.x );
folder.add( bone.position, 'y', -10 + bone.position.y, 10 + bone.position.y );
folder.add( bone.position, 'z', -10 + bone.position.z, 10 + bone.position.z );
folder.add( bone.rotation, 'x', -Math.PI * 0.5, Math.PI * 0.5 );
folder.add( bone.rotation, 'y', -Math.PI * 0.5, Math.PI * 0.5 );
folder.add( bone.rotation, 'z', -Math.PI * 0.5, Math.PI * 0.5 );
folder.add( bone.scale, 'x', 0, 2 );
folder.add( bone.scale, 'y', 0, 2 );
folder.add( bone.scale, 'z', 0, 2 );
folder.__controllers[0].name("position.x")
folder.__controllers[1].name("position.y")
folder.__controllers[2].name("position.z")
folder.__controllers[3].name("rotation.x")
folder.__controllers[4].name("rotation.y")
folder.__controllers[5].name("rotation.z")
folder.__controllers[6].name("scale.x")
folder.__controllers[7].name("scale.y")
folder.__controllers[8].name("scale.z")
}
}
function initBones () {
var segmentHeight = 8;
var segmentCount = 4;
var height = segmentHeight * segmentCount
var halfHeight = height * 0.5
var sizing = {
segmentHeight : segmentHeight,
segmentCount : segmentCount,
height : height,
halfHeight : halfHeight
};
var geometry = createGeometry( sizing );
var bones = createBones( sizing );
mesh = createMesh( geometry, bones );
mesh.scale.multiplyScalar( 1 );
scene.add( mesh );
};
function render () {
requestAnimationFrame( render );
var time = Date.now() * 0.001;
var bone = mesh;
//Wiggle the bones
if( state.animateBones ) {
for( var i=0; i < mesh.skeleton.bones.length; i++ ) {
mesh.skeleton.bones[i].rotation.z = Math.sin( time ) * 2 / mesh.skeleton.bones.length;
}
}
skeletonHelper.update();
renderer.render( scene, camera );
};
initScene();
render();
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册