はじめに
この記事はopenFrameworksで3dモデルを扱いたいんだけどどうすればいいの?
openFrameworks初めて触って、3dモデルを扱いたいのですが!
みたいな方に向けて書いてる記事です。(最近そういう質問が多かったので記事にしました / OSX向けです)
ofxAssimpleModelLoaderという3Dモデルを扱えるAddonがありますがaddonにsampleプロジェクトがないので今回作りました。
下準備
openFrameworksをダウンロードすると
http://openframeworks.cc/download/
ofxAssimpleModelLoaderという、3dモデルを扱うAddonが含まれています。
ProjectGeneratorから
AddonにofxAssimpleModelLoaderを追加して、Generateをします。
作成した、プロジェクトのbin/data
ディレクトリに適当な3Dのモデルを配置します。
この時モデルファイルの拡張子は
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の変数を宣言します。
#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;
};
次に実装ファイルに関してです。
//--------------------------------------------------------------
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として描画しています。
結果
このような感じで3Dモデルが、描画されます
発展
3Dモデルを面を描画する方法について、以下のように、実装ファイルを変更します。
//--------------------------------------------------------------
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();
}
drawFace()
を用いると面が描画され、drawVertices()
で頂点が描画されています。
次の例では、drawWireframe()
で先ほど描画した3Dモデルの辺を点線として描画する方法を紹介します。
辺を点線として扱うには
glEnable();
と`glLinStipple();`を使います。後者の関数に関しては、こちらに詳細がまとまっており参考にさせていただきました。
#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();
}
結果は以下の通りです
また、随時更新していきます。