[work 94] Two Ribbons

[work 94] Two Ribbons

Movie

Source code

about

  • 絡み合った2つのリボン

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::vector<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);
    
    ofEnableDepthTest();
    
    for (int i = 0; i < 2; i++) {
        ribbon.push_back(make_shared<Ribbon>(ofVec3f(0, 0, 0)));
        ribbon.back()->setup();
    }
    ribbon.at(1)->setColor(ofColor(255, 255, 255, 128));
}

//--------------------------------------------------------------
void ofApp::update(){
    for (int i = 0; i < ribbon.size(); i++) {
        ribbon.at(i)->update();
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    cam.begin();
    for (int i = 0; i < ribbon.size(); i++) {
        ribbon.at(i)->display();
    }
    cam.end();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if (key == 's') {
        ofImage img;
        img.grabScreen(0, 0, ofGetWidth(), ofGetHeight());
        img.save("screenshot.png");
    }
}
#ifndef Ribbon_hpp
#define Ribbon_hpp

#include <stdio.h>
#include "ofMain.h"

#include "Trochoid.hpp"


#define MAX_LINE (40)

class Ribbon {
public:
    Ribbon(ofVec3f c);
    ~Ribbon();
    void setup();
    void update();
    void display();
    void reset();
    void setColor(ofColor c);
    
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, 3, false, true);
    trochoid->setup();
    
    ofColor c;
    c.setHsb(ofRandom(255), ofRandom(255), 255);
    setColor(c);
}


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(2);
    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();
}


void Ribbon::setColor(ofColor c)
{
    for (int i = 0; i < colors.size(); i++) {
        colors.at(i) = c;
    }
}
#ifndef Trochoid_hpp
#define Trochoid_hpp

#include <stdio.h>
#include "ofMain.h"


class Trochoid {
public:
    Trochoid(ofVec3f org, int dim, bool dec, bool t3d);
    ~Trochoid();
    void setup();
    void update();
    void display();
    void getLocations(std::vector<ofVec3f> &loc);
    ofVec3f getPoint();
private:
    Trochoid();
    
    bool trochoid3d;
    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, bool t3d)
{
    trochoid3d = t3d;
    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 * 10)) * 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(120, 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::vec3 deg = glm::vec3(0, 0, ofRandom(0, 360));
        if (trochoid3d) {
            deg.x = ofRandom(0, 360);
            deg.y = ofRandom(0, 360);
        }
        glm::mat4 rotX = glm::rotate(glm::mat4(), ofDegToRad(deg.x), glm::vec3(1, 0, 0));
        glm::mat4 rotY = glm::rotate(glm::mat4(), ofDegToRad(deg.y), glm::vec3(0, 1, 0));
        glm::mat4 rotZ = glm::rotate(glm::mat4(), ofDegToRad(deg.z), glm::vec3(0, 0, 1));
        loc = glm::vec4(loc, 0) * rotZ * rotY * rotX;
        
        if (trochoid3d) {
            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;
}

Link to the reference page

ソースコードで使用したAPIの中から要点になりそうなものをいくつか選んでリストアップしました。

categoryAPI/Lib
openframeworksofMesh
openframeworksglm::rotate
openframeworksglm::vec3
openframeworksglm::mat4

Development environment

  • openframeworks 0.10.1
  • c++
  • macOS
  • Xcode