bones-browser.html 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>Three.js Bones Browser</title>
  6. <link rel="shortcut icon" href="../../files/favicon.ico" />
  7. <link rel="stylesheet" type="text/css" href="../../files/main.css">
  8. <style>
  9. canvas { width: 100%; height: 100% }
  10. #newWindow {
  11. display: block;
  12. position: absolute;
  13. bottom: 0.3em;
  14. left: 0.5em;
  15. color: #fff;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <a id='newWindow' href='./bones-browser.html' target='_blank'>Open in New Window</a>
  21. <script src="../../build/three.min.js"></script>
  22. <script src='../../examples/js/libs/dat.gui.min.js'></script>
  23. <script src="../../examples/js/controls/OrbitControls.js"></script>
  24. <script>
  25. var gui, scene, camera, renderer, orbit, lights, mesh, bones, skeletonHelper;
  26. var state = {
  27. animateBones: false
  28. };
  29. function initScene() {
  30. gui = new dat.GUI();
  31. scene = new THREE.Scene();
  32. scene.background = new THREE.Color( 0x444444 );
  33. camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 200 );
  34. camera.position.z = 30;
  35. camera.position.y = 30;
  36. renderer = new THREE.WebGLRenderer( { antialias: true } );
  37. renderer.setPixelRatio( window.devicePixelRatio );
  38. renderer.setSize( window.innerWidth, window.innerHeight );
  39. document.body.appendChild( renderer.domElement );
  40. orbit = new THREE.OrbitControls( camera, renderer.domElement );
  41. orbit.enableZoom = false;
  42. lights = [];
  43. lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
  44. lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
  45. lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
  46. lights[ 0 ].position.set( 0, 200, 0 );
  47. lights[ 1 ].position.set( 100, 200, 100 );
  48. lights[ 2 ].position.set( - 100, - 200, - 100 );
  49. scene.add( lights[ 0 ] );
  50. scene.add( lights[ 1 ] );
  51. scene.add( lights[ 2 ] );
  52. window.addEventListener( 'resize', function () {
  53. camera.aspect = window.innerWidth / window.innerHeight;
  54. camera.updateProjectionMatrix();
  55. renderer.setSize( window.innerWidth, window.innerHeight );
  56. }, false );
  57. initBones();
  58. setupDatGui();
  59. }
  60. function createGeometry( sizing ) {
  61. var geometry = new THREE.CylinderBufferGeometry(
  62. 5, // radiusTop
  63. 5, // radiusBottom
  64. sizing.height, // height
  65. 8, // radiusSegments
  66. sizing.segmentCount * 3, // heightSegments
  67. true // openEnded
  68. );
  69. var position = geometry.attributes.position;
  70. var vertex = new THREE.Vector3();
  71. var skinIndices = [];
  72. var skinWeights = [];
  73. for ( var i = 0; i < position.count; i ++ ) {
  74. vertex.fromBufferAttribute( position, i );
  75. var y = ( vertex.y + sizing.halfHeight );
  76. var skinIndex = Math.floor( y / sizing.segmentHeight );
  77. var skinWeight = ( y % sizing.segmentHeight ) / sizing.segmentHeight;
  78. skinIndices.push( skinIndex, skinIndex + 1, 0, 0 );
  79. skinWeights.push( 1 - skinWeight, skinWeight, 0, 0 );
  80. }
  81. geometry.addAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4 ) );
  82. geometry.addAttribute( 'skinWeight', new THREE.Float32BufferAttribute( skinWeights, 4 ) );
  83. return geometry;
  84. }
  85. function createBones( sizing ) {
  86. bones = [];
  87. var prevBone = new THREE.Bone();
  88. bones.push( prevBone );
  89. prevBone.position.y = - sizing.halfHeight;
  90. for ( var i = 0; i < sizing.segmentCount; i ++ ) {
  91. var bone = new THREE.Bone();
  92. bone.position.y = sizing.segmentHeight;
  93. bones.push( bone );
  94. prevBone.add( bone );
  95. prevBone = bone;
  96. }
  97. return bones;
  98. }
  99. function createMesh( geometry, bones ) {
  100. var material = new THREE.MeshPhongMaterial( {
  101. skinning: true,
  102. color: 0x156289,
  103. emissive: 0x072534,
  104. side: THREE.DoubleSide,
  105. flatShading: true
  106. } );
  107. var mesh = new THREE.SkinnedMesh( geometry, material );
  108. var skeleton = new THREE.Skeleton( bones );
  109. mesh.add( bones[ 0 ] );
  110. mesh.bind( skeleton );
  111. skeletonHelper = new THREE.SkeletonHelper( mesh );
  112. skeletonHelper.material.linewidth = 2;
  113. scene.add( skeletonHelper );
  114. return mesh;
  115. }
  116. function setupDatGui() {
  117. var folder = gui.addFolder( "General Options" );
  118. folder.add( state, "animateBones" );
  119. folder.__controllers[ 0 ].name( "Animate Bones" );
  120. folder.add( mesh, "pose" );
  121. folder.__controllers[ 1 ].name( ".pose()" );
  122. var bones = mesh.skeleton.bones;
  123. for ( var i = 0; i < bones.length; i ++ ) {
  124. var bone = bones[ i ];
  125. folder = gui.addFolder( "Bone " + i );
  126. folder.add( bone.position, 'x', - 10 + bone.position.x, 10 + bone.position.x );
  127. folder.add( bone.position, 'y', - 10 + bone.position.y, 10 + bone.position.y );
  128. folder.add( bone.position, 'z', - 10 + bone.position.z, 10 + bone.position.z );
  129. folder.add( bone.rotation, 'x', - Math.PI * 0.5, Math.PI * 0.5 );
  130. folder.add( bone.rotation, 'y', - Math.PI * 0.5, Math.PI * 0.5 );
  131. folder.add( bone.rotation, 'z', - Math.PI * 0.5, Math.PI * 0.5 );
  132. folder.add( bone.scale, 'x', 0, 2 );
  133. folder.add( bone.scale, 'y', 0, 2 );
  134. folder.add( bone.scale, 'z', 0, 2 );
  135. folder.__controllers[ 0 ].name( "position.x" );
  136. folder.__controllers[ 1 ].name( "position.y" );
  137. folder.__controllers[ 2 ].name( "position.z" );
  138. folder.__controllers[ 3 ].name( "rotation.x" );
  139. folder.__controllers[ 4 ].name( "rotation.y" );
  140. folder.__controllers[ 5 ].name( "rotation.z" );
  141. folder.__controllers[ 6 ].name( "scale.x" );
  142. folder.__controllers[ 7 ].name( "scale.y" );
  143. folder.__controllers[ 8 ].name( "scale.z" );
  144. }
  145. }
  146. function initBones() {
  147. var segmentHeight = 8;
  148. var segmentCount = 4;
  149. var height = segmentHeight * segmentCount;
  150. var halfHeight = height * 0.5;
  151. var sizing = {
  152. segmentHeight: segmentHeight,
  153. segmentCount: segmentCount,
  154. height: height,
  155. halfHeight: halfHeight
  156. };
  157. var geometry = createGeometry( sizing );
  158. var bones = createBones( sizing );
  159. mesh = createMesh( geometry, bones );
  160. mesh.scale.multiplyScalar( 1 );
  161. scene.add( mesh );
  162. }
  163. function render() {
  164. requestAnimationFrame( render );
  165. var time = Date.now() * 0.001;
  166. //Wiggle the bones
  167. if ( state.animateBones ) {
  168. for ( var i = 0; i < mesh.skeleton.bones.length; i ++ ) {
  169. mesh.skeleton.bones[ i ].rotation.z = Math.sin( time ) * 2 / mesh.skeleton.bones.length;
  170. }
  171. }
  172. renderer.render( scene, camera );
  173. }
  174. initScene();
  175. render();
  176. </script>
  177. </body>
  178. </html>