root/samples/tokoi/sprite1/trackball.php

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qmul
  2. qrot
  3. Init
  4. Region
  5. Start
  6. Motion
  7. Stop
  8. 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;
    }
}

/* [<][>][^][v][top][bottom][index][help] */