// List of Model3D.java

import java.awt.*;
import java.util.*;


/** Model3Dクラス
 * 
 * @author  Satoshi Kitade
 * @version 1.4, 04/08/27
 */
public class Model3D extends Object implements GeomDefs {

	/** 親モデルへの参照 */
	private Model3D m_parentModel;
	/** 中心位置（親モデル相対） */
	private Vector3D m_vecCenterOrg;
	/** 中心位置 */
	private Vector3D m_vecCenter;
	/** ３軸方向のスケール */
	private Vector3D m_vecScale;
	/** ３軸方向のスケール増加速度 */
	private Vector3D m_vecScaleVel;
	/** 各軸回転角（親モデル相対、ラジアン） */
	private Vector3D m_vecRotAngle;
	/** 各軸回転角速度（ラジアン/frame） */
	private Vector3D m_vecRotAngleVel;
	/** 回転行列 */
	public Vector3D m_vecRot[] = new Vector3D[VECNUM_TRANS];
	/** 描画要素のArrayList */
	private ArrayList m_primList;
	/** 子モデルのArrayList */
	private ArrayList m_childList;
	/** 描画基本色 */
	private Color m_color;

	/** コンストラクタ */
	public Model3D(Vector3D vecCenterOrg, Vector3D vecRotAngle, int r, int g, int b, int a) {
		m_parentModel = null;
		m_vecCenterOrg = new Vector3D(vecCenterOrg);
		m_vecCenter = new Vector3D(vecCenterOrg);
		m_vecScale = new Vector3D(1.0f, 1.0f, 1.0f);
		m_vecScaleVel = new Vector3D(0.0f, 0.0f, 0.0f);
		m_vecRotAngle = new Vector3D(vecRotAngle);
		m_vecRotAngleVel = new Vector3D(0.0f, 0.0f, 0.0f);
		m_primList = new ArrayList();
		m_childList = new ArrayList();
		m_vecRot[0] = new Vector3D();
		m_vecRot[1] = new Vector3D();
		m_vecRot[2] = new Vector3D();
		m_color = new Color(r, g, b, a);
		updateRotMatrix();
		updateVecCenter();
	}

	/** 三角形の追加 */
	public void addTriangle3D(int nTriNum, Triangle3D tri3D[]) {
		for ( int i = 0; i < nTriNum; i++ ) {
			m_primList.add( new Triangle3D(this, i, tri3D[i].m_vec3DOrg[0], tri3D[i].m_vec3DOrg[1], tri3D[i].m_vec3DOrg[2]) );
		}
	}

	/** 三角形の追加 */
	public void addTriangle3D(int nTriNum, Vector3D vec3D[]) {
		for ( int i = 0; i < nTriNum; i++ ) {
			m_primList.add( new Triangle3D(this, i, vec3D[3*i + 0], vec3D[3*i + 1], vec3D[3*i + 2]) );
		}
	}

	/** 三角形の追加 */
	public void addTriangle3D(int nTriNum, float fVert[]) {
		for ( int i = 0; i < nTriNum; i++ ) {
			m_primList.add( new Triangle3D(this, i,
										fVert[9*i + 0], fVert[9*i + 1], fVert[9*i + 2],
										fVert[9*i + 3], fVert[9*i + 4], fVert[9*i + 5],
										fVert[9*i + 6], fVert[9*i + 7], fVert[9*i + 8] ) );
		}
	}

	/** 親モデルを設定する  */
	public final void setParent(Model3D parentModel) {
		m_parentModel = parentModel;
	}
	/** 親モデルを返す */
	public final Model3D getParent() {
		return m_parentModel;
	}

	/** 子モデルの追加 */
	public final void addChild(Model3D model) {
		model.setParent(this);
		model.updateRotMatrix();
		model.updateVecCenter();
		m_childList.add(model);
	}

	/** 子モデルのリストの中の要素を返す */
	public final Model3D getChild(int nIndex) {
		return (Model3D)(m_childList.get(nIndex));
	}

	/** 親モデル相対中心位置を設定 */
	public final void setCenterOrg(Vector3D vecCenterOrg) {
		m_vecCenterOrg.set(vecCenterOrg);
	}
	/** 親モデル相対中心位置を設定 */
	public final void setCenterOrg(float fX, float fY, float fZ) {
		m_vecCenterOrg.set(fX, fY, fZ);
	}
	/** 親モデル相対中心位置ベクトルを返す */
	public final Vector3D getVecCenterOrg() {
		return m_vecCenterOrg;
	}

