diff --git a/app/src/main/java/org/ntlab/radishforandroidstudio/java3d/Sphere.java b/app/src/main/java/org/ntlab/radishforandroidstudio/java3d/Sphere.java index e60953f..c71cb0c 100644 --- a/app/src/main/java/org/ntlab/radishforandroidstudio/java3d/Sphere.java +++ b/app/src/main/java/org/ntlab/radishforandroidstudio/java3d/Sphere.java @@ -6,7 +6,93 @@ private float radius; int divisions; - + + private Shape3D bodyShape = null; + + public Sphere(float r, Appearance ap){ + divisions = MID_REZ_DIV; + + radius = r; + // 各面のジオメトリを作成 + IndexedTriangleArray bodyGeom = new IndexedTriangleArray(divisions * (divisions / 2 - 1) + 2, + IndexedTriangleArray.COORDINATES | IndexedTriangleArray.NORMALS | IndexedTriangleArray.TEXTURE_COORDINATE_2, + divisions * ((divisions - 2) * 6 + 2 * 3)); + + // 頂点座標と法線の設定 + float coordinates[][] = new float[divisions * (divisions / 2 - 1) + 2][3]; + for (int i = 0; i <= divisions / 2; i++) { // 緯度方向のループ(北極から南極に向かって) + if (i == 0) { + // 北極の場合 + coordinates[0][0] = 0.0f; + coordinates[0][1] = radius; + coordinates[0][2] = 0.0f; + bodyGeom.setNormal(0, new float[]{0.0f, 1.0f, 0.0f}); + } else if (i == divisions / 2) { + // 南極の場合 + coordinates[divisions * (divisions / 2 - 1) + 1][0] = 0.0f; + coordinates[divisions * (divisions / 2 - 1) + 1][1] = -radius; + coordinates[divisions * (divisions / 2 - 1) + 1][2] = 0.0f; + bodyGeom.setNormal(divisions * (divisions / 2 - 1) + 1, new float[]{0.0f, -1.0f, 0.0f}); + } else { + float y = r * (float) Math.cos(2 * Math.PI * ((double) i / divisions)); + float r2 = r * (float) Math.sin(2 * Math.PI * ((double) i / divisions)); + for (int j = 0; j < divisions; j++) { // 経度方向のループ + float x = r2 * (float) Math.cos(2 * Math.PI * ((double) j / divisions)); + float z = -r2 * (float) Math.sin(2 * Math.PI * ((double) j / divisions)); + coordinates[(i - 1) * divisions + j + 1][0] = x; + coordinates[(i - 1) * divisions + j + 1][1] = y; + coordinates[(i - 1) * divisions + j + 1][2] = z; + bodyGeom.setNormal((i - 1) * divisions + j + 1, new float[]{x / r, y / r, z / r}); + } + } + } + + for (int i = 0; i < divisions * (divisions / 2 - 1) + 2; i++) { + bodyGeom.setCoordinate(i , coordinates[i]); + } + + int coordinateIndices[] = new int[divisions * ((divisions - 2) * 6 + 2 * 3)]; + int index = 0; + for (int i = 0; i < divisions / 2; i++) { + for (int j = 0; j < divisions; j++) { + if (i == 0) { + // 北極付近 + coordinateIndices[index] = 0; // 北極 + coordinateIndices[index + 1] = j + 1; + coordinateIndices[index + 2] = (j + 1) % divisions + 1; + index += 3; + } else if (i == divisions / 2 - 1) { + // 南極付近 + coordinateIndices[index] = (i - 1) * divisions + j + 1; + coordinateIndices[index + 1] = divisions * (divisions / 2 - 1) + 1; // 南極 + coordinateIndices[index + 2] = (i - 1) * divisions + (j + 1) % divisions + 1; + index += 3; + } else { + coordinateIndices[index] = (i - 1) * divisions + j + 1; + coordinateIndices[index + 1] = i * divisions + j + 1; + coordinateIndices[index + 2] = i * divisions + (j + 1) % divisions + 1; + coordinateIndices[index + 3] = (i - 1) * divisions + j + 1; + coordinateIndices[index + 4] = i * divisions + (j + 1) % divisions + 1; + coordinateIndices[index + 5] = (i - 1) * divisions + (j + 1) % divisions + 1; + index += 6; + } + } + } + + bodyGeom.setCoordinateIndices(0, coordinateIndices); + + float uv[] = { 0, 0, 1, 0, 1, 1, 0, 1, }; + bodyGeom.setTextureCoordinates(0, uv); // + + // 表面属性の作成 + if (ap == null) { + ap = new Appearance(); + } + setAppearance(ap); + + bodyShape = new Shape3D(bodyGeom, ap); + } + public float getRadius() { return radius; } @@ -17,6 +103,20 @@ @Override public Shape3D getShape(int partid) { + switch (partid) { + case BODY: + return bodyShape; + } return null; } + + @Override + public Node cloneTree() { + Appearance ap = getAppearance(); + if (ap != null) { + ap = (Appearance)ap.cloneNodeComponent(); + } + Sphere s = new Sphere(radius, ap); + return s; + } }