AS3S.ORG

ACTIONSCRIPT 3.0 SOURCES

RadioheadのプロモーションがGoogle Codeで行われている理由

RadioheadがGoogle Codeで"House of Cards"のPVを公開しています。
http://code.google.com/creative/radiohead/

このPVはビデオカメラをいっさい使わず、レーザースキャニング技術を使った3Dデータをもとに構成されており、
Flash版のViewerでは、リアルタイムに視点を変えながら再生することもできます。

http://code.google.com/creative/radiohead/viewer.html

さらに、この3DデータはCSV形式で公開されており、誰でもこのデータを使って作品を作ることができるようになっています。
http://code.google.com/p/radiohead/downloads/list

Processingのサンプルはダウンロードできますが、Flash版はなかったので、簡単なサンプルを作ってみました。

サンプルとソースは以下の通り。

Radiohead "House of Cards" Sample

なるべく単純なサンプルにするために、3Dの描画はPapervision3Dなどは使わず、もっとも単純な透視投影の計算結果をBitmap.setPixelを使って描画するだけにしました。マウス移動も視点が平行移動するだけ、マウスクリックによるモードの切り替えも単に毎フレーム描画をリフレッシュするかどうかという違いだけです。

公開されているCSVデータは毎フレーム毎に1ファイルになっていて、1ファイルの各行が描画点の
x,y,z,濃度
というデータになっています。1ファイルで12,000行くらいあるので、このサンプルでは255フレーム目から12フレーム分だけを描画しています。

なお、複数ファイルの読み込みには以前紹介したQueueクラスを利用しています。

package {
import flash.display.*;
import flash.events.*;
import flash.geom.Rectangle;
import flash.net.*;

import org.as3s.*;

[SWF(width='600',height='400',backgroundColor='0x000000',frameRate='30')]
public class Radiohead extends Document {

private var queue:Queue;
private var loaderList:Array;
private var loaderCount:int = 0;

private var image:Bitmap;
private var bitmap:BitmapData;

private var r:Number = 500;
private var start:int = 255;
private var total:int = 12;
private var count:int = 0;
private var scale:Number = 1.5;

private var afterglow:Boolean = false;

public function Radiohead() {

Document.scaleMode = StageScaleMode.NO_SCALE;

bitmap = new BitmapData(600, 400, false, 0x000000);
image = new Bitmap(bitmap);
addChild(image);

queue = new Queue();
queue.addEventListener(Queue.PROGRESS, onProgress);
queue.addEventListener(Queue.COMPLETE, onComplete);

loaderList = new Array();
for (var i:int=0; i
var loader:URLLoader = new URLLoader();
loaderList.push(loader);
queue.put(onLoadComplete);
}

loaderCount = 0;
Document.addEventListener(Event.ENTER_FRAME, load);
Document.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

}

private function load(event:Event):void {

var loader:URLLoader = loaderList[loaderCount];
try {
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadIOError);
loader.load(new URLRequest("csv/"+(start+loaderCount)+".csv"));
} catch (error:Error) {
queue.get(onLoadComplete);
}

if (++loaderCount>=total) {
Document.removeEventListener(Event.ENTER_FRAME, load);
}

}

private function onMouseDown(event:MouseEvent):void {

afterglow = !afterglow;

}

private function onLoadComplete(event:Event):void {

var data:String = event.target.data;
var lines:Array = data.split("\n");
var dataList:Array = new Array();

for each(var line:String in lines) {
var words:Array = line.split(",");
if (words.length==4) {
dataList.push({x:words[0]*scale, y:words[1]*scale, z:words[2]*scale, i:words[3]*1.3});
event.target.data = dataList;
}
}

queue.get(onLoadComplete);
}

private function onLoadIOError(event:Event):void {

queue.get(onLoadComplete);

}

private function onProgress(event:Event):void {

bitmap.fillRect(new Rectangle(0, 200, (queue.total-queue.length)/queue.total*600, 1), 0xffffff);

}

private function onComplete(event:Event):void {

bitmap.fillRect(new Rectangle(0, 0, 600, 400), 0x000000);
queue.removeEventListener(Queue.COMPLETE, onComplete);
Document.addEventListener(Event.ENTER_FRAME, update);

}

private function draw(dataList:Array):void {

for each (var p:Object in dataList) {
bitmap.setPixel((p.x-this.mouseX+200)*r/(r-p.z)+300, (p.y-this.mouseY)*r/(r-p.z)+200, p.i<<16 | p.i<<8 | p.i);
}

}

private function update(event:Event):void {

if (!afterglow) bitmap.fillRect(new Rectangle(0, 0, 600, 400), 0x000000);
draw(loaderList[count].data);
count = (count+1)%loaderList.length;

}

}

}

Written by admin

July 16th, 2008 at 12:08 am

Posted in misc.

Leave a Reply