physics_rapier_joints.html 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <title>three.js physics - rapier3d joints</title>
  5. <meta charset="utf-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  7. <meta property="og:title" content="three.js physics - rapier3d joints">
  8. <meta property="og:type" content="website">
  9. <meta property="og:url" content="https://threejs.org/examples/physics_rapier_joints.html">
  10. <meta property="og:image" content="https://threejs.org/examples/screenshots/physics_rapier_joints.jpg">
  11. <link type="text/css" rel="stylesheet" href="main.css">
  12. <style>
  13. body {
  14. color: #333;
  15. }
  16. </style>
  17. </head>
  18. <body>
  19. <div id="info">
  20. <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> physics - <a href="https://github.com/dimforge/rapier.js" target="_blank">rapier</a> joints
  21. </div>
  22. <script type="importmap">
  23. {
  24. "imports": {
  25. "three": "../build/three.module.js",
  26. "three/addons/": "./jsm/"
  27. }
  28. }
  29. </script>
  30. <script type="module">
  31. import * as THREE from 'three';
  32. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  33. import { RapierPhysics } from 'three/addons/physics/RapierPhysics.js';
  34. import { RapierHelper } from 'three/addons/helpers/RapierHelper.js';
  35. import Stats from 'three/addons/libs/stats.module.js';
  36. let camera, scene, renderer, stats;
  37. let physics, pivot, physicsHelper;
  38. init();
  39. async function init() {
  40. scene = new THREE.Scene();
  41. scene.background = new THREE.Color( 0xbfd1e5 );
  42. camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.1, 100 );
  43. camera.position.set( 0, 3, 10 );
  44. const ambient = new THREE.HemisphereLight( 0x555555, 0xFFFFFF );
  45. scene.add( ambient );
  46. const light = new THREE.DirectionalLight( 0xffffff, 4 );
  47. light.position.set( 0, 12.5, 12.5 );
  48. light.castShadow = true;
  49. light.shadow.radius = 3;
  50. light.shadow.blurSamples = 8;
  51. light.shadow.mapSize.width = 1024;
  52. light.shadow.mapSize.height = 1024;
  53. const size = 10;
  54. light.shadow.camera.left = - size;
  55. light.shadow.camera.bottom = - size;
  56. light.shadow.camera.right = size;
  57. light.shadow.camera.top = size;
  58. light.shadow.camera.near = 1;
  59. light.shadow.camera.far = 50;
  60. scene.add( light );
  61. renderer = new THREE.WebGLRenderer( { antialias: true } );
  62. renderer.setPixelRatio( window.devicePixelRatio );
  63. renderer.setSize( window.innerWidth, window.innerHeight );
  64. renderer.shadowMap.enabled = true;
  65. document.body.appendChild( renderer.domElement );
  66. renderer.setAnimationLoop( animate );
  67. const controls = new OrbitControls( camera, renderer.domElement );
  68. controls.target = new THREE.Vector3( 0, 2, 0 );
  69. controls.update();
  70. stats = new Stats();
  71. document.body.appendChild( stats.dom );
  72. //Create pivot point
  73. const geometry = new THREE.SphereGeometry( 0.5 );
  74. const material = new THREE.MeshStandardMaterial( { color: 0xFF0000 } );
  75. pivot = new THREE.Mesh( geometry, material );
  76. pivot.position.y = 6;
  77. pivot.userData.physics = { mass: 0 };
  78. scene.add( pivot );
  79. initPhysics();
  80. onWindowResize();
  81. window.addEventListener( 'resize', onWindowResize, false );
  82. }
  83. async function initPhysics() {
  84. //Initialize physics engine using the script in the jsm/physics folder
  85. physics = await RapierPhysics();
  86. physics.addScene( scene );
  87. //Optionally display collider outlines
  88. physicsHelper = new RapierHelper( physics.world );
  89. scene.add( physicsHelper );
  90. const link1 = addLink( pivot, 0 );
  91. const link2 = addLink( link1, 2 );
  92. addLink( link2, 4 );
  93. }
  94. //link - the mesh that the new link will be attached to
  95. //x - used to position the new link
  96. function addLink( link, x ) {
  97. const geometry = new THREE.CapsuleGeometry( 0.25, 1.8 );
  98. const material = new THREE.MeshStandardMaterial( { color: 0xCCCC00 } );
  99. const mesh = new THREE.Mesh( geometry, material );
  100. mesh.rotateZ( Math.PI * 0.5 );
  101. mesh.position.set( x + 0.9, 5.8, 0 );
  102. scene.add( mesh );
  103. physics.addMesh( mesh, 1, 0.5 );
  104. const jointParams = physics.RAPIER.JointData.spherical(
  105. ( link == pivot ) ? new physics.RAPIER.Vector3( 0, - 0.5, 0 ) : new physics.RAPIER.Vector3( 0, - 1.15, 0 ), // Joint position in world space
  106. new physics.RAPIER.Vector3( 0, 1.15, 0 ) // Corresponding attachment on sphere
  107. );
  108. const body1 = link.userData.physics.body;
  109. const body2 = mesh.userData.physics.body;
  110. body2.setAngularDamping( 10.0 );
  111. physics.world.createImpulseJoint( jointParams, body1, body2, true );
  112. return mesh;
  113. }
  114. function onWindowResize( ) {
  115. camera.aspect = window.innerWidth / window.innerHeight;
  116. camera.updateProjectionMatrix();
  117. renderer.setSize( window.innerWidth, window.innerHeight );
  118. }
  119. function animate() {
  120. if ( physicsHelper ) physicsHelper.update();
  121. renderer.render( scene, camera );
  122. stats.update();
  123. }
  124. </script>
  125. </body>
  126. </html>
粤ICP备19079148号