yoppa.org


Blog

コーディングリハビリ – 球とパーリン・ノイズ

年末年始、ボーっとしてたらなんだか頭が呆けてきそうになったので、コーディングのリハビリ。

ofShperePrimitiveって、getMesh()メソッドを使うと生成した球のメッシュが取得できる。これを活用すると球をいろいろ歪ませて遊べるんじゃないかということで、球にパーリン・ノイズをかけてみた。ちなみに、パーリン・ノイズを考案したのはパーリン(Ken Perlin)さん。フォンシェーディングを発明したのはフォン(Bui Tuong Phong)さん。豆知識な。

ノイズの強さをサウンド入力のパワーで変化させると、音に反応する球になったりして面白そう。

ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
    
public:
    void setup();
    void update();
    void draw();   
    void createMesh();
    
    ofEasyCam cam;
    ofMesh mesh;
    vector currentVertex;
    ofImage img;
    ofTexture tex;
    ofLight light;
};

ofApp.cpp

#include "ofApp.h"

void ofApp::setup(){
    ofBackground(0);
    ofEnableDepthTest();
    
    light.enable();
    
    int width = 1024;
    int height = 1024;
    unsigned char pixels[width * height];
    
    for (int i = 0; i < width * height; i++){
        pixels[i] = sin(i / 4000.0) * 127 + 127;
    }
    tex.loadData(pixels, width, height, GL_LUMINANCE);
    
    createMesh();
}

void ofApp::update(){
    float noiseScale = 4.0;
    float shiftSpeed = 1.0;
    float noiseStrength = 50.0;
    for (int i = 0; i < mesh.getVertices().size(); i++) {
        float noiseX = ofMap(currentVertex[i].x, 0, ofGetWidth(), 0, noiseScale);
        float noiseY = ofMap(currentVertex[i].y, 0, ofGetWidth(), 0, noiseScale);
        float offset = ofNoise(noiseX + ofGetElapsedTimef() * shiftSpeed,
                               noiseY + ofGetElapsedTimef() * shiftSpeed);
        currentVertex[i] = currentVertex[i].normalize() * (offset * noiseStrength + ofGetWidth() / 6.0);
        mesh.setVertex(i, currentVertex[i]);
    }
}

void ofApp::draw(){
    cam.begin();
    tex.bind();
    ofRotateX(40);
    ofRotateY(180);
    ofSetColor(255);
    mesh.draw();
    tex.unbind();
    cam.end();
}

void ofApp::createMesh(){
    mesh = ofSpherePrimitive(ofGetWidth(), 128).getMesh();
    for (int i = 0; i < mesh.getVertices().size(); i++) {
        ofVec2f texCoord = mesh.getTexCoord(i);
        texCoord.x *= tex.getWidth();
        texCoord.y = (1.0 - texCoord.y) * tex.getHeight();
        mesh.setTexCoord(i, texCoord);
        currentVertex.push_back(ofVec3f(mesh.getVertices()[i].x, mesh.getVertices()[i].y, mesh.getVertices()[i].z));
    }
}