ピラミッドの回転

ピラミッド(3D立体図形)の表示には数学的な計算が必要です。3次元の図形を2次元の平面状に表示する理論については「3D描画の基礎知識」を参考にして下さい。

ピラミッドの垂直回転

ピラミッドを垂直回転させてみましょう。
下のViewbox内でマウスを押下した状態で上下に動かしてみて下さい。奥行方向がy軸方向で手前方向がマイナスです。また回転は前方が下がる方向がマイナスの角度です。
ピラミッドのサイズは横(x) x 縦(y) x 高さ(z) = 200 x 200 x 100 pxです。
各面の表示順は背面、左右の面、前面の順番です。
陰面処理をしていないので、背面(青色)が他の面よりも前面になった時でも背面が隠れてしまいます。
135°~ -135°の間は正しく表示されます。とりあえずここでは0°~-90°で正しく表示できれば良しとします。
各頂点の座標の計算は、初期の座標に対して回転角度による3Dのビュー変換(座標変換を参照)を計算して、各頂点にセットしています。 初期の座標を記憶しておく方法は色々ありますが、ここでは以下のようにpathノードの中にpointsという本来含まれない属性(pointsとは別の名前でもよい)を記述し、その中に各点のx、y、z座標の値を入れておきます。順番はdに設定されている頂点の順番と同じにしておきます。
   <path id="angle4" d="M 0,100 L -100,0 100,0" fill="#F00"
         points="0,0,100 -100,-100,0 100,-100,0"/>
投射図を計算する場合はgetAttributeメソッドで
var attrPoints = angle.getAttribute("points");
というようにしてpoints全体の値を取得します。
他に各点の記憶方法として他にいい方法があればその方法でもかまいません。
pointsの値を取得後、1回目のsplitメソッドで各点に分け、2回目のsplitメソッドでx,y,zの各値を取得し回転角度を用いて3Dアフィン変換を行います。
三角形を形成するタグpathのdの内容はNode.pathSegList.getItem(index)でindexの値を0から順番インクリメントして各点のSVGPathSeg属性のオブジェクトを得ることができます。各点のデータは例えば各点のSVGPathSeg属性をpointとすると x = point.x、y = point.yとして得られます。
今回は上下方向だけの回転なので、図形を変形するためにはpoint.yの値を変更するだけです。
point.y = 変形後の値
属性の値を変更すると直ちにSVGに反映されます..........?
ところがIEの場合変更が反映されません。W3Cの仕様では以下のようになっています。

8.5.21 Interface SVGPathSegList
の中で
SVGPathSeg getItem(in unsigned long index)
  Returns the specified item from the list. The returned item is the item itself and not a copy. Any changes made to the item are immediately reflected in the list.

FirefoxとGoogle Chromeでは仕様通り正しく図形が変更されます。Microsoftの手抜きだと思われます。(2013/2/1時点)
そのためd属性全体を直接変更して図形を変更するようにしました。
このサンプルの目的は、初期値の記憶方法と3Dビュー変換(アフィン変換)と図形の変形のテクニックの確認です。

x軸の回転Δθ = 0° /* visible/hidden */ /* 上 */ /* 左 */ /* 右 */ /* 下 */ O x z /* visible/hidden */ /* X axis & Arrow */ /* Z axis & Arrow */


陰面処理(描画順番)を考慮したピラミッドの垂直回転

前の例の場合ピラミッドを垂直回転した時に、赤の面が常に全面に表示されるため、うまく回転されていませんでした。視点からの距離により描画順番を変更するようにしてみましょう。これは陰面処理の中の塗り重ね法に当たります。
各三角形の視点からの距離の代表値として重心を使用することにし、描画順番は距離の大きい図形から描画し視点に一番近い図形が最後に手前に表示するようにします。ただし、今回は各面の形状が三角形だけなので、視点からの距離の順番を計算するのに重心を計算する必要はなく、3つの頂点の奥行(y軸)方向の合計値を比較することで計算できます。
左上の2行目が三角形の描画順番です。
このサンプルの目的は、重心による描画順番の計算方法と変更のテクニックの確認です。

x軸の回転Δθ = 0° 1,2,3,4 /* visible/hidden */ /* 上 */ /* 左 */ /* 右 */ /* 下 */ O x z /* visible/hidden */ /* X axis & Arrow */ /* Z axis & Arrow */


裏面を考慮したピラミッドの垂直回転

裏面を考慮してピラミッドを垂直回転させてみましょう。前の例では、ピラミッドの表と裏側の色が同じため、ピラミッドの表面が表示された時と裏表が表示された時の区別がつきませんでした。裏面が表示された時は色を暗くするようにしてみましょう。
視点に対して表面か裏面かは法線ベクトルが視点に対して負か正かで判断します。法線ベクトルの正負の判別は、法線ベクトルのy軸方向の値を計算することにより判別できます。法線ベクトルのy軸方向の値は、ny = (z3 - z2)(x1 - x2)-(x3 - x2)(z1 - z2)です。この値が負の場合、表面が視点の方向に向いています。
左上の3行目が各三角形の法線ベクトルの正( = 1)負( = 0)のフラグです。
このサンプルの目的は、法線ベクトルを利用して面の向きを計算し描画処理するテクニックの確認です。

x軸の回転Δθ = 0° 1,2,3,4 1,0,0,0 /* visible/hidden */ /* 上 */ /* 左 */ /* 右 */ /* 下 */ O x z /* visible/hidden */ /* X axis & Arrow */ /* Z axis & Arrow */


ピラミッドの水平・垂直回転

ではいよいよピラミッドを水平・垂直に回転させてみましょう。今までのものに対してz軸の回転を追加するだけです。z軸の反時計回りが正になるのに注意が必要です。
このサンプルの目的は、水平・垂直回転のテクニックの確認です。

x軸の回転Δθx = 0° z軸の回転Δθz = 0° 1,2,3,4 1,0,0,0 /* visible/hidden */ /* 上 */ /* 左 */ /* 右 */ /* 下 */ O x z /* visible/hidden */ /* X axis & Arrow */ /* Z axis & Arrow */
 

最終更新のRSS
Last-modified: 2015-08-30 (日) 19:41:37 (3322d)