SQLの窓

2014年02月14日


別ドメインの画像を『テクスチャ』として使った、Three.js(v65) + WebGL キューブアニメーション

実行ページ
( IE は IE11 以上でないと動作しません )


画像を THREE.ImageUtils.loadTexture で読み込んで、3D オブジェクトにテクスチャとして使用します。公式の説明は発見していませんが、Google+ と Picasa(実質 Google+と同じ) の画像データは、access-control-allow-origin: * を返すので、このような処理に適しています。

ここでは、一つの画像を繰り返し貼り付ける事を想定しています。単純に一枚の画像を面にフィットさせる場合は縦・横のサイズは自由ですが、繰り返して貼りつける場合には、64、128、256、512といったサイズである必要があります( 縦と横が同じサイズの正方形である必要はありませんが、正方形以外のサイズはあまり意味がありません )

サイズが自由である事の確認は、リンク先のページで任意の画像( Google+ のどなたの画像でも OK )のURL をセットして、x、y方向の繰り返しを 1 と 1 にして送信ボタンをクリックすると処理されますのでご確認下さい。また、そのサイズで複数繰り返しを行うとうまく処理されないのも確認できます。 







access-control-allow-origin ヘッダ が返されていますが、Three.js の機能として、THREE.ImageUtils.crossOrigin = "*"; を実行する必要があります。

この処理は、ここ最近のバージョンでやっときちんと実装されたものだと思います。いつ変更されたかは確認していませんが、少なくとも r57 のバージョンで実行すると、設定しなくても動作してしまいます。しかし、r65 では設定が必要になっていますので、実装する場合はバージョンに注意する必要があります。( Three.js は仕様変更が頻繁なので、現実的にはバージョンアップで常に確認する必要があります )
<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/three.min65.js"></script>
<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/user_play1.js"></script>

<div id="three_area" style='width:600px;height:600px;'></div>

<script type="text/javascript"> 
 
var camera, scene, renderer; 
var user_play; 
 
// 処理開始 
build_3d_world(); 
 
function build_3d_world() { 
 
	// カメラ 
	camera = new THREE.PerspectiveCamera( 70, 1, 1, 10000 ); 
 
	// シーン 
	scene = new THREE.Scene(); 

	// MeshBasicMaterial( 影を使わない ) を使用しているのでライトは必要ありませんが、実行してもかまいません
//	scene.add( new THREE.AmbientLight( 0xffffff ) );

	// 別ドメインの場合必要です( access-control-allow-origin: * の例 )
	THREE.ImageUtils.crossOrigin = "*";

	// 画像は、repeat.set で繰り返しで貼り付ける事ができますが、
	// その為には、64、128、256、512といったサイズである必要があります 
	// 別ドメインの場合は、access-control-allow-origin: ヘッダを返す必要がありますが、
	// Google+ や Picasa の画像は全てかえすようです
	var map = THREE.ImageUtils.loadTexture( "https://lh5.googleusercontent.com/-Xgh7ru0xoXs/UvujW9la76I/AAAAAAAASd4/IFWELp7fpA8/s512/st.png" );
	map.wrapS = map.wrapT = THREE.RepeatWrapping = 1000;
	map.repeat.set( 2, 2 );

	object = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 ), new THREE.MeshBasicMaterial( { map: map } ) );

	object.position.set( 0, 0, 0 );
	scene.add( object );
 
	// レンダラー 
	renderer = new THREE.WebGLRenderer();
	// 以前は、div の背景色で設定していましたが、クリアカラーを指定するようになっています
	renderer.setClearColor( 0x444444 );
	renderer.setSize( 600, 600 ); 
 
	// 実装 
	document.getElementById("three_area").appendChild( renderer.domElement ); 
 
	// アニメーション 
	// 150 は回転効果の半径です
	user_play = new THREE.UserPlay1( scene, camera, renderer, animate, 150 ); 
	user_play.start(); 
 
} 
// ループ処理 
function animate() { 
 
	// アニメーションを行う為の次のフレームの呼び出し処理です
	requestAnimationFrame( animate ); 
	// この中で回転効果を処理しています
	user_play.render(); 
 
} 
 
</script>
THREE.ImageUtils.loadTexture で返されるのは THREE.Texture オブジェクトです。ここで最も重要な THREE.Texture の機能は、wrapSwrapT プロパティです。これは、平面における繰り返し方向に対するオプションをセットするプロパティで、それぞれ x 方向と y方向と考えて下さい。( S: 水平, T: 深さ, H: 高さ / 内部で、Vector2 に対応しているので、x と y )

オプションの値は 3つ 用意されていて、以下のようになっています
THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;
デフォルトは THREE.ClampToEdgeWrapping で、テクスチャを面に対して伸縮してセットする事を意味します。THREE.RepeatWrappingTHREE.MirroredRepeatWrapping は、それぞれテクスチャを繰り返してマッピングするもので、前者は境界毎に同じものが繰り返され、後者は境界毎に反転されたものが使用されます。 ただ、繰り返し処理を使っていても、繰り返す回数を 1 回だけにすると THREE.ClampToEdgeWrapping と同じ結果になります。 ※ map.repeat.set( 1, 1 ); 以下の処理は、Three.js の構築部分のみを明確にするためにアニメーション部分を外に出しています。 user_play1.js
THREE.UserPlay1 = function ( scene, camera, renderer, animate, radius ) {

	this.scene = scene;
	this.camera = camera;
	this.renderer = renderer;
	this.radius = ( radius !== undefined ) ? radius : 600;

	this.theta = 0
	this.animate = animate;


};
THREE.UserPlay1.prototype = {
	constructor: THREE.UserPlay1,
	start: function() {
		this.animate();
	},
	render: function() {
		this.theta += 0.1;

		this.camera.position.x = this.radius * Math.sin( THREE.Math.degToRad( this.theta ) );
		this.camera.position.y = this.radius * Math.sin( THREE.Math.degToRad( this.theta ) );
		this.camera.position.z = this.radius * Math.cos( THREE.Math.degToRad( this.theta ) );

		this.camera.lookAt( this.scene.position );
		this.renderer.render( this.scene, this.camera );
	}

};
これらのコードは、THREE.CanvasRenderer でも動作します。但しその場合はセグメントの境界が表示されてしまうので、THREE.MeshBasicMaterial のオプションとして overdraw: true を追加します。また、キューブのセグメント数( 4, 4, 4 ) は、THREE.CanvasRenderer での処理時に効力を発揮します( セグメント単位の画像のゆがみ表現となるので、セグメント数が少ないと全体としての歪みが大きくなります )

3D の原理の専門的な部分はよく解らないのですが、WebGL では平面のセグメント数が少なくても良いように感じています。『 object = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100 ), new THREE.MeshBasicMaterial( { map: map } ) );』

関連する資料

ポリゴンメッシュ



posted by lightbox at 2014-02-14 17:43 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり