1 /* 2 * 3 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * - Neither the name of Oracle nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package java2d.demos.Colors; 33 34 35 import static java.lang.Math.PI; 36 import static java.lang.Math.abs; 37 import static java.lang.Math.cos; 38 import static java.lang.Math.min; 39 import static java.lang.Math.random; 40 import static java.lang.Math.sin; 41 import static java.lang.Math.sqrt; 42 import java.awt.Color; 43 import java.awt.Graphics2D; 44 import java2d.AnimatingSurface; 45 46 47 /** 48 * 3D objects with color & lighting translated, rotated and scaled. 49 */ 50 @SuppressWarnings("serial") 51 public class Rotator3D extends AnimatingSurface { 52 53 private Objects3D objs[] = new Objects3D[3]; 54 private static final int[][][] polygons = { 55 // Solid cube 56 { { 5, 1, 15, 13, 21, 23, 15 }, 57 { 5, 2, 21, 13, 19, 27, 21 }, 58 { 5, 3, 23, 15, 17, 25, 23 }, 59 { 5, 4, 19, 13, 15, 17, 19 }, 60 { 5, 5, 27, 21, 23, 25, 27 }, 61 { 5, 6, 27, 19, 17, 25, 27 } }, 62 // Polygonal faces cube 63 { { 5, 1, 21, 13, 19, 27, 21 }, 64 { 5, 5, 23, 15, 17, 25, 23 }, 65 { 4, 0, 15, 14, 16, 15 }, { 7, 6, 16, 14, 13, 12, 18, 17, 16 }, { 4, 66 0, 12, 19, 18, 12 }, 67 { 4, 2, 22, 21, 20, 22 }, { 7, 0, 24, 23, 22, 20, 27, 26, 24 }, { 4, 68 2, 24, 26, 25, 24 }, 69 { 4, 3, 15, 13, 23, 15 }, { 4, 0, 23, 13, 21, 23 }, 70 { 5, 0, 27, 26, 18, 19, 27 }, { 5, 4, 25, 17, 18, 26, 25 } }, 71 // Octahedron 72 { { 4, 3, 18, 21, 16, 18 }, { 4, 1, 20, 16, 18, 20 }, 73 { 4, 1, 18, 21, 16, 18 }, { 4, 3, 20, 17, 19, 20 }, 74 { 4, 2, 20, 26, 27, 20 }, { 5, 3, 26, 18, 16, 27, 26 }, 75 { 5, 0, 17, 24, 25, 19, 17 }, { 4, 3, 21, 25, 24, 21 }, 76 { 4, 4, 18, 21, 22, 18 }, { 4, 2, 22, 21, 17, 22 }, 77 { 4, 5, 20, 23, 16, 20 }, { 4, 1, 20, 23, 19, 20 }, 78 { 4, 6, 21, 23, 16, 21 }, { 4, 4, 21, 23, 19, 21 }, 79 { 4, 5, 20, 18, 22, 20 }, { 4, 6, 20, 22, 17, 20 } } 80 }; 81 private static final double[][][] points = { 82 // Points for solid cube & polygonal faces cube 83 { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, 84 { 0, 0, -1 }, { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, 85 { 0, 0, 1 }, { 0, 0, -1 }, { 1, 1, 0 }, { 1, 1, 1 }, { 0, 1, 1 }, 86 { -1, 1, 1 }, { -1, 1, 0 }, { -1, 1, -1 }, { 0, 1, -1 }, 87 { 1, 1, -1 }, 88 { 1, -1, 0 }, { 1, -1, 1 }, { 0, -1, 1 }, { -1, -1, 1 }, 89 { -1, -1, 0 }, 90 { -1, -1, -1 }, { 0, -1, -1 }, { 1, -1, -1 } }, 91 // Points for octahedron 92 { { 0, 0, 1 }, { 0, 0, -1 }, { -0.8165, 0.4714, 0.33333 }, 93 { 0.8165, -0.4714, -0.33333 }, { 0.8165, 0.4714, 0.33333 }, 94 { -0.8165, -0.4714, -0.33333 }, { 0, -0.9428, 0.3333 }, 95 { 0, 0.9428, -0.33333 }, { 0, 0, 1 }, { 0, 0, -1 }, 96 { -0.8165, 0.4714, 0.33333 }, { 0.8165, -0.4714, -0.33333 }, 97 { 0.8165, 0.4714, 0.33333 }, { -0.8165, -0.4714, -0.33333 }, 98 { 0, -0.9428, 0.33333 }, { 0, 0.9428, -0.33333 }, 99 { -1.2247, -0.7071, 1 }, { 1.2247, 0.7071, -1 }, 100 { 0, 1.4142, 1 }, { 0, -1.4142, -1 }, { -1.2247, 0.7071, -1 }, 101 { 1.2247, -0.7071, 1 }, { 0.61237, 1.06066, 0 }, 102 { -0.61237, -1.06066, 0 }, { 1.2247, 0, 0 }, 103 { 0.61237, -1.06066, 0 }, { -0.61237, 1.06066, 0 }, 104 { -1.2247, 0, 0 } } 105 }; 106 private static final int[][][] faces = { 107 // Solid cube 108 { { 1, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 0 }, { 1, 5 } }, 109 // Polygonal faces cube 110 { { 1, 0 }, { 1, 1 }, { 3, 2, 3, 4 }, { 3, 5, 6, 7 }, { 2, 8, 9 }, { 2, 111 10, 11 } }, 112 // Octahedron 113 { { 1, 2 }, { 1, 3 }, { 2, 4, 5 }, { 2, 6, 7 }, { 2, 8, 9 }, 114 { 2, 10, 11 }, { 2, 12, 13 }, { 2, 14, 15 } }, }; 115 116 public Rotator3D() { 117 setBackground(Color.white); 118 } 119 120 @Override 121 public void reset(int w, int h) { 122 objs[0] = new Objects3D(polygons[0], points[0], faces[0], w, h); 123 objs[1] = new Objects3D(polygons[1], points[0], faces[1], w, h); 124 objs[2] = new Objects3D(polygons[2], points[1], faces[2], w, h); 125 } 126 127 @Override 128 public void step(int w, int h) { 129 for (Objects3D obj : objs) { 130 if (obj != null) { 131 obj.step(w, h); 132 } 133 } 134 } 135 136 @Override 137 public void render(int w, int h, Graphics2D g2) { 138 for (Objects3D obj : objs) { 139 if (obj != null) { 140 obj.render(g2); 141 } 142 } 143 } 144 145 public static void main(String argv[]) { 146 createDemoFrame(new Rotator3D()); 147 } 148 149 150 /** 151 * 3D Objects : Solid Cube, Cube & Octahedron with polygonal faces. 152 */ 153 public class Objects3D { 154 155 private final int UP = 0; 156 private final int DOWN = 1; 157 private int[][] polygons; 158 private double[][] points; 159 private int npoint; 160 private int[][] faces; 161 private int nface; 162 private int ncolour = 10; 163 private Color[][] colours = new Color[ncolour][7]; 164 private double[] lightvec = { 0, 1, 1 }; 165 private double Zeye = 10; 166 private double angle; 167 private Matrix3D orient, tmp, tmp2, tmp3; 168 private int scaleDirection; 169 private double scale, scaleAmt; 170 private double ix = 3.0, iy = 3.0; 171 private double[][] rotPts; 172 private int[][] scrPts; 173 private int xx[] = new int[20]; 174 private int yy[] = new int[20]; 175 private double x, y; 176 private int p, j; 177 private int colour; 178 private double bounce, persp; 179 180 public Objects3D(int[][] polygons, 181 double[][] points, 182 int[][] faces, 183 int w, 184 int h) { 185 186 this.polygons = polygons; 187 this.points = points; 188 this.faces = faces; 189 npoint = points.length; 190 nface = faces.length; 191 192 x = w * random(); 193 y = h * random(); 194 195 ix = random() > 0.5 ? ix : -ix; 196 iy = random() > 0.5 ? iy : -iy; 197 198 rotPts = new double[npoint][3]; 199 scrPts = new int[npoint][2]; 200 201 for (int i = 0; i < ncolour; i++) { 202 int val = 255 - (ncolour - i - 1) * 100 / ncolour; 203 Color[] c = { 204 new Color(val, val, val), // white 205 new Color(val, 0, 0), // red 206 new Color(0, val, 0), // green 207 new Color(0, 0, val), // blue 208 new Color(val, val, 0), // yellow 209 new Color(0, val, val), // cyan 210 new Color(val, 0, val) // magenta 211 }; 212 colours[i] = c; 213 } 214 215 double len = sqrt(lightvec[0] * lightvec[0] + lightvec[1] 216 * lightvec[1] + lightvec[2] * lightvec[2]); 217 lightvec[0] = lightvec[0] / len; 218 lightvec[1] = lightvec[1] / len; 219 lightvec[2] = lightvec[2] / len; 220 221 double max = 0; 222 for (int i = 0; i < npoint; i++) { 223 len = sqrt(points[i][0] * points[i][0] + points[i][1] 224 * points[i][1] + points[i][2] * points[i][2]); 225 if (len > max) { 226 max = len; 227 } 228 } 229 230 for (int i = 0; i < nface; i++) { 231 len = sqrt(points[i][0] * points[i][0] + points[i][1] 232 * points[i][1] + points[i][2] * points[i][2]); 233 points[i][0] = points[i][0] / len; 234 points[i][1] = points[i][1] / len; 235 points[i][2] = points[i][2] / len; 236 } 237 238 orient = new Matrix3D(); 239 tmp = new Matrix3D(); 240 tmp2 = new Matrix3D(); 241 tmp3 = new Matrix3D(); 242 tmp.Rotation(2, 0, PI / 50); 243 CalcScrPts((double) w / 3, (double) h / 3, 0); 244 245 scale = min(w / 3 / max / 1.2, h / 3 / max / 1.2); 246 scaleAmt = scale; 247 scale *= random() * 1.5; 248 scaleDirection = scaleAmt < scale ? DOWN : UP; 249 } 250 251 private Color getColour(int f, int index) { 252 colour = (int) ((rotPts[f][0] * lightvec[0] + rotPts[f][1] 253 * lightvec[1] + rotPts[f][2] * lightvec[2]) * ncolour); 254 if (colour < 0) { 255 colour = 0; 256 } 257 if (colour > ncolour - 1) { 258 colour = ncolour - 1; 259 } 260 return colours[colour][polygons[faces[f][index]][1]]; 261 } 262 263 private void CalcScrPts(double x, double y, double z) { 264 for (p = 0; p < npoint; p++) { 265 266 rotPts[p][2] = points[p][0] * orient.M[2][0] 267 + points[p][1] * orient.M[2][1] 268 + points[p][2] * orient.M[2][2]; 269 270 rotPts[p][0] = points[p][0] * orient.M[0][0] 271 + points[p][1] * orient.M[0][1] 272 + points[p][2] * orient.M[0][2]; 273 274 rotPts[p][1] = -points[p][0] * orient.M[1][0] 275 - points[p][1] * orient.M[1][1] 276 - points[p][2] * orient.M[1][2]; 277 } 278 for (p = nface; p < npoint; p++) { 279 rotPts[p][2] += z; 280 persp = (Zeye - rotPts[p][2]) / (scale * Zeye); 281 scrPts[p][0] = (int) (rotPts[p][0] / persp + x); 282 scrPts[p][1] = (int) (rotPts[p][1] / persp + y); 283 } 284 } 285 286 private boolean faceUp(int f) { 287 return (rotPts[f][0] * rotPts[nface + f][0] + rotPts[f][1] * rotPts[nface 288 + f][1] + rotPts[f][2] * (rotPts[nface + f][2] - Zeye) < 0); 289 } 290 291 public void step(int w, int h) { 292 x += ix; 293 y += iy; 294 if (x > w - scale) { 295 x = w - scale - 1; 296 ix = -w / 100 - 1; 297 } 298 if (x - scale < 0) { 299 x = 2 + scale; 300 ix = w / 100 + random() * 3; 301 } 302 if (y > h - scale) { 303 y = h - scale - 2; 304 iy = -h / 100 - 1; 305 } 306 if (y - scale < 0) { 307 y = 2 + scale; 308 iy = h / 100 + random() * 3; 309 } 310 311 angle += random() * 0.15; 312 tmp3.Rotation(1, 2, angle); 313 tmp2.Rotation(1, 0, angle * sqrt(2) / 2); 314 tmp.Rotation(0, 2, angle * PI / 4); 315 orient.M = tmp3.Times(tmp2.Times(tmp.M)); 316 bounce = abs(cos(0.5 * (angle))) * 2 - 1; 317 318 if (scale > scaleAmt * 1.4) { 319 scaleDirection = DOWN; 320 } 321 if (scale < scaleAmt * 0.4) { 322 scaleDirection = UP; 323 } 324 if (scaleDirection == UP) { 325 scale += random(); 326 } 327 if (scaleDirection == DOWN) { 328 scale -= random(); 329 } 330 331 CalcScrPts(x, y, bounce); 332 } 333 334 public void render(Graphics2D g2) { 335 for (int f = 0; f < nface; f++) { 336 if (faceUp(f)) { 337 for (j = 1; j < faces[f][0] + 1; j++) { 338 DrawPoly(g2, faces[f][j], getColour(f, j)); 339 } 340 } 341 } 342 } 343 344 private void DrawPoly(Graphics2D g2, int poly, Color colour) { 345 for (int point = 2; point < polygons[poly][0] + 2; point++) { 346 xx[point - 2] = scrPts[polygons[poly][point]][0]; 347 yy[point - 2] = scrPts[polygons[poly][point]][1]; 348 } 349 g2.setColor(colour); 350 g2.fillPolygon(xx, yy, polygons[poly][0]); 351 g2.setColor(Color.black); 352 g2.drawPolygon(xx, yy, polygons[poly][0]); 353 } 354 355 356 /** 357 * A 3D matrix object. 358 */ 359 public class Matrix3D { 360 361 public double[][] M = { { 1, 0, 0 }, 362 { 0, 1, 0 }, 363 { 0, 0, 1 } }; 364 private double[][] tmp = new double[3][3]; 365 private int row, col, k; 366 367 public void Rotation(int i, int j, double angle) { 368 for (row = 0; row < 3; row++) { 369 for (col = 0; col < 3; col++) { 370 if (row != col) { 371 M[row][col] = 0.0; 372 } else { 373 M[row][col] = 1.0; 374 } 375 } 376 } 377 M[i][i] = cos(angle); 378 M[j][j] = cos(angle); 379 M[i][j] = sin(angle); 380 M[j][i] = -sin(angle); 381 } 382 383 public double[][] Times(double[][] N) { 384 for (row = 0; row < 3; row++) { 385 for (col = 0; col < 3; col++) { 386 tmp[row][col] = 0.0; 387 for (k = 0; k < 3; k++) { 388 tmp[row][col] += M[row][k] * N[k][col]; 389 } 390 } 391 } 392 return tmp; 393 } 394 } // End Matrix3D 395 } // End Objects3D 396 } // End Rotator3D 397