[work 30] Flow Field – rotating squares –
Movie
Source code
about
- Flow Field上に四角を配置(タイル状)
- Flowに従って四角を回転・拡縮させる
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 <random> #include "FlowField.hpp" #include "Square.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: unique_ptr<FlowField> ff; int resolution; std::vector<unique_ptr<Square>> square; };
#include "ofApp.h" ofApp::ofApp(){ } ofApp::~ofApp(){ } //-------------------------------------------------------------- void ofApp::setup(){ double fps = 30; ofSetFrameRate(fps); ofBackground(217,229,240); ofSetBackgroundAuto(true); resolution = 40; ff = make_unique<FlowField>(resolution); ff->setup(); ofVec2f point; int cols = ofGetWidth() / resolution; int rows = ofGetHeight() / resolution; for (int i = 0; i < cols; i++) { for (int j = 0; j < rows; j++) { point.x = i * resolution + (resolution / 2); point.y = j * resolution + (resolution / 2); square.push_back(make_unique<Square>(point, resolution, resolution)); } } } //-------------------------------------------------------------- void ofApp::update(){ ff->update(); for (unique_ptr<Square> &s: square) { s->follow(ff); } } //-------------------------------------------------------------- void ofApp::draw(){ for (unique_ptr<Square> &s: square) { s->display(); } }
#ifndef FlowField_hpp #define FlowField_hpp #include <stdio.h> #include "ofMain.h" class FlowField { public: FlowField(int r); ~FlowField(); void setup(); void update(); void display(); ofVec2f lookup(ofVec2f pos); private: int cols, rows; int resolution; float xoff, yoff, zoff; std::vector<std::vector<ofVec2f>> field; }; #endif /* FlowField_hpp */
#include "FlowField.hpp" FlowField::FlowField(int r) { resolution = r; cols = ofGetWidth() / resolution; rows = ofGetHeight() / resolution; field.assign(cols, std::vector<ofVec2f>(rows, ofVec2f(0, 0))); } FlowField::~FlowField() { } void FlowField::setup() { zoff = 0; } void FlowField::update() { xoff = 0; for (int x = 0; x < cols; x++) { yoff = 0; for (int y = 0; y < rows; y++) { float theta = ofMap(ofNoise(xoff, yoff, zoff), 0, 1, 0, TWO_PI); ofVec2f dir = ofVec2f(std::cos(theta), std::sin(theta)); field[x][y] = dir.normalize(); yoff += 0.05; } xoff += 0.05; } zoff += 0.01; } void FlowField::display() { for (int x = 0; x < cols; x++) { for (int y = 0; y < rows; y++) { ofPushMatrix(); ofTranslate(x * resolution, y * resolution); ofNoFill(); ofSetColor(255); ofDrawRectangle(0, 0, resolution, resolution); ofVec2f c = ofVec2f(resolution / 2, resolution / 2); int len = resolution * 3 / 4; ofVec2f t0 = c - (field[x][y] * len / 2); ofVec2f t1 = c + (field[x][y] * len / 2); ofSetColor(255, 255, 0); ofDrawLine(t0.x, t0.y, t1.x, t1.y); ofPopMatrix(); } } } ofVec2f FlowField::lookup(ofVec2f pos) { int col = (int)ofClamp(pos.x / resolution, 0, cols - 1); int row = (int)ofClamp(pos.y / resolution, 0, rows - 1); return field[col][row]; }
#ifndef Square_hpp #define Square_hpp //#define USE_MYCOL_LIB #include <stdio.h> #include "ofMain.h" #include "FlowField.hpp" #ifdef USE_MYCOL_LIB #include "myColorLib.hpp" #endif class Square { public: Square(ofVec2f pos, float w, float h); ~Square(); void display(); void follow(unique_ptr<FlowField> &flow); private: ofColor color1, color2; ofVec2f location; float angle; float width; float height; #ifdef USE_MYCOL_LIB unique_ptr<myColorLib> mc; #endif }; #endif /* Square_hpp */
#include "Square.hpp" Square::Square(ofVec2f pos, float w, float h) { #ifdef USE_MYCOL_LIB mc = make_unique<myColorLib>(); mc->addColorSet(MYCOL_ACTIVE1); mc->addColorSet(MYCOL_ACTIVE2); color1 = mc->getColor(ofRandom(1)); std::cout << "mycolor" << std::endl; #else color1 = ofColor(ofRandom(255), ofRandom(255), ofRandom(255)); #endif color2 = ofColor(255); location = pos; width = w; height = h; } Square::~Square() { } void Square::display() { ofPushMatrix(); ofTranslate(location.x, location.y); ofRotateDeg(angle); float shrink = (180 - std::abs(angle)) / 180; ofSetRectMode(OF_RECTMODE_CENTER); ofFill(); ofSetColor(color1); ofDrawRectangle(0, 0, width * shrink, height * shrink); ofNoFill(); ofSetColor(color2); ofSetLineWidth(5); ofDrawRectangle(0, 0, width * shrink, height * shrink); ofPopMatrix(); } void Square::follow(unique_ptr<FlowField> &flow) { ofVec2f dir = flow->lookup(location); ofVec2f org = ofVec2f(1, 0); angle = org.angle(dir); }
Link to the reference page
ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。
category | API/Lib |
openframeworks | ofVec2f angle |
openframeworks | ofGraphics ofSetLineWidth |
openframeworks | ofGraphics ofRotateDeg |
Development environment
- openframeworks 0.10.1
- c++
- macOS
- Xcode