ラベル processing(p5) の投稿を表示しています。 すべての投稿を表示
ラベル processing(p5) の投稿を表示しています。 すべての投稿を表示

金曜日, 1月 05, 2018

Daily Codingをはじめよう

Zachary LiebermanのInstagramMediumに触発され、2017年は毎日スケッチを書こうとしたが8日分しか書けなかった。

高尾くんの記事John Resigの記事を読み直し、再度やってみようと思い年末から少しずつ準備していた。前回の反省はVanilla JavaScriptでやろうとしたことと、特に目標がなかったこと。それを踏まえて今回はp5.jsを使い、テーマ別に書いていくつもり。

ソースコードは全てGithubに上げているのだけど、Github Pagesでリポジトリからそのままホスティングできるのは非常に便利。

https://hysysk.github.io/dailycoding/

今まで自分がよく書いてきた処理をまとめたり、気になってた表現のアルゴリズムを調べたりして、あれってどうやるんだっけなと思った時にすぐ使えるようにしたい。ライブラリほど作り込まない、スニペットのようなもの…というところまで考えて、アドベントカレンダーに書いたメタ-デザインと繋がることに気付いた。ガイドラインを規則として言葉で定義するのではなく、実行可能なデザインシステムとして思想や手法をコードに落とし込むこと。

手始めに気持ちいい動きを作るべくeasingを調べていたら、flash時代のPenner Easingから洗練されてきた歴史があるという発見があった。それまではパラメータを4つほど渡していたのだが、さまざまな工夫の甲斐あって、0から1までの値を受け取って、何らかの式を通して0から1までの値を返せば良いということになっている。非常にシンプルなので再利用性が高く、他の言語にも簡単に移植できる。その上でどれだけ遊べるかというのは、日々のスケッチで挑戦していくことだ。

ひとまずこれまで書いたものを振り返る。

  • 20171230 とりあえず並べてみた。複数のオブジェクトに異なるアニメーションを適用。
  • 20171231 ローディングアニメーション的な動き。
  • 20180104 複数のアニメーションを続けて実行。定義部分と実行部分を分離できた。
  • 20180105 Tween系ライブラリにあるDelay機能を再現し、エフェクトを作った。

単にスキンを変えてバリエーションを作るのではなく、ロジック面でも変化がないと成長しないと思うので、そこを意識して振り返るようにしたい。

日曜日, 6月 05, 2016

Processingで画像を読み込みたいけどファイルの数や名前が分からない場合

課題

Processingで大量の画像を読み込んで処理したかったのだけど、標準のloadImage()を使おうとするとファイル数やファイル名が予め分かっていないといけない。つまり画像ファイルを追加したり削除したりすると、それに合わせてコードも修正しなければならない訳で、保守性も効率も悪い。

解決法

JavaにFilenameFilterというインターフェースがあるので、新しくクラスを作ってacceptメソッドをオーバーライドする。

import java.io.File;
import java.io.FilenameFilter;

public class PngFileFilter implements FilenameFilter {
  @Override
  public boolean accept(File directory, String fileName) {
    if(fileName.endsWith(".png")) {
      return true;
    }
    return false;
  }
}

PngFileFilterクラスのインスタンスを作り、こんな感じでFileクラスのlistFilesメソッドに渡すと、".png"で終わるファイルが配列として返ってくる。ちなみにdataPath("")という関数を使うとdataフォルダまでのパスが取得できる。空の文字列を渡しているが、フォルダがある場合はその名前を指定できる。リファレンスに載っていないのである日突然なくなる可能性はある。

File[] imageFiles;
PngFileFilter filter;
void setup() {
  size(800, 800);
  filter = new PngFileFilter();
  imageFiles = new File(dataPath("")).listFiles(filter);
  for(File file: imageFiles) {
    println(file.getName());
  }
}

RubyとかPythonだと特定のフォルダ以下のアセットを特定の拡張子で読み込むのが簡単なので、ああいう感じの書き方にできるとより便利。他の言語や環境から学ぶことは沢山ある。

日曜日, 9月 21, 2014

Processingでアプリケーションを作る際に知っておくと便利なコード

ホームディレクトリのパスを取得

Processingでアプリケーションとして書き出す際に、リソースを後で差し替えたかったり、dataフォルダ以外に置きたい場合があります。ProcessingというよりはJavaのAPIですが、
System.getProperty("user.home")
でユーザのホームディレクトリの絶対パスが取得できます。例えば、
import java.io.*;
File movieFolder = new File(System.getProperty("user.home") + "/movies");
File[] movieFiles = movieFolder.listFiles(getFileExtensionFilter(".mp4"));

とすると、ホームディレクトリ以下に置いたmoviesフォルダ内にある.mp4ファイルを取得できます。.mp4を他の拡張子に変えれば他の拡張子も取得可能です。

スライドショー機能で使った画像のフェードイン・アウトのサンプルコード

