LoginSignup
11
13

More than 5 years have passed since last update.

three.jsのサンプルをいじってカメラの動きを確認してみた

Last updated at Posted at 2016-02-22

カメラ位置を自動で動かすなら、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 );
}

11
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
13