package java3d;
public class Cylinder extends Primitive {
public static final int BODY = 0;
public static final int TOP = 1;
public static final int BOTTOM = 2;
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 topShape = null;
private Shape3D bottomShape = null;
public Cylinder() {
this(0.5f, 1.0f, null);
}
public Cylinder(float r, float h) {
this(r, h, null);
}
public Cylinder(float r, float h, Appearance ap) {
xdivisions = MID_REZ_DIV_X;
ydivisions = MID_REZ_DIV_Y;
float coordinates[][] = new float[xdivisions * 2][3];
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;
for (int i = 0; i < xdivisions; i++) { // TOP(上面)側の点の(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));
}
for (int i = 0; i < xdivisions; i++) { // BOTTOM(底面)の点の(x,y,z)座標
coordinates[i + xdivisions][0] = r * (float) Math.cos(2 * Math.PI * ((double)i / xdivisions));
coordinates[i + xdivisions][1] = -h / 2;
coordinates[i + xdivisions][2] = r * (float) Math.sin(2 * Math.PI * ((double)i / xdivisions));
}
float uv[] = { 0, 0, 1, 0, 1, 1, 0, 1, };
// 各面のジオメトリを作成
IndexedTriangleStripArray bodyGeom = new IndexedTriangleStripArray(xdivisions * 2,
IndexedTriangleStripArray.COORDINATES | IndexedTriangleStripArray.NORMALS | IndexedTriangleStripArray.TEXTURE_COORDINATE_2,
xdivisions * 2 + 2,
new int[] { xdivisions * 2 + 2 });
TriangleFanArray topGeom = new TriangleFanArray(xdivisions + 2,
TriangleFanArray.COORDINATES | TriangleFanArray.NORMALS | TriangleFanArray.TEXTURE_COORDINATE_2,
new int[] { xdivisions + 2 });
TriangleFanArray bottomGeom = new TriangleFanArray(xdivisions + 2,
TriangleFanArray.COORDINATES | TriangleFanArray.NORMALS | TriangleFanArray.TEXTURE_COORDINATE_2,
new int[] { xdivisions + 2 });
// 頂点座標の設定
//側面
for (int i = 0; i < xdivisions; i++) { //上面から底面へ垂直に降りて、底面から上面へ斜めに上る順に座標を設定
bodyGeom.setCoordinate(2 * i , coordinates[i]);
bodyGeom.setCoordinate(2 * i + 1, coordinates[i + xdivisions]);
}
int coordinateIndices[] = new int[xdivisions * 2 + 2];
for (int i = 0; i < xdivisions * 2; i++) {
coordinateIndices[i] = i;
}
coordinateIndices[xdivisions * 2] = 0;
coordinateIndices[xdivisions * 2 + 1] = 1;
bodyGeom.setCoordinateIndices(0, coordinateIndices);
//上面
topGeom.setCoordinate(0,coordinates_center[0]);
for(int i = 0; i < xdivisions; i++){
topGeom.setCoordinate(i + 1, coordinates[i]); //上から見て反時計回りの順
}
topGeom.setCoordinate(xdivisions + 1, coordinates[0]);
//底面
bottomGeom.setCoordinate(0,coordinates_center[1]);
bottomGeom.setCoordinate(1, coordinates[xdivisions]);
for(int i = 0; i < xdivisions; i++){
bottomGeom.setCoordinate(i + 2, coordinates[2 * xdivisions - i - 1]); //上から見て時計回りの順
}
// テクスチャ座標の設定
bodyGeom.setTextureCoordinates(0, uv); //
topGeom.setTextureCoordinates(0, uv);
bottomGeom.setTextureCoordinates(0, uv);
// 法線の設定
for (int i = 0; i < xdivisions * 2; i++) {
float[] bodyNorm = new float[]{(float) Math.cos(Math.PI * ((double)i / xdivisions)),0.0f,(float) Math.sin(Math.PI * ((double)i / xdivisions))};
bodyGeom.setNormal(i, bodyNorm);
}
float[] topNorm = new float[]{0.0f, 1.0f, 0.0f};
for (int i = 0; i < xdivisions + 2; i++) {
topGeom.setNormal(i, topNorm);
}
float[] bottomNorm = new float[]{0.0f, -1.0f, 0.0f};
for (int i = 0; i < xdivisions + 2; i++) {
bottomGeom.setNormal(i, bottomNorm);
}
// 表面属性の作成
if (ap == null) {
ap = new Appearance();
}
setAppearance(ap);
// Appearance ap1 = new Appearance();
// Appearance ap2 = new Appearance();
// Appearance ap3 = new Appearance();
// Appearance ap4 = new Appearance();
// Appearance ap5 = new Appearance();
// Appearance ap6 = new Appearance();
// Texture tex = ap.getTexture();
// if (tex != null && tex instanceof TextureCubeMap) {
// GL10 では GL_TEXTURE_CUBE_MAP が使えないので、TextureCubeMap の場合は Texture2D
// に分解する
// ImageComponent ic1 = tex.getImage(TextureCubeMap.POSITIVE_Z);
// Texture2D tex1 = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGB,
// ic1.width, ic1.height);
// tex1.setImage(0, ic1);
// ap1.setTexture(tex1);
// ImageComponent ic2 = tex.getImage(TextureCubeMap.NEGATIVE_Z);
// Texture2D tex2 = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGB,
// ic2.width, ic2.height);
// tex2.setImage(0, ic2);
// ap2.setTexture(tex2);
// ImageComponent ic3 = tex.getImage(TextureCubeMap.POSITIVE_X);
// Texture2D tex3 = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGB,
// ic3.width, ic3.height);
// tex3.setImage(0, ic3);
// ap3.setTexture(tex3);
// ImageComponent ic4 = tex.getImage(TextureCubeMap.NEGATIVE_X);
// Texture2D tex4 = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGB,
// ic4.width, ic4.height);
// tex4.setImage(0, ic4);
// ap4.setTexture(tex4);
// ImageComponent ic5 = tex.getImage(TextureCubeMap.POSITIVE_Y);
// Texture2D tex5 = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGB,
// ic5.width, ic5.height);
// tex5.setImage(0, ic5);
// ap5.setTexture(tex5);
// ImageComponent ic6 = tex.getImage(TextureCubeMap.NEGATIVE_Y);
// Texture2D tex6 = new Texture2D(Texture2D.BASE_LEVEL, Texture2D.RGB,
// ic6.width, ic6.height);
// tex6.setImage(0, ic6);
// ap6.setTexture(tex6);
// }
// 各面の作成 //全て同じテクスチャー(ap)を貼り付ける
bodyShape = new Shape3D(bodyGeom, ap);
topShape = new Shape3D(topGeom, ap);
bottomShape = new Shape3D(bottomGeom, 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 TOP:
return topShape;
case BOTTOM:
return bottomShape;
}
return null;
}
public Node cloneTree() {
Appearance ap = getAppearance();
if (ap != null) {
ap = (Appearance)ap.cloneNodeComponent();
}
Cylinder c = new Cylinder(radius, height, ap);
return c;
}
}