Skip to content

Instantly share code, notes, and snippets.

@edom18
Created August 23, 2013 05:34
Show Gist options
  • Select an option

  • Save edom18/6315849 to your computer and use it in GitHub Desktop.

Select an option

Save edom18/6315849 to your computer and use it in GitHub Desktop.
Three.jsのCSS3DRendererでサイコロ
#CSS3DRenderer使ってみました
あまり複雑なモデルなどは表現できませんが、ちょっとした形のものとか
立体感のある演出、くらいなら問題なく使えそうです。
Cannon.jsと組み合わせてサイコロを振ったような演出を作ってみました。
CSSレンダリングなのでもちろんiPhoneでも動きます。
画面をクリックすることで、サイコロを追加することができます。
@import "compass/reset";
<div id="d0"></div>
(function (win, doc) {
'use strict';
var world, ground, timeStep = 1 / 60,
diceRigids = [], dicies = [],
camera, scene, renderer, floorObj,
startDiceNum = 3,
cubeSize = 2;
function createCube(w, h, d) {
var geometry = new THREE.CubeGeometry(w, h, d, 10, 10);
var material = new THREE.MeshLambertMaterial({
color: 0x666666
});
var mesh = new THREE.Mesh(geometry, material);
return mesh;
}
function createPlane(w, h) {
var geometry = new THREE.PlaneGeometry(w, h);
var material = new THREE.MeshPhongMaterial({
color: 0xffffff,
specular: 0xeeeeee,
shininess: 50
});
var mesh = new THREE.Mesh(geometry, material);
return mesh;
}
function createDice(x, y, z) {
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 ]
}
];
{
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);
}
scene.add(dice);
dicies.push(dice);
}
//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;
world.add(body);
diceRigids.push(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, 1, 10000);
camera.position.set(Math.cos(Math.PI / 5) * 30, 20, Math.sin(Math.PI / 5) * 80);
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene = new THREE.Scene();
renderer = new THREE.CSS3DRenderer();
renderer.setSize(w, h);
var floorEle = doc.createElement('div');
floorEle.style.width = '200px';
floorEle.style.height = '200px';
floorEle.style.background = '-webkit-linear-gradient(0deg, #ccc 0%, #444 100%)';
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() {
requestAnimationFrame(animate);
updatePhysics();
render();
}
function updatePhysics() {
//物理エンジンの時間を進める
world.step(timeStep);
//物理エンジンで計算されたbody(RigidBody)の位置をThree.jsのMeshにコピー
for (var i = 0; i < diceRigids.length; i++) {
diceRigids[i].position.copy(dicies[i].position);
diceRigids[i].quaternion.copy(dicies[i].quaternion);
}
ground.position.copy(floorObj.position);
ground.quaternion.copy(floorObj.quaternion);
}
function render() {
renderer.render(scene, camera);
}
initCannon();
initThree();
animate();
//
(function throwDice() {
if (!startDiceNum) {
return;
}
setTimeout(throwDice, 1000);
createDice(0, 30, 30);
startDiceNum--;
}());
//
var camBasePos = camera.position;
var camBaseLookAt = new THREE.Vector3(3, 3, -10);
var flg = false;
var container = doc.getElementById('d0');
var isTouch = 'ontouchstart' in window,
M_DOWN = isTouch ? 'touchstart' : 'mousedown',
M_MOVE = isTouch ? 'touchmove' : 'mousemove',
M_UP = isTouch ? 'touchend' : 'mouseup';
doc.addEventListener(M_DOWN, function (e) {
flg = true;
}, false);
doc.addEventListener(M_UP, function (e) {
flg = false;
}, false);
doc.addEventListener(M_MOVE, function(e){
if(flg){
var 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());
}
}, false);
doc.addEventListener('click', function (e) {
createDice(0, 30, 30);
}, false);
}(window, document));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment