見出し画像

p5.jsでプロジェクションマッピングする方法を探る

はじめに

こんにちは。木村です。

今日ももくもく会をやっていますので、次の技術書典に向けて調査をしていきたいと思います。想定よりも次の技術書典が早く(11月末が出展申込締切)大変焦っております。

p5.jsでプロジェクションマッピングという本を書きたいので、そもそもできるのか、前回の記事に引き続き調べていきたいと思います。

できる目処を立てないと本のタイトルを決められない=申し込みができない!

Processingでプロジェクションマッピング

とりあえずp5.jsの元になったProcessingでプロジェクションマッピングをする方法を検索すると以下の記事がヒットしました。

コピペテックはチュートリアルなのでこういうシンプルでわかりやすいのいいですね。上記は「Processing2.2.1で動作を確認」と書かれていて、今は3.5.3なので、そのままでは動かず、少し修正したのが以下になります。

import processing.video.*;

Movie movie;
int   selected = -1;  // 選択されている頂点
int   pos[][] = {{0,0},{400,0},{400,300},{0,300}}; // 頂点座標

void setup() {
 size(1440, 1080, P2D);  
 background(0);  
 movie = new Movie(this, "lili.mov");
 movie.loop();
}

void movieEvent(Movie movie) {  
 movie.read();
}

void draw() {  
 background(0);
 
 // ビデオテクスチャの描画
 beginShape();
   texture(movie);  
   vertex(pos[0][0], pos[0][1], 0, 0);
   vertex(pos[1][0], pos[1][1], movie.width, 0);
   vertex(pos[2][0], pos[2][1], movie.width, movie.height);
   vertex(pos[3][0], pos[3][1], 0, movie.height);
 endShape(CLOSE);
 
 // マウスによる頂点操作
 if ( mousePressed && selected >= 0 ) {
   pos[selected][0] = mouseX;
   pos[selected][1] = mouseY;
 }
 else {
   float min_d = 20; // この値が頂点への吸着の度合いを決める
   selected = -1;
   for (int i=0; i<4; i++) {
     float d = dist( mouseX, mouseY, pos[i][0], pos[i][1] );
     if ( d < min_d ) {
       min_d = d;
       selected = i;
     }      
   }
 }
 if ( selected >= 0 ) {
   ellipse( mouseX, mouseY, 20, 20 );
 }
}

動かすと以下のようになります。プロジェクターで対象物にコンテンツを投射した後に、コンテンツをマウスで対象物に合わせていくというスタイルですね。

画像1

これは平面一枚ですが、複数組合わせれば箱とかにも投射できますね。

p5.jsに移植する

これをp5.jsに移植します。p5.jsのWEBGLモードはキャンバスの中心が原点になるので、ちょっと混乱しますが、以下のようなコードでできました。

let movie;
let selected = -1;  // 選択されている頂点
let pos = [[0,0],[400,0],[400,300],[0,300]]; // 頂点座標

function setup() {
 createCanvas(800, 600, WEBGL);
 movie = createVideo(['lili.mov']);
 movie.hide();
 movie.loop();
}

function draw() {
 background(0);
 beginShape();
   texture(movie);
   vertex(pos[0][0] - 400, pos[0][1] - 300, 0, 0);
   vertex(pos[1][0] - 400, pos[1][1] - 300, movie.width, 0);
   vertex(pos[2][0] - 400, pos[2][1] - 300, movie.width, movie.height);
   vertex(pos[3][0] - 400, pos[3][1] - 300, 0, movie.height);
 endShape(CLOSE);
 
 // マウスによる頂点操作
 if ( mouseIsPressed && selected >= 0 ) {
   pos[selected][0] = mouseX;
   pos[selected][1] = mouseY;
 }
 else {
   let min_d = 20; // この値が頂点への吸着の度合いを決める
   selected = -1;
   for (let i=0; i<4; i++) {
     let d = dist( mouseX, mouseY, pos[i][0], pos[i][1] );
     if ( d < min_d ) {
       min_d = d;
       selected = i;
     } 
   }
 }
 if ( selected >= 0 ) {
   ellipse( mouseX - 400, mouseY - 300, 20, 20 );
 }
}

動かすとこんな感じです。普通に移植できました。

画像2

p5.js EditorのURLも貼っておきます。こちらで実際に動作を試すことができます。

https://editor.p5js.org/atskimura/sketches/egss-RS-4

おわりに

今回はマウスで自力で変形させるという方法でやりましたが、以下の記事のようにMadMapperを使うこともできそうなので、もしかしたらその方法にするかもしれません。

ともかく「p5.jsでプロジェクションマッピング」的なタイトルで本を書くことは可能そうだというところにまでは辿り着きました。よかったよかった。

この記事が気に入ったらサポートをしてみませんか?