(メモ)ofxMSAInterpolatorのバグ取り
openFrameworksのofxMSAInterpolatorというアドオンは、1次、2次、3次のスプライン補間(置いた点を通る)を提供してくれるライブラリです。0.7時代でメンテナンスが止まってしまっているので、新しいバージョンのopenFrameworksで動かすためには少しだけ手直しが必要です。そのための、メモ。
動かした環境 openframeworks0.8.4 on Microsoft VisualStudio 2012
Addon ofxMSAInterpolator
Bugfix
MSAInterpolator3D.h
/**************************** 3D InterpolatorT (of Vec3) ****************************/ #pragma once #include "MSAInterpolatorT.h" namespace msa { typedef InterpolatorT<Vec3f> Interpolator3D; //-------------------------------------------------------------- inline float lengthOf(const Vec3f& v) { return v.length(); } //-------------------------------------------------------------- // OpenGL ES compatibility added by Rob Seward // http://www.openframeworks.cc/forum/viewtopic.php?f=25&t=3767&p=19865 inline void drawInterpolatorRaw(Interpolator3D spline, int dotSize = 20, int lineWidth = 4){ int numItems = spline.size(); if(numItems == 0) return; if(lineWidth) { glLineWidth(lineWidth); //GLfloat vertex[numItems * 3]; GLfloat* vertex = new GLfloat[numItems * 3 + 3]; for(int i=0; i<numItems; i++) { vertex[i*3] = spline.at(i).x; vertex[(i*3)+1] = spline.at(i).y; vertex[(i*3)+2] = spline.at(i).z; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex); glDrawArrays(GL_LINE_STRIP, 0, numItems); delete [] vertex; } if(dotSize) { glPointSize(dotSize); //GLfloat vertex[numItems * 3]; GLfloat* vertex=new GLfloat[numItems * 3 + 3]; for(int i=0; i<numItems; i++) { vertex[i*3] = spline.at(i).x; vertex[(i*3)+1] = spline.at(i).y; vertex[(i*3)+2] = spline.at(i).z; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex); glDrawArrays(GL_POINTS, 0, numItems); delete [] vertex; } } //-------------------------------------------------------------- inline void drawInterpolatorSmooth(Interpolator3D spline, int numSteps, int dotSize = 8, int lineWidth = 2) { float spacing = 1.0/numSteps; if(spline.size() == 0) return; if(lineWidth) { glLineWidth(lineWidth); //GLfloat vertex[numSteps * 3]; GLfloat* vertex = new GLfloat[numSteps * 3 + 3]; //int i=0; //for(float f=0; f<1; f+= spacing) { for(int i=0; i<numSteps; i++){ float f=i*spacing; Vec3f v = spline.sampleAt(f); vertex[i*3] = v.x; vertex[(i*3)+1] = v.y; vertex[(i*3)+2] = v.z; //i++; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex); glDrawArrays(GL_LINE_STRIP, 0, numSteps); if(vertex) delete [] vertex; } if(dotSize) { glPointSize(dotSize); //GLfloat vertex[numSteps * 3]; GLfloat* vertex = new GLfloat[numSteps * 3 + 3]; //int i=0; //for(float f=0; f<1; f+= spacing) { for(int i=0; i<numSteps; i++){ float f=i*spacing; Vec3f v = spline.sampleAt(f); vertex[i*3] = v.x; vertex[(i*3)+1] = v.y; vertex[(i*3)+2] = v.z; //i++; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex); glDrawArrays(GL_POINTS, 0, numSteps); if(vertex) delete [] vertex; } } }
Also, MSAInterpolator2D.h
/**************************** 2D InterpolatorT (of Vec2) ****************************/ #pragma once #include "MSAInterpolatorT.h" namespace msa { typedef InterpolatorT<Vec2f> Interpolator2D; //-------------------------------------------------------------- inline float lengthOf(const Vec2f& v) { return v.length(); } //-------------------------------------------------------------- // OpenGL ES compatibility added by Rob Seward // http://www.openframeworks.cc/forum/viewtopic.php?f=25&t=3767&p=19865 inline void drawInterpolatorRaw(Interpolator2D &spline, int dotSize = 20, int lineWidth = 4){ int numItems = spline.size(); if(lineWidth) { glLineWidth(lineWidth); //GLfloat vertex[numItems * 2]; GLfloat* vertex = new GLfloat[numItems * 2]; for(int i=0; i<numItems; i++) { vertex[i*2] = spline.at(i).x; vertex[(i*2)+1] = spline.at(i).y; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex); glDrawArrays(GL_LINE_STRIP, 0, numItems); delete [] vertex; } if(dotSize) { glPointSize(dotSize); //GLfloat vertex[numItems * 2]; GLfloat* vertex = new GLfloat[numItems * 2]; for(int i=0; i<numItems; i++) { vertex[i*2] = spline.at(i).x; vertex[(i*2)+1] = spline.at(i).y; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex); glDrawArrays(GL_POINTS, 0, numItems); delete [] vertex; } } //-------------------------------------------------------------- inline void drawInterpolatorSmooth(Interpolator2D &spline, int numSteps, int dotSize = 8, int lineWidth = 2) { float spacing = 1.0/numSteps; if(lineWidth) { glLineWidth(lineWidth); //GLfloat vertex[numSteps * 2]; GLfloat* vertex = new GLfloat[numSteps * 2]; //int i=0; //for(float f=0; f<1; f+= spacing) { for(int i=0; i<numSteps; i++){ float f=i*spacing; Vec2f v = spline.sampleAt(f); vertex[i*2] = v.x; vertex[(i*2)+1] = v.y; //i++; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex); glDrawArrays(GL_LINE_STRIP, 0, numSteps); delete [] vertex; } if(dotSize) { glPointSize(dotSize); //GLfloat vertex[numSteps * 2]; GLfloat* vertex = new GLfloat[numSteps * 2]; //int i=0; //for(float f=0; f<1; f+= spacing) { for(int i=0; i<numSteps; i++){ float f=i*spacing; Vec2f v = spline.sampleAt(f); vertex[i*2] = v.x; vertex[(i*2)+1] = v.y; //i++; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex); glDrawArrays(GL_POINTS, 0, numSteps); delete [] vertex; } } }
MSACoreなるライブラリは、Vec2fやVec3fをofVec2fやofVec3fに置き換えて、clamp関数を[2]などを参考に
inline float clamp(float a, float min, float max) { if (min < a) return a < max ? a : max; else return min; }
書き換えてしまえば不要になる。
追記20150824: openFrameworksにofClampなる関数があったので、そっちを使えば良いですね。
メモリ確保の+3は、lengthでサンプリングするときの場当たり的なエラーの回避のため。indexの数が正しく合わず場合によっては、最後の結果が表示されない。
多少、無駄を省いた版。
ただし、OpenGL ESの対応は外れてしまっていると思われます。
// OpenGL ES compatibility added by Rob Seward
// http://www.openframeworks.cc/forum/viewtopic.php?f=25&t=3767&p=19865
/**************************** 3D InterpolatorT (of Vec3) ****************************/ #pragma once #include "MSAInterpolatorT.h" namespace msa { typedef InterpolatorT<ofVec3f> Interpolator3D; //-------------------------------------------------------------- inline float lengthOf(const ofVec3f& v) { return v.length(); } //-------------------------------------------------------------- inline void drawInterpolatorRaw(Interpolator3D spline, int dotSize = 20, int lineWidth = 4){ int numItems = spline.size(); if(numItems == 0) return; if(!lineWidth && !dotSize) return; GLfloat* vertex = new GLfloat[numItems * 3]; for(int i=0; i<numItems; i++) { vertex[i*3] = spline.at(i).x; vertex[(i*3)+1] = spline.at(i).y; vertex[(i*3)+2] = spline.at(i).z; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex); if(lineWidth){ glLineWidth(lineWidth); glDrawArrays(GL_LINE_STRIP, 0, numItems); } if(dotSize){ glPointSize(dotSize); glDrawArrays(GL_POINTS, 0, numItems); } delete [] vertex; } //-------------------------------------------------------------- inline void drawInterpolatorSmooth(Interpolator3D spline, int numSteps, int dotSize = 8, int lineWidth = 2) { float spacing = 1.0/numSteps; if(spline.size() == 0) return; if(!lineWidth && !dotSize) return; GLfloat* vertex = new GLfloat[(numSteps + 1) * 3]; for(int i=0; i<numSteps; i++){ float f=i*spacing; ofVec3f v = spline.sampleAt(f); vertex[i*3] = v.x; vertex[(i*3)+1] = v.y; vertex[(i*3)+2] = v.z; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex); if(lineWidth){ glLineWidth(lineWidth); glDrawArrays(GL_LINE_STRIP, 0, numSteps); } if(dotSize){ glPointSize(dotSize); glDrawArrays(GL_POINTS, 0, numSteps); } if(vertex) delete [] vertex; } }
/**************************** 2D InterpolatorT (of Vec2) ****************************/ #pragma once #include "MSAInterpolatorT.h" namespace msa { typedef InterpolatorT<ofVec2f> Interpolator2D; //-------------------------------------------------------------- inline float lengthOf(const ofVec2f& v) { return v.length(); } //-------------------------------------------------------------- inline void drawInterpolatorRaw(Interpolator2D &spline, int dotSize = 20, int lineWidth = 4){ int numItems = spline.size(); if(!lineWidth && !dotSize) return; GLfloat* vertex = new GLfloat[numItems * 2]; for(int i=0; i<numItems; i++) { vertex[i*2] = spline.at(i).x; vertex[(i*2)+1] = spline.at(i).y; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex); if(lineWidth){ glLineWidth(lineWidth); glDrawArrays(GL_LINE_STRIP, 0, numItems); } if(dotSize){ glPointSize(dotSize); glDrawArrays(GL_POINTS, 0, numItems); } delete [] vertex; } //-------------------------------------------------------------- inline void drawInterpolatorSmooth(Interpolator2D &spline, int numSteps, int dotSize = 8, int lineWidth = 2) { float spacing = 1.0/numSteps; if(!lineWidth && !dotSize) return; GLfloat* vertex = new GLfloat[numSteps * 2]; for(int i=0; i<numSteps; i++){ float f=i*spacing; ofVec2f v = spline.sampleAt(f); vertex[i*2] = v.x; vertex[(i*2)+1] = v.y; } glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, vertex); if(lineWidth){ glLineWidth(lineWidth); glDrawArrays(GL_LINE_STRIP, 0, numSteps); } if(dotSize){ glPointSize(dotSize); glDrawArrays(GL_POINTS, 0, numSteps); } delete [] vertex; } }
バグフィックスのために、MSAInterpolatorT.hのなかのgetLength関数で!_dist.empty()ではなかったらサイズを返す、の判断を入れます。
//-------------------------------------------------------------- template <typename T> const float InterpolatorT<T>::getLength(int i) const { if(_useLength&&!_dist.empty()) { return i < 0 ? _dist[_dist.size()-1] : _dist.at(i); } else { return 0; } }
[1] www.memo.tv
[2] C3(Composite Computer Club) » clamp関数の書き方
- 作者: 桜井明
- 出版社/メーカー: 東京電機大学出版局
- 発売日: 1981/06
- メディア: 単行本
- 購入: 1人 クリック: 2回
- この商品を含むブログ (1件) を見る
- 作者: 菅野敬祐,高山文雄,吉村和美
- 出版社/メーカー: 東京電機大学出版局
- 発売日: 1993/03
- メディア: 単行本
- この商品を含むブログを見る
スプライン関数とその応用 (シリーズ新しい応用の数学 20)
- 作者: 市田浩三,吉本富士市
- 出版社/メーカー: 教育出版
- 発売日: 1979/01
- メディア: 単行本
- この商品を含むブログを見る