Crossfire JXClient, Trunk
ThreeD.java
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * - Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * - Neither the name of Oracle nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * This source code is provided to illustrate the usage of a given feature
34  * or technique and has been deliberately simplified. Additional steps
35  * required for a production-quality application, such as security checks,
36  * input validation and proper error handling, might not be present in
37  * this sample code.
38  */
39 
40 
41 
42 import java.applet.Applet;
43 import java.awt.Graphics;
44 import java.awt.Color;
45 import java.awt.event.*;
46 import java.io.*;
47 import java.net.URL;
48 
49 
50 /* A set of classes to parse, represent and display 3D wireframe models
51 represented in Wavefront .obj format. */
52 @SuppressWarnings("serial")
53 class FileFormatException extends Exception {
54 
55  public FileFormatException(String s) {
56  super(s);
57  }
58 }
59 
60 
62 final class Model3D {
63 
64  float vert[];
65  int tvert[];
66  int nvert, maxvert;
67  int con[];
68  int ncon, maxcon;
69  boolean transformed;
71  float xmin, xmax, ymin, ymax, zmin, zmax;
72 
73  Model3D() {
74  mat = new Matrix3D();
75  mat.xrot(20);
76  mat.yrot(30);
77  }
78 
80  Model3D(InputStream is) throws IOException, FileFormatException {
81  this();
82  StreamTokenizer st = new StreamTokenizer(
83  new BufferedReader(new InputStreamReader(is, "UTF-8")));
84  st.eolIsSignificant(true);
85  st.commentChar('#');
86  scan:
87  while (true) {
88  switch (st.nextToken()) {
89  default:
90  break scan;
91  case StreamTokenizer.TT_EOL:
92  break;
93  case StreamTokenizer.TT_WORD:
94  if ("v".equals(st.sval)) {
95  double x = 0, y = 0, z = 0;
96  if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
97  x = st.nval;
98  if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
99  y = st.nval;
100  if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
101  z = st.nval;
102  }
103  }
104  }
105  addVert((float) x, (float) y, (float) z);
106  while (st.ttype != StreamTokenizer.TT_EOL && st.ttype
107  != StreamTokenizer.TT_EOF) {
108  st.nextToken();
109  }
110  } else if ("f".equals(st.sval) || "fo".equals(st.sval) || "l".
111  equals(st.sval)) {
112  int start = -1;
113  int prev = -1;
114  int n = -1;
115  while (true) {
116  if (st.nextToken() == StreamTokenizer.TT_NUMBER) {
117  n = (int) st.nval;
118  if (prev >= 0) {
119  add(prev - 1, n - 1);
120  }
121  if (start < 0) {
122  start = n;
123  }
124  prev = n;
125  } else if (st.ttype == '/') {
126  st.nextToken();
127  } else {
128  break;
129  }
130  }
131  if (start >= 0) {
132  add(start - 1, prev - 1);
133  }
134  if (st.ttype != StreamTokenizer.TT_EOL) {
135  break scan;
136  }
137  } else {
138  while (st.nextToken() != StreamTokenizer.TT_EOL
139  && st.ttype != StreamTokenizer.TT_EOF) {
140  // no-op
141  }
142  }
143  }
144  }
145  is.close();
146  if (st.ttype != StreamTokenizer.TT_EOF) {
147  throw new FileFormatException(st.toString());
148  }
149  }
150 
152  int addVert(float x, float y, float z) {
153  int i = nvert;
154  if (i >= maxvert) {
155  if (vert == null) {
156  maxvert = 100;
157  vert = new float[maxvert * 3];
158  } else {
159  maxvert *= 2;
160  float nv[] = new float[maxvert * 3];
161  System.arraycopy(vert, 0, nv, 0, vert.length);
162  vert = nv;
163  }
164  }
165  i *= 3;
166  vert[i] = x;
167  vert[i + 1] = y;
168  vert[i + 2] = z;
169  return nvert++;
170  }
171 
173  void add(int p1, int p2) {
174  int i = ncon;
175  if (p1 >= nvert || p2 >= nvert) {
176  return;
177  }
178  if (i >= maxcon) {
179  if (con == null) {
180  maxcon = 100;
181  con = new int[maxcon];
182  } else {
183  maxcon *= 2;
184  int nv[] = new int[maxcon];
185  System.arraycopy(con, 0, nv, 0, con.length);
186  con = nv;
187  }
188  }
189  if (p1 > p2) {
190  int t = p1;
191  p1 = p2;
192  p2 = t;
193  }
194  con[i] = (p1 << 16) | p2;
195  ncon = i + 1;
196  }
197 
199  void transform() {
200  if (transformed || nvert <= 0) {
201  return;
202  }
203  if (tvert == null || tvert.length < nvert * 3) {
204  tvert = new int[nvert * 3];
205  }
207  transformed = true;
208  }
209 
210  /* Quick Sort implementation
211  */
212  private void quickSort(int a[], int left, int right) {
213  int leftIndex = left;
214  int rightIndex = right;
215  int partionElement;
216  if (right > left) {
217 
218  /* Arbitrarily establishing partition element as the midpoint of
219  * the array.
220  */
221  partionElement = a[(left + right) / 2];
222 
223  // loop through the array until indices cross
224  while (leftIndex <= rightIndex) {
225  /* find the first element that is greater than or equal to
226  * the partionElement starting from the leftIndex.
227  */
228  while ((leftIndex < right) && (a[leftIndex] < partionElement)) {
229  ++leftIndex;
230  }
231 
232  /* find an element that is smaller than or equal to
233  * the partionElement starting from the rightIndex.
234  */
235  while ((rightIndex > left) && (a[rightIndex] > partionElement)) {
236  --rightIndex;
237  }
238 
239  // if the indexes have not crossed, swap
240  if (leftIndex <= rightIndex) {
241  swap(a, leftIndex, rightIndex);
242  ++leftIndex;
243  --rightIndex;
244  }
245  }
246 
247  /* If the right index has not reached the left side of array
248  * must now sort the left partition.
249  */
250  if (left < rightIndex) {
251  quickSort(a, left, rightIndex);
252  }
253 
254  /* If the left index has not reached the right side of array
255  * must now sort the right partition.
256  */
257  if (leftIndex < right) {
258  quickSort(a, leftIndex, right);
259  }
260 
261  }
262  }
263 
264  private void swap(int a[], int i, int j) {
265  int T;
266  T = a[i];
267  a[i] = a[j];
268  a[j] = T;
269  }
270 
272  void compress() {
273  int limit = ncon;
274  int c[] = con;
275  quickSort(con, 0, ncon - 1);
276  int d = 0;
277  int pp1 = -1;
278  for (int i = 0; i < limit; i++) {
279  int p1 = c[i];
280  if (pp1 != p1) {
281  c[d] = p1;
282  d++;
283  }
284  pp1 = p1;
285  }
286  ncon = d;
287  }
288  static Color gr[];
289 
294  void paint(Graphics g) {
295  if (vert == null || nvert <= 0) {
296  return;
297  }
298  transform();
299  if (gr == null) {
300  gr = new Color[16];
301  for (int i = 0; i < 16; i++) {
302  int grey = (int) (170 * (1 - Math.pow(i / 15.0, 2.3)));
303  gr[i] = new Color(grey, grey, grey);
304  }
305  }
306  int lg = 0;
307  int lim = ncon;
308  int c[] = con;
309  int v[] = tvert;
310  if (lim <= 0 || nvert <= 0) {
311  return;
312  }
313  for (int i = 0; i < lim; i++) {
314  int T = c[i];
315  int p1 = ((T >> 16) & 0xFFFF) * 3;
316  int p2 = (T & 0xFFFF) * 3;
317  int grey = v[p1 + 2] + v[p2 + 2];
318  if (grey < 0) {
319  grey = 0;
320  }
321  if (grey > 15) {
322  grey = 15;
323  }
324  if (grey != lg) {
325  lg = grey;
326  g.setColor(gr[grey]);
327  }
328  g.drawLine(v[p1], v[p1 + 1],
329  v[p2], v[p2 + 1]);
330  }
331  }
332 
334  void findBB() {
335  if (nvert <= 0) {
336  return;
337  }
338  float v[] = vert;
339  float _xmin = v[0], _xmax = _xmin;
340  float _ymin = v[1], _ymax = _ymin;
341  float _zmin = v[2], _zmax = _zmin;
342  for (int i = nvert * 3; (i -= 3) > 0;) {
343  float x = v[i];
344  if (x < _xmin) {
345  _xmin = x;
346  }
347  if (x > _xmax) {
348  _xmax = x;
349  }
350  float y = v[i + 1];
351  if (y < _ymin) {
352  _ymin = y;
353  }
354  if (y > _ymax) {
355  _ymax = y;
356  }
357  float z = v[i + 2];
358  if (z < _zmin) {
359  _zmin = z;
360  }
361  if (z > _zmax) {
362  _zmax = z;
363  }
364  }
365  this.xmax = _xmax;
366  this.xmin = _xmin;
367  this.ymax = _ymax;
368  this.ymin = _ymin;
369  this.zmax = _zmax;
370  this.zmin = _zmin;
371  }
372 }
373 
374 
376 @SuppressWarnings("serial")
377 public class ThreeD extends Applet
378  implements Runnable, MouseListener, MouseMotionListener {
379 
381  boolean painted = true;
382  float xfac;
383  int prevx, prevy;
384  float scalefudge = 1;
385  Matrix3D amat = new Matrix3D(), tmat = new Matrix3D();
386  String mdname = null;
387  String message = null;
388 
389  @Override
390  public void init() {
391  mdname = getParameter("model");
392  try {
393  scalefudge = Float.valueOf(getParameter("scale")).floatValue();
394  } catch (Exception ignored) {
395  // fall back to default scalefudge = 1
396  }
397  amat.yrot(20);
398  amat.xrot(20);
399  if (mdname == null) {
400  mdname = "model.obj";
401  }
402  resize(getSize().width <= 20 ? 400 : getSize().width,
403  getSize().height <= 20 ? 400 : getSize().height);
404  addMouseListener(this);
405  addMouseMotionListener(this);
406  }
407 
408  @Override
409  public void destroy() {
410  removeMouseListener(this);
411  removeMouseMotionListener(this);
412  }
413 
414  @Override
415  public void run() {
416  InputStream is = null;
417  try {
418  Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
419  is = getClass().getResourceAsStream(mdname);
420  Model3D m = new Model3D(is);
421  md = m;
422  m.findBB();
423  m.compress();
424  float xw = m.xmax - m.xmin;
425  float yw = m.ymax - m.ymin;
426  float zw = m.zmax - m.zmin;
427  if (yw > xw) {
428  xw = yw;
429  }
430  if (zw > xw) {
431  xw = zw;
432  }
433  float f1 = getSize().width / xw;
434  float f2 = getSize().height / xw;
435  xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge;
436  } catch (Exception e) {
437  md = null;
438  message = e.toString();
439  }
440  try {
441  if (is != null) {
442  is.close();
443  }
444  } catch (Exception e) {
445  }
446  repaint();
447  }
448 
449  @Override
450  public void start() {
451  if (md == null && message == null) {
452  new Thread(this).start();
453  }
454  }
455 
456  @Override
457  public void stop() {
458  }
459 
460  @Override
461  public void mouseClicked(MouseEvent e) {
462  }
463 
464  @Override
465  public void mousePressed(MouseEvent e) {
466  prevx = e.getX();
467  prevy = e.getY();
468  e.consume();
469  }
470 
471  @Override
472  public void mouseReleased(MouseEvent e) {
473  }
474 
475  @Override
476  public void mouseEntered(MouseEvent e) {
477  }
478 
479  @Override
480  public void mouseExited(MouseEvent e) {
481  }
482 
483  @Override
484  public void mouseDragged(MouseEvent e) {
485  int x = e.getX();
486  int y = e.getY();
487 
488  tmat.unit();
489  float xtheta = (prevy - y) * 360.0f / getSize().width;
490  float ytheta = (x - prevx) * 360.0f / getSize().height;
491  tmat.xrot(xtheta);
492  tmat.yrot(ytheta);
493  amat.mult(tmat);
494  if (painted) {
495  painted = false;
496  repaint();
497  }
498  prevx = x;
499  prevy = y;
500  e.consume();
501  }
502 
503  @Override
504  public void mouseMoved(MouseEvent e) {
505  }
506 
507  @Override
508  public void paint(Graphics g) {
509  if (md != null) {
510  md.mat.unit();
511  md.mat.translate(-(md.xmin + md.xmax) / 2,
512  -(md.ymin + md.ymax) / 2,
513  -(md.zmin + md.zmax) / 2);
514  md.mat.mult(amat);
515  md.mat.scale(xfac, -xfac, 16 * xfac / getSize().width);
516  md.mat.translate(getSize().width / 2, getSize().height / 2, 8);
517  md.transformed = false;
518  md.paint(g);
519  setPainted();
520  } else if (message != null) {
521  g.drawString("Error in model:", 3, 20);
522  g.drawString(message, 10, 40);
523  }
524  }
525 
526  private synchronized void setPainted() {
527  painted = true;
528  notifyAll();
529  }
530 
531  @Override
532  public String getAppletInfo() {
533  return "Title: ThreeD \nAuthor: James Gosling? \n"
534  + "An applet to put a 3D model into a page.";
535  }
536 
537  @Override
538  public String[][] getParameterInfo() {
539  String[][] info = {
540  { "model", "path string", "The path to the model to be displayed." },
541  { "scale", "float", "The scale of the model. Default is 1." }
542  };
543  return info;
544  }
545 }
Model3D.xmax
float xmax
Definition: ThreeD.java:71
Model3D.swap
void swap(int a[], int i, int j)
Definition: ThreeD.java:264
ThreeD.destroy
void destroy()
Definition: ThreeD.java:409
Model3D.findBB
void findBB()
Definition: ThreeD.java:334
Model3D.paint
void paint(Graphics g)
Definition: ThreeD.java:294
Matrix3D.unit
void unit()
Definition: Matrix3D.java:209
Model3D.Model3D
Model3D()
Definition: ThreeD.java:73
Model3D.add
void add(int p1, int p2)
Definition: ThreeD.java:173
ThreeD.prevy
int prevy
Definition: ThreeD.java:383
Model3D.maxcon
int maxcon
Definition: ThreeD.java:68
ThreeD.getAppletInfo
String getAppletInfo()
Definition: ThreeD.java:532
Matrix3D
Definition: Matrix3D.java:44
Model3D.gr
static Color gr[]
Definition: ThreeD.java:288
Model3D.ncon
int ncon
Definition: ThreeD.java:68
ThreeD.xfac
float xfac
Definition: ThreeD.java:382
Model3D.tvert
int tvert[]
Definition: ThreeD.java:65
Model3D.mat
Matrix3D mat
Definition: ThreeD.java:70
ThreeD.mouseMoved
void mouseMoved(MouseEvent e)
Definition: ThreeD.java:504
Model3D.transformed
boolean transformed
Definition: ThreeD.java:69
FileFormatException
Definition: ThreeD.java:53
ThreeD.init
void init()
Definition: ThreeD.java:390
Model3D.vert
float vert[]
Definition: ThreeD.java:64
t
MemoryMonitor demonstrates the use of the java lang management API in observing the memory usage of all memory pools consumed by the application This simple demo program queries the memory usage of each memory pool and plots the memory usage history graph To run the MemoryMonitor demo java jar< JDK_HOME > demo management MemoryMonitor MemoryMonitor jar These instructions assume that this installation s version of the java command is in your path If it isn t
Definition: README.txt:44
ThreeD.mousePressed
void mousePressed(MouseEvent e)
Definition: ThreeD.java:465
ThreeD.setPainted
synchronized void setPainted()
Definition: ThreeD.java:526
ThreeD.mouseDragged
void mouseDragged(MouseEvent e)
Definition: ThreeD.java:484
Model3D.Model3D
Model3D(InputStream is)
Definition: ThreeD.java:80
Model3D.xmin
float xmin
Definition: ThreeD.java:71
ThreeD.mouseEntered
void mouseEntered(MouseEvent e)
Definition: ThreeD.java:476
Model3D.compress
void compress()
Definition: ThreeD.java:272
Model3D.zmax
float zmax
Definition: ThreeD.java:71
Model3D.nvert
int nvert
Definition: ThreeD.java:66
Model3D.transform
void transform()
Definition: ThreeD.java:199
Matrix3D.yrot
void yrot(double theta)
Definition: Matrix3D.java:98
Model3D.quickSort
void quickSort(int a[], int left, int right)
Definition: ThreeD.java:212
ThreeD.start
void start()
Definition: ThreeD.java:450
Matrix3D.transform
void transform(float v[], int tv[], int nvert)
Definition: Matrix3D.java:228
class
About including and JRadioButtonMenuItem Metalworks is optimized to work with the Java look and such as that are specific to the Java look and feel Running then you should either specify the complete path to the java command or update your PATH environment variable as described in the installation instructions for the and many controls are non functional They are intended only to show how to construct the UI for such interfaces Things that do work in the Metalworks demo but also the sizes of many controls Also included with this demo is the PropertiesMetalTheme class
Definition: README.txt:54
ThreeD.md
Model3D md
Definition: ThreeD.java:380
a
Xmixed mixed mode execution(default) -Xint interpreted mode execution only -Xbootclasspath set search path for bootstrap classes and resources Xbootclasspath a
Definition: Xusage.txt:1
Model3D.maxvert
int maxvert
Definition: ThreeD.java:66
ThreeD.run
void run()
Definition: ThreeD.java:415
Model3D.ymax
float ymax
Definition: ThreeD.java:71
ThreeD.getParameterInfo
String[][] getParameterInfo()
Definition: ThreeD.java:538
Matrix3D.scale
void scale(float f)
Definition: Matrix3D.java:59
ThreeD.mouseClicked
void mouseClicked(MouseEvent e)
Definition: ThreeD.java:461
Model3D.con
int con[]
Definition: ThreeD.java:67
ThreeD.stop
void stop()
Definition: ThreeD.java:457
Model3D.zmin
float zmin
Definition: ThreeD.java:71
Model3D.ymin
float ymin
Definition: ThreeD.java:71
Model3D
Definition: ThreeD.java:62
ThreeD
Definition: ThreeD.java:377
Model3D.addVert
int addVert(float x, float y, float z)
Definition: ThreeD.java:152
Matrix3D.mult
void mult(Matrix3D rhs)
Definition: Matrix3D.java:176
ThreeD.mouseExited
void mouseExited(MouseEvent e)
Definition: ThreeD.java:480
Matrix3D.translate
void translate(float x, float y, float z)
Definition: Matrix3D.java:91
ThreeD.paint
void paint(Graphics g)
Definition: ThreeD.java:508
ThreeD.mouseReleased
void mouseReleased(MouseEvent e)
Definition: ThreeD.java:472
Matrix3D.xrot
void xrot(double theta)
Definition: Matrix3D.java:124
FileFormatException.FileFormatException
FileFormatException(String s)
Definition: ThreeD.java:55