SQLの窓

2014年11月29日

r69 で再チェックしました / Three.js(r53) で追加された LineDashedMaterial のサンプルを簡素化して解りやすくしました



中央に点線でキューブが回るだけのサンプルですが、LineDashedMaterial の確認だけならこれで十分です。

cube ファンクションで 12 個の 線が作成されていますが、一つの線に Vector3 座標を二つ使って線を引いています。THREE.LinePieces を使っているので、二点のペアをを繋げるので連鎖はしません。デフォルトの THREE.LineStrip を使うと、点が連鎖して描画されるので、一筆書きになります。

このサンプルでは正確に立方体を作成する為に、『二点のペア』を使っているので、同一座標がある事に注意して下さい。

r53 では WebGL、r56 で Canvas

※ WebGL では、	geometryCube.computeLineDistances(); でキューブのデータを完成させる必要があります。また、{ antialias: true } を WebGLRenderer の引数に渡さないと、ラインの表示の乱れが大きいです

更新履歴にそうあります。このサンプルコードは r56 で動作しますし、r53 〜 r55 までなら、WebGLRenderer で動作するはずです。ですが、いずれにしても点線が動作するのは Google Chrome か Firefox だけなので注意して下さい。 IE11 で動作していました。

canvas でのデモ

WebGL でのデモ
( three69.min.js のみで動作します )

▼ CanvasRenderer
※ 利便性の為に、jQuery を使用しています。
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="http://winofsql.jp/js/three/three69.min.js"></script>
<script type="text/javascript" src="http://winofsql.jp/js/three/renderers/Projector.js"></script>
<script type="text/javascript" src="http://winofsql.jp/js/three/renderers/CanvasRenderer.js"></script>

<div id="three_canvas_container"></div>

<script type="text/javascript">
var WIDTH = 600;
var HEIGHT = 600;
var renderer, scene, camera, stats;
var object;

$("#three_canvas_container")
	.css({
		width: WIDTH+"px",
		height: HEIGHT+"px"
	});


init();		// 仕様作成
animate();	// アニメーション開始

// ***********************************
// 描画仕様作成
// ***********************************
function init() {

	// 遠近法カメラ作成
	camera = new THREE.PerspectiveCamera(
		// 視野の上下角度
		40,
		// カメラビューのアスペクト比
		WIDTH / HEIGHT,
		// 表示可能な一番近い距離
		1,
		// 表示可能な一番遠い距離
		200
	);

	// 座標におけるカメラの位置
	camera.position.z = 150;

	// シーン作成	
	scene = new THREE.Scene();

	// 一辺 50 のキューブの座標を作成	
	var geometryCube = cube( 50 );

	// ラインでキューブを作成	
	object = new THREE.Line(
		geometryCube,
		// 点線の仕様を決定
		new THREE.LineDashedMaterial( {
			color: 0xffaa00,
			dashSize: 3,
			gapSize: 1,
			linewidth: 2
		} ),
		// 二つの座標をペアとして使用する
		THREE.LinePieces
	);

	// シーンにオブジェクト(ラインで作成したキューブ)を追加	
	scene.add( object );

	// Canvas で描画します	
	renderer = new THREE.CanvasRenderer( );
	// 描画サイズの設定
	renderer.setSize( WIDTH, HEIGHT );
	// 描画領域の色を設定します
	renderer.setClearColor( 0x404040 );

	// 描画対象とする three_canvas_container に Three.js の
	// 描画システムを実装	
	var container = $( '#three_canvas_container' )[0];
	container.appendChild( renderer.domElement );

}

