package jp.sourceforge.acerola3d.a3viewer;

import jp.sourceforge.acerola3d.a3.*;
import java.awt.event.*;
import javax.media.j3d.*;
import javax.vecmath.*;

class MyExamController extends A3Controller {
    //注視点
    Vector3d fixationPoint= new Vector3d(0.0,1.0,0.0);
    double distance = 3.0;
    Quat4d cameraQuat = new Quat4d(0.0,0.0,0.0,1.0);
    int lastMouseX;
    int lastMouseY;
    /**
     * 初期化します．
     */
    public void init() {
        fixationPoint.set(0.0,1.0,0.0);
        distance = 3.0;
        cameraQuat.set(0.0,0.0,0.0,1.0);
        setCamera();
    }
    /**
     * リセットします．
     */
    public void reset(Action3D a3) {
        Node n = a3.getNode();
        Bounds b = n.getBounds();
        if (b instanceof BoundingSphere) {
            BoundingSphere bs = (BoundingSphere)b;
            Point3d p = new Point3d();
            bs.getCenter(p);
            double r = bs.getRadius();
            if (r>0.0) {
                fixationPoint.set(p);
                distance = r*2.5;
            } else {
                fixationPoint.set(0.0,1.0,0.0);
                distance = 3.0;
            }
        } else {
            fixationPoint.set(0.0,1.0,0.0);
            distance = 3.0;
        }
        cameraQuat.set(0.0,0.0,0.0,1.0);
        setCamera();
    }
    /**
     * マウスが押された時のイベントをキャッチします。
     */
    public void mousePressed(A3Event ae) {
        MouseEvent me = ae.getMouseEvent();
        lastMouseX = me.getX();
        lastMouseY = me.getY();
    }

    /**
     * マウスがドラッグされた時のイベントをキャッチします。
     */
    public void mouseDragged(A3Event ae) {
        MouseEvent me = ae.getMouseEvent();
        int shiftX = me.getX() - lastMouseX;
        int shiftY = me.getY() - lastMouseY;
        if ((me.getModifiersEx()&MouseEvent.BUTTON1_DOWN_MASK)!=0) {
            //回転
            Quat4d q0 = new Quat4d(0.0,0.0,0.0,1.0);
            double t = - shiftX * 0.01;
            Quat4d q1 = new Quat4d(0.0,Math.sin(t),0.0,Math.cos(t));
            t = - shiftY * 0.01;
            Quat4d q2 = new Quat4d(Math.sin(t),0.0,0.0,Math.cos(t));
            q0.mul(q1);
            q0.mul(q2);
            cameraQuat.mul(q0);
        } else if ((me.getModifiersEx()&MouseEvent.BUTTON2_DOWN_MASK)!=0) {
            //平行移動(Shift+で奥行も)
            Vector3d v = a3canvas.virtualCSToPhysicalCS(fixationPoint);
            Tuple3d shift = a3canvas.canvasToPhysicalCS(lastMouseX,lastMouseY,-v.z); 
            shift.sub(a3canvas.canvasToPhysicalCS(me.getX(),me.getY(),-v.z));
            if ((me.getModifiers()&MouseEvent.SHIFT_MASK)!=0) {
                shift.set(shift.x,0.0,-shift.y);
            }
            Vector3d vx = a3canvas.getCameraUnitVecX();
            Vector3d vy = a3canvas.getCameraUnitVecY();
            Vector3d vz = a3canvas.getCameraUnitVecZ();
            vx.scale(shift.x);
            vy.scale(shift.y);
            vz.scale(shift.z);
            fixationPoint.add(vx);
            fixationPoint.add(vy);
            fixationPoint.add(vz);
        } else if ((me.getModifiersEx()&MouseEvent.BUTTON3_DOWN_MASK)!=0) {
            //拡大縮小
            distance = distance*(100+shiftY)/100.0;
        }
        setCamera();
        lastMouseX = me.getX();
        lastMouseY = me.getY();
    }

    void setCamera() {
        Quat4d tmpQ = new Quat4d(0.0,0.0,1.0,0.0);
        Quat4d cameraQuatC = new Quat4d();
        cameraQuatC.conjugate(cameraQuat);
        tmpQ.mul(cameraQuat,tmpQ);
        tmpQ.mul(cameraQuatC);
        tmpQ.scale(distance);
        Vector3d tmpV = new Vector3d(fixationPoint);
        tmpV.set(tmpV.x+tmpQ.x,tmpV.y+tmpQ.y,tmpV.z+tmpQ.z);
        a3canvas.setCameraLocImmediately(tmpV);
        a3canvas.setCameraQuatImmediately(cameraQuat);
        a3canvas.setCameraScaleImmediately(distance/2.0);
    }

    /**
     * マウスがリリースされた時のイベントをキャッチします。
     */
    public void mouseReleased(A3Event e) {
    }

    /**
     * マウスがクリックされた時のイベントをキャッチします。
     */
    public void mouseClicked(A3Event ae) {
    }

    /**
     * マウスがダブルクリックされた時のイベントをキャッチします。
     */
    public void mouseDoubleClicked(A3Event ae) {
        ;
    }

    /**
     * キーボードが押された時のイベントをキャッチします。
     */
    public void keyPressed(KeyEvent e) {
    }

    /**
     * キーボードが離された時のイベントをキャッチします。
     */
    public void keyReleased(KeyEvent e) {
    }

    /**
     * キーボードがタイプされた時のイベントをキャッチします。
     */
    public void keyTyped(KeyEvent e) {
    }
}
