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

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

カメラ ofCamera 注視点 |3Dプログラミング整理

カメラ注視点について

カメラを置く位置が決まったので、 次にカメラのレンズが向く方向を操作してみる。

ハンディーカメラを想像してみると分かりやすいかと。

自分自身の立っている「位置」は、動かない(歩かない)でも、 手を動かす事でカメラを動かして撮影する事って良くあると思います。

この時って、言い換えると、 ”カメラの位置(position)は動いていないけど、 カメラのレンズが向いている方向が動いている” と言えますよね。

つまりレンズがカメラの目だとしたら、 その目が注目している方向(ベクトル)の事を注視点と想像してもらえれば、 たぶん、ほぼほぼイメージOKかなと思っています。

今日は、

1)カメラのポジション固定

2)画面中心に球を描画

この後に、 カメラの注視点を変化させてみたいと思います。

ofCameraの注視点を変更するには、 lookAtメソッドを使用します。

lookAtメソッドはofNodeクラスのメソッドです。 ofCameraはofNodeクラスを継承しているのでlookAtメソッドを使えます。

openFrameworksのDocumentを見ると、 lookAt(const ofVec3f &lookAtPosition, ofVec3f upVector=ofVec3f(0, 1, 0))

と、引数が2つあります。

1つ目が今回課題にしている注視点を表すベクトル。2つ目はカメラの法線ベクトルを表しています。 2つ目に関しては別の機会に触れますが、簡単に書いておくとカメラ全体(そのもの)の、上方向を表すベクトルを指定するベクトルになります。

今回は、upVectorに関しては省略しますね。

では、上記1)2)をふまえた上で、 カメラの注視点を毎フレーム毎にx軸のみ変更してみます。 注視点(ハンディーカメラ)で、徐々に横方向にパンしているイメージです。 ちょっと分かりにくいかもしれませんが、中央にある黄色い円が注視点になっています。 黄色円の位置は動いていないのでプログラム的には、球を動かしているように錯覚する方も いらっしゃるかと思いますが、注視点は、カメラ(自分の目)が向いている方向になるので、 常に画面上では動かないように見えます。

自分の目が1つだとすると、首を動かした時、 見えるものや風景は変わりますが、注視点は常に真ん中なのです。(たぶん)

#include "testApp.h"

int centerx, centery;
float _x;
float _direction_x;
float _max;

//何かキーを押したらスタート
bool isStart;

//注視点
ofVec3f lookVec;


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

    ofBackground(100);

    ofSetFrameRate(60);
    ofEnableSmoothing();
    glEnable(GL_DEPTH_TEST);
    
    centerx = ofGetWidth()/2;
    centery = ofGetHeight()/2;
    
    
    //  注視点x座標
    _x = 0;
    
    
    // 注視点が右に進むかどうかの掛数
    _direction_x = 1;
    
    _max = 300.0;
    
    isStart = false;
    
    
    //  カメラポジション
    cam.setPosition( centerx, centery, 500);
    
    //  注視点 デフォルト
    lookVec = ofVec3f(0,0,0);
}

//--------------------------------------------------------------
void testApp::update(){

    if (isStart == false) return;
    
    _x += _direction_x;
    if ( _x > _max ){
        _direction_x = -1;
    } else if ( _x < _max && _direction_x > 0) {
        _direction_x = 1;
    }
    
    lookVec.x = centerx + _x;
    lookVec.y = centery;
    lookVec.z = 0;
    
    cameraUp += 0.1;
    
    // 注視点の変更
    cam.lookAt(lookVec);
}

//--------------------------------------------------------------
void testApp::draw(){
    
    
    ofSetColor(255);
    string pos = "camera x = " + ofToString(_x);
    ofDrawBitmapString(pos, ofPoint(10,10,0));
    
    cam.begin();
        ofSetColor(255, 0, 0);
        ofNoFill();

        // 球は常に同じ位置に描画(建物や木は常に同じところに存在するのと同じ意味)
        ofSphere(centerx, centery, 0, 100);
    
        // 注視点
        ofFill();
        ofSetColor(255, 255, 0);
        ofSphere(lookVec, 10);
    cam.end();

}

//--------------------------------------------------------------
void testApp::keyPressed(int key){
    //  何かキーを押したらスタート
    isStart = true;
}