not good but great

プログラミング、アート、映画・本の感想について書きます。

三角関数で波打つパーティクルを作成する

demo


三角関数による位置・大きさの調整

・参考
https://threejsdoc.appspot.com/doc/three.js/examples/canvas_particles_waves.html
https://threejsdoc.appspot.com/doc/three.js/examples/canvas_particles_floor.html

particles = new Array();

まずパーティクル一つ一つの位置を扱う必要があるので、作成したパーティクルを配列に入れる。

//パーティクルの個数
var AMOUNTX = 50;
var AMOUNTY = 50;
//パーティクル同士の間隔
var SEPARATION = 50;

次にパーティクルを等間隔で整列させることを考える。これはfor文を使って、X,Y軸方向に並べたらよい。for文を習いたてのころよくやったやつだ。ここでは予めパーティクルの個数、間隔という定数を宣言しておく。

パーティクルの整列

var i = 0;

    for(var ix = 0;ix < AMOUNTX;ix++){
        for(var iy = 0;iy < AMOUNTY;iy++){
            particle = particles[i++] = new THREE.Particle(material);

            particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2);
            particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2);

            scene.add(particle);
        }
    }

パーティクルを生成して、指定の位置に並べさせている。原点が画面の中心であることを考えると、マイナス方向にもパーティクルを並べる必要がある。だから(個数×間隔)÷2を引いている。

パーティクルを波打たせる

var i = 0;

    for(var ix = 0;ix < AMOUNTX;ix++){
        for(var iy = 0;iy < AMOUNTY;iy++){
            particle = particles[i++];
            
            particle.position.y = Math.sin((ix + theta)*0.3)*100 + Math.sin((iy + theta)*0.3)*100;
            
            particle.scale.x = particle.scale.y = Math.sin((ix + theta)*0.3) + Math.sin((iy + theta)*0.3)*2;

        }
    }

theta += 0.1;

アニメーションする際に繰り返し実行される関数に、上のコードを書く。thetaの値が変わることにより、y軸方向の位置はsinカーブを描く。数式はこれといった公式があるわけではなく、随時変更して確認しながら決めた。x軸方向をcosで動かすと円を描くこともできる。

codepenに円で回るバージョンもあげてみた。
http://codepen.io/naoyashiga/details/KmHFx

平行・透視投影カメラの切り替え

カメラの種類によって見え方が大きく変わるので、関数に分けてみた。

平行投影カメラ(OrthographicCamera)

/*-----------------------------------
    平行投影カメラ
-----------------------------------*/
function Orthographic_Camera(){
    //平行投影カメラにおける視線の領域
    var left = - SCREEN_WIDTH;
    var right = SCREEN_WIDTH;
    var top = SCREEN_HEIGHT;
    var bottom = - SCREEN_HEIGHT;

    //クリッピング手前
    var near = -2000;
    //クリッピング奥
    var far = 1000;

    //平行投影カメラを生成
    camera = new THREE.OrthographicCamera( left , right , top , bottom , near , far );
    camera.position.x = 200;
    camera.position.y = 100;
    camera.position.z = 200;
}

関数に分けているので定数はグローバルで定義している。

var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;

透視投影カメラ(PerspectiveCamera)

/*-----------------------------------
    透視投影カメラ
-----------------------------------*/
function Perspective_Camera(){
    //画角
    var fov = 75;
    //縦横比
    var aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
    //クリッピング手前
    var near = 1;
    //クリッピング奥
    var far = 10000;
    
    //カメラを生成
    camera = new THREE.PerspectiveCamera(fov,aspect,near,far);

    camera.position.x = 1000;
    camera.position.z = 100;
}

これでデバッグ時にカメラの切り替えが楽になった。変数の宣言の仕方に注意する必要が出てきたが、メインの関数の記述がスッキリした。