assimpExampleのソースコードを読んで、ofxAssimpModelLoaderで3Dモデルを描画する
openFrameworksのsamplesに入っているassimpExampleのソースコードを読みます。
assimpExampleとは
これ
openFrameworksのライブラリofxAssimpModelLoaderを使用して、読み込んだ3Dモデルをインタラクティブに表示切り替えするsampleです。
このソースを読んで、ofxAssimpModelLoaderで3Dモデルを描画するエッセンスを習得します。
まずはヘッダファイル。
ofApp.h
#ifndef _TEST_APP #define _TEST_APP #include "ofMain.h" #include "ofxAssimpModelLoader.h" #include "ofVboMesh.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); ofxAssimpModelLoader model; bool bHelpText; bool bAnimate; bool bAnimateMouse; float animationPosition; ofMesh mesh; ofLight light; }; #endif
ヘッダファイルをincludeします。
#include "ofxAssimpModelLoader.h"
この部分でクラスofxAssimpModelLoaderを初期化しています。
ofxAssimpModelLoader model;
また、ofLightを使って照明オブジェクトを初期化しています。
ofLight light;
ofApp.cpp
次はcppファイル。setupとupdateを確認。
#include "ofApp.h" void ofApp::setup(){ ofSetLogLevel(OF_LOG_VERBOSE); ofBackground(50, 0); ofDisableArbTex(); // we need GL_TEXTURE_2D for our models coords. bAnimate = false; bAnimateMouse = false; animationPosition = 0; model.loadModel("astroBoy_walk.dae", false); model.setPosition(ofGetWidth() * 0.5, (float)ofGetHeight() * 0.75 , 0); model.setLoopStateForAllAnimations(OF_LOOP_NORMAL); model.playAllAnimations(); if(!bAnimate) { model.setPausedForAllAnimations(true); } bHelpText = true; } void ofApp::update(){ model.update(); if(bAnimateMouse) { model.setPositionForAllAnimations(animationPosition); } mesh = model.getCurrentAnimatedMesh(0); }
3Dモデルを描画するだけなら、いろいろなものを読み飛ばして良さそう。
とりあえずmodelの設定関連が必要なので、以下が必須のコード。
void ofApp::setup(){ ofBackground(50, 0); ofDisableArbTex(); // we need GL_TEXTURE_2D for our models coords. model.loadModel("astroBoy_walk.dae", false); model.setPosition(ofGetWidth() * 0.5, (float)ofGetHeight() * 0.75 , 0); model.setLoopStateForAllAnimations(OF_LOOP_NORMAL); model.playAllAnimations(); } void ofApp::update(){ mode.update(); }
ofxAssimpModelLoaderのクラスメソッドは、公式ドキュメントに記載がほぼなく使い方がわからない。
唯一このページが参考になる。
openframeworks.cc
最後はdraw内のソースコード。
void ofApp::draw(){ ofSetColor(255); ofEnableBlendMode(OF_BLENDMODE_ALPHA); ofEnableDepthTest(); #ifndef TARGET_PROGRAMMABLE_GL glShadeModel(GL_SMOOTH); //some model / light stuff #endif light.enable(); ofEnableSeparateSpecularLight(); ofPushMatrix(); ofTranslate(model.getPosition().x+100, model.getPosition().y, 0); ofRotateDeg(-mouseX, 0, 1, 0); ofTranslate(-model.getPosition().x, -model.getPosition().y, 0); model.drawFaces(); ofPopMatrix(); #ifndef TARGET_PROGRAMMABLE_GL glEnable(GL_NORMALIZE); #endif ofPushMatrix(); ofTranslate(model.getPosition().x-300, model.getPosition().y, 0); ofRotateDeg(-mouseX, 0, 1, 0); ofTranslate(-model.getPosition().x, -model.getPosition().y, 0); ofxAssimpMeshHelper & meshHelper = model.getMeshHelper(0); ofMultMatrix(model.getModelMatrix()); ofMultMatrix(meshHelper.matrix); ofMaterial & material = meshHelper.material; if(meshHelper.hasTexture()){ meshHelper.getTextureRef().bind(); } material.begin(); mesh.drawWireframe(); material.end(); if(meshHelper.hasTexture()){ meshHelper.getTextureRef().unbind(); } ofPopMatrix(); ofDisableDepthTest(); light.disable(); ofDisableLighting(); ofDisableSeparateSpecularLight(); if(bHelpText){ ofSetColor(255, 255, 255 ); stringstream ss; ss << "FPS: " << ofToString(ofGetFrameRate(),0) <<endl<<endl; ss <<"(keys 1-5): load models"<<endl; ss << "num of animations in this model: " + ofToString(model.getAnimationCount()); ss <<endl <<"(Spacebar): toggle animation"<<endl; ss <<"(LEFT MOUSE BUTTON DRAG in y-axis): control animation."<<endl; ss <<"(h): toggle help."<<endl; ofDrawBitmapString(ss.str().c_str(), 20, 20); } }
いろいろな記載があるけど、モデルの描画を行う記述は以下。
void ofApp::draw(){ ofSetColor(255); light.enable(); ofEnableSeparateSpecularLight(); model.drawFaces(); }
ofEnableSeparateSpecularLightは、モデルに光沢がつくような処理を行う記述。
openframeworks.jp
鏡面ハイライトと呼ぶ。詳細は以下。
area.autodesk.jp
自分で書いてみる
というわけで以下のofApp.cppを作成。
#include "ofApp.h" //-------------------------------------------------------------- void ofApp::setup(){ ofBackground(50, 0); ofDisableArbTex(); model.loadModel("astroBoy_walk.dae"); model.setPosition(ofGetWidth() * 0.5, (float)ofGetWidth() * 0.75, 0); model.setLoopStateForAllAnimations(OF_LOOP_NORMAL); model.playAllAnimations(); } //-------------------------------------------------------------- void ofApp::update(){ model.update(); } //-------------------------------------------------------------- void ofApp::draw(){ ofSetColor(255); ofEnableBlendMode(OF_BLENDMODE_ALPHA); ofEnableDepthTest(); light.enable(); ofEnableSeparateSpecularLight(); model.drawFaces(); // loadModelで読み込んだモデルを表示 }
実行結果は以下の通り。
陰影もあって良い感じ。3Dモデルの描画に成功した。
ちなみに、light.enable(); を外すとこんな感じ。