LoginSignup
16
11

More than 5 years have passed since last update.

openFrameworksで3Dモデルを扱う~ofxAssimpleModelLoader編~

Last updated at Posted at 2017-03-29

はじめに

この記事はopenFrameworksで3dモデルを扱いたいんだけどどうすればいいの?
openFrameworks初めて触って、3dモデルを扱いたいのですが!
みたいな方に向けて書いてる記事です。(最近そういう質問が多かったので記事にしました / OSX向けです)
ofxAssimpleModelLoaderという3Dモデルを扱えるAddonがありますがaddonにsampleプロジェクトがないので今回作りました。

下準備

openFrameworksをダウンロードすると
http://openframeworks.cc/download/

標準でaddonsディレクトリに
17555002_1317846104964234_684798948_n.png

ofxAssimpleModelLoaderという、3dモデルを扱うAddonが含まれています。

ProjectGeneratorから

Screen Shot 2017-03-29 at 17.59.48.png

AddonにofxAssimpleModelLoaderを追加して、Generateをします。

作成した、プロジェクトのbin/dataディレクトリに適当な3Dのモデルを配置します。

Screen Shot 2017-03-29 at 21.10.53.png

この時モデルファイルの拡張子は

3DS, ASE. DXF, HMP, MD2, MD3, MD5, MDC, MDL, NFF, PLY
, STL, X, LWO, OBJ, SMD, Collada, LWO, Ogre XML, partly LWS

のいずれかである必要があります。

実装

ヘッダファイルでofxAssimpModelLoader.hをincludeします。
その後に、ofxAssimpModelLoaderの変数、ofCameraの変数を宣言します。

ofApp.h
#pragma once

#include "ofMain.h"
#include "ofxAssimpModelLoader.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 mouseEntered(int x, int y);
        void mouseExited(int x, int y);
        void windowResized(int w, int h);
        void dragEvent(ofDragInfo dragInfo);
        void gotMessage(ofMessage msg);

    ofCamera camera;
    ofxAssimpModelLoader mAssimpModelLoader;
    string model_path;
};

次に実装ファイルに関してです。

ofApp.cpp
//--------------------------------------------------------------
void ofApp::setup(){
    model_path = "model_sample.stl";
    mAssimpModelLoader.setScale(0.5, 0.5, 0.5);
    mAssimpModelLoader.loadModel(model_path);
}

//--------------------------------------------------------------
void ofApp::update(){
    mAssimpModelLoader.update();
    camera.lookAt(ofVec3f(0,0,0));
    camera.setPosition(500*cos(ofGetElapsedTimef()/10), 200, 500*sin(ofGetElapsedTimef()/10));
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);
    ofPushMatrix();
    ofTranslate(ofGetWidth()/2,ofGetHeight()/2);
    camera.begin();
    ofRotateX(-90);
    ofSetLineWidth(1);
    mAssimpModelLoader.drawWireframe();  //モデルを描画
    camera.end();
    ofPopMatrix();
}

構成は単純で、setup()でモデルの大きさ(scale)をどうするかを設定
また、モデル自体のロードを行います

update()はofVideoPlayerなど同様にAssimpModelLoaderのインスタンスのupdate()を呼びます。
今回はサンプルとして3Dモデルの周りをカメラが回ってる感じを出すために、その更新も書いています。

draw()は位置や座標系を調整して、mAssimpModelLoader.drawWireframe()でモデルをwirefranmeとして描画しています。

結果

gif

このような感じで3Dモデルが、描画されます

発展

3Dモデルを面を描画する方法について、以下のように、実装ファイルを変更します。

ofApp.cpp
//--------------------------------------------------------------
void ofApp::setup(){
    model_path = "model_sample.stl";
    mAssimpModelLoader.setScale(0.5, 0.5, 0.5);
    mAssimpModelLoader.loadModel(model_path);
}

//--------------------------------------------------------------
void ofApp::update(){
    mAssimpModelLoader.update();
    camera.lookAt(ofVec3f(0,0,0));
    camera.setPosition(500*cos(ofGetElapsedTimef()/10), 200, 500*sin(ofGetElapsedTimef()/10));
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);
    ofSetColor(255,30);
    ofPushMatrix();
    ofTranslate(ofGetWidth()/2,ofGetHeight()/2);
    camera.begin();
    ofRotateX(-90);
    ofSetLineWidth(1);
    mAssimpModelLoader.drawVertices(); //モデルの頂点を描画
    mAssimpModelLoader.drawFaces();  //モデルの面を描画
    camera.end();
    ofPopMatrix();
}

このまま実行すると以下のようになります。
gif

drawFace()を用いると面が描画され、drawVertices()で頂点が描画されています。

次の例では、drawWireframe()で先ほど描画した3Dモデルの辺を点線として描画する方法を紹介します。
辺を点線として扱うには

glEnable();と`glLinStipple();`を使います。後者の関数に関しては、こちらに詳細がまとまっており参考にさせていただきました。

ofApp.cpp
#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    model_path = "model_sample.stl";
    mAssimpModelLoader.setScale(0.5, 0.5, 0.5);
    mAssimpModelLoader.loadModel(model_path);
}

//--------------------------------------------------------------
void ofApp::update(){
    mAssimpModelLoader.update();
    camera.lookAt(ofVec3f(0,0,0));
    camera.setPosition(500*cos(ofGetElapsedTimef()/10), 200, 500*sin(ofGetElapsedTimef()/10));
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofSetColor(255,30);
    ofBackground(0);
    ofPushMatrix();
    ofTranslate(ofGetWidth()/2,ofGetHeight()/2);
    camera.begin();
    ofRotateX(-90);
    ofSetLineWidth(1);
    glEnable(GL_LINE_STIPPLE);
    glLineStipple(0.1 , 0x0101);
    mAssimpModelLoader.drawWireframe();  //モデルを描画
    glDisable(GL_LINE_STIPPLE);
    camera.end();
    ofPopMatrix();
}

結果は以下の通りです

gif

また、随時更新していきます。

16
11
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
16
11