yoppa.org


第7回: Processingで3Dプログラミング (OpenGL)

この演習では、ここまで主に2次元平面上での描画による表現を扱ってきました。今回は2次元での表現からさらに(文字通り)次元を越えて、3次元空間での表現について考えていきたいと思います。

ProcessingにはOpenGLという3Dのための描画エンジンを用いて3D表示をするモードが用意されています。これによって、複雑な数学的な処理や演算をすることなく3Dの描画が直感的に行えます。

しかし、3Dの物体を扱うには、これまでとは2Dの描画とは違った様々な要素が加わります。カメラ(視点)、ライティング、光と影(シェーディング)、奥行の重なりなどといった2次元の平面には無かった様々な技術や概念の理解が必要となります。

スライド資料

サンプルプログラム


第7回 : 写真 2 – ライブカメラの映像を処理、コンピュータビジョン導入

メディアアート作品では、カメラから取得した映像を用いてインタラクションを行う事例が沢山存在しています。映像を使ったインタラクションは、特別なセンサーを使用することなく、また鑑賞者に直接接触することなく高度なインタラクションが可能となり、多くの可能性を秘めた手法です。また、近年では映像の中から物体を認識したり、映像の中の微妙な差分や動きを検出したりといった、コンピュータ・ビジョン(Computer Vision = CV)の技術が発展し、高度な映像解析が活用できるようになりました。今回は、まず始めにカメラからリアルタイムに映像を取得し加工する方法を学んだあと、CVの技術の中でもオープンソースで多くの利用実績のあるOpenCVというCVのためのライブラリをopenFrameworksで活用する方法について紹介していきます。

スライド資料

サンプルコード

サンプルコードは下記のリンクからダウンロードしてください。


第7回: 生成的な形をつくる – Processing オブジェクト指向プログラミング入門

今回はProcessingで生成的(Generative)な形態を生みだすにはどうすればよいのか、試行錯誤しながら実験していきます。まず初めに、コードを用いた生成的な表現の実例をいくつか紹介した後、実際にProcessingでプログラミングしていきます。

まず始めに、完全にランダムな確率で動きまわる「ランダムウォーク」な動きをする点の動きをつくり、その軌跡を描いてみます。次にこのランダムな動きを増殖させていきます。増殖の際に今回は全てを一つのプログラムに書くのではなく、それぞれの点を細かなプログラムで実装し、その小さなプログラム達を組合せることで一つの機能を生みだすような設計にします。この小さなプログラムを「オブジェクト (Object)」と呼び、オブジェクトを構成単位にしてプログラムを作成していく手法を、オブジェクト指向プログラミング (OOP) と呼びます。このOOPの考え方は今後も重要な内容となってきますので、実例を通して確実に理解していきましょう。

スライド資料

サンプルプログラム

ランダムウォーク (クラス無し)

PVector location;
PVector velocity;
void setup() {
  size(800, 600);
  frameRate(60);
  //位置と速度のベクトルを初期化
  location = new PVector(width/2, height/2);
  velocity = new PVector();
  //背景は一度だけ (軌跡を残す)
  background(0);
}

void draw() {
  //描画設定
  noStroke();
  fill(255, 31);
  //速度を設定
  velocity.x = random(-1, 1);
  velocity.y = random(-1, 1);
  location.add(velocity);
  //円を描く
  ellipse(location.x, location.y, 2, 2);
}

ランダムウォーク10倍速 (クラス無し)

PVector location;
PVector velocity;
void setup() {
  size(800, 600);
  frameRate(60);
  //位置と速度のベクトルを初期化
  location = new PVector(width/2, height/2);
  velocity = new PVector();
  //背景は一度だけ (軌跡を残す)
  background(0);
}

void draw() {
  //描画設定
  noStroke();
  fill(255, 31);
  for (int i = 0; i < 10; i++) {
    //速度を設定
    velocity.x = random(-1, 1);
    velocity.y = random(-1, 1);
    location.add(velocity);
    //円を描く
    ellipse(location.x, location.y, 2, 2);
  }
}

Walkerクラスによるランダムウォーク

//Walkerクラスのオブジェクトの宣言
Walker walker;

void setup() {
  size(800, 600);
  frameRate(60);
  //クラスをインスタンス化
  walker = new Walker();
  background(0);
}

void draw() {
  //Walkerクラスのdraw()メソッドを実行
    noStroke();
    fill(255, 31);
  walker.draw();
}

class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  //ランダムウォークを描画
  void draw() {
    for (int i = 0; i < 10; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

Walkerクラスの配列 (10個)

//Walkerクラスのオブジェクトの宣言
int NUM = 10;
Walker[] walker = new Walker[NUM];

void setup() {
  size(800, 600);
  frameRate(60);
  //配列の数だけインスタンス化
  for (int i = 0; i < NUM; i++) {
    walker[i] = new Walker();
  }
  background(0);
}

void draw() {
  //色の設定
  noStroke();
  fill(255, 31);
  //配列の数だけ描画
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

//Walkerクラス
class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  //ランダムウォークを描画
  void draw() {
    for (int i = 0; i < 10; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      ellipse(location.x, location.y, 2, 2);
    }
  }
}

Walkerクラスの配列 (100個)

int NUM = 100;
Walker[] walker = new Walker[NUM];

void setup() {
  size(1280, 720);
  frameRate(60);
  //Walker配列の初期化
  for (int i = 0; i < NUM; i++) {
    walker[i] = new Walker();
  }
  //背景
  background(0);
}

void draw() {
  //画面をフェードさせる
  blendMode(BLEND);
  fill(0, 5);
  rect(0, 0, width, height);
  //色の設定
  noStroke();
  blendMode(ADD);
  fill(255, 31);
  //Walker配列を描画
  for (int i = 0; i < NUM; i++) {
    walker[i].draw();
  }
}

//Walkerクラス
class Walker {
  PVector location;
  PVector velocity;

  Walker() {
    location = new PVector(width/2, height/2);
    velocity = new PVector();
  }

  void draw() {
    for (int i = 0; i < 10; i++) {
      velocity.x = random(-1, 1);
      velocity.y = random(-1, 1);
      location.add(velocity);
      rect(location.x, location.y, 2, 2);
    }
  }
}

第6回: 画像の分析・再合成 (画像データ、ピクセル、ラスタ画像)

ProcessingのPImageクラスは、外部のビットマップ画像(Jpeg, GIF、PNGなど)をデータとしてプログラムに読み込むことができます。読み込んだ画像は単に画面に表示するだけでなく、色や明度やサイズを変更して表示することができます。さらには、画像に含まれる全てのピクセルの色情報を読み取り配列に格納することが可能です。そのデータをもとに別の画像を再生成することが可能となり、読み込んだ画像データの色情報をもとにした多彩な表現が可能となります。

今回はProcessingに画像を読み込んで、分析再合成することで、様々な表現の可能性について探っていきます。

スライド資料

サンプルファイル


第6回: openFrameworks Addon 1 : Addonについて – ofxGui

Addon(アドオン)とは、openFrameworksに機能を拡張するためのライブラリーやフレームワークです。processingのLibrariesのように、openFrameworks単体ではできなかった様々な機能を実現することが可能となります。Addonは、oF本体の開発者以外でも独自に開発して追加することが可能であり、繰り返し用いる機能や、CやC++で記述された既存のライブラリーをopenFrameworksに統合することが可能となります。

今回はAddonの導入を、まずofxGuiというプロジェクトにGUIを追加するアドオンで行います。ofxGuiを使用することで、例えば周囲の環境が異なる場所でインスタレーションを設置する時など、すぐにパラメータを最適な状態に調整して保存することができ、とても便利です。

スライド資料

サンプルコード


第6回: 画像の分析・再合成 (画像データ、ピクセル、ラスタ画像)

ProcessingのPImageクラスは、外部のビットマップ画像(Jpeg, GIF、PNGなど)をデータとしてプログラムに読み込むことができます。読み込んだ画像は単に画面に表示するだけでなく、色や明度やサイズを変更して表示することができます。さらには、画像に含まれる全てのピクセルの色情報を読み取り配列に格納することが可能です。そのデータをもとに別の画像を再生成することが可能となり、読み込んだ画像データの色情報をもとにした多彩な表現が可能となります。

今回はProcessingに画像を読み込んで、分析再合成することで、様々な表現の可能性について探っていきます。

スライド資料

サンプルファイル

課題: Proessingに読み込んだ画像ファイルのデータで表現する

  • PImageに読み込んだ画像ファイルの情報から、新たなイメージを生成してください
    • 読み込む画像は自由です

課題の提出方法

  • emailで提出
    • To : tadokoro+teu18@gmail.com
    • Subject: 課題1
    • 作成したプログラムの実行結果をスクリーンキャプチャーしてメールに添付
    • 本文に以下の内容を記入して提出
      • 作品のタイトル
      • 学籍番号
      • 氏名
    • 締切: 次回の講義開始時間まで

第5回: 振動によるアニメーション表現 – ビジュアルハーモニー、三角関数

今回は、より複雑なアニメーションに挑戦します。たくさんの図形を、一定の手続き(= アルゴリズム)にそって動かしてみます。動きのアルゴリズムはいろいろありますが、今回はその一例として、三角関数(sin, cos , tan)を使用した動きをとりあげます。三角関数の定義は、直角三角形の角度とそれを取り囲む辺の比率で定義されます。しかし、同時に円運動を座標に変換する仕組みとしても活用可能です。この仕組みを応用してアニメーションするとどうなるか、三角関数を用いたアニメーションで美しいパターン「ビジュアルハーモニー」を生成する手法を紹介します。

スライド資料

サンプルプログラム


第5回 : 写真 1 – 画像データの読み込みと再合成

今回は、このワークショップのテーマにもなっている「写真」についての第一弾として、openFrameworksによる画像データの読み込みと再合成を行います。

ofImageクラスは、openFrameworksのプロジェクトに画像ファイルのデータを読み込み自由な場所とサイズで表示することが可能です。まず、ofImageでの画像データの取り扱いについて解説します。

さらに、一度ofImageに読み込んだデータは、ofPixels形式に変換することで全てのピクセルの色情報を配列として格納することができます。この機能を使うことで、読み込んだ画像のピクセル単位でのデータを取得してそれを元に別の画像を再合成するという手法で様々な表現が可能となります。いくつかの実例を紹介しながら、この画像データの読み込みと再合成について考えていきます。

スライド資料

サンプルファイル

スライド内で使用しているサンプルのソースコードは以下からダウンロードしてください。


第5回: ビジュアルハーモニー (アルゴリズム、三角関数)

今回は、より複雑なアニメーションに挑戦します。たくさんの図形を、一定の手続き(= アルゴリズム)にそって動かしてみます。動きのアルゴリズムはいろいろありますが、今回はその一例として、三角関数(sin, cos , tan)を使用した動きをとりあげます。三角関数の定義は、直角三角形の角度とそれを取り囲む辺の比率で定義されます。しかし、同時に円運動を座標に変換する仕組みとしても活用可能です。この仕組みを応用してアニメーションするとどうなるか、三角関数を用いたアニメーションで美しいパターン「ビジュアルハーモニー」を生成する手法を紹介します。

スライド資料

サンプルプログラム


第4回: 図形を動かす、ベクトルによる運動の記述

今回からいよいよ動きのある表現(= アニメーション)について扱っていきます。アニメーションを実現するには、まず時間を扱う基本構造を知る必要があります。Processingでは、setup(), draw() という2つのブロックにわけて、初期化と更新を行うことでアニメーションを実現しています。まず始めはこの基本構造について理解します。次に、これから動きを扱う際に、向きと大きさをもった「ベクトル」という概念を理解します。ベクトルを理解することで、位置や運動を整理して記述することが可能となります。最後に、この基本構造をベクトルを活用して簡単なアニメーションを作成します。

スライド資料

サンプルプログラム

授業内で使用したサンプルプログラムは下記からダウンロードしてください。