ポリゴンテスト解説・x3dom使い方



NAS6LIB

ポリゴンテスト & NAS6LIB ヘルプ ドキュメント.htm

ポリゴンテスト & NAS6LIB ヘルプ ドキュメント.zip

同次座標がw,x,y,z,...の順番で定義されたものの説明です。順番が違うだけで、機能に変わりはありませんが・・・

・./testpoly.htm


<!DOCTYPE html>
<html lang="ja">
<head>
<title>ポリゴンテスト & NAS6LIB ヘルプ ドキュメント</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<script language="JavaScript" type="text/javascript" src="./javascripts/x3dom/jquery-2.1.4.min.js" ></script>
<link rel='stylesheet' type='text/css' href='./javascripts/x3dom/x3dom.css'>
<script language="JavaScript" type='text/javascript' src='./javascripts/x3dom/x3dom.js'> </script>
<link rel='stylesheet' type='text/css' href='./javascripts/x3dom/x3dom.css'>


<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/timer.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/vector.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/matrix.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/quaternion.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6/help.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6/testpoly.js"></script>

<style>
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section { display: block; }
#x3dabs{
    position: absolute;
    float: left;
    top: 76px;
    left: 20px;
    background:#8080b0;
    border: 2px #000000 solid;
}
</style>
</head>
<body text="black" link="#3333cc" vlink="#663399" alink="#cc0000" bgcolor="#faebf1" background="./img/kumausagineko.jpg">
<b>
<h1>ポリゴンテスト & NAS6LIB ヘルプ ドキュメント</h1>

<div style = 'width:500px; height:250px; border: 0px; overflow:hidden;'>

<x3d id='x3dabs' width='500px' height='250px'>
    <scene>
        <Viewpoint id='viewp001' position='0 3 20' orientation='0 1 0 0' description='camera'></Viewpoint>

	<directionalLight id="directional" direction='1 -1 1' on ="TRUE" intensity='1.0' shadowIntensity='0.0'></directionalLight> 
	
        <Transform center='0 0 0' translation='0 0 8' id='box0' DEF='box0'>
            <Transform rotation='0 1 0 0' id='box1' DEF='box1'>
            <shape>
                <appearance>
                    <ImageTexture  url="./img/koala.jpg"></ImageTexture>
                    <material diffuseColor='0.8 0.8 0.8'></material>
                </appearance>
                <Box size = '5 5 5'></Box>
            </shape>
            </Transform>
        </Transform>
    </scene>
</x3d>
</div>

// ……… 中 略 ………

</b>
</font>
</body>
</html>



・./javascripts/nas6/testpoly.js


var TMan = new N6LTimerMan();  //timer manager//タイマーマネージャー
jQuery(document).ready(function(){
  TMan.add();
  TMan.timer[0].setalerm(function() { GLoop(0); }, 50);  //set main loop//メインループセット
});

var bx = new N6LVector(new Array('1','0','0','8'), true);  //pos Box//Box座標
var bm = new N6LMatrix(4).UnitMat();  //mat Box//Box回転行列

//main loop//メインループ
function GLoop(id){

// ……… 中 略 ………

  var MatWK = new N6LMatrix(4).UnitMat();
  var v = new N6LVector(4, false);
  //unit vector//単位ベクトル
  var ax = new N6LVector(4, true).UnitVec(1);
  var ay = new N6LVector(4, true).UnitVec(2);
  var az = new N6LVector(4, true).UnitVec(3);

  //rot mov obj//物体回転移動
  MatWK = MatWK.RotAxis(ay, 1.0 * Math.PI / 180.0);  //around y axis rotate 1 degree//y軸回りに1度回転する回転行列を乗算
  bx = MatWK.Mul(bx);  //pos Box multiply matrix//Box座標に回転行列を乗算して更新

  //unit vector//単位ベクトル
  ax = ax.UnitVec(1);
  ay = ay.UnitVec(2);
  az = az.UnitVec(3);
  //rot obj//物体回転
  MatWK = new N6LMatrix(bm);  //mat Box//Box回転行列
  MatWK = MatWK.RotAxis(az, 3.0 * Math.PI / 180.0);  //around z axis rotate 3 degree//z軸回りに3度回転する回転行列を乗算
  MatWK = MatWK.RotAxis(ay, 2.0 * Math.PI / 180.0);  //around y axis rotate 2 degree//y軸回りに2度回転する回転行列を乗算
  bm = MatWK.RotAxis(ax, 1.0 * Math.PI / 180.0);     //around x axis rotate 1 degree//x軸回りに1度回転する回転行列を乗算

  v = bm.Vector();  //rot vector//回転行列から回転ベクトルを取得

  var angle = bm.EulerAngle(3, 2, 1);  //rotate order ZYX //回転順番 ZYX

// ↑ 前 半 : ↓ 後 半

  //apply x3dom
  var pos = bx.ToX3DOM(true);
  var elm = document.getElementById('box0');
  elm.setAttribute('translation', pos.toString());
  var rot = v.ToX3DOM();
  elm = document.getElementById('box1');
  elm.setAttribute('rotation', rot.toString());

  //debug//デバッグ用
  elm = document.getElementById('debug');
  elm.innerText = 
  'EulerAngle(rotate per degree z(3)_y(2)_x(1))\n' + angle.x[0] + ' ' + Math.floor(angle.x[1] * 180.0 / Math.PI) + ' ' + Math.floor(angle.x[2] * 180.0 / Math.PI) + ' ' + Math.floor(angle.x[3] * 180.0 / Math.PI); 

  TMan.timer[id].setalerm(function() { GLoop(id); }, 50);  //reset main loop//メインループ再セット
}