地味にProcessingで画像がフェードイン・アウトする処理を書いたのは初めてでした。tint()を使うとできます。
fadeInOut.pde

これらは現在『六甲ミーツ・アート 芸術散歩』で展示中のNadegata Instant Partyの作品の自動撮影システムに活かされています。撮影された画像は自動でTumblrにアップロードされるのですが、開発の期間が限られていたため、IFTTTのDropbox連携を使いました。
PHOTO SPOT PARTY

火曜日, 8月 27, 2013

Weighted Voronoi Stippling


何となくいい感じに点を散らす方法を探していて、Evil Mad Scientistの人が作っていたやつを思い出した。 StippleGen: Weighted Voronoi stippling and TSP paths in Processing | Evil Mad Scientist Laboratories

元のソースはこれ。 Weighted Voronoi Stippling
論文もあって、他にも面白そうな研究が沢山。

仕組みとしては適当に点を置いた後、ボロノイ領域に分け、その領域を正方形に近づくよう変形したものの中心に点を移動させて描画している。

中身を整理して必要なところだけ抜き出した。Processingの2.0.2で、toxiclibと適当な画像を用意して下さい(コードと同階層にdataフォルダを作り、img.jpgで保存)。
stipple.pde

VoronoiができるということはDelaunayもすぐできるだろうと思ってJonathan PuckeyのDelaunay Raster的なことをやってみた。
weighted_delaunay.pde


が、あんまり面白くない


できていく過程だったり


点の結び方を変える(vertexをコメントアウトしてわざと三角形にしない)とか


整然としているのであれば線の方がまだ何かに使えるかも知れない

点の打ち方と、色の塗り方をどうするかが大事なんだと思った。

Evil Mad Scientistのやつは巡回セールスマン問題のアルゴリズムを使って、点を打つ機械が最短の動きで描画できるようにもしてある。実行時間を縮めるにはああいう処理が必要になってくるんですね。かつ視覚的にも面白い。

土曜日, 10月 02, 2010

ArrayListについて認識を改めたところ

以前の投稿(build ribbons)で、
for文のところを単にかっこいい書き方としか認識してなかったんですけど、
配列の長さがループの途中で変わるので、ああいう風にしておかないとremoveで取り除かれた分の添字が詰まった結果、参照されないオブジェクトがでてきてしまってちらつきが起こってしまいます。

こういう場合。
試しにdraw()内のfor文の初期化式をint i=0、継続条件式をi<ripples.size()、再初期化式をi++にしてみると分かります。
リファレンスにも似たような例が書いてあって、Examples>Topics>Advanced Data>ArrayListClassでも確認できます。
[Ripple.pde]
class Ripple {
float x, y, w, speed;
float age;
int intensity;
color c;
float a;
boolean finished;

Ripple(float x, float y, int intensity, color c, float speed) {
this.x = x;
this.y = y;
this.intensity = intensity;
this.c = c;
this.speed = speed;
this.age = 0;
this.a = 255-255*(age-speed)/intensity;
this.finished = false;
}

void display() {
age += speed;
a = 255-255*(age-speed)/intensity;
if(a<=5) {
finished = true;
}
stroke(c, a);
ellipse(x, y, age, age);
}

boolean finished() {
return finished;
}
}

[drawRipple.pde]
Ripple r;
ArrayList ripples;
void setup() {
size(400, 400);
background(255);
noFill();
smooth();
ripples = new ArrayList();
for(int i=0; i < 100; i++) {
ripples.add(new Ripple(random(width), random(height), (int)random(20, 80), color(0), random(0.1, 0.4)));
}
}

void draw() {
background(255);
for (int i = ripples.size()-1; i >= 0; i--) {
Ripple ripple = (Ripple)ripples.get(i);
ripple.display();
if(ripple.finished()) {
ripples.remove(ripple);
}
}
}

土曜日, 8月 14, 2010

ProcessingでGUIを簡単に使う

Algorithm for Visual Designより。
controlP5とかその他色々あるけどちょっと試したい時とかAWT使うのもいいと思う。
サンプルではaddActionListenerのところがこんな感じ
a.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
println("A");
}
}

だったけどActionScriptぽく書き直してみた。
ボタンが押されたときに呼び出されるメソッドは全てactionPerformedになるのでその中で分岐。
[guiTest.pde]
MyControl control;
void setup() {
control = new MyControl();
}

void draw() {
}

[MyControl.pde]
import java.awt.Button;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
class MyControl implements ActionListener {
Button a;
Button b;

MyControl() {
a = new Button("A");
a.addActionListener(this);
add(a);
b = new Button("B");
b.addActionListener(this);
add(b);
}

public void actionPerformed(ActionEvent e) {
if(e.getSource()==a) {
println("A");
} else if(e.getSource()==b) {
println("B");
}
}
}

火曜日, 8月 11, 2009

Processing IDEからEcho Nest APIを使う

Echo NestのJavaクライアントが出ていたのでProcessingで動かしてみた。
Echo Nestが何なのかよくわかってないけど、とりあえずネットと音という大好きな要素が混ざっている。
曲やレビュー、記事のリコメンドからテンポ、ビート等の音響解析にも使えるらしい。

まずはdeveloper用のサイトでEcho NestのAPI Accountを取得してAPI Keyを発行してもらう。
サイトも綺麗だしブラウザから実行例を見られるので勉強しやすい。APIキーとか入れといてくれてる。

Echo NestのJava APIをダウンロードする。

Javaのライブラリなので、OSXの場合"ユーザ名/Library/Java/Extensions"以下にEchoNestAPI.jarを置いて.bash_profileにCLASSPATHを書くのでもいいけど、Documents/Processing/librariesの中にEchoNestAPIというフォルダを作り、さらにlibraryフォルダを作って、その中にEchoNestAPI.jarを入れても動く。ProcessingのIDEから簡単にimportできる。

JavaのサンプルそのままだとProcessingのIDEの場合for文のところでエラーになってしまうので書き換えた。
import com.echonest.api.v3.artist.Artist;
import com.echonest.api.v3.artist.ArtistAPI;
import com.echonest.api.v3.artist.Audio;
import com.echonest.api.v3.EchoNestException;
import com.echonest.api.v3.artist.Scored;
import java.util.List;

String API_KEY = "自分のAPI KEY";
String ARTISTNAME = "weezer";

ArtistAPI artistAPI;

try {
artistAPI = new ArtistAPI(API_KEY);
List<Artist> artists = artistAPI.searchArtist(ARTISTNAME, false);
if(artists.size()>0) {
for(int i=0; i<artists.size(); i++) {
Artist artist = artists.get(i);
List<Scored<Artist>> similars = artistAPI.getSimilarArtists(artists, 0, 10);
println(" === Similar artists for " + artist.getName() + " ===");
for(int j=0;j<similars.size(); j++) {
Scored<Artist> simArtist = similars.get(j);
println(simArtist.getItem());
}
}
}
}
catch(EchoNestException e) {
System.err.println("Trouble: " + e);
}


実行結果

=== Similar artists for Weezer ===
The Smashing Pumpkins
Ozma
Biffy Clyro
The Breeders
Rivers Cuomo
Nerf Herder
Jimmy Eat World
Foo Fighters
Veruca Salt
The Flaming Lips
=== Similar artists for Weezer Tribute ===
The Smashing Pumpkins
Ozma
Biffy Clyro
The Breeders
Rivers Cuomo
Nerf Herder
Jimmy Eat World
Foo Fighters
Veruca Salt
The Flaming Lips
=== Similar artists for Matt Sharp (of Weezer, The Rentals) ===
The Smashing Pumpkins
Ozma
Biffy Clyro
The Breeders
Rivers Cuomo
Nerf Herder
Jimmy Eat World
Foo Fighters
Veruca Salt
The Flaming Lips



開発者の人のデモがここにある。eclipseで開発してる。

*2009年11月11日追記
EchoNestAPIを使用する場合はJavaのバージョンを1.6にする必要があります。
Applications/Utilities/Java Preferencesを起動して、GeneralタブのJava ApplicationsのJava SE 6を一番上にする。

で、いつの間にかechonestp5というものができてた。

土曜日, 3月 07, 2009

steering behaviorのメモ

seekがターゲットに向かう動き、fleeがターゲットから遠ざかる動き。まずこれを押さえる。
ここからflockするために、cohesion、separation、alignmentを加えるんだけど、

cohesionは仲間の平均の位置をseekすることで、separationは近づき過ぎた仲間からfleeすること、alignmentは仲間の平均の速度に合わせること。

基本はAdvanced ActionScript 3.0 Animationで勉強した。
最近また新しいサンプルが増えたnature of codeもよくわかる。
どちらも大元にあるのはcraig reynolds。
Steering Behaviors For Autonomous Characters

nature of codeは夏に本が出るらしい。
Nature of Code Book at daniel shiffman

早速メーリングリスト登録した。

火曜日, 3月 03, 2009

as3corelibのJSONクラスを使ってNew York TimesのAPIからデータを取得する

ProcessingでNew York TimesのAPIからデータを取ってきて視覚化するサンプルを参考に、ActionScript 3.0で実現してみます。
Processing, JSON & The New York Times | blprnt.blg

環境はMac OS 10.5.6、Flex SDK 3、Xcode 3.1です。

まずNew York TimesのDevelopper Networkにアクセスしてアカウントを作成し、API KEYを取得する必要があります。
Times Developer Network - Welcome

色々ありますが今回はThe Article Search APIを使います。
レスポンス形式はJSON。

