[work 76] Rain

[work 76] Rain

Movie

Source code

about

  • 「雨」から雨粒がしたたり落ちる様子
  • 日本語フォントを使うときは、ofTrueTypeFontSettingsのaddRangesで日本語を設定する
  • settingsをofTrueTypeFontでloadする場合、ofPathからOutlineを取得するためにofTrueTypeFontSettingsのcontoursをtrueにする

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 "ofxEasing.h"


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::vector<glm::vec3>> org;
    std::vector<std::vector<glm::vec3>> temp;
    std::vector<std::vector<glm::vec3>> drawPoint;
    ofRectangle box;
    std::vector<std::vector<glm::vec3>> rain;
    std::vector<std::vector<int>> count;
    
    std::shared_ptr<ofTrueTypeFont> font;
};
#include "ofApp.h"


ofApp::ofApp(){
    
}

ofApp::~ofApp(){
    
}

//--------------------------------------------------------------
void ofApp::setup(){
    double fps = 30;
    
    
    ofSetFrameRate(fps);
    ofBackground(255);
    ofSetBackgroundAuto(true);
    ofSetVerticalSync(true);
    
    ofTrueTypeFontSettings settings("font/HiraginoProNW4.ttc", 60);
    settings.addRanges(ofAlphabet::Japanese);
    settings.contours = true;
    font = make_shared<ofTrueTypeFont>();
    font->load(settings);
    
    std::vector<ofPath> paths = font->getStringAsPoints("雨", true, false);
    
    float amp = 3;
    box = paths.at(0).getOutline().at(0).getBoundingBox();
    box.scale(amp);
    
    for (ofPath path : paths) {
        std::vector<ofPolyline> lines = path.getOutline();
        
        for (ofPolyline pl : lines) {
            std::vector<glm::vec3> points = pl.getVertices();
            std::vector<int> c;
            
            for (glm::vec3 &p : points) {
                p *= amp;
                c.push_back(0);
            }
            drawPoint.push_back(points);
            org.push_back(points);
            temp.push_back(points);
            count.push_back(c);
        }
    }
}

//--------------------------------------------------------------
void ofApp::update(){
    int maxFrame = (int)ofGetTargetFrameRate() * 3;
    int speed = 3;
    
    for (int i = 0; i < drawPoint.size(); i++) {
        for (int j = 0; j < drawPoint.at(i).size(); j++) {
            glm::vec3 p1 = org.at(i).at(j);
            glm::vec3 &p2 = drawPoint.at(i).at(j);
            glm::vec3 &t = temp.at(i).at(j);
            
            if ((int)p1.y != (int)p2.y) {
                if (count.at(i).at(j) != 0) {
                    float step = ofxeasing::map(count.at(i).at(j), 0, maxFrame - 1, 0, 1, ofxeasing::elastic::easeOut);
                    p2 = t + (p1 - t) * step;
                    
                    count.at(i).at(j) = (count.at(i).at(j) + 1) % maxFrame;
                } else {
                    if (glm::length(p2 - p1) < 60) {
                        p2.y += speed;
                    } else {
                        std::vector<glm::vec3> r;
                        r.push_back(p2 + glm::vec3(0, 0, 0));
                        r.push_back(p2 + glm::vec3(5, 10, 0));
                        r.push_back(p2 + glm::vec3(0, 15, 0));
                        r.push_back(p2 + glm::vec3(-5, 10, 0));
                        rain.push_back(r);
                        
                        t = p2;
                        count.at(i).at(j) = (count.at(i).at(j) + 1) % maxFrame;
                    }
                }
            } else {
                if ((int)ofRandom(drawPoint.at(i).size() * 30) == 0) {
                    p2.y += speed;
                }
            }
        }
    }
    
    for (std::vector<glm::vec3> &r : rain) {
        for (glm::vec3 &p : r) {
            p.y += speed;
        }
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofSetPolyMode(OF_POLY_WINDING_NONZERO);
    ofPushMatrix();
    ofSetColor(0);
    ofNoFill();
    ofTranslate((ofGetWidth() / 2) - box.width / 2, box.height + 10);
    for (std::vector<glm::vec3> p : drawPoint) {
        ofBeginShape();
        ofVertices(p);
        ofEndShape();
    }
    
    
    ofSetColor(0, 0, 255);
    ofFill();
    for (std::vector<glm::vec3> r : rain) {
        ofBeginShape();
        ofCurveVertex(r.back());
        ofCurveVertices(r);
        ofCurveVertex(r.at(0));
        ofCurveVertex(r.at(1));
        ofEndShape();
    }
    ofPopMatrix();
}

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

Link to the reference page

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

categoryAPI/Lib
openframeworksofTrueTypeFont
openframeworksofTrueTypeFontSettings
openframeworksofPath
openframeworksofPolyLine
openframeworksglm::vec3
openframeworksofxeasing map

Development environment

  • openframeworks 0.10.1
  • c++
  • macOS
  • Xcode