Skip to content

Instantly share code, notes, and snippets.

@edom18
Created August 29, 2013 09:17
Show Gist options
  • Save edom18/6375953 to your computer and use it in GitHub Desktop.
Save edom18/6375953 to your computer and use it in GitHub Desktop.
Three.jsのCSS3DRendererでサイコロ2
#Three.js x CSS3DRendererでサイコロ
今回は投げたサイコロにカメラを追従させて、
実際に出た目を確認できる仕様にしてみました。
[2013.08.29] サイコロを何度でも振れるよう修正。
[2013.08.27 追記] サイコロの目をプログラム側で識別できるよう修正。
@import "compass/reset";
#gui {
position: absolute;
left: 5px;
top: 5px;
z-index: 100;
padding: 10px;
background: rgba(0, 0, 0, 0.5);
border: solid 1px #666;
color: #fff;
}
#num {
position: absolute;
right: 15px;
bottom: 10px;
z-index: 100;
font-size: 90px;
font-weight: bold;
color: #fff;
-webkit-text-stroke: 5px black;
text-stroke: 5px black;
}
<div id="gui">クリックでサイコロを振ります</div>
<div id="d0"></div>
<div id="num">-</div>
(function (win, doc) {
'use strict';
var world, ground, timeStep = 1 / 60,
diceRigid, dice,
camera, scene, renderer, floorObj,
startDiceNum = 3,
cubeSize = 5;
function createDice() {
var boxInfo = [
{
url: 'http://jsrun.it/assets/g/N/z/s/gNzsx.png',
position: [ -cubeSize, 0, 0 ],
rotation: [ 0, Math.PI / 2, 0 ]
},
{
url: 'http://jsrun.it/assets/b/X/8/T/bX8TN.png',
position: [ cubeSize, 0, 0 ],
rotation: [ 0, -Math.PI / 2, 0 ]
},
{
url: 'http://jsrun.it/assets/u/G/6/B/uG6BH.png',
position: [ 0, cubeSize, 0 ],
rotation: [ Math.PI / 2, 0, Math.PI ]
},
{
url: 'http://jsrun.it/assets/e/s/z/w/eszwi.png',
position: [ 0, -cubeSize, 0 ],
rotation: [ - Math.PI / 2, 0, Math.PI ]
},
{
url: 'http://jsrun.it/assets/9/t/3/9/9t39J.png',
position: [ 0, 0, cubeSize ],
rotation: [ 0, Math.PI, 0 ]
},
{
url: 'http://jsrun.it/assets/h/e/o/9/heo9V.png',
position: [ 0, 0, -cubeSize ],
rotation: [ 0, 0, 0 ]
}
];
//for three.js
{
var el, dice,
info, img, face;
el = doc.createElement('div');
el.style.width = cubeSize * 2 + 'px';
el.style.height = cubeSize * 2 + 'px';
dice = new THREE.CSS3DObject(el);
for (var j = 0; j < boxInfo.length; j++) {
info = boxInfo[j];
img = document.createElement('img');
img.width = cubeSize * 2;
img.src = info.url;
face = new THREE.CSS3DObject(img);
face.position.fromArray(info.position);
face.rotation.fromArray(info.rotation);
dice.add(face);
}
}
//Create physics.
{
var mass = 1;
var box = new CANNON.Box(new CANNON.Vec3(cubeSize, cubeSize, cubeSize));
var body = new CANNON.RigidBody(mass, box);
//body.position.set(x, y, z);
//body.velocity.set(0, 0, Math.random() * -50 - 30);
//body.angularVelocity.set(10, 10, 10);
//body.angularDamping = 0.001;
}
return {
dice: dice,
rigid: body
};
}
//
function initCannon() {
//Cannonの世界を生成
world = new CANNON.World();
//重力を設定
world.gravity.set(0, -90.82, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
world.solver.tolerance = 0.001;
//地面用にPlaneを生成
var plane = new CANNON.Plane();
//Planeの剛体を質量0で生成する
ground= new CANNON.RigidBody(0, plane);
//X軸に90度(つまり地面)に回転
ground.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
world.add(ground);
}
function initThree() {
var w = win.innerWidth;
var h = win.innerHeight;
camera = new THREE.PerspectiveCamera(60, w / h, 0.1, 1000);
camera.position.set(10, 40, 50);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene = new THREE.Scene();
renderer = new THREE.CSS3DRenderer();
renderer.setSize(w, h);
var textureSize = 800;
var floorEle = doc.createElement('div');
floorEle.style.width = textureSize + 'px';
floorEle.style.height = textureSize + 'px';
floorEle.style.background = 'url(http://jsrun.it/assets/d/x/0/w/dx0wl.png) left top repeat';
floorEle.style.backgroundSize = textureSize / 20 + 'px ' + textureSize / 20 + 'px';
floorObj = new THREE.CSS3DObject(floorEle);
floorObj.position.fromArray([0, 0, 0]);
floorObj.rotation.fromArray([Math.PI / 2, 0, 0]);
scene.add(floorObj);
scene.add(camera);
var container = doc.getElementById('d0');
container.appendChild(renderer.domElement);
renderer.render(scene, camera);
}
function animate() {
if (stopped) {
return;
}
requestAnimationFrame(animate);
updatePhysics();
render();
}
var stopped = false;
function updatePhysics() {
//物理エンジンの時間を進める
world.step(timeStep);
//物理エンジンで計算されたbody(RigidBody)の位置をThree.jsのMeshにコピー
if (diceRigid) {
diceRigid.position.copy(dice.position);
diceRigid.quaternion.copy(dice.quaternion);
diceRigid.position.copy(camera.position);
camera.position.y += 50;
camera.position.x += 50;
camera.lookAt(diceRigid.position.copy(new THREE.Vector3(0, 0, 0)));
}
ground.position.copy(floorObj.position);
ground.quaternion.copy(floorObj.quaternion);
}
function render() {
renderer.render(scene, camera);
}
initCannon();
initThree();
//
//create a dice.
var ret = createDice();
dice = ret.dice;
diceRigid = ret.rigid;
world.allowSleep = true;
diceRigid.allowSleep = true;
diceRigid.sleepSpeedLimit = 0.1;
diceRigid.sleepTimeLimit = 1;
function initAnimation() {
diceRigid.position.set(0, 50, 30);
diceRigid.velocity.set(
Math.random() * 20 + 0,
Math.random() * 100 + 20,
Math.random() * -50 - 30);
diceRigid.angularVelocity.set(10, 10, 10);
diceRigid.angularDamping = 0.001;
}
diceRigid.addEventListener('sleepy', function (e) {
var px = new THREE.Vector4( 1, 0, 0, 0),
nx = new THREE.Vector4(-1, 0, 0, 0),
py = new THREE.Vector4( 0, 1, 0, 0),
ny = new THREE.Vector4( 0, -1, 0, 0),
pz = new THREE.Vector4( 0, 0, 1, 0),
nz = new THREE.Vector4( 0, 0, -1, 0),
UP = 0.99,
tmp;
function showNum(num) {
doc.getElementById('num').innerHTML = num;
}
if (px.applyMatrix4(dice.matrixWorld).y > UP) {
showNum(5);
}
else if (nx.applyMatrix4(dice.matrixWorld).y > UP) {
showNum(2);
}
else if (py.applyMatrix4(dice.matrixWorld).y > UP) {
showNum(1);
}
else if (ny.applyMatrix4(dice.matrixWorld).y > UP) {
showNum(6);
}
else if (pz.applyMatrix4(dice.matrixWorld).y > UP) {
showNum(3);
}
else if (nz.applyMatrix4(dice.matrixWorld).y > UP) {
showNum(4);
}
stopped = true;
});
diceRigid.addEventListener('sleep', function (e) {
//alert('sleep');
});
scene.add(dice);
world.add(diceRigid);
render();
//
doc.addEventListener('click', function (e) {
stopped = false;
initAnimation();
animate();
}, false);
}(window, document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment