/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- qmul
- qrot
- Init
- Region
- Start
- Motion
- Stop
- Rotation
<?php
class trackball {
/* ドラッグ開始位置 */
static $cx = 0, $cy = 0;
/* マウスの絶対位置→ウィンドウ内での相対位置の換算係数 */
static $sx = 0.0;
static $sy = 0.0;
/* マウスの相対位置→回転角の換算係数 */
const SCALE = 6.2831853070; // 2 * M_PI;
/* 回転の初期値 (クォータニオン) */
static $cq = array( 1.0, 0.0, 0.0, 0.0 );
/* ドラッグ中の回転 (クォータニオン) */
static $tq = array(0.0, 0.0, 0.0, 0.0);
/* 回転の変換行列 */
static $rt = array (
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0,
);
/* ドラッグ中か否か */
static $drag = 0;
/*
** r <- p x q
*/
function qmul(&$r, $p, $q)
{
$r[0] = $p[0] * $q[0] - $p[1] * $q[1] - $p[2] * $q[2] - $p[3] * $q[3];
$r[1] = $p[0] * $q[1] + $p[1] * $q[0] + $p[2] * $q[3] - $p[3] * $q[2];
$r[2] = $p[0] * $q[2] - $p[1] * $q[3] + $p[2] * $q[0] + $p[3] * $q[1];
$r[3] = $p[0] * $q[3] + $p[1] * $q[2] - $p[2] * $q[1] + $p[3] * $q[0];
}
/*
** 回転変換行列 r <- クォータニオン q
*/
function qrot(&$r, $q)
{
$x2 = $q[1] * $q[1] * 2.0;
$y2 = $q[2] * $q[2] * 2.0;
$z2 = $q[3] * $q[3] * 2.0;
$xy = $q[1] * $q[2] * 2.0;
$yz = $q[2] * $q[3] * 2.0;
$zx = $q[3] * $q[1] * 2.0;
$xw = $q[1] * $q[0] * 2.0;
$yw = $q[2] * $q[0] * 2.0;
$zw = $q[3] * $q[0] * 2.0;
$r[ 0] = 1.0 - $y2 - $z2;
$r[ 1] = $xy + $zw;
$r[ 2] = $zx - $yw;
$r[ 4] = $xy - $zw;
$r[ 5] = 1.0 - $z2 - $x2;
$r[ 6] = $yz + $xw;
$r[ 8] = $zx + $yw;
$r[ 9] = $yz - $xw;
$r[10] = 1.0 - $x2 - $y2;
$r[ 3] = $r[ 7] = $r[11] = $r[12] = $r[13] = $r[14] = 0.0;
$r[15] = 1.0;
}
/*
** トラックボール処理の初期化
** プログラムの初期化処理のところで実行する
*/
function Init()
{
/* ドラッグ中ではない */
self::$drag = 0;
/* 単位クォーターニオン */
$cq = array(1.0, 0.0, 0.0, 0.0);
/* 回転行列の初期化 */
qrot(self::$rt, $cq);
}
/*
** トラックボールする領域
** Reshape コールバック (resize) の中で実行する
*/
function Region($w, $h)
{
/* マウスポインタ位置のウィンドウ内の相対的位置への換算用 */
self::$sx = 1.0 / $w;
self::$sy = 1.0 / $h;
}
/*
** ドラッグ開始
** マウスボタンを押したときに実行する
*/
function Start($x, $y)
{
/* ドラッグ開始 */
self::$drag = 1;
/* ドラッグ開始点を記録 */
self::$cx = $x;
self::$cy = $y;
}
/*
** ドラッグ中
** マウスのドラッグ中に実行する
*/
function Motion($x, $y)
{
if (self::$drag) {
/* マウスポインタの位置のドラッグ開始位置からの変位 */
$dx = ($x - self::$cx) * self::$sx;
$dy = ($y - self::$cy) * self::$sy;
/* マウスポインタの位置のドラッグ開始位置からの距離 */
$a = sqrt($dx * $dx + $dy * $dy);
if ($a != 0.0) {
$ar = $a * self::SCALE * 0.5;
$as = sin($ar) / $a;
$dq = array( cos($ar), $dy * $as, $dx * $as, 0.0 );
/* クォータニオンを掛けて回転を合成 */
self::qmul($tq, $dq, self::$cq);
/* クォータニオンから回転の変換行列を求める */
self::qrot(self::$rt, self::$tq);
}
}
}
/*
** 停止
** マウスボタンを離したときに実行する
*/
function Stop($x, $y)
{
/* ドラッグ終了点における回転を求める */
self::Motion($x, $y);
/* 回転の保存 */
self::$cq = self::$tq;
/* ドラッグ終了 */
self::$drag = 0;
}
function Rotation()
{
/* 回転の変換行列 */
return self::$rt;
}
}