// List of Camera3D.java

import java.math.*;


/** Camera3Dクラス
 * 
 * @author  Satoshi Kitade
 * @version 1.1, 04/08/20
 */
public class Camera3D extends Object implements GeomDefs {

	/** カメラ位置 */
	private Vector3D m_vecPos;
	/** 注視点座標 */
	private Vector3D m_vecLookPos;
	/** 回転変換行列の列ベクトル */
	private Vector3D m_vecTrans[] = new Vector3D[VECNUM_TRANS];

	/** カメラベクトル */
	private Vector3D m_vecCam;


	/** コンストラクタ */
	public Camera3D() {
		m_vecPos = new Vector3D();
		m_vecLookPos = new Vector3D();
		m_vecTrans[0] = new Vector3D();
		m_vecTrans[1] = new Vector3D();
		m_vecTrans[2] = new Vector3D();
		m_vecCam = new Vector3D();
		calcTransMatrix();
	}

	/** コンストラクタ */
	public Camera3D(Vector3D vecPos, Vector3D vecLookPos) {
		m_vecPos = new Vector3D(vecPos);
		m_vecLookPos = new Vector3D(vecLookPos);
		m_vecTrans[0] = new Vector3D();
		m_vecTrans[1] = new Vector3D();
		m_vecTrans[2] = new Vector3D();
		m_vecCam = new Vector3D();
		calcTransMatrix();
	}

	/** コンストラクタ */
	public Camera3D(float fVert[]) {
		m_vecPos = new Vector3D(fVert[0], fVert[1], fVert[2]);
		m_vecLookPos = new Vector3D(fVert[3], fVert[4], fVert[5]);
		m_vecTrans[0] = new Vector3D();
		m_vecTrans[1] = new Vector3D();
		m_vecTrans[2] = new Vector3D();
		m_vecCam = new Vector3D();
		calcTransMatrix();
	}


	/** カメラベクトルを返す */
	public final Vector3D getVecCam() {
		return m_vecCam;
	}

	/** カメラ位置を設定 */
	public final void setPos(Vector3D vecPos) {
		m_vecPos.set(vecPos);
		calcTransMatrix();
	}
	/** カメラ位置ベクトルを設定 */
	public final void setVecPos(Vector3D vecPos) {
		m_vecPos = vecPos;
		calcTransMatrix();
	}
	/** カメラ位置ベクトルを返す */
	public final Vector3D getVecPos() {
		return m_vecPos;
	}

	/** 注視点を設定 */
	public final void setLookPos(Vector3D vecLookPos) {
		m_vecLookPos.set(vecLookPos);
		calcTransMatrix();
	}
	/** 注視点位置ベクトルを設定 */
	public final void setVecLookPos(Vector3D vecLookPos) {
		m_vecLookPos = vecLookPos;
		calcTransMatrix();
	}
	/** 注視点位置ベクトルを返す */
	public final Vector3D getVecLookPos() {
		return m_vecLookPos;
	}

	/** カメラベクトルを計算する */
	protected void calcCamVector() {
		float fX = m_vecLookPos.m_fX - m_vecPos.m_fX;
		float fY = m_vecLookPos.m_fY - m_vecPos.m_fY;
		float fZ = m_vecLookPos.m_fZ - m_vecPos.m_fZ;
		// 正規化しておく
		float leng = fX*fX + fY*fY + fZ*fZ;
		leng = (float)(Math.sqrt(leng));
		m_vecCam.m_fX = fX/leng;
		m_vecCam.m_fY = fY/leng;
		m_vecCam.m_fZ = fZ/leng;
	}

	/** 回転変換行列を計算する */
	protected void calcTransMatrix() {
		float aleng, bleng, s2, c2, s1, c1;
		bleng = (m_vecPos.m_fX - m_vecLookPos.m_fX)*(m_vecPos.m_fX - m_vecLookPos.m_fX) + (m_vecPos.m_fZ - m_vecLookPos.m_fZ)*(m_vecPos.m_fZ - m_vecLookPos.m_fZ);
		aleng = bleng + (m_vecPos.m_fY - m_vecLookPos.m_fY)*(m_vecPos.m_fY - m_vecLookPos.m_fY);
		bleng = (float)(Math.sqrt(bleng));
		aleng = (float)(Math.sqrt(aleng));
		s2 = -(m_vecLookPos.m_fX - m_vecPos.m_fX) / bleng;	// sin(-a) = -sin(a)
		c2 = (m_vecLookPos.m_fZ - m_vecPos.m_fZ) / bleng;	// cos(-a) =  cos(a)
		s1 = (m_vecLookPos.m_fY - m_vecPos.m_fY) / aleng;
		c1 = bleng/aleng;
		m_vecTrans[0].m_fX = c2;  m_vecTrans[1].m_fX = 0.0f; m_vecTrans[2].m_fX = s2;
		m_vecTrans[0].m_fY = s1*s2; m_vecTrans[1].m_fY = c1;  m_vecTrans[2].m_fY = -s1*c2;
		m_vecTrans[0].m_fZ = -c1*s2; m_vecTrans[1].m_fZ = s1; m_vecTrans[2].m_fZ = c1*c2;
		// カメラベクトルを計算しておく
		calcCamVector();
	}

	/** 透視変換 */
	public void persConv(Vector3D vec3D, Vector3D vecScreen) {
		Vector3D cv = new Vector3D();
		// 回転変換行列・（位置ベクトル−カメラ位置）
		cv.m_fX += m_vecTrans[0].m_fX * (vec3D.m_fX - m_vecPos.m_fX);
		cv.m_fX += m_vecTrans[1].m_fX * (vec3D.m_fY - m_vecPos.m_fY);
		cv.m_fX += m_vecTrans[2].m_fX * (vec3D.m_fZ - m_vecPos.m_fZ);
		cv.m_fY += m_vecTrans[0].m_fY * (vec3D.m_fX - m_vecPos.m_fX);
		cv.m_fY += m_vecTrans[1].m_fY * (vec3D.m_fY - m_vecPos.m_fY);
		cv.m_fY += m_vecTrans[2].m_fY * (vec3D.m_fZ - m_vecPos.m_fZ);
		cv.m_fZ += m_vecTrans[0].m_fZ * (vec3D.m_fX - m_vecPos.m_fX);
		cv.m_fZ += m_vecTrans[1].m_fZ * (vec3D.m_fY - m_vecPos.m_fY);
		cv.m_fZ += m_vecTrans[2].m_fZ * (vec3D.m_fZ - m_vecPos.m_fZ);
		// 透視変換
		vecScreen.m_fX = (float)CENTER_X + cv.m_fX*F_DIST_SCREEN/cv.m_fZ;
		vecScreen.m_fY = (float)CENTER_Y - cv.m_fY*F_DIST_SCREEN/cv.m_fZ;	// ２Ｄの座標系は下方向が＋なので
		vecScreen.m_fZ = cv.m_fZ;
	}

}
// End of Camera3D.java
