Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/applets/WireFrame/ThreeD.java
38829 views
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
61
/** The representation of a 3D model */
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;
70
Matrix3D mat;
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
79
/** Create a 3D model by parsing an input stream */
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
151
/** Add a vertex to this model */
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
172
/** Add a line from vertex p1 to vertex p2 */
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
198
/** Transform all the points in this model */
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
}
206
mat.transform(vert, tvert, nvert);
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
271
/** eliminate duplicate lines */
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
290
/** Paint this model to a graphics context. It uses the matrix associated
291
with this model to map from model space to screen space.
292
The next version of the browser should have double buffering,
293
which will make this *much* nicer */
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
333
/** Find the bounding box of this model */
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
375
/** An applet to put a 3D model into a page */
376
@SuppressWarnings("serial")
377
public class ThreeD extends Applet
378
implements Runnable, MouseListener, MouseMotionListener {
379
380
Model3D md;
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
}
546
547