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;
}
}