	/** 現在の中心位置ベクトルを返す */
	public final Vector3D getVecCenter() {
		return m_vecCenter;
	}
	/** 現在の中心位置ベクトルを計算する */
	public void updateVecCenter() {
		Model3D parent = getParent();
		if ( parent != null ) {
			// 親モデルがあれば、親モデルの中心位置と回転行列から計算する
			Vector3D vecCenterParent = parent.getVecCenter();
			m_vecCenter.m_fX = vecCenterParent.m_fX +
								parent.m_vecRot[0].m_fX*m_vecCenterOrg.m_fX +
								parent.m_vecRot[1].m_fX*m_vecCenterOrg.m_fY +
								parent.m_vecRot[2].m_fX*m_vecCenterOrg.m_fZ;
			m_vecCenter.m_fY = vecCenterParent.m_fY +
								parent.m_vecRot[0].m_fY*m_vecCenterOrg.m_fX +
								parent.m_vecRot[1].m_fY*m_vecCenterOrg.m_fY +
								parent.m_vecRot[2].m_fY*m_vecCenterOrg.m_fZ;
			m_vecCenter.m_fZ = vecCenterParent.m_fZ +
								parent.m_vecRot[0].m_fZ*m_vecCenterOrg.m_fX +
								parent.m_vecRot[1].m_fZ*m_vecCenterOrg.m_fY +
								parent.m_vecRot[2].m_fZ*m_vecCenterOrg.m_fZ;
		}
		else {
			m_vecCenter.set(m_vecCenterOrg);
		}
		// スケールを掛け算
		m_vecCenter.multi(m_vecScale);
	}

	/** ３軸方向のスケールを設定 */
	public final void setScale(Vector3D vecScale) {
		m_vecScale.set(vecScale);
	}
	/** ３軸方向のスケールを設定 */
	public final void setScale(float fX, float fY, float fZ) {
		m_vecScale.set(fX, fY, fZ);
	}
	/** ３軸方向のスケールベクトルを返す */
	public final Vector3D getVecScale() {
		return m_vecScale;
	}

	/** ３軸方向のスケール増加速度を設定 */
	public final void setScaleVel(Vector3D vecScaleVel) {
		m_vecScaleVel.set(vecScaleVel);
	}
	/** ３軸方向のスケール増加速度を設定 */
	public final void setScaleVel(float fX, float fY, float fZ) {
		m_vecScaleVel.set(fX, fY, fZ);
	}
	/** ３軸方向のスケール増加速度ベクトルを返す */
	public final Vector3D getVecScaleVel() {
		return m_vecScaleVel;
	}

	/** 各軸回転角を設定 */
	public final void setRotAngle(Vector3D vecRotAngle) {
		m_vecRotAngle.set(vecRotAngle);
	}
	/** 各軸回転角を設定 */
	public final void setRotAngle(float fX, float fY, float fZ) {
		m_vecRotAngle.set(fX, fY, fZ);
	}
	/** 各軸回転角ベクトルを返す */
	public final Vector3D getVecRotAngle() {
		return m_vecRotAngle;
	}

	/** 各軸回転角速度を設定 */
	public final void setRotAngleVel(Vector3D vecRotAngleVel) {
		m_vecRotAngleVel.set(vecRotAngleVel);
	}
	/** 各軸回転角速度を設定 */
	public final void setRotAngleVel(float fX, float fY, float fZ) {
		m_vecRotAngleVel.set(fX, fY, fZ);
	}
	/** 各軸回転角速度をクリア */
	public final void resetRotAngleVel() {
		m_vecRotAngleVel.set(0.0f, 0.0f, 0.0f);
	}
	/** 各軸回転角速度ベクトルを返す */
	public final Vector3D getVecRotAngleVel() {
		return m_vecRotAngleVel;
	}

	/** 描画基本色を設定 */
	public final void setColor(int r, int g, int b, int a) {
		m_color = new Color(r, g, b, a);
	}
	/** 描画基本色を返す */
	public final Color getColor() {
		return m_color;
	}

	/** 回転行列を計算する */
	public void updateRotMatrix() {
		float sin1 = (float)Math.sin(m_vecRotAngle.m_fX);
		float cos1 = (float)Math.cos(m_vecRotAngle.m_fX);
		float sin2 = (float)Math.sin(m_vecRotAngle.m_fY);
		float cos2 = (float)Math.cos(m_vecRotAngle.m_fY);
		float sin3 = (float)Math.sin(m_vecRotAngle.m_fZ);
		float cos3 = (float)Math.cos(m_vecRotAngle.m_fZ);
		m_vecRot[0].m_fX = cos2*cos3 - sin1*sin2*sin3;
		m_vecRot[0].m_fY = cos2*sin3 + sin1*sin2*sin3;
		m_vecRot[0].m_fZ = -cos1*sin2;
		m_vecRot[1].m_fX = -cos1*sin3;
		m_vecRot[1].m_fY = cos1*cos3;
		m_vecRot[1].m_fZ = sin1;
		m_vecRot[2].m_fX = sin2*cos3 + sin1*cos2*sin3;
		m_vecRot[2].m_fY = sin2*sin3 - sin1*cos2*cos3;
		m_vecRot[2].m_fZ = cos1*cos2;
		// 親モデルがあれば、親モデルの回転行列と掛け算
		Model3D parent = getParent();
		if ( parent != null ) {
			float fV0X = parent.m_vecRot[0].m_fX*m_vecRot[0].m_fX +
							parent.m_vecRot[1].m_fX*m_vecRot[0].m_fY +
							parent.m_vecRot[2].m_fX*m_vecRot[0].m_fZ;
			float fV0Y = parent.m_vecRot[0].m_fY*m_vecRot[0].m_fX +
							parent.m_vecRot[1].m_fY*m_vecRot[0].m_fY +
							parent.m_vecRot[2].m_fY*m_vecRot[0].m_fZ;
			float fV0Z = parent.m_vecRot[0].m_fZ*m_vecRot[0].m_fX +
							parent.m_vecRot[1].m_fZ*m_vecRot[0].m_fY +
							parent.m_vecRot[2].m_fZ*m_vecRot[0].m_fZ;
			float fV1X = parent.m_vecRot[0].m_fX*m_vecRot[1].m_fX +
							parent.m_vecRot[1].m_fX*m_vecRot[1].m_fY +
							parent.m_vecRot[2].m_fX*m_vecRot[1].m_fZ;
			float fV1Y = parent.m_vecRot[0].m_fY*m_vecRot[1].m_fX +
							parent.m_vecRot[1].m_fY*m_vecRot[1].m_fY +
							parent.m_vecRot[2].m_fY*m_vecRot[1].m_fZ;
			float fV1Z = parent.m_vecRot[0].m_fZ*m_vecRot[1].m_fX +
							parent.m_vecRot[1].m_fZ*m_vecRot[1].m_fY +
							parent.m_vecRot[2].m_fZ*m_vecRot[1].m_fZ;
			float fV2X = parent.m_vecRot[0].m_fX*m_vecRot[2].m_fX +
							parent.m_vecRot[1].m_fX*m_vecRot[2].m_fY +
							parent.m_vecRot[2].m_fX*m_vecRot[2].m_fZ;
			float fV2Y = parent.m_vecRot[0].m_fY*m_vecRot[2].m_fX +
							parent.m_vecRot[1].m_fY*m_vecRot[2].m_fY +
							parent.m_vecRot[2].m_fY*m_vecRot[2].m_fZ;
			float fV2Z = parent.m_vecRot[0].m_fZ*m_vecRot[2].m_fX +
							parent.m_vecRot[1].m_fZ*m_vecRot[2].m_fY +
							parent.m_vecRot[2].m_fZ*m_vecRot[2].m_fZ;
			m_vecRot[0].m_fX = fV0X; m_vecRot[0].m_fY = fV0Y; m_vecRot[0].m_fZ = fV0Z;
			m_vecRot[1].m_fX = fV1X; m_vecRot[1].m_fY = fV1Y; m_vecRot[1].m_fZ = fV1Z;
			m_vecRot[2].m_fX = fV2X; m_vecRot[2].m_fY = fV2Y; m_vecRot[2].m_fZ = fV2Z;
		}
	}

	/** 表示座標を計算 */
	public void update(SceneManager3D sceneManager3D) {
		// 各軸方向スケール更新
		m_vecScale.add(m_vecScaleVel);
		// 各軸回転角更新
		m_vecRotAngle.add(m_vecRotAngleVel);
		// 回転行列更新
		updateRotMatrix();
		// 中心位置更新
		updateVecCenter();
		// 子モデルについて更新
		for ( int i = 0; i < m_childList.size(); i++ ) {
			Model3D child = (Model3D)(m_childList.get(i));
			child.update(sceneManager3D);
		}
		// このモデルに属する描画要素の更新
		for ( int i = 0; i < m_primList.size(); i++ ) {
			Primitive3D prim = (Primitive3D)(m_primList.get(i));
			prim.update(sceneManager3D);
		}
	}

}
// End of Model3D.java
