1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
package my3d; import java.util.ArrayList; import javafx.scene.image.Image; import javafx.scene.image.PixelReader; import javafx.scene.paint.Color; import my3d._math3d.*; public class _shape3d2 extends _shape3d { public _shape3d2() {} public _shape3d2(_shape3d shape) { vertices = shape.vertices; faces = new ArrayList<>(); for (_face face : shape.faces) faces.add(new _face2(face)); } @Override public void add_face(int... indices) { _face2 face = new _face2(); face.vertex_indices = indices; faces.add(face); } public static class _face2 extends _face { public _face2() {} public _face2(_face face) { vertex_indices = face.vertex_indices; } // --- chap12: 法線情報 --- public _material material; public int[] normal_indices; public double stretch; public Color get_color() { return (material != null) ? material.color : null; } public void set_color(Color color) { if (material == null) material = new _material(color); else material.color = color; } public void set_normal_indices(int... indices) { normal_indices = indices; } // --- chap13: テクスチャ情報 --- public _point[] texture_coordinates; public void set_texture_coordinates(_point... texture_coordinates) { this.texture_coordinates = texture_coordinates; } } // 立方体 public static _shape3d2 create_box(double x, double y, double z) { _shape3d2 shape = new _shape3d2(_shape3d.create_box(x, y, z)); _point[] tc = { new _point(1, 0), new _point(1, 1), new _point(0, 1), new _point(0, 0) }; for (_face face : shape.faces) ((_face2)face).texture_coordinates = tc; return shape; } // 球 public static _shape3d2 create_ball(double radius, int slice_n) { _shape3d2 shape = new _shape3d2(_shape3d.create_ball(radius, slice_n)); shape.normals = shape.vertices; ArrayList<_face> faces = shape.faces; for (_face face : faces) { ((_face2)face).normal_indices = face.vertex_indices; } int round_n = 2 * slice_n; double k; for (int i = 0; i < slice_n - 2; i++) { k = shape.vertices[i * round_n].z / shape.vertices[(i + 1) * round_n].z; for (int j = 0; j < round_n; j++) ((_face2)faces.get(i * round_n + j)).stretch = k; } _point[][] tc = new _point[slice_n + 1][round_n + 1]; for (int i = 0; i < slice_n + 1; i++) for (int j = 0; j < round_n + 1; j++) tc[i][j] = new _point( 1 - (double)j / round_n, (1 - Math.cos(Math.PI * i / slice_n)) / 2); int x1, x2, y1, y2; for (int i = 0; i < slice_n - 2; i++) { for (int j = 0; j < round_n; j++) { x1 = j; x2 = j + 1; y1 = i + 1; y2 = i + 2; ((_face2)faces.get(i * round_n + j)).set_texture_coordinates( tc[y1][x1], tc[y2][x1], tc[y2][x2], tc[y1][x2]); } } _face2 face; for (int i = slice_n - 2; i < slice_n; i++) { for (int j = 0; j < round_n; j++) { if (i == slice_n - 2) { x1 = j; x2 = j + 1; y1 = 0; y2 = 1; } else { x1 = j + 1; x2 = j; y1 = slice_n; y2 = slice_n - 1; } face = (_face2)faces.get(i * round_n + j); face.set_texture_coordinates( tc[y1][x1], tc[y2][x1], tc[y2][x2], tc[y1][x2]); face.stretch = 1e-9; } } return shape; } // 円柱 public static _shape3d2 create_tube(double r, double h, int n) { _shape3d2 shape = new _shape3d2(_shape3d.create_tube(r, h, n)); _vector[] va = shape.vertices; _vector[] normals = new _vector[va.length]; for (int i = 0; i < va.length; i++) normals[i] = new _vector(va[i].x, 0, va[i].z); shape.normals = normals; ArrayList<_face> faces = shape.faces; for (int i = 0; i < n; i++) ((_face2)faces.get(i)).normal_indices = faces.get(i).vertex_indices; _point[][] tc = new _point[2][n + 1]; for (int i = 0; i < n + 1; i++) { tc[0][i] = new _point(1 - (double)i / n, 0); tc[1][i] = new _point(1 - (double)i / n, 1); } for (int i = 0; i < n; i++) ((_face2)faces.get(i)).set_texture_coordinates( tc[0][i], tc[1][i], tc[1][i + 1], tc[0][i + 1]); return shape; } // 円錐 public static _shape3d2 create_corn(double r, double h, int n) { _shape3d2 shape = new _shape3d2(_shape3d.create_corn(r, h, n)); _vector[] normals = new _vector[n]; double t; for (int i = 0; i < n; i++) { t = i * 2 * Math.PI / n; normals[i] = new _vector(h * Math.sin(t), r / 2, h * Math.cos(t)); } shape.normals = normals; ArrayList<_face> faces = shape.faces; for (int i = 0; i < n; i++) ((_face2)faces.get(i)).set_normal_indices(i, (i + 1) % n); _point[][] tc = new _point[2][n + 1]; for (int i = 0; i < n + 1; i++) { tc[0][i] = new _point(1 - (double)i / n, 0); tc[1][i] = new _point(1 - (double)i / n, 1); } _face2 face; for (int i = 0; i < n; i++) { face = (_face2)faces.get(i); face.stretch = 1e-9; face.set_texture_coordinates( tc[0][i], tc[1][i], tc[1][i + 1]); } return shape; } public static class _material { public Color color; public double shininess; public _texture texture; public _material(Color color) { this(color, 0); } public _material(Color color, double shininess) { this.color = color; this.shininess = shininess; } public _material(Color color, double shininess, _texture texture) { this.color = color; this.shininess = shininess; this.texture = texture; } } public _material material; public _vector[] normals; public Color get_color() { return (material != null) ? material.color : null; } public void set_color(Color color) { if (material == null) material = new _material(color); else material.color = color; } public static class _texture { public static interface _geometry_image { int get_color(double x, double y); } private _geometry_image geometry_image; private PixelReader pr; private double w, h; public _texture(_geometry_image geometry_image) { set_geometry_image(geometry_image); } public void set_geometry_image(_geometry_image geometry_image) { pr = null; this.geometry_image = geometry_image; } public _texture(Image image) { this.set_image(image); } public void set_image(Image image) { pr = image.getPixelReader(); w = image.getWidth(); h = image.getHeight(); } public final int get_color(double x, double y) { if (x < 0 || x >= 1 || y < 0 || y >= 1) return 0; if (pr != null) return pr.getArgb((int) (x * w), (int) (y * h)); return geometry_image.get_color(x, y); } } }