// ***********************************
// ラインによるキューブ作成
// ***********************************
function cube( size ) {
	
	var h = size * 0.5;
	
	var geometry = new THREE.Geometry();
	
	geometry.vertices.push( new THREE.Vector3( -h, -h, -h ) );
	geometry.vertices.push( new THREE.Vector3( -h, h, -h ) );
	
	geometry.vertices.push( new THREE.Vector3( -h, h, -h ) );
	geometry.vertices.push( new THREE.Vector3( h, h, -h ) );
	
	geometry.vertices.push( new THREE.Vector3( h, h, -h ) );
	geometry.vertices.push( new THREE.Vector3( h, -h, -h ) );
	
	geometry.vertices.push( new THREE.Vector3( h, -h, -h ) );
	geometry.vertices.push( new THREE.Vector3( -h, -h, -h ) );
	
	geometry.vertices.push( new THREE.Vector3( -h, -h, h ) );
	geometry.vertices.push( new THREE.Vector3( -h, h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( -h, h, h ) );
	geometry.vertices.push( new THREE.Vector3( h, h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( h, h, h ) );
	geometry.vertices.push( new THREE.Vector3( h, -h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( h, -h, h ) );
	geometry.vertices.push( new THREE.Vector3( -h, -h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( -h, -h, -h ) );
	geometry.vertices.push( new THREE.Vector3( -h, -h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( -h, h, -h ) );
	geometry.vertices.push( new THREE.Vector3( -h, h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( h, h, -h ) );
	geometry.vertices.push( new THREE.Vector3( h, h, h ) );
	
	geometry.vertices.push( new THREE.Vector3( h, -h, -h ) );
	geometry.vertices.push( new THREE.Vector3( h, -h, h ) );

	return geometry;

}


// ***********************************
// アニメーション用繰り返し処理
// ***********************************
function animate() {

	// アニメーション用のこの関数の再呼び出しの予約
	requestAnimationFrame( animate );

	// 描画
	render();

}

// ***********************************
// 実際の描画
// ***********************************
function render() {

	// アニメーション用の時間間隔
	var time = Date.now() * 0.001;

	// x 軸で回転
	object.rotation.x = 0.25 * time;
//	object.rotation.y = 0.25 * time;

	// 描画実行
	renderer.render( scene, camera );

}
</script>


posted by at 2014-11-29 00:34 | Three.js | このブログの読者になる | 更新情報をチェックする

2014年11月26日

Three.js(r69) : Lineメソッドで使用する頂点の配列を持つ Geometry オブジェクト

この記事を最初に書いた、2012-03-25 では、Three.js は r47 でした。現在 r69 になり、js ライブラリの参照単位や、クラスの仕様も変わり、座標の設定方法もかなり変わっていました。( 現在 THREE.Sprite を使用しており、ソース内にあるサンプルのマテリアルを使用できますが、昔は無かったので {} を変わりに使用して単純な線を引いています。引数に何も指定しないと、規定のマテリアルが使用されて、ソースコード上で未使用のマテリアルを引数にセットした状態と同じになります )

さらにいろいろテストしてみると、Vertex オブジェクトが無くなっている事がわかりました。r69 では、直接 Vector3 を geometry.vertices.push できるようです。

Vector3 によるデモ

Sprite によるデモ



※ リロードする毎にランダムに線を引きます

正直 3D に関する知識はたいして持ち合わせていないので、サンプルの動作からオリジナルソースの中を読んで自分なりに納得した内容を記述しているので、間違っているかもしれま
せん。
<script type="text/javascript" src="http://winofsql.jp/js/three/three69.min.js"></script>
<script type="text/javascript" src="http://winofsql.jp/js/three/renderers/Projector.js"></script>
<script type="text/javascript" src="http://winofsql.jp/js/three/renderers/CanvasRenderer.js"></script>
<script type="text/javascript">

container = document.createElement('div');
container.setAttribute("id", "container");
document.body.appendChild(container);

camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.z = 1200;
camera.position.y = -200;

scene = new THREE.Scene();

scene.add( camera );

renderer = new THREE.CanvasRenderer();
renderer.setClearColor( 0xffffff );
renderer.setSize( 700, 500 );
container.appendChild( renderer.domElement );

// **************************************
// Geometry は、描画に必要なデータ収納庫
// **************************************
var geometry = new THREE.Geometry();

// **************************************
// ライン用のマテリアル( ここでは未使用 )
// **************************************
var PI2 = Math.PI * 2;
var material = new THREE.SpriteCanvasMaterial( {

	color: 0xffffff,
	program: function ( context ) {

		context.beginPath();
		context.arc( 0, 0, 0.5, 0, PI2, true );
		context.fill();

	}

} );


// 座標を4つ作成
for ( var i = 0; i < 4; i ++ ) {

	// 座標を作成
	particle = new THREE.Sprite( {} );
	particle.position.x = Math.random() * 2 - 1;
	particle.position.y = Math.random() * 2 - 1;
	particle.position.z = Math.random() * 2 - 1;
	particle.position.normalize();
	particle.position.multiplyScalar( Math.random() * 10 + 450 );
	particle.scale.x = particle.scale.y = 10;
	scene.add( particle );

	geometry.vertices.push( particle.position );

}

// **************************************
// geometry を使って順につなげる『線』を描画
// 線に対する属性として、色と不透明度と太さを設定
// **************************************
line = new THREE.Line(
	geometry, 
	new THREE.LineBasicMaterial( { color: 0x000000, opacity: 1.0, linewidth: 5 } ) 
);
scene.add( line );

renderer.render( scene, camera );


</script>


posted by at 2014-11-26 22:52 | Comment(0) | Three.js | このブログの読者になる | 更新情報をチェックする

2014年09月25日

Three.js : 好きな背景透過画像を飛翔させる

url を指定しない場合は、以下の画像が飛翔します。別に背景透過でなくても、なんでも飛翔するんですが、単純な画像でないと、何がなんだか良くわかりません。

url:
関連する記事

Three.js の canvas_geometry_birds の『鳥』だけを取り出して考える


▼ 以下は、さらに発展型で、カラフルな鳥が飛翔した軌跡を残します。

※ もう一度クリックすると止まります


posted by at 2014-09-25 02:04 | Comment(0) | Three.js | このブログの読者になる | 更新情報をチェックする

2014年06月19日

Three.js : Vector3 オブジェクトのコンストラクタ / result = x || 0; という書き方

var x;
var result = x || 0;
で、result に入るのは、x と 0 の論理和では無く、最初に 真になった結果または、最後に false になった結果です。undefined も "" も 0 も false 扱いですが、この書き方だと、x に false や "" が入っている時は result は 0 になるという書き方です。 ですから、var obj = new THREE.Vector3(); は、obj.xとobj.yとobj.z は全 て0になっています。
THREE.Vector3 = function ( x, y, z ) {

	this.x = x || 0;
	this.y = y || 0;
	this.z = z || 0;

};




タグ:javascript
posted by at 2014-06-19 00:03 | Comment(0) | Three.js | このブログの読者になる | 更新情報をチェックする

2013年05月06日

Three.js : WebGL限定の Cube テクスチャによる『パノラマ背景』

WebGL でしか表示できませんが、球で使用する専用のパノラマ画像を使うより元画像を作るのは比較的簡単です。

▼ サンプル実行ページ

( ソースコードはリンク先にあります )

このままでは、どの画像がどこに表示されるのか解りづらいのでこんなのを作りました。

▼ サンプル実行ページ

( ソースコードはリンク先にあります )


▼ 球なので元画像作るのが大変
Three.js : 球を使った『パノラマ背景』




タグ:Three.js
posted by at 2013-05-06 21:22 | Three.js | このブログの読者になる | 更新情報をチェックする

2013年04月22日

Three.js : 球を使った『パノラマ背景』

オリジナルソースコードは webgl_materials_cubemap_dynamic2.html です。名前が cubemap とあるのは、このパノラマの中央でオブジェクトをアニメーションして背景を映りこみさせる『cubeCamera』を使ってるからだと思います。

▼ 背景画像


ちょっと作るのは違う知識が必要そうなので、オリジナルの画像を使っています。
( 結構簡単に美しい画像を手に入れる事ができました )


▼ 実行中のスクリーンショット


実行ページ

※ 掲示板の一部に実装しています。

ソースコードは掲示板ページの一番下にありますが、Google Chrome ではマウスホイールでしかスクロールできないようなので注意して下さい( Three.js のコントロールの仕様です )

※ 掲示板で取得したコードは、リアルタイム HTML テスターでそのまま実行できるようにしています。( 同じパスで画像を同一ドメイン内に置いています )

この処理で重要なのは、mesh.scale.x = -1; です。具体的な仕様は解りませんが、スケールを負にする事によって、球の内側を見ているようになります。ですから、カメラ位置が 1 であるにもかかわらずカメラを中心に画像が表示されています( カメラは全て 0 では表示されない仕様です )


posted by at 2013-04-22 00:20 | Three.js | このブログの読者になる | 更新情報をチェックする

2013年03月24日

Three.js の canvas_geometry_birds の『鳥』だけを取り出して考える



飛ばしている画像



こんな感じで以下で表示できます。
本来オリジナルで飛ばしているものは、8つの点からなるオブジェクトです。形は上から見ると以下のようになります。



この座標は x と z の座標軸で、通常の Three.js 空間で見たときは地面に対して平行な形です。実際の動きのアルゴリズムは良く解りませんのですが、動く際には必ずしも頭の方向が移動方向とは限らないようです。ただ、羽のはばたきは、この座標の2点を上下に動かして表現しています。(その位置の算出方法もまた良くわかりません)。ですから、この Bird オブジェクトのかわりに平面オブシェクトを使い、その上部の二点を同様に動かす事によって、飛翔する表現を自由に変更る事ができます。

飛翔する初音ミク

Bird の代わりに平面
	var image = new Image()
	image.onload = function () {

		texture = new THREE.Texture( this );
		texture.needsUpdate = true;
		material = new THREE.MeshBasicMaterial({map: texture, overdraw: true});
		material.side = 2

		for ( var i = 0; i < 200; i ++ ) {

			boid = boids[ i ] = new Boid();
			boid.position.x = Math.random() * 400 - 200;
			boid.position.y = Math.random() * 400 - 200;
			boid.position.z = Math.random() * 400 - 200;
			boid.velocity.x = Math.random() * 2 - 1;
			boid.velocity.y = Math.random() * 2 - 1;
			boid.velocity.z = Math.random() * 2 - 1;
			boid.setAvoidWalls( true );
			boid.setWorldSize( 500, 500, 400 );

			birds[ i ] = new THREE.Mesh( new THREE.PlaneGeometry(30, 30, 2, 1), material );
			bird = birds[ i ]
			bird.phase = Math.floor( Math.random() * 62.83 );
			bird.position = boids[ i ].position;
			scene.add( bird );

		}
		
	};
	image.src = "http://lh3.googleusercontent.com/-4Em5315jEAI/T_GVyEMF5BI/AAAAAAAAHBg/s78i3fY94vU/s60/Black_Eagle_Miku_Elf4.png";

後は、render の中の座標変更で x 軸を 90度 rotation して地面に対して平行にして、羽ばたく対象の頂点を設定します。

bird.geometry.vertices[ 0 ].z
bird.geometry.vertices[ 2 ].z
に、Math.sin( bird.phase ) * 15;

を設定していますが、15は係数で、オリジナルは 5 でしたが実行しながら調整しました。


posted by at 2013-03-24 02:40 | Three.js | このブログの読者になる | 更新情報をチェックする

2013年03月18日

ユーザ定義の THREE.UserCubes1 オブジェクトを使って、カメラでその周りを周回する



THREE.UserCubes1 は、複数のキューブを一つの Object3D にまとめたもので、作成メソッドと削除メソッドを持ちます。

実行ページ

コンストラクタ

❶ シーン
❷ キューブの基本サイズ ( 規定値 20 )
❸ キューブの数 ( 規定値 100 )
❹ 表示幅( 発生させる座標の範囲の長さ ) ( 規定値 : 800 )

その他

カメラのコンストラクタの最後の引数は、描画対象とする最も遠い距離で、この距離を超えた物体は描画されません。
<script type="text/javascript">
// 主となるライブラリを複数回ロードしない
if ( window['loadThree'] !== true ) {
	window['loadThree'] = true;
	document.write("<"+"script type=\"text/javascript\" src=\"http://homepage2.nifty.com/lightbox/three/three.min56.js\"></"+"script>");
}
</script>
<!-- ユーザ定義オブジェクト -->
<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/user_cubes1.js" charset="utf-8"></script>

<script type="text/javascript">

var w = 600;
var h = 500;

// 変数から表示エリアを作成
document.write("<div id=\"three_area\" style='width:"+w+"px;height:"+h+"px;'></div>");

// お決まり『三種の神器』
var camera, scene, renderer;

// 環境作成
init();

// ループ処理
animate();

// ****************************************************************
// 表示環境の準備( 開始は animate )
// ****************************************************************
function init() {

	// ********************************************************
	// 引数について : http://mrdoob.github.com/three.js/docs/56/#Reference/Cameras/PerspectiveCamera を参照、
	// 概念について : https://github.com/landongn/three.js-tutorials/tree/master/1 の画像を参照
	// FOV について : http://ja.wikipedia.org/wiki/%E7%94%BB%E8%A7%92 を参照
	// ********************************************************

	// カメラ作成
	camera = new THREE.PerspectiveCamera( 70, w / h, 1, 10000 );

	// ********************************************************
	// http://mrdoob.github.com/three.js/docs/56/#Reference/Math/Vector3
	// x、y、z は結局 render で決定する
	// ********************************************************
	camera.position.set( 0, 0, 0 );

	// シーン作成
	scene = new THREE.Scene();

	// ********************************************************
	// メインオブジェクト作成
	// 初期値 : cubeSize:20, cubeNum:100, displaySpan:800
	// 1) キューブの基本サイズ( 見た目は後でスケールで変化する )
	// 2) キューブの数
	// 3) 表示幅( 発生させる座標の範囲の長さ )
	// ********************************************************
	var UserCubes = new THREE.UserCubes1( scene );

	// Canvas レンダラー作成
	renderer = new THREE.CanvasRenderer();
	// 表示を定義サイズと一致させる
	renderer.setSize( w, h );

	// ********************************************************
	// 指定した DOM 内に 3D 表示用の空間を作成する
	// ********************************************************
	document.getElementById("three_area").appendChild( renderer.domElement );

}

function animate() {

	requestAnimationFrame( animate );
	render();

}

var radius = 600;
var theta = 0;

// ********************************************************
// 半径 600 で シーンの中心を周回する
// ********************************************************
function render() {

	theta += 0.1;

	// ************************************************
	// x が sin で、z が cos なので、周回軌道。(上から見たら半径600の円運動)
	// 但し、y は、その時の x の値と同じ値だけ上下
	// ( カメラから見たら、被写体が上に行ったり下に行ったりする )
	// ************************************************
	camera.position.x = radius * Math.sin( THREE.Math.degToRad( theta ) );
	camera.position.y = radius * Math.sin( THREE.Math.degToRad( theta ) );
	camera.position.z = radius * Math.cos( THREE.Math.degToRad( theta ) );

	// カメラをシーンの中心に向ける
	camera.lookAt( scene.position );

	// 実際の描画
	renderer.render( scene, camera );

}

</script>
関連する記事

Three.js では、複数のオブジェクトを一つの Object3D に追加して一括管理します。

関連する情報

カメラの引数
FOV( Wikipedia )
カメラの near と far 

位置オブジェクト(Vector3)


posted by at 2013-03-18 01:45 | Three.js | このブログの読者になる | 更新情報をチェックする

2013年03月03日

Three.js : カメラが発射する Ray(光) にヒットするオブジェクトを総取りする


ここから、実行ページを開きます( 但し、WebGL でのみ動作します )

カメラを使った当たり判定

要するに、マウスクリックに対する座標を使って、3D エリア内のオブジェクトとの当たり判定を行います。

画面に対して垂直に光線が進んで行き、その光線に触れたオブジェクトが最初に接した座標が一覧として取得できるようになっています。

※ ソース内では、intersects がそれです。

当たった位置に新しいオブジェクトを作成



この画像をテクスチャとして使って、球オブジェクトを作成して、画面内に複数のオブジェクトを追加して行きます。動作としてはクリックする毎に、その位置に表示されている立方体の手前の表面に球が埋め込まれて行くことになります。

このオブジェクトは、transparent: true が設定されており、PNG 画像が背景透過なので、画面内では口の中が奥まで見えて立方体の中に入った部分は見えたり見えなかったりします( 厳密な仕様は解りません )
※ 立方体側は、opacity: 0.5

画像は同一ドメインで

ご自分で再現する場合、ソースコードそのままでほぼ動作しますが、画像のみ同一ドメインである必要があります。WebGL での仕様だと思われますが、同一ドメインの画像を用意して下さい。( ここの画像をダウンロードして使って下さい )

ページ上の部分エリア用のクリック位置判定

Three.js の殆どのサンプルページはブラウザ上のページを全て使うので必要無いですが、実際の WEB ページでは、スクロールを考慮した DIV の位置よりクリックした位置を正確に計算する必要があります。その為、ちょっと面倒ですが以下のような処理を行っています
var parent = document.getElementById("three_area")
while (parent) {
	numx += parent.offsetLeft;
	numy += parent.offsetTop;
	parent = parent.offsetParent;
}
さらに、ブラウザによってスクロール距離の取得場所が違うので、現時点で以下のように書いています。( 将来的にはどうなるか解らないので注意 ) var top = document.documentElement.scrollTop + document.body.scrollTop
<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/three.min56.js"></script>
<div id="three_area" style='width:600px;height:500px;'></div>

<script type="text/javascript">
if( !( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )() ) {
	document.write("<span style='font-weight:bold;font-size:30px;'>WebGLが使用できません</span>");
	document.getElementById("three_area").style.display = 'none';
}

var w = 600;
var h = 500;
var numx = 0;
var numy = 0;

var container;
var camera, scene, projector, renderer;

var texture,material;

init();
animate();

function init() {

	camera = new THREE.PerspectiveCamera( 70, w / h, 1, 10000 );
	camera.position.set( 0, 300, 500 );

	scene = new THREE.Scene();

	var geometry = new THREE.CubeGeometry( 20, 20, 20 );

	for ( var i = 0; i < 1000; i ++ ) {

		var object = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, transparent: true,opacity: 0.5 } ) );
		object.position.x = Math.random() * 800 - 400;
		object.position.y = Math.random() * 800 - 400;
		object.position.z = Math.random() * 800 - 400;

		object.scale.x = Math.random() * 2 + 1;
		object.scale.y = Math.random() * 2 + 1;
		object.scale.z = Math.random() * 2 + 1;

		object.rotation.x = Math.random() * 2 * Math.PI;
		object.rotation.y = Math.random() * 2 * Math.PI;
		object.rotation.z = Math.random() * 2 * Math.PI;

		scene.add( object );

	}

	// Ray 判定用のプロジェクター
	projector = new THREE.Projector();

	renderer = new THREE.WebGLRenderer();
	renderer.setSize( w, h );

	document.getElementById("three_area").appendChild( renderer.domElement );

	document.addEventListener( 'mousedown', onDocumentMouseDown, false );

	var image = new Image()
	image.onload = function () {

		texture = new THREE.Texture( this );
		texture.needsUpdate = true;
		material = new THREE.MeshBasicMaterial({map: texture, transparent: true});
	};
	image.src = "http://lightbox.matrix.jp/imgpatio/smile.png";

	var parent = document.getElementById("three_area")
	while (parent) {
		numx += parent.offsetLeft;
		numy += parent.offsetTop;
		parent = parent.offsetParent;
	}


}

// *********************************************
// クリックした位置の Ray 判定 
// *********************************************
function onDocumentMouseDown( event ) {

	var top = document.documentElement.scrollTop + document.body.scrollTop

	event.preventDefault();

	// 対象座標のベクタ( 0.5 は 1 でも良いはず。意味が解りやすい 0.5 が使われている )
	var vector = new THREE.Vector3( (( event.clientX - numx ) / w ) * 2 - 1, - ( (event.clientY - (numy - top) ) / h ) * 2 + 1, 0.5 );
	projector.unprojectVector( vector, camera );

	// Ray 判定の本体
	var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );

	// 対象となるオブジェクトの一覧の取得
	var intersects = raycaster.intersectObjects( scene.children );

	if ( intersects.length > 0 ) {

		var mesh = null;

		for( var i = 0; i < intersects.length; i++ ) {

			// テクスチャ付の球オブジェクト
			mesh = new THREE.Mesh(new THREE.SphereGeometry(15, 20, 20), material);
			mesh.position = intersects[ i ].point;
			mesh.rotation.y = Math.random() * Math.PI * 2;
			scene.add(mesh);

		}

	}
}

function animate() {

	requestAnimationFrame( animate );
	render();

}

var radius = 600;
var theta = 0;

function render() {

	theta += 0.1;

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

	renderer.render( scene, camera );

}

</script>


posted by at 2013-03-03 08:00 | Three.js | このブログの読者になる | 更新情報をチェックする

2013年02月28日

Three.js の点線表示の詳細( 特に Windows で WebGL では線の太さは実装なし )

このコードは、WebGL と Canvas とを同じコードで同時に表示する為のものです。ですから、Chrome と Firefox では以下のように表示されますが、WebGL が動作しないブラウザでは、右側だけが表示されます



LineDashedMaterial と LineBasicMaterial

前者が新しいマテリアルですが、大きく違うのは geometry の computeLineDistances メソッドで、これを実行しないと点線になりません。何故そのような仕様なのかは解りませんが、実装されたばかりの仕様であるせいかもしれません。

参考

Drawing the coordinate axes | soledad penadés

また、Canvas か WebGL かでも結果は大きく違い、LineDashedMaterial において以下のようなデフォルト値になっているにもかかわらず、WebGL では(少し大きめに描画?)正確では無いようです。
this.dashSize = 3;
this.gapSize = 1;
linewidth が WebGL で無視される これは、LineDashedMaterial よりかなり前の LineBasicMaterial からの仕様のようで、そもそも Windows では動作しないという事が言われています。 参考 LineBasicMaterial.linewidth is ignored when using WebGLRenderer ・ Issue #269 ・ mrdoob/three.js ・ GitHub javascript - Thickness of lines using THREE.LineBasicMaterial - Stack Overflow 現状では、他の方法で表現するしか無いとは思いますが Canvas では動作するので、グラフ表示等では Canvas を使うのがもともと現実的かと思います。 clearColor と clearAlpha について これらは、WebGL で利用できるものですが、実行画像を見てもらえれば一目瞭然です。clearColor は背景色で、clearAlpha はその背景色をどの程度透過するかのパラメータです。( 1 で不透過 ) Line オブジェクトのデフォルトは THREE.LineStrip ここでは、THREE.LinePieces が使用されていますが、THREE.LineStrip で点座標を連続してつないで線が描画(ひとふでがき)されます。しかし、THREE.LinePieces では、2つづつのペアで線が引かれるので、座標が並んでいるとしたら点線になります。
<style type="text/css">
body {
  background: url(https://lh4.googleusercontent.com/-qGsOjUoCvyw/T-VZ62iPMSI/AAAAAAAAG5Y/O0NhvMUvm9U/s200/_img.png);
  font-size: 30px;
}

span {
    color: #ffffff;
    font-weight:bold;
}
</style>
<div id="container"></div>

<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/three.min56.js"></script>
<script type="text/javascript">
var webgl_flg = true;
if( !( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )() ) {
    webgl_flg = false;
}


var scene, camera;
var object;

// WebGLRenderer
var renderer

// CanvasRenderer
var renderer2;


var WIDTH = 250,
    HEIGHT = 250;

init();
animate();

function init() {
    
    camera = new THREE.PerspectiveCamera( 60, WIDTH / HEIGHT, 1, 200 );
    camera.position.z = 150;
    
    scene = new THREE.Scene();
    
    var geometryCube = cube( 50 );

    // LineDashedMaterial で必要
    geometryCube.computeLineDistances();
    
    object = new THREE.Line( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 3, gapSize: 1, linewidth: 5  } ), THREE.LinePieces );
    
    scene.add( object );

    if ( webgl_flg ) {    
	    renderer = new THREE.WebGLRenderer( { clearColor: 0x111111, clearAlpha: 0.8, antialias: true } );
	    renderer.setSize( WIDTH, HEIGHT );
    }

    renderer2 = new THREE.CanvasRenderer( );
    renderer2.setSize( WIDTH, HEIGHT );
    
    var container = document.getElementById( 'container' );
    if ( webgl_flg ) {    
        container.appendChild( renderer.domElement );
    }
    container.appendChild( renderer2.domElement );
    
    
}

function cube( size ) {
    
    var h = size * 0.5;
    
    var geometry = new THREE.Geometry();
    
    geometry.vertices.push( new THREE.Vector3( -h, -h, -h ) );
    geometry.vertices.push( new THREE.Vector3( -h, h, -h ) );
    
    geometry.vertices.push( new THREE.Vector3( -h, h, -h ) );
    geometry.vertices.push( new THREE.Vector3( h, h, -h ) );
    
    geometry.vertices.push( new THREE.Vector3( h, h, -h ) );
    geometry.vertices.push( new THREE.Vector3( h, -h, -h ) );
    
    geometry.vertices.push( new THREE.Vector3( h, -h, -h ) );
    geometry.vertices.push( new THREE.Vector3( -h, -h, -h ) );
    
    
    geometry.vertices.push( new THREE.Vector3( -h, -h, h ) );
    geometry.vertices.push( new THREE.Vector3( -h, h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( -h, h, h ) );
    geometry.vertices.push( new THREE.Vector3( h, h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( h, h, h ) );
    geometry.vertices.push( new THREE.Vector3( h, -h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( h, -h, h ) );
    geometry.vertices.push( new THREE.Vector3( -h, -h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( -h, -h, -h ) );
    geometry.vertices.push( new THREE.Vector3( -h, -h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( -h, h, -h ) );
    geometry.vertices.push( new THREE.Vector3( -h, h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( h, h, -h ) );
    geometry.vertices.push( new THREE.Vector3( h, h, h ) );
    
    geometry.vertices.push( new THREE.Vector3( h, -h, -h ) );
    geometry.vertices.push( new THREE.Vector3( h, -h, h ) );
    
    return geometry;
    
}


function animate() {
    
    requestAnimationFrame( animate );
    
    render();
    
}

function render() {
    
    var time = Date.now() * 0.001;
    
    object.rotation.x = 0.25 * time;
    object.rotation.y = 0.25 * time;
    
    if ( webgl_flg ) {    
        renderer.render( scene, camera );
    }
    renderer2.render( scene, camera );
    
}</script>
Three.js リファレンス

http://mrdoob.github.com/three.js/docs

関連する記事

Three.js(r53) で追加された LineDashedMaterial のサンプルを簡素化して解りやすくしました



posted by at 2013-02-28 10:00 | Three.js | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します


Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX