[three.js] モデル (5) ~ねぎ振りミク (影付き)~

three.jsを使って、モデルを作るよ。 :boy:

threejs_model5

WebGLRendererで描画するよ。
ColladaLoader を使ってみたよ。 :bouzu:

さらに、DirectionalLight も使ったよ。 :cake:  影もつけてみたよ。
レンダラー、ライト、影を落とす物体、影を落とされる物体の4つに設定が必要だよ! :beer:

OrbitControls で、ぐるんぐるん動かせるようにしてみたよ。 :sun:

@rect 先生 :hakase: の「note.x | [Papervision3D]ねぎ振り完了」から、Colladaデータとテクスチャをダウンロードさせていただきました。 :doki:

index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0">
<title>モデル (5) | three.js</title>
<script src="js/three.min.js"></script>
<script src="js/loaders/ColladaLoader.js"></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/createjs/easeljs-0.8.1.min.js"></script>
<script src="js/createjs/tweenjs-0.6.1.min.js"></script>
<script src="js/detector.js"></script>
<script src="js/stats.min.js"></script>
<style type="text/css">
  html { overflow:hidden; }
  body { margin:0; padding:0; }
</style>
</head>
<body style="background-color:#333333">
<script>
var scene, camera, renderer, stats;
var loader, negimiku, hand, arm, negi, plane, front, back;
var light;
var controller;
var radius = 500;
var radian = Math.PI/180;
var center = new THREE.Object3D();
var filePath = "assets/negimiku/negimiku.dae";

window.onload = init;

function init() {
  if (!Detector.webgl) Detector.addGetWebGLMessage();

  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 0.1, 1000);
  scene.add(camera);
  light = new THREE.DirectionalLight(0xFFFFFF);
  scene.add(light);
  controller = new THREE.OrbitControls(camera);
  renderer = new THREE.WebGLRenderer({antialias: true});
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
  setup();
  //initialize();
  loader = new THREE.ColladaLoader();
  loader.options.convertUpAxis = true;
  loader.load(filePath, loaded);

  stats = new Stats();
  stats.setMode(0);
  stats.domElement.style.position = "fixed";
  stats.domElement.style.right = "0px";
  stats.domElement.style.top = "0px";
  document.body.appendChild(stats.domElement);

  render();
  window.addEventListener("resize", resize, false);
}
function setup() {
  renderer.setClearColor(0x333333, 1);
  camera.position.z = radius;
  light.position.set(0, 400, 160);
  light.distance = 800;
  light.intensity = 1.2;

  renderer.shadowMapEnabled = true;
  light.castShadow = true;
  light.shadowDarkness = 0.5;
  light.shadowMapWidth = 1024;
  light.shadowMapHeight = 1024;
  //light.shadowCameraVisible = true;

  controller.maxPolarAngle = Math.PI/2;
}
function loaded(data) {
  negimiku = data.scene;
  for (var n in negimiku.children) {
    var child = negimiku.children[n];
    switch (child.name) {
      case "R_arm" :
        arm = child;
        break;
      case "negi" :
        negi = child;
        break;
    }
    var material = child.children[0].material;
    material.transparent = true;
    material.emissive.set(0x333333);
    child.children[0].castShadow = true;
  }

  background();
  initialize();
  jump();
  swingHand();
}
function background() {
  plane = new THREE.Group();
  scene.add(plane);
  var geometry = new THREE.PlaneGeometry(300, 300, 4, 4);
  var fmaterial = new THREE.MeshPhongMaterial({color: 0x666666, side: THREE.BackSide});
  fmaterial.emissive.set(0x333333);
  var bmaterial = new THREE.MeshPhongMaterial({color: 0x666666, side: THREE.FrontSide});
  bmaterial.emissive.set(0x333333);
  front = new THREE.Mesh(geometry, fmaterial);
  back = new THREE.Mesh(geometry, bmaterial);
  plane.add(front);
  plane.add(back);
  front.rotation.x = 90*radian;
  back.rotation.x = 90*radian;
  plane.position.y = 184;
  front.receiveShadow = true;
}
function initialize() {
  negimiku.rotation.y = 180*radian;
  negimiku.scale.set(12.6, 12.6, 12.6);
  scene.add(negimiku);
  negimiku.position.y = 50;
  hand = new THREE.Group();
  negimiku.add(hand);
  hand.add(arm);
  hand.add(negi);
  //negimiku.castShadow = true;
}
function jump() {
  createjs.Tween.get(negimiku.position, {override: false, paused: false, loop: true, useTicks: true})
    .to({"y": 50}, 30, createjs.Ease.circOut)
    .to({"y": 50}, 30, createjs.Ease.circIn)
  ;
}
function swingHand() {
  createjs.Tween.get(hand.rotation, {override: false, paused: false, loop: true, useTicks: true})
    .to({"x": 40*radian}, 9, createjs.Ease.quadOut)
    .to({"x": 0}, 9, createjs.Ease.quadIn)
    .to({"x": 20*radian}, 6, createjs.Ease.quadOut)
    .to({"x": 0}, 6, createjs.Ease.quadIn)
  ;
}
function render() {
  requestAnimationFrame(render);

  createjs.Tween.tick(16, false);

  controller.update();
  camera.lookAt(center.position);

  renderer.render(scene, camera);

  stats.update();
}
function resize(event) {
  camera.aspect = window.innerWidth/window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}
</script>
</body>
</html>