Upgrade to Pro — share decks privately, control downloads, hide ads and more …

three.jsとRapierでレースゲームが3日でできた話

yomotsu
October 21, 2023

 three.jsとRapierでレースゲームが3日でできた話

yomotsu

October 21, 2023
Tweet

More Decks by yomotsu

Other Decks in Programming

Transcript

  1. terrainMesh.updateWorldMatrix( true, true ); terrainMesh.traverse( ( object ) => {

    if ( ! object.isMesh ) return; const geometry = object.geometry.clone(); geometry.applyMatrix4( object.matrix ); geometry.computeVertexNormals(); const vertices = new Float32Array( geometry.attributes.position.array ); const indices = new Uint32Array( geometry.index.array ); const groundColliderDesc = RAPIER.ColliderDesc.trimesh( new Float32Array(vertices), new Uint32Array(indices) ) .setActiveEvents( RAPIER.ActiveEvents.COLLISION_EVENTS ); const groundCollider = world.createCollider( groundColliderDesc ); } ); QPTJUJPO΍SPUBUJPO͕ ద༻͞Ε͍ͯΔ৔߹͸ ࣄલʹߦྻʹ൓ө͢Δ ʢ௨ৗ͸SFOEFS࣌ʹద༻͞ΕΔʣ
  2. terrainMesh.updateWorldMatrix( true, true ); terrainMesh.traverse( ( object ) => {

    if ( ! object.isMesh ) return; const geometry = object.geometry.clone(); geometry.applyMatrix4( object.matrix ); geometry.computeVertexNormals(); const vertices = new Float32Array( geometry.attributes.position.array ); const indices = new Uint32Array( geometry.index.array ); const groundColliderDesc = RAPIER.ColliderDesc.trimesh( new Float32Array(vertices), new Uint32Array(indices) ) .setActiveEvents( RAPIER.ActiveEvents.COLLISION_EVENTS ); const groundCollider = world.createCollider( groundColliderDesc ); } ); .FTI಺ͷ શδΦϝτϦʔʹରͯ͠ʜ
  3. terrainMesh.updateWorldMatrix( true, true ); terrainMesh.traverse( ( object ) => {

    if ( ! object.isMesh ) return; const geometry = object.geometry.clone(); geometry.applyMatrix4( object.matrix ); geometry.computeVertexNormals(); const vertices = new Float32Array( geometry.attributes.position.array ); const indices = new Uint32Array( geometry.index.array ); const groundColliderDesc = RAPIER.ColliderDesc.trimesh( new Float32Array(vertices), new Uint32Array(indices) ) .setActiveEvents( RAPIER.ActiveEvents.COLLISION_EVENTS ); const groundCollider = world.createCollider( groundColliderDesc ); } ); ίϐʔͨ͠δΦϝτϦΛ ഁյૢ࡞͍ͯ͘͠
  4. terrainMesh.updateWorldMatrix( true, true ); terrainMesh.traverse( ( object ) => {

    if ( ! object.isMesh ) return; const geometry = object.geometry.clone(); geometry.applyMatrix4( object.matrix ); geometry.computeVertexNormals(); const vertices = new Float32Array( geometry.attributes.position.array ); const indices = new Uint32Array( geometry.index.array ); const groundColliderDesc = RAPIER.ColliderDesc.trimesh( new Float32Array(vertices), new Uint32Array(indices) ) .setActiveEvents( RAPIER.ActiveEvents.COLLISION_EVENTS ); const groundCollider = world.createCollider( groundColliderDesc ); } ); ม׵ߦྻΛ௖఺ʹম͖෇͚Δ
  5. terrainMesh.updateWorldMatrix( true, true ); terrainMesh.traverse( ( object ) => {

    if ( ! object.isMesh ) return; const geometry = object.geometry.clone(); geometry.applyMatrix4( object.matrix ); geometry.computeVertexNormals(); const vertices = new Float32Array( geometry.attributes.position.array ); const indices = new Uint32Array( geometry.index.array ); const groundColliderDesc = RAPIER.ColliderDesc.trimesh( new Float32Array(vertices), new Uint32Array(indices) ) .setActiveEvents( RAPIER.ActiveEvents.COLLISION_EVENTS ); const groundCollider = world.createCollider( groundColliderDesc ); } ); UISFFKTͷHFPNFUSZ͔Β ಺༰ΛऔΓग़ͯ͠
  6. terrainMesh.updateWorldMatrix( true, true ); terrainMesh.traverse( ( object ) => {

    if ( ! object.isMesh ) return; const geometry = object.geometry.clone(); geometry.applyMatrix4( object.matrix ); geometry.computeVertexNormals(); const vertices = new Float32Array( geometry.attributes.position.array ); const indices = new Uint32Array( geometry.index.array ); const groundColliderDesc = RAPIER.ColliderDesc.trimesh( new Float32Array(vertices), new Uint32Array(indices) ) .setActiveEvents( RAPIER.ActiveEvents.COLLISION_EVENTS ); const groundCollider = world.createCollider( groundColliderDesc ); } ); ௖఺഑ྻ͔Β 3BQJFSͷ߶ମΛ࡞ΕΔ
  7. w UISFFKT w %ඳըػೳ w ೚ҙϞσϧͷಡΈࠐΈʢHM5'ʣ w 3BQJFS w ೚ҙϝογϡ͔Β߶ମΛ࡞Δ

    w ࣗಈं෺ཧγϛϡϨʔγϣϯʢ*TBBD͞Μ੡ʣ ཁ݅ୡ੒ʹඞཁͳػೳ
  8. // 物理 const gravity = { x: 0, y: -9.81,

    z: 0 }; const world = new RAPIER.World( gravity ); world.timestep = 0.016; // 表示 const width = window.innerWidth; const height = window.innerHeight; const clock = new THREE.Clock(); const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 60, width / height, 0.01, 100 ); const renderer = new THREE.WebGLRenderer(); renderer.setSize( width, height ); document.body.appendChild( renderer.domElement ); https://github.com/yomotsu/rapier-tryout ෺ཧγϛϡϨʔγϣϯೖΕ෺XPSME දࣔͷೖΕ෺TDFOF
  9. const radius = 1; // 表示 const ballMesh = new

    Mesh( new SphereGeometry( radius, 16, 16 ), new MeshNormalMaterial( { wireframe: true } ) ); scene.add( ballMesh ); // 物理 const rigidBodyDesc = RAPIER.RigidBodyDesc.dynamic() .setLinearDamping( 0.1 ) .setTranslation( 0, 3, 0 ); const rigidBody = world.createRigidBody( rigidBodyDesc ); const colliderDesc = RAPIER.ColliderDesc.ball( radius ) .setFriction( 0.1 ) .setFrictionCombineRule( RAPIER.CoefficientCombineRule.Max ) .setRestitution( 0.6 ) .setRestitutionCombineRule( RAPIER.CoefficientCombineRule.Max ); world.createCollider( colliderDesc, rigidBody ); https://github.com/yomotsu/rapier-tryout ൒ܘ̍ͷٿମͷϝογϡ ൒ܘ̍ͷٿମͷ߶ମ TDFOF಺ʹ഑ஔ XPSME಺ʹ഑ஔ
  10. ( function gameLoop() { world.step(); ballMesh.position.copy( rigidBody.translation() ); ballMesh.quaternion.copy( rigidBody.rotation()

    ); setTimeout( gameLoop, world.timestep ); } )(); https://github.com/yomotsu/rapier-tryout UJNFTUFQ͸ඵͰݻఆࡁΈ ෺ཧ͸S"'Λ࢖Θͣɺݻఆඵϧʔϓͤ͞Δ ෺ཧγϛϡϨʔγϣϯ݁ՌΛ දࣔҐஔʹίϐʔ
  11. ( function renderLoop () { requestAnimationFrame( renderLoop ); renderer.render( scene,

    camera ); } )(); https://github.com/yomotsu/rapier-tryout දࣔ͸S"'Ͱɺ σόΠεෛՙʹԠͨ͡ϧʔϓΛͤ͞Δ
  12. const curvePath: THREE.CurvePath<THREE.Vector3> = new THREE.CurvePath(); curvePath.add( new THREE.CatmullRomCurve3( [

    new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 0.1 ), new THREE.Vector3( 0, 0, 10 ), new THREE.Vector3( 0, 18, 50 ), new THREE.Vector3( 20, 18, 60 ), new THREE.Vector3( 20, 18, 0 ), new THREE.Vector3( 0, 18, 0 ), new THREE.Vector3( - 10, 18, 0 ), new THREE.Vector3( - 50, 0, - 50 ), new THREE.Vector3( 0, 0, - 50 ), new THREE.Vector3( 0, 0, - 10 ), ] ) );