// ……… 後 略 ………



・ヘッダの書き方


<head>
<title>タイトルを入れてください</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">

<script language="JavaScript" type="text/javascript" src="./javascripts/x3dom/jquery-2.1.4.min.js" ></script>
<link rel='stylesheet' type='text/css' href='./javascripts/x3dom/x3dom.css'>
<script language="JavaScript" type='text/javascript' src='./javascripts/x3dom/x3dom.js'> </script>
<link rel='stylesheet' type='text/css' href='./javascripts/x3dom/x3dom.css'>


<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/timer.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/vector.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/matrix.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6lib/quaternion.js"></script>
<script language="JavaScript" type="text/javascript" src="./javascripts/nas6/testpoly.js"></script>

<style>
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section { display: block; }
#x3dabs{
    position: absolute;
    float: left;
    top: 76px;
    left: 20px;
    background:#8080b0;
    border: 2px #000000 solid;
}
</style>
</head>



これはほとんどコピペでいいです


・オブジェクトの書き方


<div style = 'width:500px; height:250px; border: 0px; overflow:hidden;'>

<x3d id='x3dabs' width='500px' height='250px'>
    <scene>
        <Viewpoint id='viewp001' position='0 3 20' orientation='0 1 0 0' description='camera'></Viewpoint>

	<directionalLight id="directional" direction='1 -1 1' on ="TRUE" intensity='1.0' shadowIntensity='0.0'></directionalLight> 
	
        <Transform center='0 0 0' translation='0 0 8' id='box0' DEF='box0'>
            <Transform rotation='0 1 0 0' id='box1' DEF='box1'>
            <shape>
                <appearance>
                    <ImageTexture  url="./img/koala.jpg"></ImageTexture>
                    <material diffuseColor='0.8 0.8 0.8'></material>
                </appearance>
                <Box size = '5 5 5'></Box>
            </shape>
            </Transform>
        </Transform>
    </scene>
</x3d>
</div>



<div>で<x3d>をくくっているのは、レイアウト合わせのためです

orientationやrotationは回転ベクトルなのでN6LMatrixで行列計算をしたら
N6LMatrix.Vector();で回転ベクトルに変換したのを入れましょう

オブジェクトはBoxやSphereなど色々あります
くわしくはx3dom本家を見てください

<transform>で<shape>を2回くくっているのは
外側の<transform>で平行移動して内側の<transform>でその場で回転するためです


・メインループを登録する


var TMan = new N6LTimerMan();  //タイマーマネージャー
jQuery(document).ready(function(){
  TMan.add();
  TMan.timer[0].setalerm(function() { GLoop(0); }, 50);  //メインループセット
});



グローバルスコープに
var TMan = new N6LTimerMan(); //タイマーマネージャー
タイマーマネージャーを構築します

ページリロード時に、メインループを登録するとして
jQuery(document).ready(function(){});
をいじります

タイマーマネージャーに0番目のタイマーTMan.timer[0]を構築するため、TMan.add();をします

TMan.timer[0].setalerm(function() { GLoop(0); }, 50); //メインループセット

function() { GLoop(0); }でメインループをsetalerm();で登録してください
50は50ミリ秒後、メインループを呼び出しますという意味です


・メインループを実装する


var bx = new N6LVector(new Array('1','0','0','8'), true);  //pos Box//Box座標
var bm = new N6LMatrix(4).UnitMat();  //mat Box//Box回転行列

//main loop//メインループ
function GLoop(id){

// ……… 中 略 ………

  var MatWK = new N6LMatrix(4).UnitMat();
  var v = new N6LVector(4, false);
  //unit vector//単位ベクトル
  var ax = new N6LVector(4, true).UnitVec(1);
  var ay = new N6LVector(4, true).UnitVec(2);
  var az = new N6LVector(4, true).UnitVec(3);

  //rot mov obj//物体回転移動
  MatWK = MatWK.RotAxis(ay, 1.0 * Math.PI / 180.0);  //around y axis rotate 1 degree//y軸回りに1度回転する回転行列を乗算
  bx = MatWK.Mul(bx);  //pos Box multiply matrix//Box座標に回転行列を乗算して更新

  //unit vector//単位ベクトル
  ax = ax.UnitVec(1);
  ay = ay.UnitVec(2);
  az = az.UnitVec(3);
  //rot obj//物体回転
  MatWK = new N6LMatrix(bm);  //mat Box//Box回転行列
  MatWK = MatWK.RotAxis(az, 3.0 * Math.PI / 180.0);  //around z axis rotate 3 degree//z軸回りに3度回転する回転行列を乗算
  MatWK = MatWK.RotAxis(ay, 2.0 * Math.PI / 180.0);  //around y axis rotate 2 degree//y軸回りに2度回転する回転行列を乗算
  bm = MatWK.RotAxis(ax, 1.0 * Math.PI / 180.0);     //around x axis rotate 1 degree//x軸回りに1度回転する回転行列を乗算

  v = bm.Vector();  //rot vector//回転行列から回転ベクトルを取得

  var angle = bm.EulerAngle(3, 2, 1);  //rotate order ZYX //回転順番 ZYX

// ↑ 前 半 : ↓ 後 半

  //apply x3dom
  var pos = bx.ToX3DOM(true);
  var elm = document.getElementById('box0');
  elm.setAttribute('translation', pos.toString());
  var rot = v.ToX3DOM();
  elm = document.getElementById('box1');
  elm.setAttribute('rotation', rot.toString());

  //debug//デバッグ用
  elm = document.getElementById('debug');
  elm.innerText = 
  'EulerAngle(rotate per degree z(3)_y(2)_x(1))\n' + angle.x[0] + ' ' + Math.floor(angle.x[1] * 180.0 / Math.PI) + ' ' + Math.floor(angle.x[2] * 180.0 / Math.PI) + ' ' + Math.floor(angle.x[3] * 180.0 / Math.PI); 

  TMan.timer[id].setalerm(function() { GLoop(id); }, 50);  //reset main loop//メインループ再セット
}



前半でNAS6LIBを使って回転行列計算をします
orientationやrotationは回転ベクトルなのでN6LMatrixで行列計算をしたら
N6LMatrix.Vector()で回転ベクトルに変換したのを入れましょう

後半でx3domに値を適用します
NAS6LIBは同次座標だとw,x,y,z...の順番で、x3domはx,y,z,w...の順番なので注意しましょう
N6LVector.ToX3DOM(b)で、SFVecXfに変換します。b=trueにするとVectorの次数が4→3になります。
N6LVector.FromX3DOM(sf)で、sf=SFVecXfから変換します。
N6LMatrix.ToX3DOM()で、SFMatrix4fに変換します。
N6LMatrix.FromX3DOM(sf)で、sf=SFMatrix4fから変換します。

document.getElementById();でエレメントを取得して
setAttribute('変更する名前', SFVecXf.toString());でx3domに値を適用しましょう

最後に
TMan.timer[id].setalerm(function() { GLoop(id); }, 50); //reset main loop//メインループ再セット
でメインループを再セットして完了です


バグりそうな目星(うっかりするところ):
・ゼロ除算、-の根、undefined
・値や絶対値の1.0オーバー(ノーマライズされていない、逆三角関数の範囲外、など)
・objA = new N6LType(objB);とするところを、objA = objB;としてしまって、ディープコピーのし忘れ
・bHomoフラグ関連(bHomoが同次座標行列N6LMatrixの各行のN6LVectorはfalseなのに対して
それを軸として取り出そうとするときは、.SetHomo(true)をして
その後、元の行列を使うときは、.SetHomo(false)をしなければならない、など)
*SetHomo()がバグの元なので、その実行でthisの変更するのをやめて、戻り値を返す方式にした
*行や列の操作に、より安全なGet/Set-Col/Row()関数を用意した





3Dプログラミング講座
NAS6LIB
ポリゴンテスト解説・x3dom使い方
その1:ベクトル
その2:行列
その3:クォータニオン
その4:基本総復習・実践
その5:応用その1・メッシュアニメーション、動的テクスチャ
その6:応用その2・GLSL、カスタムシェーダー、キーボード、ファイル
その7:応用その3・ゲームプログラミング、タグの動的追加
その8:応用その4・GLSL、シェーダー、その2

<<prev 戻る : ベクトル next>>





戻る