ActionScriptでJSONを扱うには、as3corelibを使うのが良いと思います。
as3corelib - Google Code
ファイルをダウンロードして解凍したら、libというフォルダにas3corelib.swcというファイルがあるので、それをFlex SDKのframeworksフォルダに入っているlibsの中に入れます。

新しいプロジェクトを作って、NYTimesTestと名付けます。
2005年1月1日から2009年3月3日まででObamaという言葉がいくつあるかというプログラム。

NYTimesTest.as

package {
import com.adobe.serialization.json.JSON;

import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;

public class NYTimesTest extends Sprite {
private var baseURL:String = "http://api.nytimes.com/svc/search/v1/article";
private var apiKey:String = "取得したAPIキー";
private var word:String = "Obama";
private var beginDate:String = "20050101";
private var endDate:String = "20090303";

public function NYTimesTest() {
var loader:URLLoader = new URLLoader();

loader.load(new URLRequest(baseURL+"?query="+word+"&begin_date="+beginDate+"&end_date="+endDate+"&api-key="+apiKey));
loader.addEventListener(Event.COMPLETE, decodeJSON);
loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}

private function decodeJSON(e:Event):void {
var loader:URLLoader = URLLoader(e.target);
var totalArticles:uint = JSON.decode(loader.data).total;
trace("there were " + totalArticles + " occurences of the term " + word + " between " + beginDate + " and " + endDate);
}

private function ioErrorHandler(e:IOErrorEvent):void {
trace("ioErrorHandler: " + e);
}
}
}

Flash CSを持ってなくてFlex SDKで開発している場合、Flash Playerで普通に再生しても何も起こらないと思います。Flash Playerのdebugger versionsと、その他色々と設定が必要です。
Archived Flash Players available for testing purposes
flickr APIの時にやった色々設定(今気付いたけど01って何...続きないし)
hysysk:blog: using flickr api 01

フォルダはアカウントの権限とか環境によって変わるのかも。

今の僕の環境では

ユーザ名/ライブラリ/Preferences/Macromedia/FlashPlayer

の中に#Securityというフォルダがあり、その中にFlashPlayerTrustフォルダを置いて、mms.cfgを格納しています。ない場合は作って下さい。
最近は通信関係を開発しているフォルダはまとめてこのファイルで指定しています。

traceした結果はこのFlashPlayerフォルダの中のLogs/flashlog.txtに出力されています。これもない場合は作って下さい。
there were 9595 occurences of the term Obama between 20050101 and 20090303
と出れば成功。
次回(!)以降データの中身をもう少しみていくつもり。

あとこのblprintの人が書いてるActionScriptの本が面白そう。彼だけでなくJonathan HarrisとかAaron KoblinとかProcessingの強者達が書いてる。値段が変動してるな。
Amazon.co.jp: Best Practice: The Pros on Adobe Flash: Douglas Easterly: 洋書

日曜日, 1月 25, 2009

toxi audio!!!

以前フォルダだけはあるなーと思ってたtoxiのaudioutils、できてた。
toxiclibs - Google Code

JOALがバンドルされてて3次元音響が鳴らせる。
サンプル動かしてみ。
geomutilsとprefutilsも必要なので一緒にdownloadしてLibrariesフォルダに入れとく。

toxi rocks!

日曜日, 11月 23, 2008

forward kinematics

関節みたいな動きのプログラミング。
ActionScript 3.0アニメーションからporting。
PVectorクラスを使ってみた。
Processing Monster作りたい。

walking.pde

Segment s1, s2, s3, s4;
float cycle = 0;
float offset = -PI*0.5;

void setup() {
size(200, 200);
smooth();
frameRate(30);
fill(255);
s1 = new Segment(width*0.5, height*0.5, 30, 10);
s2 = new Segment(s1.getPin().x, s1.getPin().y, 30, 10);
s3 = new Segment(width*0.5, height*0.5, 30, 10);
s4 = new Segment(s3.getPin().x, s3.getPin().y, 30, 10);
}

void draw() {
background(255);
walk(s1, s2, cycle);
walk(s3, s4, cycle+PI);
cycle += .2;
}

void walk(Segment segA, Segment segB, float cyc) {
float angleA = sin(cyc) * HALF_PI*0.25 + HALF_PI;
float angleB = sin(cyc+offset) * HALF_PI*0.17 + HALF_PI*0.12;
segA.rotation = angleA;
segB.rotation = segA.rotation + angleB;
segB.x = segA.getPin().x;
segB.y = segA.getPin().y;
segA.render();
segB.render();
}

Segment.pde

class Segment {
float x;
float y;
float w;
float h;
float rotation;
PVector v;

Segment(float x, float y, float w, float h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
v = new PVector();
}

void render() {
pushMatrix();
translate(x, y);
rotate(rotation);
rect(0, -h*0.5, w, h);
ellipse(0, 0, 2, 2);
ellipse(w, 0, 2, 2);
popMatrix();
}

PVector getPin() {
v.x = x + cos(rotation) * w;
v.y = y + sin(rotation) * w;
return v;
}
}

火曜日, 11月 04, 2008

build ribbons

erik natzkeのflash on the beachの発表なのかな。jonathan harrisへのレスポンスと一緒に上げられてた気がするけど。
Untitled Document
Flash on the Beach and “The Jonathan Harris Affair” | THOMAS KRÄFTNER

これのParticlesのソース見て、動かしてみて、この書き方がいいのかどうかは知らないけどprocessingでもループ内でnewしてParticlesを生み出したいと思った。最初に思いついたのが配列を使って実現する方法。サイズの宣言と値を代入する必要があるので、適当に埋めてやってたんだけど、ださい(し、これでは意味がない。最初に決まった数のオブジェクトを作るんじゃなくて、ループの度に増やしたい)。

とりあえずParticleクラス
Particle.pde

class Particle {
float x;
float y;
float vx;
float vy;
float rad;

Particle(float x, float y, float vx, float vy, float rad) {
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.rad = rad;
}
void draw() {
x += vx;
y += vy;
ellipse(x, y, rad, rad);
}
}

実行するメインのコード。
particleTest1.pde

Particle[] p = new Particle[500];
int idx = 0;
float rad = 10;
void setup() {
size(800, 400);
fill(0);
smooth();
for(int i=0;i<p.length;i++) {
p[i] = new Particle(0,0,0,0,0);
}
}

void draw() {
background(255);
spawnParticles();
drawParticles();
}

void spawnParticles() {
if(idx>p.length-1) {
idx = 0;
}
float vx = random(-1, 1);
float vy = random(-1, 1);
p[idx] = new Particle(mouseX, mouseY, vx, vy, rad);
idx++;
}

void drawParticles() {
for(int i=0;i<p.length;i++) {
p[i].draw();
}
}


actionscript3の場合は描画されるオブジェクトはディスプレイリストで管理されるから、addChildでひたすらオブジェクトを追加しつつ増え過ぎたら削除、みたいな書き方ができる。
processingでもそんな方法はないのかなと思ったらサンプルにあった。
ArrayListClass \ Learning \ Processing 1.0 (BETA)

これはBallクラスにlifeプロパティをもたせてあり、255回ループで呼ばれたらfinished()メソッドがtrueを返して、ballsから削除されるようになってる。

(Example>Topics>Simulate>MultipleParticleSystemsとかもいい。nature of codeでやったVector3DクラスがPVectorクラスとして組み込まれてる。各メソッドについてもサンプルがついてて親切。)


for (int i = balls.size()-1; i >= 0; i--) {

は毎回balls.size()を参照しなくてもいいようにするかっこいい書き方。

というのを参考にしつつ、一定数超えたら削除していく方法で書き直したのがこれ。前出のParticleクラスはそのまま使える。
ArrayList使った思い通りの方法。
particleTest1_2.pde

ArrayList particles;
float rad = 10;
void setup() {
size(800, 400);
fill(0);
smooth();
particles = new ArrayList();
}

void draw() {
background(255);
spawnParticles();
drawParticles();
}

void spawnParticles() {
float vx = random(-1, 1);
float vy = random(-1, 1);
particles.add(new Particle(mouseX, mouseY, vx, vy, rad));
if (particles.size()>500) {
particles.remove(0);
}
}

void drawParticles() {
for(int i=particles.size()-1; i >= 0; i--) {
Particle p = (Particle)particles.get(i);
p.draw();
}
}


(11/7修正)重力のための変数gravityを削除。まだ関係ないので。

日曜日, 11月 02, 2008

non-formatize

六本木のTSUTAYAでお洒落なデザイン本などを眺めていたら発見したnon-formatの作品集。
これの左上。
で大体やりたいことはわかると思うけど、やってみました。

輝度が低い、暗いとこは振幅を大きくして、線が重なることで濃くしてある。だけ。
オリジナルに近づけるにはもうちょっと詰める必要あるな。元画像の作り方にも左右されると思うけど。

モナリザの画像探してる時に見つけたこんなんもある。錯視とかもっと勉強したい。

トラック毎に切り分けて音で聴けるようにしたいところだけど、それはまたいずれ。
最新版(0154)だとminim音鳴らないし。
Processing 1.0 (BETA) - Minim problem... I can't hear ANYTHING

flashでもできるな。BitmapDataクラスでgetPixel()して、値をSampleDataEventに渡す感じだろうか(地味に昨日flashでsine wave鳴らすの直した)。ファイル書き出しもできるからwaveファイルとかも作れるし(miztにソースいただきました)。

ビジュアルからインスパイアされて誰にでも説明できる方法で音作りに持っていけるようになったのはよかったよね。

scriptographerでやりたい。

PImage img;
int x = 0;
int y = 0;
int imgW;
int imgH;
float val;
float amp;

background(255);
colorMode(HSB, 255);
img = loadImage("lisa.jpg");
imgW = img.width;
imgH = img.height;
size(imgW*2, imgH);
image(img, 0, 0);

loadPixels();
for(y = 0; y < imgH; y++) {
for(x = 0; x < imgW; x+=5) {
val = brightness(pixels[y*imgW*2+x]);
amp = (255-val)*0.05;
stroke(100, amp+100);
line(imgW+x-amp, y, imgW+x+amp, y);
}
}
saveFrame("nonformatize.jpg");

金曜日, 9月 05, 2008

Encapsulation

前回の続き。短いけど。
何でメインになるプログラムのところでt.x++とかして値を代入しないのか、という話。
tを動かすには速度を代入すればいいから、普通の感覚だとt.x += vx;って感じにすると思う。

これはEncapsulation(カプセル化)というやつで、オブジェクト指向プログラミングの基本のひとつ。クラスの外から値を変えたりできないようにする。単純に言うと「オブジェクトのデータに直接アクセスするのではなく、メソッドを使え」ということらしい。
つまりt.go()で動くようにThingクラスを作っておくという訳。

なんだけど、Vectorクラスについては変数をパブリックにしておくと何かと便利なので、今回は例外にして、別のクラスでちゃんとやろうとのこと。Actionscript3.0アニメーションもそんな感じだったな...(13ページの「クラスとOOP」参照)まぁでもその程度のレベルでもこれだけのことができるってのがポイントだと思うので、あんまり堅く考え過ぎないようにしよう。

土曜日, 8月 09, 2008

Vectors

nature of codeをちゃんとやろうと思った。何となく読んだりコード書き換えてみたりはしてたんだけど、いくつか勉強しておきたい項目を取り上げて書くつもり。まずはVectorsから。実はVector3Dクラスが何をしてるのかとかよく理解してなかった。

motion 101のメインになる部分(hellomotion.pde)とThingクラスの余計なところを削って円の動きだけに注目。Vector3Dクラスを使うにはVector3D.javaをAdd File...でスケッチフォルダに追加するかライブラリを入れてimport noc.*;と書いておく必要がある。

vec3dmotion.pde

Thing t;
void setup() {
t = new Thing(new Vector3D(0.01, 0.01), new Vector3D(0, 0), new Vector3D(0, 0));
}

void draw() {
background(204);
t.go();
}

Thing.pde

class Thing {
Vector3D loc;
Vector3D vel;
Vector3D acc;

Thing(Vector3D a, Vector3D v, Vector3D l) {
this.acc = a.copy();
this.vel = v.copy();
this.loc = l.copy();
}

void go() {
update();
borders();
render();
}

void update() {
vel.add(acc);
loc.add(vel);
}

void borders() {
if(loc.x > width) {
loc.x = 0;
}
if(loc.x < 0) {
loc.x = width;
}
if(loc.y > height) {
loc.y = 0;
}
if(loc.y < 0) {
loc.y = height;
}
}

void render() {
ellipse(loc.x, loc.y, 10, 10);
}
}


位置は点(Points)であり、速度/加速度はベクトル(Vectors)。コーディングをシンプルにするために、これらを全てベクトル(大きさと方向)として扱う。

setup()メソッドの中でThingクラスのインスタンスを作る時に、Vector3Dのインスタンスを生成して値を渡してるんだけど、この時の引数が2つ(new Vector3D(x,y))だと2次元、3つ(new Vector3D(x,y,z))だと3次元になる。実際には2つの場合はzに0が入るというだけなのでVector3Dのインスタンスは常にx,y,zで3次元の値を持ってるんだけど。

Thingクラスのコンストラクタではcopy()メソッドを使って、先ほど生成されたVector3Dクラスのインスタンス変数からThingクラスのインスタンス変数に値をコピーして格納してる。

加速度から速度を導いて、速度から位置を導く、という流れ。

Vector3D使わないとすればこうなる。
normalmotion.pde

Thing t;
void setup() {
t = new Thing(0.01, 0.01, 0, 0, 0, 0);
}

void draw() {
background(204);
t.go();
}

Thing.pde

class Thing {
float x;
float y;
float vx;
float vy;
float ax;
float ay;

Thing(float ax, float ay, float vx, float vy, float x, float y) {
this.ax = ax;
this.ay = ay;
this.vx = vx;
this.vy = vy;
this.x = x;
this.y = y;
}

void go() {
update();
borders();
render();
}

void update() {
vx += ax;
vy += ay;
x += vx;
y += vy;
}

void borders() {
if(x > width) {
x = 0;
}
if(x < 0) {
x = width;
}
if(y > height) {
y = 0;
}
if(y < 0) {
y = height;
}
}

void render() {
ellipse(x, y, 10, 10);
}
}

これはこれでわかりやすい。けど多分後々Vector3Dが効いてくるんだと思う。

ベクトルとかの数学的な概念とか、コード使ったアニメーションで勉強になるのは『ActionScript 3.0 アニメーション』。
スクリプトだけで全部やるからflash持ってなくても動くものが作れる。flex環境のセットアップとかも丁寧に書いてあるしその辺は検索すれば出てくる。値段は高いけど、夏休み(もう大分過ぎてますが)にこれ1冊やると思えばどっか遊びに行くより楽めるし安い。続編も出るらしいし。

processingとActionscript3.0の行き来はそれほど苦ではないと思うので、両方読み書きできるといいと思う。既に使えるソースコードが沢山公開されてる訳だし。

今までは使えそうなコードを集めて勘でプログラミングしてたんだけど、細かい調整できるようにそろそろスクラッチでも色々ちゃんと書けるようになりたい。DJからトラックメイカーへ。

自前のblog環境整えないとな、と思う。かゆいところに手が届かないストレスで投稿が減ってるってのもあるから、何とかしたい。

火曜日, 5月 06, 2008

richard paul lohse remix



tumblr見てたらコードにしやすそうなグラフィックを見かけたのでコードにしてみた。
元ネタはこれ。Richard Paul Lohse

元画像から色情報とって描画したりするのが正確なんだろうけど、自分の目でどれくらい色を数値に置き換えられるか試してみた。印刷に長けてる人は色を見てCMYKがそれぞれ何%か言えるらしい。

色空間はHSBで、最初は全部真ん中の列の明度(Brightness)だけが下がってるのかなと思ってたんだけど、どうもそれではうまくいかないので、黄色の行だけ明度はそのままで彩度(Saturation)を下げたらそれっぽくなった。

元画像をPhotoshopで調べてみたら、青色の行も黄色と同じで、明度は変わらず彩度が下がっていた。
あと全部の行の真ん中の列は色相(Hue)も微妙に変化してた。思ってたよりかは単純じゃなかった。

何かIAMASでこういうプロジェクトあったな。芸術情報アーカイブだっけ?こんなぬるいのではないけど、昔の人の作品の特徴を解析するやつ。特定の画家のジェネレータをつくったりするとか何とか。

コードは結構無駄なことしてる。上から下に実行って感じ。色のおかしいところは直してない。

PFont font;

size(500, 710);
background(255);
noStroke();
font = loadFont("HelveticaNeue-Light-48.vlw");
textFont(font, 21);
colorMode(HSB, 360);
smooth();

int rectSize = 156;
int offY = 16;
int offX = 16;

background(340);
for(int i=0;i<3;i++) {
int h;
int s;
int b;
for(int j=0;j<3;j++) {
if(i==1) {
b = 250;
}
else {
b = 280;
}
if(j==0) {
h = 322;
s = 290;
}
else if(j==1) {
h = 224;
s = 300;
}
else {
h = 55;
s = 360;
b = 360;
if(i==1) {
h = 44;
}
}
fill(h, s, b);
rect(offX+i*rectSize, offY+j*rectSize, rectSize, rectSize);
}
}
fill(0);
text("Richard Paul Lohse Remix\n5. May 2008\nHayashi Yosuke, Processing",
offX+rectSize, rectSize*4-10);
saveFrame("richard remix.tiff");

木曜日, 5月 01, 2008

golden rectangle



Balance in Design
読みながらprocessingで黄金長方形のコーディング。作図法を参照しながら、コードは自分で考えるというのがちょうどいい。

スクリーンのサイズ、背景色、塗りなどを設定。

size(400, 250);
background(255);
smooth();
noFill();

正方形を描く。

int square = 200;
rect(0, 0, square, square);

一辺の中点aから相対する角bまで斜線を引く。

float[] a = {square/2, square};
float[] b = {square, 0};
line(a[0], b[0], a[1], b[1]);

斜線abを半径とする弧を描く。
abの長さは三平方の定理で求められる。
dist(a[0], a[1], b[0], b[1])でも同じだけど、数学的な考え方を確認。
傾きはatan2(y, x)で求められる。

float ab = sqrt(pow(b[0] - a[0], 2) + pow(b[1] - a[1], 2));
arc(a[0], a[1], ab*2, ab*2, atan2(b[1] - a[1], b[0] - a[0]), 0);

正方形の伸ばした線と弧が交わる点をもつ小さな長方形。

rect(b[0], b[1], ab-a[0], square);

この小さな長方形と正方形で黄金長方形。
整理してまとめておく。

int square = 200;
float[] a = {square/2, square};
float[] b = {square, 0};
float ab = sqrt(pow(b[0] - a[0], 2) + pow(b[1] - a[1], 2));

size(400, 250);
background(255);
smooth();
noFill();

rect(0, 0, square, square);
line(a[0], b[0], a[1], b[1]);
arc(a[0], a[1], ab*2, ab*2, atan2(b[1] - a[1], b[0] - a[0]), 0);
rect(b[0], b[1], ab-a[0], square);

月曜日, 2月 11, 2008

glitch (alike) for vjs 2

画像と合わせるのは簡単。

PImage型の変数を宣言(imgは合わせる画像、capはノイズをキャプチャした画像のために使う)

PImage img, cap;

して、setup()の中で画像を読み込む。background()にPImageのインスタンスを入れる場合は画像とウィンドウのサイズを合わせなければならないことに注意。

void setup() {
size(200, 200);
img = loadImage("mkk.jpg");
noiser = new Noiser(colNumber, rowNumber);
}


draw()はこんな感じ。

void draw() {
noiser.drawNoise();
cap = get();
background(img);
blend(cap, 0, 0, width, height, 0, 0, width, height, ADD);
}


noiser.drawNoise()でノイズを作った後、capに代入。
背景をimgで塗りつぶして、blend()使ってcapと合成。

blend()のシンタックス
blend(srcImg, x, y, width, height, dx, dy, dwidth, dheight, MODE)
x, y, width, heightは読み込む画像のx座標、y座標、幅、高さ
dx, dy, dwidth, dheightは書き出し先のx座標、y座標、幅、高さ
MODEはADDの他にも色々あるけどビットシフトはない。イラストレーターとかフォトショップのエフェクトと同じようなもの。試してみると面白い。

ということで、今後この辺は使いそうな気がする。
勿論pixels使って1ピクセル単位で操作することもできるし、ビットシフトはblend()じゃできないからいずれ使うことになるけど、とりあえず簡単な方法から。

金曜日, 2月 08, 2008

glitch (alike) for vjs

vade » Blog Archive » Real World Max/MSP/Jitter 1 - Glitch (alike) for VJs

glitchっぽい映像を、jitterで作るチュートリアル。
glitchの特徴はfragmentation, repetition, linearity and complexityだそう。
随分前にブックマークしておいたんだけど、今になってprocessingでやってみようと思った。

まずイメージと、ブロックノイズを組み合わせてるんだけど、ブロックノイズの作り方。
2通り思いつく。

普通にrect()で作る。

Noiser noiser;
int colNumber = 5;
int rowNumber = 5;

void setup() {
size(200, 200);
noiser = new Noiser(colNumber, rowNumber);
}

void draw() {
noiser.drawNoise();
}

class Noiser {
int col;
int row;
public Noiser(int col, int row) {
this.col = col;
this.row = row;
}
void drawNoise() {
for(int j=0; j<height; j+=height/row) {
for(int i=0;i<width;i+=width/col) {
noStroke();
fill(random(255),random(255),random(255));
rect(i, j, width/col, height/row);
}
}
}
}


pixels使う。widthをcolで割った数が整数にならなかったりした時とかに今後の展開感じる。

Noiser noiser;
color[][] colorTable;
int colIndex = 0;
int rowIndex = 0;
int colNumber = 5;
int rowNumber = 5;

void setup() {
size(200, 200);
noiser = new Noiser(colNumber, rowNumber);
colorTable = new color[colNumber][rowNumber];
}

void draw() {
noiser.drawNoise();
}

class Noiser {
int col;
int row;
public Noiser(int col, int row) {
this.col = col;
this.row = row;
}

void drawNoise() {
for(int j=0; j<height; j+=height/row) {
for(int i=0; i<width; i+=width/col) {
if(colIndex>=col) {
colIndex = 0;
}
if(rowIndex>=row) {
rowIndex = 0;
}
colorTable[colIndex][rowIndex] = color(random(255), random(255), random(255));
colIndex++;
}
rowIndex++;
}

loadPixels();
for(int j=0; j<height; j++) {
for(int i=0; i int pos = i+j*width;
if(pos%(width/col)==0) {
colIndex++;
}
if(pos%(width*height/row)==0){
rowIndex++;
}
if(colIndex>=col) {
colIndex = 0;
}
if(rowIndex>=row) {
rowIndex = 0;
}
pixels[pos] = colorTable[colIndex][rowIndex];
}
}
updatePixels();
}
}


次回、画像と合わせる。

金曜日, 2月 01, 2008

MAX_FLOAT, MIN_FLOAT

visualizing data読み始めて、知った。
最小値とか最大値を比べて取得する場合、初期値を代入する時に

float dataMax = MIN_FLOAT;
float dataMin = MAX_FLOAT;

としておく。
読んで字のごとくMIN_FLOATはfloatで一番小さい値で、MAX_FLOATはfloatで一番大きい値。
どんな数値もこれより小さくて大きい。

sonicodeでは文字をビットマップにして黒いところに順番に番号つけて、縦のセルで大きさを比べて最大値と最小値を出してるんだけど、最大値を入れるための変数の初期値を0にしてた。これだと負の値がきたときに動かない。
設計上負の値がくることはないからいいや、と思ってたけど、気持ち悪かったんだよね。
MIN_INT, MAX_INTもある。

0126から追加されたみたい。