「がんばれない」けど「がんばりたい」

ITエンジニアの仕事のこと。AI、機械学習、ディープラーニング。地頭力。車のこと。

simple particle engine +1 / ofxWorkshop

今から3.5年くらい前の2012年4月にopenFrameworksのワークショップが土日の2日間@ライゾマティクスさんで行われました。その時の応募資格に遠く及ばなかったのですが、まさに清水の舞台から・・な、心持ちで参加したのを今でも思い出します。。

その第1日目に学んだパーティクルエンジンと、このブログでも何本かの記事にしていますダニエルシェフマンさんのNature of Codeで学んだことが、唯一僕の3Dの知識として現在まで辛うじて残っている状態です。それ以上の事は全く無知・・なので、徐々に広げていこうと思っていますが、今回はこのライゾマの第1日目で行ったSimpleParticleEngineの覚書をPostすることで備忘とマトメにしようと思います。

simple_particle_engine


1. Introduction

第1日目。集まった人数は10名ほどでした。講師には、現在はライゾマを退いていらっしゃいますが、伝説?を作り続けてきた比嘉さん。

ちょうどライゾマに入社して、数ヶ月くらいな時だったかなと・・

そして始まる前に大度さんから、ちょっとした挨拶があったのを覚えています。 確か、ライゾマさんで初めてのワークショップという事と、oFを普段使っている人とのコミュニティーが少しでも出来て、またoFを使っている人って、どんな人たちが居るのかな。。という興味がありますという感じな事をおっしゃっていた・・かな。

次に比嘉さんの自己紹介が、ざっくりあって、始まり〜。LTなんかではPPTを使うのが主流ですが、比嘉さんはIllustratorを使っていたのが、なんか他の人と違ってて、カッコよかったです。


2. Simple Particle Engine

まずパーティクルつくってみましょっか。ということで、たぶん、参加者のパーティクルのイメージを統一するために、まったく動かないパーティクル・・いわば、無数の点・・を表示するところから開始。

あ、そうそう。この頃、自分はoFを触り始めた頃で、しかもiPhoneでoFしたい+なにか作りたいという熱があったため、openGLはopenGLESを使用することになってたのです・・細かいところですが、そのあたりでESとの違いに戸惑いながら講義を聞いていました。


3. 目的

  • 無数のといっても、1000個の動かない点を、決められた範囲内に打っていく

パーティクル・クラス

  • particle.hで幾つかプロパティを定義していますが、今回は動かないのでlocationしか使いません。
  • glVertex3fv関数についてはググってもらうとわかるのですが、普通は面の頂点を配列で指定する為の関数。引数にlocationのポインタを渡す=配列を渡すです。
  • glVertex3f関数というのも使える(はず)のですが、この場合は配列ではなく、x, y, zの3つの引数で渡すことになります

Particle.h

#ifndef ___1SimpleParticleEngine__Particle__
#define ___1SimpleParticleEngine__Particle__

#include <stdio.h>
#include "ofMain.h"

class Particle {

public:

    //コンストラクタ
    Particle () {
    }

    //デストラクタ
    virtual ~Particle() {
    }

    //位置
    ofVec3f location;

    //加速度
    ofVec3f acceleration;

    //速さ
    ofVec3f velocity;

    //oFの流儀ですね
    void setup();
    void update();
    void draw();

    //Nature of Codeにならって用意しています
    //今回は使用しません!
    void applyForce(ofVec3f f);
};
#endif /* defined(___1SimpleParticleEngine__Particle__) */

Particle.cpp

//
//  Particle.cpp
//  01SimpleParticleEngine
//
//  Created by KAZUYOSHI UENO on 2015/02/21.
//
//

#include "Particle.h"

float randomValue(float min, float max) {
    return ofRandom(min, max);
}

void Particle::setup() {
    location.set(randomValue(-1000, 1000), randomValue(-1000, 1000), randomValue(-1000, 1000));
}

void Particle::update() {
}

void Particle::draw() {
    glVertex3fv(location.getPtr());
}

メイン・クラス

メインクラスでは特に難しいことはしていないのですが、 * 画面描画後にマウスでカメラ視点を変えられるようにofEasyCamを使っている * パーティクルを描画する箇所(draw())内ではglBegin(GL_POINTS);と宣言し、openGLにおいて、各頂点が点として描画されるようにしています。

ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
    public:
        void setup();
        void update();
        void draw();

        void keyPressed(int key);
        void keyReleased(int key);
        void mouseMoved(int x, int y);
        void mouseDragged(int x, int y, int button);
        void mousePressed(int x, int y, int button);
        void mouseReleased(int x, int y, int button);
        void windowResized(int w, int h);
        void dragEvent(ofDragInfo dragInfo);
        void gotMessage(ofMessage msg);

    ofEasyCam cam;
};

ofApp.cpp

#include "ofApp.h"

#include "Particle.h"

//パーティクルの数
#define NUM_PARTICLES 1000

//パーティクル配列
vector<Particle> particles;

//--------------------------------------------------------------
void ofApp::setup(){

    ofSetVerticalSync(true);
    ofSetFrameRate(60);
    ofBackground(0, 0, 0);

    //particle init.
    particles.resize(NUM_PARTICLES); // -> ここでインスタンス化されている

    for (int i = 0; i < NUM_PARTICLES; i++) {
        Particle *p = &particles[i]; // resizeメソッドで既にインスタンス化されているからポインタが取得できる
        p->setup(); // -> 位置を決定
    }
}

//--------------------------------------------------------------
void ofApp::update(){
}

//--------------------------------------------------------------
void ofApp::draw(){

    cam.begin(); //-> カメラ有効
    glBegin(GL_POINTS); // -> 点として描画
    for (int i = 0; i < NUM_PARTICLES; i++) {
        Particle *p = &particles[i];
        p->draw();
    }
    glEnd();
    cam.end();
}

動画