Created
August 18, 2013 18:04
-
-
Save edom18/6263033 to your computer and use it in GitHub Desktop.
Cannon.js x Three.jsで3D物理演算2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Cannon.jsで物理演算Demo2 | |
[こちらの記事を参考](http://www56.atwiki.jp/threejs/pages/85.html)に、勉強のためにちょっと手を加えたものです。 | |
また、[質量などの設定はこれを参考](http://stackoverflow.com/questions/16424500/what-would-be-realistic-values-for-gravity-mass-and-contact-material-in-canno)にしました。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import "compass/reset"; | |
img, canvas { | |
vertical-align: top; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div id="d0"></div> | |
<script src="http://jsrun.it/assets/f/J/B/D/fJBDQ"></script> | |
<script src="http://jsrun.it/assets/u/4/z/N/u4zNG"></script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (win, doc) { | |
'use strict'; | |
var fps = 60; | |
var w = win.innerWidth; | |
var h = win.innerHeight; | |
var world, timeStep = 1/fps, renderer, scene, camera; | |
var cPlane1Body, cPlane1Mesh, cPlane2Body, cPlane2Mesh, cPlane2Material, sphereGeometry, sphereMaterial; | |
var sphereShape, sphereBody, sphereMesh; | |
var boxShape, boxGeometry, boxMaterial; | |
var box1Mesh, box1Body, box2Mesh, box2Body; | |
var groundShape, groundBody, groundMesh; | |
var cp; | |
var flg = false, cnt = 0; | |
function sinit() { | |
initThree(); | |
initCannon(); | |
animate(); | |
} | |
function initCannon(){ | |
world = new CANNON.World(); | |
world.gravity.set( 0, -100, 0); | |
world.broadphase = new CANNON.NaiveBroadphase(); | |
world.solver.iterations = 16; | |
function convexPlaneShape(xSize, ySize) { | |
return new CANNON.ConvexPolyhedron([ | |
// vertices | |
new CANNON.Vec3(-xSize/2, ySize/2, 0), | |
new CANNON.Vec3( xSize/2, ySize/2, 0), | |
new CANNON.Vec3( xSize/2, -ySize/2, 0), | |
new CANNON.Vec3(-xSize/2, -ySize/2, 0) | |
], [ | |
// Faces | |
[3,2,1,0] | |
], [ | |
// Normals | |
new CANNON.Vec3(0,0,1) | |
]); | |
} | |
var cPlanePhysMat = new CANNON.Material(); | |
var cPlaneShape = convexPlaneShape(8, 8); | |
var qo, qo2, qo3; | |
cPlane1Body = new CANNON.RigidBody(0, cPlaneShape, cPlanePhysMat); | |
cPlane1Body.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2); | |
qo = new CANNON.Quaternion(); | |
qo2 = new CANNON.Quaternion(); | |
cPlane1Body.quaternion.copy(qo); | |
qo2.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), -0.07); | |
cPlane1Body.quaternion = qo2.mult(qo); | |
cPlane1Body.position.set(-5, 14, 0); | |
world.add(cPlane1Body); | |
cPlane2Body = new CANNON.RigidBody(0, cPlaneShape, cPlanePhysMat); | |
cPlane2Body.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2); | |
qo = new CANNON.Quaternion(); | |
qo2 = new CANNON.Quaternion(); | |
qo3 = new CANNON.Quaternion(); | |
cPlane2Body.quaternion.copy(qo); | |
qo2.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), -Math.PI / 6); | |
qo3.setFromAxisAngle(new CANNON.Vec3(0, 1, 0), Math.PI / 4); | |
cPlane2Body.quaternion = qo3.mult(qo2.mult(qo)); | |
cPlane2Body.position.set(4, 2, 2); | |
world.add(cPlane2Body); | |
var spherePhysMat = new CANNON.Material(); | |
sphereShape = new CANNON.Sphere(2); | |
//Create a ball as a stone. | |
var density = 2515; // kg/m^3 | |
var mass = density * sphereShape.volume(); | |
sphereBody = new CANNON.RigidBody(mass, sphereShape, spherePhysMat); | |
sphereBody.position.set(-4, 34, 0); | |
sphereBody.quaternion.set(0, 0, 0, 1); | |
sphereBody.velocity.set(0, 0, 0); | |
sphereBody.angularVelocity.set(0, 0, 100); | |
world.add(sphereBody); | |
var boxPhysMat = new CANNON.Material(); | |
boxShape = new CANNON.Box(new CANNON.Vec3(2, 2, 2)); | |
density = 50; | |
mass = density * boxShape.volume(); | |
box1Body = new CANNON.RigidBody(mass, boxShape, boxPhysMat); | |
box1Body.position.set(17,2,-11); | |
box1Body.quaternion.set(0,0,0,1); | |
box1Body.velocity.set(0,0,0); | |
box1Body.angularVelocity.set(0,0,0); | |
world.add(box1Body); | |
density = 30; | |
mass = density * boxShape.volume(); | |
box2Body = new CANNON.RigidBody(mass, boxShape, boxPhysMat); | |
box2Body.position.set(17,6,-11); | |
box2Body.quaternion.set(0,0,0,1); | |
box2Body.velocity.set(0,0,0); | |
box2Body.angularVelocity.set(0,0,0); | |
world.add(box2Body); | |
var groundPhysMat = new CANNON.Material(); | |
groundShape = new CANNON.Plane(new CANNON.Vec3(0, 0, 1)); | |
groundBody = new CANNON.RigidBody(0, groundShape, groundPhysMat); | |
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1,0,0), -Math.PI/2); | |
world.add(groundBody); | |
var friction = 0.0; | |
var restitution = 0.0; | |
var sphere_cPlane = new CANNON.ContactMaterial(cPlanePhysMat, spherePhysMat, friction, restitution); | |
var sphere_box = new CANNON.ContactMaterial(spherePhysMat, groundPhysMat, friction, restitution); | |
sphere_cPlane.contactEquationStiffness = 1e8; | |
sphere_cPlane.contactEquationRegularizationTime = 3; | |
sphere_cPlane.frictionEquationStiffness = 1e8; | |
sphere_cPlane.frictionEquationRegularizationTime = 3; | |
world.addContactMaterial(sphere_cPlane); | |
world.addContactMaterial(sphere_box); | |
} | |
function initThree() { | |
// scene | |
scene = new THREE.Scene(); | |
scene.fog = new THREE.Fog(0xffffff, 80, 150); | |
// camera | |
camera = new THREE.PerspectiveCamera(60, w / h, 1, 10000); | |
camera.position.set(-1, 14, 10).multiplyScalar(1.6); | |
camera.lookAt(new THREE.Vector3(3, 3, -10)); | |
// light | |
var d = 10; | |
var light = new THREE.DirectionalLight(0xffffff, 1); | |
light.position.set(d, d, d); | |
light.castShadow = true; | |
//light.shadowCameraVisible = true; | |
light.shadowMapWidth = 1024; | |
light.shadowMapHeight = 1024; | |
light.shadowCameraLeft = -d * 3; | |
light.shadowCameraRight = d * 3; | |
light.shadowCameraTop = d; | |
light.shadowCameraBottom = -d; | |
light.shadowCameraNear = 1; | |
light.shadowCameraFar = 10000; | |
light.shadowDarkness = 0.5; | |
scene.add(light); | |
// floor | |
var oneWidth = 5, | |
oneHeight = 5, | |
wUnits = 70, | |
hUnits = 70, | |
groundGeo = new THREE.PlaneGeometry(oneWidth * wUnits, oneHeight * hUnits, wUnits, hUnits); | |
for(var i = 0, len = groundGeo.faces.length, f; i < len; i++){ | |
f = -1; | |
if((i / wUnits | 0) % 2 == 1){ | |
f = ~f; | |
} | |
if((i % wUnits) % 2 == 1){ | |
f = ~f; | |
} | |
groundGeo.faces[i].materialIndex = f + 1; | |
} | |
groundMesh = new THREE.Mesh( | |
groundGeo, | |
new THREE.MeshFaceMaterial([ | |
new THREE.MeshBasicMaterial({color: 0x999999 }), | |
new THREE.MeshBasicMaterial({color: 0x4d4d4d }) | |
]) | |
); | |
groundMesh.rotation.x = -Math.PI / 2; | |
groundMesh.castShadow = true; | |
groundMesh.receiveShadow = true; | |
scene.add(groundMesh); | |
// step plane | |
var cPlaneGeometry = new THREE.PlaneGeometry(8, 8); | |
// red step plane | |
var cPlane1Material = new THREE.MeshLambertMaterial({color: 0xffcccc}); | |
cPlane1Mesh = new THREE.Mesh(cPlaneGeometry, cPlane1Material); | |
cPlane1Mesh.castShadow = true; | |
cPlane1Mesh.receiveShadow = true; | |
scene.add(cPlane1Mesh); | |
// blue step plane | |
cPlane2Material = new THREE.MeshLambertMaterial( { color: 0xccccff } ); | |
cPlane2Mesh = new THREE.Mesh( cPlaneGeometry, cPlane2Material ); | |
cPlane2Mesh.castShadow = true; | |
cPlane2Mesh.receiveShadow = true; | |
scene.add(cPlane2Mesh); | |
// red ball | |
sphereGeometry = new THREE.SphereGeometry(2, 25, 25); | |
sphereMaterial = new THREE.MeshPhongMaterial({color: 0xff0000, specular: 0xff8833}); | |
sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial); | |
sphereMesh.castShadow = true; | |
sphereMesh.receiveShadow = true; | |
scene.add(sphereMesh); | |
// box 1 | |
boxGeometry = new THREE.CubeGeometry(4, 4, 4); | |
boxMaterial = new THREE.MeshLambertMaterial({color: 0x00ff00}); | |
box1Mesh = new THREE.Mesh(boxGeometry, boxMaterial); | |
box1Mesh.castShadow = true; | |
box1Mesh.receiveShadow = true; | |
scene.add(box1Mesh); | |
// box 2 | |
box2Mesh = box1Mesh.clone(); | |
scene.add(box2Mesh); | |
// renderer | |
renderer = new THREE.WebGLRenderer({antialias: true}); | |
renderer.setSize(w, h); | |
renderer.shadowMapEnabled = true; | |
var container = document.getElementById('d0'); | |
container.appendChild(renderer.domElement); | |
var camBasePos = camera.position; | |
var camBaseLookAt = new THREE.Vector3(3, 3, -10); | |
document.addEventListener('mousemove', function(e){ | |
if(flg){ | |
cp = container.getBoundingClientRect(); | |
camera.position = camBasePos.clone(); | |
camera.position.subVectors(camera.position, camBaseLookAt); | |
camera.position.applyAxisAngle( new THREE.Vector3(0,1,0), (e.clientX-cp.left-160) / 72 ); | |
camera.lookAt(scene.position); | |
camera.position.addVectors(camera.position, camBaseLookAt.clone()); | |
flg = false; | |
} | |
}, false); | |
} | |
function animate() { | |
setTimeout(animate, 1000 / fps); | |
flg = true; | |
cnt++; | |
if(cnt / fps > 7) { | |
//return; | |
} | |
updatePhysics(); | |
render(); | |
} | |
function updatePhysics() { | |
// Step the physics world | |
world.step(timeStep); | |
// Copy FROM Cannon.js TO Three.js | |
cPlane1Body.position.copy(cPlane1Mesh.position); | |
cPlane1Body.quaternion.copy(cPlane1Mesh.quaternion); | |
cPlane2Body.position.copy(cPlane2Mesh.position); | |
cPlane2Body.quaternion.copy(cPlane2Mesh.quaternion); | |
sphereBody.position.copy(sphereMesh.position); | |
sphereBody.quaternion.copy(sphereMesh.quaternion); | |
box1Body.position.copy(box1Mesh.position); | |
box1Body.quaternion.copy(box1Mesh.quaternion); | |
box2Body.position.copy(box2Mesh.position); | |
box2Body.quaternion.copy(box2Mesh.quaternion); | |
groundBody.position.copy(groundMesh.position); | |
groundBody.quaternion.copy(groundMesh.quaternion); | |
} | |
function render() { | |
renderer.render(scene, camera); | |
} | |
sinit(); | |
}(window, document)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment