1
0

webgl_geometry_extrude_splines.html 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>three.js webgl - geometry - spline extrusion</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  7. <style>
  8. body {
  9. font-family: Monospace;
  10. background-color: #f0f0f0;
  11. margin: 0px;
  12. overflow: hidden;
  13. }
  14. #info {
  15. position: absolute;
  16. top: 0px;
  17. width: 100%;
  18. padding: 5px;
  19. font-family:Monospace;
  20. font-size:13px;
  21. text-align:center;
  22. }
  23. </style>
  24. </head>
  25. <body>
  26. <div id="container"></div>
  27. <div id="info"><a href="https://threejs.org" target="_blank">three.js</a> - geometry - spline extrusion examples by <a href="http://www.lab4games.net/zz85/blog" target="_blank">zz85</a></div>
  28. <script src="../build/three.js"></script>
  29. <script src="js/controls/OrbitControls.js"></script>
  30. <!-- where curves formulas are defined -->
  31. <script src="js/CurveExtras.js"></script>
  32. <script src="js/libs/stats.min.js"></script>
  33. <script src="js/libs/dat.gui.min.js"></script>
  34. <script>
  35. var container, stats;
  36. var camera, scene, renderer, splineCamera, cameraHelper, cameraEye;
  37. var binormal = new THREE.Vector3();
  38. var normal = new THREE.Vector3();
  39. var pipeSpline = new THREE.CatmullRomCurve3( [
  40. new THREE.Vector3( 0, 10, -10 ), new THREE.Vector3( 10, 0, -10 ),
  41. new THREE.Vector3( 20, 0, 0 ), new THREE.Vector3( 30, 0, 10 ),
  42. new THREE.Vector3( 30, 0, 20 ), new THREE.Vector3( 20, 0, 30 ),
  43. new THREE.Vector3( 10, 0, 30 ), new THREE.Vector3( 0, 0, 30 ),
  44. new THREE.Vector3( -10, 10, 30 ), new THREE.Vector3( -10, 20, 30 ),
  45. new THREE.Vector3( 0, 30, 30 ), new THREE.Vector3( 10, 30, 30 ),
  46. new THREE.Vector3( 20, 30, 15 ), new THREE.Vector3( 10, 30, 10 ),
  47. new THREE.Vector3( 0, 30, 10 ), new THREE.Vector3( -10, 20, 10 ),
  48. new THREE.Vector3( -10, 10, 10 ), new THREE.Vector3( 0, 0, 10 ),
  49. new THREE.Vector3( 10, -10, 10 ), new THREE.Vector3( 20, -15, 10 ),
  50. new THREE.Vector3( 30, -15, 10 ), new THREE.Vector3( 40, -15, 10 ),
  51. new THREE.Vector3( 50, -15, 10 ), new THREE.Vector3( 60, 0, 10 ),
  52. new THREE.Vector3( 70, 0, 0 ), new THREE.Vector3( 80, 0, 0 ),
  53. new THREE.Vector3( 90, 0, 0 ), new THREE.Vector3( 100, 0, 0 )
  54. ] );
  55. var sampleClosedSpline = new THREE.CatmullRomCurve3( [
  56. new THREE.Vector3( 0, -40, -40 ),
  57. new THREE.Vector3( 0, 40, -40 ),
  58. new THREE.Vector3( 0, 140, -40 ),
  59. new THREE.Vector3( 0, 40, 40 ),
  60. new THREE.Vector3( 0, -40, 40 )
  61. ] );
  62. sampleClosedSpline.type = 'catmullrom';
  63. sampleClosedSpline.closed = true;
  64. // Keep a dictionary of Curve instances
  65. var splines = {
  66. GrannyKnot: new THREE.Curves.GrannyKnot(),
  67. HeartCurve: new THREE.Curves.HeartCurve( 3.5 ),
  68. VivianiCurve: new THREE.Curves.VivianiCurve( 70 ),
  69. KnotCurve: new THREE.Curves.KnotCurve(),
  70. HelixCurve: new THREE.Curves.HelixCurve(),
  71. TrefoilKnot: new THREE.Curves.TrefoilKnot(),
  72. TorusKnot: new THREE.Curves.TorusKnot( 20 ),
  73. CinquefoilKnot: new THREE.Curves.CinquefoilKnot( 20 ),
  74. TrefoilPolynomialKnot: new THREE.Curves.TrefoilPolynomialKnot( 14 ),
  75. FigureEightPolynomialKnot: new THREE.Curves.FigureEightPolynomialKnot(),
  76. DecoratedTorusKnot4a: new THREE.Curves.DecoratedTorusKnot4a(),
  77. DecoratedTorusKnot4b: new THREE.Curves.DecoratedTorusKnot4b(),
  78. DecoratedTorusKnot5a: new THREE.Curves.DecoratedTorusKnot5a(),
  79. DecoratedTorusKnot5c: new THREE.Curves.DecoratedTorusKnot5c(),
  80. PipeSpline: pipeSpline,
  81. SampleClosedSpline: sampleClosedSpline
  82. };
  83. var parent, tube, tubeMesh;
  84. var params = {
  85. spline: 'GrannyKnot',
  86. scale: 4,
  87. extrusionSegments: 100,
  88. radiusSegments: 3,
  89. closed: true,
  90. animationView: false,
  91. lookAhead: false,
  92. cameraHelper: false,
  93. };
  94. function addTube() {
  95. if ( tubeMesh !== undefined ) parent.remove( tubeMesh );
  96. extrudePath = splines[ params.spline ];
  97. tube = new THREE.TubeBufferGeometry( extrudePath, params.extrusionSegments, 2, params.radiusSegments, params.closed );
  98. addGeometry( tube, 0xff00ff );
  99. setScale();
  100. }
  101. function setScale() {
  102. tubeMesh.scale.set( params.scale, params.scale, params.scale );
  103. }
  104. function addGeometry( geometry, color ) {
  105. // 3D shape
  106. tubeMesh = THREE.SceneUtils.createMultiMaterialObject( geometry, [
  107. new THREE.MeshLambertMaterial( {
  108. color: color
  109. } ),
  110. new THREE.MeshBasicMaterial( {
  111. color: 0x000000,
  112. opacity: 0.3,
  113. wireframe: true,
  114. transparent: true
  115. } ) ] );
  116. parent.add( tubeMesh );
  117. }
  118. function animateCamera() {
  119. cameraHelper.visible = params.cameraHelper;
  120. cameraEye.visible = params.cameraHelper;
  121. }
  122. init();
  123. animate();
  124. function init() {
  125. container = document.getElementById( 'container' );
  126. // camera
  127. camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 10000 );
  128. camera.position.set( 0, 50, 500 );
  129. // scene
  130. scene = new THREE.Scene();
  131. // light
  132. var light = new THREE.DirectionalLight( 0xffffff );
  133. light.position.set( 0, 0, 1 );
  134. scene.add( light );
  135. // tube
  136. parent = new THREE.Object3D();
  137. scene.add( parent );
  138. splineCamera = new THREE.PerspectiveCamera( 84, window.innerWidth / window.innerHeight, 0.01, 1000 );
  139. parent.add( splineCamera );
  140. cameraHelper = new THREE.CameraHelper( splineCamera );
  141. scene.add( cameraHelper );
  142. addTube();
  143. // debug camera
  144. cameraEye = new THREE.Mesh( new THREE.SphereGeometry( 5 ), new THREE.MeshBasicMaterial( { color: 0xdddddd } ) );
  145. parent.add( cameraEye );
  146. cameraHelper.visible = params.cameraHelper;
  147. cameraEye.visible = params.cameraHelper;
  148. // renderer
  149. renderer = new THREE.WebGLRenderer( { antialias: true } );
  150. renderer.setClearColor( 0xf0f0f0 );
  151. renderer.setPixelRatio( window.devicePixelRatio );
  152. renderer.setSize( window.innerWidth, window.innerHeight );
  153. container.appendChild( renderer.domElement );
  154. // stats
  155. stats = new Stats();
  156. container.appendChild( stats.dom );
  157. // dat.GUI
  158. var gui = new dat.GUI( { width: 300 } );
  159. var folderGeometry = gui.addFolder( 'Geometry' );
  160. folderGeometry.add( params, 'spline', Object.keys( splines ) ).onChange( function( value ) { addTube(); } );
  161. folderGeometry.add( params, 'scale', 2, 10 ).step( 2 ).onChange( function( value ) { setScale(); } );
  162. folderGeometry.add( params, 'extrusionSegments', 50, 500 ).step( 50 ).onChange( function( value ) { addTube(); } );
  163. folderGeometry.add( params, 'radiusSegments', 2, 12 ).step( 1 ).onChange( function( value ) { addTube(); } );
  164. folderGeometry.add( params, 'closed').onChange( function( value ) { addTube(); } );
  165. folderGeometry.open();
  166. var folderCamera = gui.addFolder( 'Camera' );
  167. folderCamera.add( params, 'animationView').onChange( function( value ) { animateCamera( true ); } );
  168. folderCamera.add( params, 'lookAhead').onChange( function( value ) { animateCamera(); } );
  169. folderCamera.add( params, 'cameraHelper').onChange( function( value ) { animateCamera(); } );
  170. folderCamera.open();
  171. // controls
  172. controls = new THREE.OrbitControls( camera, renderer.domElement );
  173. // event listener
  174. window.addEventListener( 'resize', onWindowResize, false );
  175. }
  176. function onWindowResize() {
  177. camera.aspect = window.innerWidth / window.innerHeight;
  178. camera.updateProjectionMatrix();
  179. renderer.setSize( window.innerWidth, window.innerHeight );
  180. }
  181. //
  182. function animate() {
  183. requestAnimationFrame( animate );
  184. render();
  185. stats.update();
  186. }
  187. function render() {
  188. // animate camera along spline
  189. var time = Date.now();
  190. var looptime = 20 * 1000;
  191. var t = ( time % looptime ) / looptime;
  192. var pos = tube.parameters.path.getPointAt( t );
  193. pos.multiplyScalar( params.scale );
  194. // interpolation
  195. var segments = tube.tangents.length;
  196. var pickt = t * segments;
  197. var pick = Math.floor( pickt );
  198. var pickNext = ( pick + 1 ) % segments;
  199. binormal.subVectors( tube.binormals[ pickNext ], tube.binormals[ pick ] );
  200. binormal.multiplyScalar( pickt - pick ).add( tube.binormals[ pick ] );
  201. var dir = tube.parameters.path.getTangentAt( t );
  202. var offset = 15;
  203. normal.copy( binormal ).cross( dir );
  204. // we move on a offset on its binormal
  205. pos.add( normal.clone().multiplyScalar( offset ) );
  206. splineCamera.position.copy( pos );
  207. cameraEye.position.copy( pos );
  208. // using arclength for stablization in look ahead
  209. var lookAt = tube.parameters.path.getPointAt( ( t + 30 / tube.parameters.path.getLength() ) % 1 ).multiplyScalar( params.scale );
  210. // camera orientation 2 - up orientation via normal
  211. if ( ! params.lookAhead ) lookAt.copy( pos ).add( dir );
  212. splineCamera.matrix.lookAt( splineCamera.position, lookAt, normal );
  213. splineCamera.rotation.setFromRotationMatrix( splineCamera.matrix, splineCamera.rotation.order );
  214. cameraHelper.update();
  215. renderer.render( scene, params.animationView === true ? splineCamera : camera );
  216. }
  217. </script>
  218. </body>
  219. </html>
粤ICP备19079148号