Created
August 24, 2013 00:25
-
-
Save edom18/6325224 to your computer and use it in GitHub Desktop.
パシフィック・リムのイェーガーモデルを読み込ませてみた
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
#パシフィック・リムのイェーガーのモデルデータが配布されていたのでThree.jsで読み込ませてみた。 | |
[更新履歴] | |
* [2013.08.27] 視点を変えてダイナミックに見えるように修正。 | |
* [2013.08.26] Walkアニメーションをちょっとだけ最適化。ビル群モデルを追加。 | |
* [2013.08.24] BlenderのIKを使ってアニメーションをつけてみた。だいぶぎこちないけどw | |
TrackballControlsを使ってカメラの位置をマウスから操作できるようにした。 |
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; | |
} | |
#ctrl { | |
position: absolute; | |
left: 0; | |
top: 0; | |
} |
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
<script type="x-shader/x-vertex" id="vs"> | |
uniform bool edge; | |
varying vec3 vNormal; | |
void main(void) { | |
vec3 pos = position; | |
if (edge) { | |
pos += normal * 0.04; | |
} | |
vNormal = normal; | |
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0); | |
} | |
</script> | |
<script type="x-shader/x-fragment" id="fs"> | |
precision mediump float; | |
uniform vec3 lightDirection; | |
uniform sampler2D texture; | |
uniform vec4 edgeColor; | |
varying vec3 vNormal; | |
void main(void) { | |
if (edgeColor.a > 0.0) { | |
gl_FragColor = edgeColor; | |
} | |
else { | |
float diffuse = clamp(dot(vNormal, lightDirection), 0.0, 1.0); | |
vec4 smpColor = texture2D(texture, vec2(diffuse, 0.0)); | |
gl_FragColor = smpColor; | |
} | |
} | |
</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 container, camera, controls, scene, | |
projector, renderer, model, | |
globalLight, | |
clock, | |
//for skybox. | |
sceneCube, cameraCube, textureCube, meshCube; | |
//for model information. | |
var modelUrl = 'http://resources.edo-m18.me/models/gips-danger/gips-danger_rig.js'; | |
var modelFrames = { | |
walk: [0, 32, 15, {state: 'stand', action: false}], | |
run : [0, 72, 30, {state: 'stand', action: false}] | |
}; | |
var groundTextureUrl = 'http://jsrun.it/assets/h/M/n/q/hMnqT.jpg'; | |
// | |
function createModel(geometry, materials) { | |
var facematerial; | |
var scale = 17; | |
if (materials) { | |
for (var i = 0; i < materials.length; i++) { | |
materials[i].morphTargets = true; | |
} | |
facematerial = new THREE.MeshFaceMaterial(materials); | |
} | |
else { | |
facematerial = new THREE.MeshLambertMaterial({color: 0xcccccc}); | |
facematerial.morphTargets = true; | |
} | |
model = new THREE.MorphAnimMesh(geometry, facematerial); | |
model.scale.set(scale, scale, scale); | |
model.position.set(-70, 0, -400); | |
model.castShadow = true; | |
model.receiveShadow = true; | |
model.setFrameRange(modelFrames.walk[0], modelFrames.walk[1]); | |
scene.add(model); | |
animate(); | |
} | |
/** | |
* Initialize sky box. | |
*/ | |
function initSkybox() { | |
//Skyebox用のシーン、カメラを生成 | |
sceneCube = new THREE.Scene(); | |
cameraCube = new THREE.PerspectiveCamera(25, window.innerWidth / window.innerHeight, 1, 10000); | |
cameraCube.position.y = -50; | |
sceneCube.add(cameraCube); | |
//p = positive, n = negative | |
var urls = [ | |
'/assets/k/z/5/Y/kz5YB.jpg', | |
'/assets/x/P/8/J/xP8JV.jpg', | |
'/assets/p/S/A/e/pSAes.jpg', | |
'/assets/4/v/3/x/4v3xz.jpg', | |
'/assets/g/a/G/S/gaGSG.jpg', | |
'/assets/x/z/w/I/xzwIo.jpg' | |
]; | |
//キューブマップ用にテクスチャをロード | |
textureCube = THREE.ImageUtils.loadTextureCube(urls); | |
// | |
var shader, material; | |
//Skyebox用にデフォルトで準備されているシェーダを読み込み | |
shader = THREE.ShaderLib.cube; | |
//キューブマップ用テクスチャを、uniform変数「tCube」にアップロード | |
shader.uniforms.tCube.value = textureCube; | |
//上記のシェーダを、ShaderMaterialとしてマテリアルを生成 | |
material = new THREE.ShaderMaterial({ | |
fragmentShader: shader.fragmentShader, | |
vertexShader : shader.vertexShader, | |
uniforms : shader.uniforms, | |
depthWrite : false, | |
side : THREE.BackSide | |
}); | |
//Skyboxメッシュを生成 | |
meshCube = new THREE.Mesh(new THREE.CubeGeometry(1000, 1000, 1000), material); | |
//生成したメッシュをSkybox用シーンに追加 | |
sceneCube.add(meshCube); | |
} | |
/** | |
* Initialize ground plane. | |
*/ | |
function initGround() { | |
var initColor, initTexture, | |
groundMaterial, groundTexture, | |
mesh; | |
initColor = new THREE.Color(0xaea893); | |
initTexture = THREE.ImageUtils.generateDataTexture(1, 1, initColor); | |
groundMaterial = new THREE.MeshPhongMaterial({color: 0xffffff, specular: 0x111111, map: initTexture}); | |
groundTexture = THREE.ImageUtils.loadTexture(groundTextureUrl, undefined, function () { groundMaterial.map = groundTexture; }); | |
groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping; | |
groundTexture.repeat.set(500, 500); | |
groundTexture.anisotropy = 6; | |
mesh = new THREE.Mesh(new THREE.PlaneGeometry(20000, 20000), groundMaterial); | |
mesh.rotation.x = -Math.PI / 2; | |
mesh.receiveShadow = true; | |
mesh.castShadow = true; | |
scene.add(mesh); | |
} | |
/** | |
* All of initialize to the WebGL scene. | |
*/ | |
function init() { | |
container = doc.createElement('div'); | |
doc.body.appendChild(container); | |
clock = new THREE.Clock(); | |
camera = new THREE.PerspectiveCamera(50, win.innerWidth / win.innerHeight, 1, 10000); | |
camera.position.set(0, 30, 100); | |
camera.target = new THREE.Vector3(0, 200, 0); | |
camera.lookAt(0, 0, 0); | |
controls = new THREE.TrackballControls(camera); | |
controls.rotateSpeed = 0.8; | |
controls.zoomSpeed = 0.5; | |
controls.panSpeed = 0.3; | |
//それぞれzoomなどをオフにする。デフォルトはfalse. | |
//controls.noRotate = false; | |
//controls.noZoom = false; | |
//controls.noPan = false; | |
//controls.staticMoving = false; | |
controls.dynamicDampingFactor = 0.5; | |
// | |
//Create a main scene. | |
scene = new THREE.Scene(); | |
// | |
var d = 100; | |
var pos = d; | |
globalLight = new THREE.DirectionalLight(0xefefff, 2); | |
globalLight.position.set(-pos, pos, pos);//.normalize(); | |
globalLight.castShadow = true; | |
globalLight.shadowMapWidth = 2048; | |
globalLight.shadowMapHeight = 2048; | |
globalLight.shadowCameraLeft = -d; | |
globalLight.shadowCameraRight = d; | |
globalLight.shadowCameraTop = d; | |
globalLight.shadowCameraBottom = -d; | |
globalLight.shadowCameraNear = 0.1; | |
globalLight.shadowCameraFar = 1000; | |
globalLight.shadowCameraFov = 40; | |
//globalLight.shadowCameraVisible = true; | |
globalLight.shadowBias = 0.0001; | |
globalLight.shadowDarkness = 0.5; | |
scene.add(globalLight); | |
var light2 = new THREE.DirectionalLight( 0xffefef, 2 ); | |
light2.position.set(-1, -1, -1).normalize(); | |
scene.add(light2); | |
//load a gips-danger | |
var loader = new THREE.JSONLoader(); | |
loader.load(modelUrl, createModel); | |
//load buildings. | |
loader.load('http://resources.edo-m18.me/models/gips-danger/building.js', function (geometry, materials) { | |
var face_material, | |
s = 100; | |
if (materials) { | |
face_material = new THREE.MeshFaceMaterial(materials); | |
} | |
else { | |
face_material = new THREE.MeshLambertMaterial({color: 0xcccccc}); | |
} | |
var building = new THREE.Mesh(geometry, face_material); | |
building.scale.set(s, s, s); | |
building.position.y += 35; | |
building.castShadow = true; | |
building.receiveShadow = true; | |
scene.add(building); | |
}); | |
// | |
initGround(); | |
initSkybox(); | |
// | |
renderer = new THREE.WebGLRenderer({antialias: true}); | |
renderer.sortObjects = false; | |
renderer.setSize(win.innerWidth, win.innerHeight); | |
renderer.setClearColor(0x000000, 1); | |
renderer.shadowMapEnabled = true; | |
renderer.shadowMapType = THREE.PCFShadowMap; | |
renderer.autoClear = false; | |
container.appendChild(renderer.domElement); | |
// | |
win.addEventListener('resize', onWindowResize, false); | |
} | |
// | |
function onWindowResize() { | |
camera.aspect = win.innerWidth / win.innerHeight; | |
camera.updateProjectionMatrix(); | |
renderer.setSize(win.innerWidth, win.innerHeight); | |
} | |
// | |
function animate() { | |
requestAnimationFrame(animate); | |
render(); | |
} | |
// | |
//var duration = 5000, | |
// keyframes = 30, | |
// lastKeyframe = 0, | |
// currentKeyframe = 0, | |
// interpolation = duration / keyframes; | |
function render() { | |
//camera.lookAt(camera.target); | |
if (model) { | |
var delta = clock.getDelta(); | |
model.updateAnimation(500 * delta); | |
//camera.position.copy(model.position); | |
//camera.position.z += 50; | |
var target = new THREE.Vector3(0, 0, 0); | |
target.copy(model.position); | |
target.y += 50; | |
camera.target = target; | |
//if (model.morphTargetInfluences) { | |
// // Alternate morph targets | |
// var time = Date.now() % duration; | |
// var keyframe = Math.floor(time / interpolation); | |
// if (keyframe != currentKeyframe) { | |
// model.morphTargetInfluences[lastKeyframe] = 0; | |
// model.morphTargetInfluences[currentKeyframe] = 1; | |
// model.morphTargetInfluences[keyframe] = 0; | |
// lastKeyframe = currentKeyframe; | |
// currentKeyframe = keyframe; | |
// } | |
// model.morphTargetInfluences[keyframe] = (time % interpolation) / interpolation; | |
// model.morphTargetInfluences[lastKeyframe] = 1 - model.morphTargetInfluences[keyframe]; | |
//} | |
} | |
renderer.clear(); | |
renderer.render(sceneCube, cameraCube); | |
renderer.render(scene, camera); | |
controls.update(); | |
} | |
//A = left, S = back, D = right, W = front | |
var A = 97, S = 115, D = 100, W = 119; | |
var vec = new THREE.Vector3(); | |
var xAxis = new THREE.Vector3(1, 0, 0); | |
var sp = 2; | |
doc.addEventListener('keypress', function (e) { | |
if (!/97|115|100|119/.test(e.keyCode)) { | |
return; | |
} | |
var delta = vec.subVectors(camera.target, camera.position).normalize(); | |
var deg = THREE.Math.radToDeg(Math.acos(xAxis.dot(delta))); | |
var rad, x, z; | |
switch (e.keyCode) { | |
case A: | |
deg += 90; | |
break; | |
case S: | |
deg += 180; | |
break; | |
case D: | |
deg += -90; | |
break; | |
case W: | |
break; | |
} | |
rad = THREE.Math.degToRad(deg); | |
x = Math.cos(rad); | |
z = Math.sin(rad); | |
model.position.x += x * sp; | |
model.position.z -= z * sp; | |
}, false); | |
// | |
doc.addEventListener('DOMContentLoaded', init, false); | |
}(window, document)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment