カメラ位置を自動で動かすなら、OrbitControlsは使えない
カメラ位置を自動で動かさないなら、OrbitControlsを使える
カメラ自動回転
render()部分のカメラの自動回転に着目。
javascript
// Detector.js webgl使えないブラウザへのサポート
// http://gupuru.hatenablog.jp/entry/2014/01/05/224813
if ( ! Detector.webgl ) {
Detector.addGetWebGLMessage();
document.getElementById( 'container' ).innerHTML = "";
}
var container, stats;
var camera, controls, scene, renderer;
var sphere;
var parameters = {
width: 2000,
height: 2000,
widthSegments: 250,
heightSegments: 250,
depth: 1500,
param: 4,
filterparam: 1
};
var waterNormals;
var clock = new THREE.Clock();
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 10000, 2000 );
scene.add( new THREE.AmbientLight( 0x444444 ) );
// 球の上のライト
var light = new THREE.DirectionalLight( 0xffffbb, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );
// 水面
waterNormals = new THREE.TextureLoader().load( 'img/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );
// 水面反射
mirrorMesh = new THREE.Mesh(
new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.material
);
mirrorMesh.add( water );
mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );
// load skybox 環境マッピング
// http://www.atmarkit.co.jp/ait/articles/1210/04/news142_3.html
var cubeMap = new THREE.CubeTexture( [] );
cubeMap.format = THREE.RGBFormat;
var loader = new THREE.ImageLoader();
loader.load( 'img/skyboxsun25degtest.png', function ( image ) {
var getSide = function ( x, y ) {
var size = 1024;
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );
return canvas;
};
cubeMap.images[ 0 ] = getSide( 2, 1 ); // px
cubeMap.images[ 1 ] = getSide( 0, 1 ); // nx
cubeMap.images[ 2 ] = getSide( 1, 0 ); // py
cubeMap.images[ 3 ] = getSide( 1, 2 ); // ny
cubeMap.images[ 4 ] = getSide( 1, 1 ); // pz
cubeMap.images[ 5 ] = getSide( 3, 1 ); // nz
cubeMap.needsUpdate = true;
} );
var cubeShader = THREE.ShaderLib[ 'cube' ];
cubeShader.uniforms[ 'tCube' ].value = cubeMap;
var skyBoxMaterial = new THREE.ShaderMaterial( {
fragmentShader: cubeShader.fragmentShader,
vertexShader: cubeShader.vertexShader,
uniforms: cubeShader.uniforms,
depthWrite: false,
side: THREE.BackSide
} );
var skyBox = new THREE.Mesh(
new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );
// 球体をつくる
// http://threejs.org/docs/#Reference/Extras.Geometries/IcosahedronGeometry
var geometry = new THREE.IcosahedronGeometry( 800, 1 );
// 一面づつ色を変える
for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
}
var material = new THREE.MeshPhongMaterial( {
vertexColors: THREE.FaceColors,
shininess: 100,
envMap: cubeMap
} );
sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
// stats.js FPSを表示する
// http://tmlife.net/programming/javascript/lasted-stats-js-usage.html
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
stats.update();
render();
requestAnimationFrame( animate );
}
function render() {
// カメラ回転
var theta = clock.getElapsedTime();
camera.position.x = 10000 * Math.sin(theta);
camera.position.y = 3000 * Math.cos(theta) + 3100; // 水面下に入らないように+100
camera.position.z = 10000 * Math.cos(theta);
camera.lookAt(new THREE.Vector3(0, 0, 0));
// 球
var time = performance.now() * 0.002; // 球のスピード
sphere.position.y = Math.sin( time ) * 1000 + 500;
sphere.rotation.x = time * 0.5;
sphere.rotation.z = time * 0.51;
// 海
water.material.uniforms.time.value += 50.0 / 60.0; // 波のスピード
water.render();
renderer.render( scene, camera );
}
カメラ手動回転
OrbitControlsの記述に着目。
javascript
if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
var stats;
var camera, controls, scene, renderer;
init();
animate();
function init() {
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xB7B5DA, 0.002 );
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( scene.fog.color );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 500;
// OrbitControls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enablePan = true;
controls.enableZoom = true;
controls.minDistance = -500.0;
controls.maxDistance = 800.0;
controls.target.set( 0, 0, 0 );
controls.maxPolarAngle = Math.PI * 1; // 0.5なら下からのぞき込めなくなる
// world
var geometry = new THREE.BoxGeometry(10, 25, 0);
var texture = new THREE.TextureLoader().load( 'img/hat.png' );
var material = new THREE.MeshPhongMaterial( { map: texture, transparent: true, side: THREE. BackSide } );
// ばらばらに配置
for ( var i = 0; i < 2000; i ++ ) {
mesh = new THREE.Mesh( geometry, material );
mesh.position.x = ( Math.random() - 0.5 ) * 1000;
mesh.position.y = ( Math.random() - 0.5 ) * 1000;
mesh.position.z = ( Math.random() - 0.5 ) * 1000;
scene.add( mesh );
}
// lights
light = new THREE.DirectionalLight( 0xffffff );
light.position.set( 1, 1, 1 );
scene.add( light );
light = new THREE.DirectionalLight( 0x002288 );
light.position.set( -1, -1, -1 );
scene.add( light );
light = new THREE.AmbientLight( 0x222222 );
scene.add( light );
// stats
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.zIndex = 100;
container.appendChild( stats.domElement );
window.addEventListener( 'resize', onWindowResize, false );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
stats.update();
render();
}
function render() {
renderer.render( scene, camera );
}