Newer
Older
CactusClient / src / java3d / Cone.java
package java3d;

public class Cone extends Primitive {
	public static final int BODY = 0;
	public static final int CAP = 1;
	
	static final int MID_REZ_DIV_X = 16;
	static final int MID_REZ_DIV_Y = 1;
	
	float radius;
	float height;
	int xdivisions;
	int ydivisions;
	

	private Shape3D bodyShape = null;
	private Shape3D capShape = null;

	public Cone() {
		this(0.5f, 1.0f, null);
	}

	public Cone(float r, float h, Appearance ap) {
		xdivisions = MID_REZ_DIV_X;
		ydivisions = MID_REZ_DIV_Y;
			
		float coordinates[][] = new float[xdivisions][3];
	
		for (int i = 0; i < xdivisions; i++) { // BOTTOM(底面)の点の(x,y,z)座標
			coordinates[i][0] = r * (float) Math.cos(2 * Math.PI * ((double)i / xdivisions));
			coordinates[i][1] = -h / 2;
			coordinates[i][2] = r * (float) Math.sin(2 * Math.PI * ((double)i / xdivisions));
		}
			
		float coordinates_center[][] = new float[2][3];//頂点と,底面の中心,の座標
		coordinates_center[0][0] = 0;
		coordinates_center[0][1] = h / 2;
		coordinates_center[0][2] = 0;
		coordinates_center[1][0] = 0;
		coordinates_center[1][1] = -h / 2;
		coordinates_center[1][2] = 0;

		float uv[] = { 0, 0, 1, 0, 1, 1, 0, 1, };

		// 各面のジオメトリを作成
		TriangleFanArray bodyGeom = new TriangleFanArray(xdivisions + 2,
				TriangleFanArray.COORDINATES | TriangleFanArray.NORMALS | TriangleFanArray.TEXTURE_COORDINATE_2,
				new int[] { xdivisions + 2 });
		TriangleFanArray capGeom = new TriangleFanArray(xdivisions + 2,
				TriangleFanArray.COORDINATES | TriangleFanArray.NORMALS | TriangleFanArray.TEXTURE_COORDINATE_2,
				new int[] { xdivisions + 2 });

		// 頂点座標の設定	
			//側面
		bodyGeom.setCoordinate(0,coordinates_center[0]);
		for (int i = 0; i < xdivisions; i++){
			bodyGeom.setCoordinate(i + 1, coordinates[i]);					//上から見て反時計回りの順
		}
		bodyGeom.setCoordinate(xdivisions + 1, coordinates[0]);
			//底面
		capGeom.setCoordinate(0,coordinates_center[1]);
		capGeom.setCoordinate(1, coordinates[0]);
		for (int i = 0; i < xdivisions; i++){	
			capGeom.setCoordinate(i + 2, coordinates[xdivisions - i - 1]);	//上から見て時計回りの順
		}

		 // テクスチャ座標の設定
		 bodyGeom.setTextureCoordinates(0, uv);	//
		 capGeom.setTextureCoordinates(0, uv);

		 // 法線の設定
		 double theta;
		 theta = Math.atan(h / r);
		 for (int i = 0; i < xdivisions; i++) {
			 float[] bodyNorm = new float[]{
					 (float)(r * Math.sin(theta) * Math.cos(90 - theta) * Math.cos(2 * Math.PI * ((double)i / xdivisions))),
					 (float)(r * Math.sin(theta) * Math.sin(90 - theta)),
					 (float) Math.sin(2 * Math.PI * ((double)i / xdivisions))
			 };
			 bodyGeom.setNormal(i, bodyNorm);
		}

		float[] bottomNorm = new float[]{0.0f, -1.0f, 0.0f};
		for (int i = 0; i < xdivisions + 2; i++) {
			capGeom.setNormal(i, bottomNorm);
		}
			
		// 表面属性の作成
		if (ap == null) {
			ap = new Appearance();
		}
		setAppearance(ap);

		// 各面の作成			//全て同じテクスチャー(ap)を貼り付ける
		bodyShape = new Shape3D(bodyGeom, ap);
		capShape = new Shape3D(capGeom, ap);

		radius = r;
		height = h;
	}
		
	public double getRadius() {
		return radius;
	}
	public double getHeight() {
		return height;
	}

	@Override
	public Shape3D getShape(int partid) {
		switch (partid) {
		case BODY:
			return bodyShape;
		case CAP:
			return capShape;
		}
		return null;
	}
	
	public Node cloneTree() {
		Appearance ap = getAppearance();
		if (ap != null) {
			ap = (Appearance)ap.cloneNodeComponent();
		}		
		Cone c = new Cone(radius, height, ap);
	    return c;
	}
}