CANNON
参考
【https://codesandbox.io/p/sandbox/bestservedbold-christmas-baubles-zxpv7】
cannonとは
オープンソースのJavascript3D物理エンジンです
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.175.0/build/three.module.js",
}
}
</script>
<script type="module">
import * as THREE from "three";
import * as CANNON from "https://cdn.skypack.dev/cannon-es";
よくわからん部分
<?php get_header(); ?>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.175.0/build/three.module.js",
"three/addons/controls/OrbitControls.js": "https://cdn.jsdelivr.net/npm/three@0.175.0/examples/jsm/controls/OrbitControls.js"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import * as CANNON from 'https://cdn.skypack.dev/cannon-es'
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(32.5, window.innerWidth / window.innerHeight, 1, 100)
camera.position.set(0, 0, 20)
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
renderer.setClearColor(0x111111, 1) // 背景を暗く
document.body.appendChild(renderer.domElement)
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// Lights
scene.add(new THREE.AmbientLight(0xffffff, 1))
const spotLight = new THREE.SpotLight(0xffffff, 1)
spotLight.position.set(20, 20, 25)
spotLight.castShadow = true
scene.add(spotLight)
const dirLight = new THREE.DirectionalLight(0xff0000, 2)
dirLight.position.set(0, -15, 0)
scene.add(dirLight)
const pointLight = new THREE.PointLight(0xffffff, 1, 100)
pointLight.position.set(0, 10, 20)
scene.add(pointLight)
// Materials
const baubleMaterial = new THREE.MeshLambertMaterial({
color: "#c0a0a0",
roughness: 0.25,
metalness: 0.6,
});
// Physics
const world = new CANNON.World()
world.gravity.set(0, 0, 0)
// Bauble geometry
const sphereGeometry = new THREE.SphereGeometry(1, 28, 28)
const baubles = []
function spawnBaubles() {
for (let i = 0; i < 50; i++) {
const scale = [0.75, 0.75, 1, 1, 1.25][Math.floor(Math.random() * 5)]
const mesh = new THREE.Mesh(sphereGeometry, baubleMaterial)
mesh.scale.set(scale, scale, scale)
mesh.castShadow = true
scene.add(mesh)
const body = new CANNON.Body({
mass: 1,
shape: new CANNON.Sphere(scale),
position: new CANNON.Vec3(
Math.random() * 40 - 20,
Math.random() * 40 - 25,
Math.random() * 40 - 10
),
linearDamping: 0.75,
angularDamping: 0.15,
})
world.addBody(body)
baubles.push({ mesh, body, scale })
}
}
spawnBaubles();
// Pointer
const pointerBody = new CANNON.Body({ mass: 0, shape: new CANNON.Sphere(2), type: CANNON.Body.KINEMATIC })
pointerBody.position.set(100, 100, 100)
world.addBody(pointerBody)
let pointerVec = new THREE.Vector3()
window.addEventListener("mousemove", (e) => {
pointerVec.x = (e.clientX / window.innerWidth) * 2 - 1
pointerVec.y = -(e.clientY / window.innerHeight) * 2 + 1
})
const clock = new THREE.Clock()
function animate() {
requestAnimationFrame(animate)
const delta = clock.getDelta()
world.step(1 / 60, delta)
controls.update(); // 追加
// Move pointer
const pointerPos = new THREE.Vector3(pointerVec.x, pointerVec.y, 0)
pointerPos.unproject(camera)
pointerBody.position.copy(pointerPos)
// Impulse & update positions
for (const { mesh, body, scale } of baubles) {
const direction = new THREE.Vector3().copy(mesh.position).normalize().multiplyScalar(-150 * delta * scale)
body.applyImpulse(new CANNON.Vec3(direction.x, direction.y, direction.z), body.position)
mesh.position.copy(body.position)
mesh.quaternion.copy(body.quaternion)
}
renderer.render(scene, camera)
}
animate()
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
</script>
<main></main>
<?php get_footer(); ?>