[work 90] Twist Ring

[work 90] Twist Ring

Movie

Source code

about

円の中心を移動させながら、XYZ軸方向に回転させる
中心点は、トロコイドの軌跡上を移動する

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 "Circle.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<Circle> circle;
    
    ofEasyCam cam;
};
#include "ofApp.h"


ofApp::ofApp(){
    
}

ofApp::~ofApp(){
    
}

//--------------------------------------------------------------
void ofApp::setup(){
    double fps = 30;
    
    
    ofSetFrameRate(fps);
    ofBackground(0);
    ofSetBackgroundAuto(true);
    ofSetVerticalSync(true);
    
    circle = make_shared<Circle>(ofVec3f(0, 0, 0));
    circle->setup();
}

//--------------------------------------------------------------
void ofApp::update(){
    circle->update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    cam.begin();
    ofRotateYDeg(ofGetFrameNum());
    circle->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 * 6)) * 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 Circle_hpp
#define Circle_hpp

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


class Circle {
public:
    Circle(ofVec3f c);
    ~Circle();
    void setup();
    void update();
    void display();
    
private:
    std::shared_ptr<Trochoid> trochoid;
    std::vector<ofMesh> meshes;
    ofColor color;
    ofVec3f center;
    std::vector<glm::vec3> baseCircle;
    float radius;
    ofVec3f angle;
    ofVec3f time;
};
#endif /* Circle_hpp */
#include "Circle.hpp"


Circle::Circle(ofVec3f c)
{
    center = c;
}


Circle::~Circle()
{
    
}


void Circle::setup()
{
    trochoid = make_shared<Trochoid>(center, 2, false);
    trochoid->setup();
    
    color.setHsb(0, 255, 255);
    angle = ofVec3f(0, 0, 0);
    time = ofVec3f(ofRandom(1000), ofRandom(1000), ofRandom(1000));
    radius = 80;
    
    for (int i = 0; i < 360; i += 5) {
        baseCircle.push_back(glm::vec3(std::cos(ofDegToRad(i)) * radius, std::sin(ofDegToRad(i)) * radius, 0));
    }
}


void Circle::update()
{
    trochoid->update();
    glm::vec3 c = trochoid->getPoint();
    
    angle.x = ofMap(ofSignedNoise(time.x), -1, 1, -180, 180);
    angle.y = ofMap(ofSignedNoise(time.y), -1, 1, -180, 180);
    angle.z = ofMap(ofSignedNoise(time.z), -1, 1, -180, 180);
    
    glm::mat4 rotX = glm::rotate(glm::mat4(), ofDegToRad(angle.x), glm::vec3(1, 0, 0));
    glm::mat4 rotY = glm::rotate(glm::mat4(), ofDegToRad(angle.y), glm::vec3(0, 1, 0));
    glm::mat4 rotZ = glm::rotate(glm::mat4(), ofDegToRad(angle.z), glm::vec3(0, 0, 1));
    
    int h = ofGetFrameNum() % 255;
    color.setHue(h);
    
    ofMesh m;
    for (glm::vec3 base : baseCircle) {
        glm::vec3 p = glm::vec4(base, 0) * rotZ * rotY * rotX;
        m.addVertex(c + p);
        m.addColor(color);
    }
    meshes.push_back(m);
    
    time += 0.01;
}


void Circle::display()
{
    ofEnableBlendMode(OF_BLENDMODE_SCREEN);
    ofSetLineWidth(2);
    for (ofMesh m : meshes) {
        m.setMode(OF_PRIMITIVE_LINE_LOOP);
        m.draw();
    }
}

Link to the reference page

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

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

Development environment

  • openframeworks 0.10.1
  • c++
  • macOS
  • Xcode