2
0
Greg Tatum 10 жил өмнө
parent
commit
949f971e2d

+ 19 - 2
docs/api/core/Geometry.html

@@ -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>

+ 17 - 8
docs/api/objects/Bone.html

@@ -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>
 
 

+ 128 - 0
docs/api/objects/Skeleton.html

@@ -0,0 +1,128 @@
+<!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>

+ 41 - 8
docs/api/objects/SkinnedMesh.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>
 
 

+ 1 - 0
docs/list.js

@@ -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" ]
 		],
 

+ 271 - 0
docs/scenes/bones-browser.html

@@ -0,0 +1,271 @@
+<!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>