[work 89] Ribbon
Movie
Source code
about
- トロコイドの一番先端にあるアームの軌跡上にリボンを描く
- work 88でトロコイドを3D対応させたのでトロコイドの仕組みを利用して作ったwork 64のリボンも3Dバージョンにした
file
- 上部にあるファイル名が表示されているボタンを押すと、表示されるファイルが切り替わります
- 別ウィンドウ表示したい時や行番号などが無いRawMode表示したい時は、コード内右上のボタンを押してください(ボタンはマウスオーバーすると表示されます)
#include "ofMain.h" #include "ofApp.h" //================================ int main( ){ // 4K:4096x2160 // 2K:2048x1080 // FullHD:1920x1080 // HD:1440x1080 // HD720p:1280x720 // DVD:720x480 // setup the GL context ofSetupOpenGL(1280, 720, OF_WINDOW); // this kicks off the running of my app // can be OF_WINDOW or OF_FULLSCREEN // pass in width and height too: ofRunApp( new ofApp()); }
#pragma once #include "ofMain.h" #include "Ribbon.hpp" class ofApp : public ofBaseApp{ public: ofApp(); ~ofApp(); 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); private: std::shared_ptr<Ribbon> ribbon; ofEasyCam cam; };
#include "ofApp.h" ofApp::ofApp(){ } ofApp::~ofApp(){ } //-------------------------------------------------------------- void ofApp::setup(){ double fps = 30; ofSetFrameRate(fps); ofBackground(0); ofSetBackgroundAuto(true); ofSetVerticalSync(true); ribbon = make_shared<Ribbon>(ofVec3f(0, 0, 0)); ribbon->setup(); } //-------------------------------------------------------------- void ofApp::update(){ ribbon->update(); } //-------------------------------------------------------------- void ofApp::draw(){ cam.begin(); ofRotateYDeg(ofGetFrameNum()); ribbon->display(); cam.end(); } //-------------------------------------------------------------- void ofApp::keyPressed(int key){ if (key == 's') { ofImage img; img.grabScreen(0, 0, ofGetWidth(), ofGetHeight()); img.save("screenshot.png"); } }
#ifndef Trochoid_hpp #define Trochoid_hpp #include <stdio.h> #include "ofMain.h" class Trochoid { public: Trochoid(ofVec3f org, int dim, bool dec); ~Trochoid(); void setup(); void update(); void display(); void getLocations(std::vector<ofVec3f> &loc); ofVec3f getPoint(); private: Trochoid(); ofVec3f origin; ofVec3f point; ofMesh locus; std::vector<float> angleVelocity; // radian std::vector<int> direction; std::vector<float> decay; std::vector<float> amplitude; std::vector<ofVec3f> location; std::vector<ofVec3f> rotAxis; bool isDecay; int dimension; }; #endif /* Trochoid_hpp */
#include "Trochoid.hpp" Trochoid::Trochoid(ofVec3f org, int dim, bool dec) { origin = org; dimension = (int)ofClamp(dim, 1, 10); isDecay = dec; } Trochoid::~Trochoid() { } void Trochoid::setup() { int k = 0; std::cout << "Create Trochoid" << std::endl; for (int i = 0; i < dimension; i++) { k = (int)ofRandom(1, 16); angleVelocity.push_back((PI / (180 * 2)) * k); std::cout << "[angleV]" << angleVelocity[i] << std::endl; k = ((ofRandom(-1,1) < 0) ? -1 : 1); direction.push_back(k); std::cout << "[direction]" << direction[i] << std::endl; if (isDecay) { decay.push_back(ofRandom(0.998, 1)); } else { decay.push_back(1); } std::cout << "[decay]" << decay[i] << std::endl; amplitude.push_back(ofRandom(80, 200)); std::cout << "[amplitude]" << amplitude[i] << std::endl; glm::vec3 loc = glm::vec3(amplitude.back(), 0, 0); glm::vec3 axis = glm::vec3(0, 0, 1); glm::mat4 rotX = glm::rotate(glm::mat4(), ofDegToRad(ofRandom(0, 360)), glm::vec3(1, 0, 0)); glm::mat4 rotY = glm::rotate(glm::mat4(), ofDegToRad(ofRandom(0, 360)), glm::vec3(0, 1, 0)); glm::mat4 rotZ = glm::rotate(glm::mat4(), ofDegToRad(ofRandom(0, 360)), glm::vec3(0, 0, 1)); loc = glm::vec4(loc, 0) * rotZ * rotY * rotX; glm::mat4 rotEx = glm::rotate(glm::mat4(), ofDegToRad(ofRandom(0, 360)), glm::vec3(1, 0, 0)); axis = glm::vec4(axis, 0) * rotEx * rotZ * rotY * rotX; location.push_back(loc); rotAxis.push_back(axis); } } void Trochoid::update() { for (int i = 0; i < location.size(); i++) { glm::vec3 pre = location.at(i); glm::vec3 axis = rotAxis.at(i); glm::mat4 rotM = glm::rotate(glm::mat4(), angleVelocity.at(i) * direction.at(i), axis); glm::vec3 s = glm::vec3(decay.at(i)); glm::mat4 sclM = glm::scale(glm::mat4(), s); glm::vec3 loc = glm::vec4(pre, 0) * rotM * sclM; location.at(i) = loc; } ofVec3f p = origin; for (int i = 0; i < location.size(); i++) { p += location.at(i); } point = p; } void Trochoid::display() { ofEnableBlendMode(OF_BLENDMODE_SCREEN); ofSetColor(ofColor(102, 188, 216), 60); ofVec3f org = origin; for (int i = 0; i < location.size(); i++) { ofNoFill(); ofSetLineWidth(1); ofDrawLine(org, org + location.at(i)); org += location.at(i); } ofSetColor(ofColor(102, 188, 216), 60); ofFill(); org = origin; ofDrawSphere(org, 3); for (int i = 0; i < location.size(); i++) { ofDrawSphere(org + location.at(i), 3); org += location.at(i); } locus.setMode(OF_PRIMITIVE_LINE_STRIP); locus.addVertex(point); locus.addColor(ofColor(255)); locus.draw(); } void Trochoid::getLocations(std::vector<ofVec3f> &loc) { std::vector<ofVec3f> l; l.push_back(origin); for (int i = 0; i < location.size(); i++) { l.push_back(l.back() + location.at(i)); } loc = l; } ofVec3f Trochoid::getPoint() { return point; }
#ifndef Ribbon_hpp #define Ribbon_hpp #include <stdio.h> #include "ofMain.h" #include "Trochoid.hpp" #define MAX_LINE (10) class Ribbon { public: Ribbon(ofVec3f c); ~Ribbon(); void setup(); void update(); void display(); void reset(); private: std::shared_ptr<Trochoid> trochoid; std::vector<ofVec3f> locations; std::array<std::vector<ofVec3f>, MAX_LINE> points; std::array<ofMesh, MAX_LINE> meshes; std::array<ofColor, MAX_LINE> colors; ofColor color; ofVec3f center; std::shared_ptr<ofFbo> fbo; }; #endif /* Ribbon_hpp */
#include "Ribbon.hpp" Ribbon::Ribbon(ofVec3f c) { center = c; } Ribbon::~Ribbon() { } void Ribbon::setup() { trochoid = make_shared<Trochoid>(center, 6, false); trochoid->setup(); for (int i = 0; i < colors.size(); i++) { colors.at(i) = ofColor(ofRandom(255), ofRandom(255), ofRandom(255), 255); } } void Ribbon::update() { locations.clear(); trochoid->update(); trochoid->getLocations(locations); auto itr = locations.rbegin(); ofVec3f tail = *itr; ofVec3f head = *(itr + 1); ofVec3f arm = tail - head; float len = arm.length(); ofVec3f unit = arm.normalize(); for (int i = 0; i < points.size(); i++) { float d = (len / points.size()) * i; points.at(i).push_back(head + unit * d); } ofNoFill(); ofSetLineWidth(1); for (int i = 0; i < MAX_LINE; i++) { meshes.at(i).setMode(OF_PRIMITIVE_LINE_STRIP); meshes.at(i).addVertex(points.at(i).back()); meshes.at(i).addColor(colors.at(i)); } } void Ribbon::display() { ofEnableBlendMode(OF_BLENDMODE_SCREEN); for (ofMesh m : meshes) { m.draw(); } } void Ribbon::reset() { fbo = nullptr; trochoid = nullptr; setup(); }
Link to the reference page
ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。
category | API/Lib |
openframeworks | glm::vec3 |
openframeworks | glm::rotate |
openframeworks | glm::scale |
openframeworks | glm::mat4 |
openframeworks | ofMesh |
Development environment
- openframeworks 0.10.1
- c++
- macOS
- Xcode