1 36 37 40 41 43 44 import java.applet.Applet ; 45 import java.awt.Graphics ; 46 import java.awt.Color ; 47 import java.awt.Event ; 48 import java.awt.event.*; 49 import java.io.*; 50 import java.net.URL ; 51 52 class FileFormatException extends Exception { 53 public FileFormatException(String s) { 54 super(s); 55 } 56 } 57 58 59 class Model3D { 60 float vert[]; 61 int tvert[]; 62 int nvert, maxvert; 63 int con[]; 64 int ncon, maxcon; 65 boolean transformed; 66 Matrix3D mat; 67 68 float xmin, xmax, ymin, ymax, zmin, zmax; 69 70 Model3D () { 71 mat = new Matrix3D (); 72 mat.xrot(20); 73 mat.yrot(30); 74 } 75 76 Model3D (InputStream is) throws IOException, FileFormatException { 77 this(); 78 StreamTokenizer st = new StreamTokenizer( 79 new BufferedReader(new InputStreamReader(is, "UTF-8"))); 80 st.eolIsSignificant(true); 81 st.commentChar('#'); 82 scan: 83 while (true) { 84 switch (st.nextToken()) { 85 default: 86 break scan; 87 case StreamTokenizer.TT_EOL: 88 break; 89 case StreamTokenizer.TT_WORD: 90 if ("v".equals(st.sval)) { 91 double x = 0, y = 0, z = 0; 92 if (st.nextToken() == StreamTokenizer.TT_NUMBER) { 93 x = st.nval; 94 if (st.nextToken() == StreamTokenizer.TT_NUMBER) { 95 y = st.nval; 96 if (st.nextToken() == StreamTokenizer.TT_NUMBER) 97 z = st.nval; 98 } 99 } 100 addVert((float) x, (float) y, (float) z); 101 while (st.ttype != StreamTokenizer.TT_EOL && 102 st.ttype != StreamTokenizer.TT_EOF) 103 st.nextToken(); 104 } else if ("f".equals(st.sval) || "fo".equals(st.sval) || "l".equals(st.sval)) { 105 int start = -1; 106 int prev = -1; 107 int n = -1; 108 while (true) 109 if (st.nextToken() == StreamTokenizer.TT_NUMBER) { 110 n = (int) st.nval; 111 if (prev >= 0) 112 add(prev - 1, n - 1); 113 if (start < 0) 114 start = n; 115 prev = n; 116 } else if (st.ttype == '/') 117 st.nextToken(); 118 else 119 break; 120 if (start >= 0) 121 add(start - 1, prev - 1); 122 if (st.ttype != StreamTokenizer.TT_EOL) 123 break scan; 124 } else { 125 while (st.nextToken() != StreamTokenizer.TT_EOL 126 && st.ttype != StreamTokenizer.TT_EOF); 127 } 128 } 129 } 130 is.close(); 131 if (st.ttype != StreamTokenizer.TT_EOF) 132 throw new FileFormatException(st.toString()); 133 } 134 135 136 int addVert(float x, float y, float z) { 137 int i = nvert; 138 if (i >= maxvert) 139 if (vert == null) { 140 maxvert = 100; 141 vert = new float[maxvert * 3]; 142 } else { 143 maxvert *= 2; 144 float nv[] = new float[maxvert * 3]; 145 System.arraycopy(vert, 0, nv, 0, vert.length); 146 vert = nv; 147 } 148 i *= 3; 149 vert[i] = x; 150 vert[i + 1] = y; 151 vert[i + 2] = z; 152 return nvert++; 153 } 154 155 void add(int p1, int p2) { 156 int i = ncon; 157 if (p1 >= nvert || p2 >= nvert) 158 return; 159 if (i >= maxcon) 160 if (con == null) { 161 maxcon = 100; 162 con = new int[maxcon]; 163 } else { 164 maxcon *= 2; 165 int nv[] = new int[maxcon]; 166 System.arraycopy(con, 0, nv, 0, con.length); 167 con = nv; 168 } 169 if (p1 > p2) { 170 int t = p1; 171 p1 = p2; 172 p2 = t; 173 } 174 con[i] = (p1 << 16) | p2; 175 ncon = i + 1; 176 } 177 178 void transform() { 179 if (transformed || nvert <= 0) 180 return; 181 if (tvert == null || tvert.length < nvert * 3) 182 tvert = new int[nvert*3]; 183 mat.transform(vert, tvert, nvert); 184 transformed = true; 185 } 186 187 189 private void quickSort(int a[], int left, int right) 190 { 191 int leftIndex = left; 192 int rightIndex = right; 193 int partionElement; 194 if ( right > left) 195 { 196 197 200 partionElement = a[ ( left + right ) / 2 ]; 201 202 while( leftIndex <= rightIndex ) 204 { 205 208 while( ( leftIndex < right ) && ( a[leftIndex] < partionElement ) ) 209 ++leftIndex; 210 211 214 while( ( rightIndex > left ) && 215 ( a[rightIndex] > partionElement ) ) 216 --rightIndex; 217 218 if( leftIndex <= rightIndex ) 220 { 221 swap(a, leftIndex, rightIndex); 222 ++leftIndex; 223 --rightIndex; 224 } 225 } 226 227 230 if( left < rightIndex ) 231 quickSort( a, left, rightIndex ); 232 233 236 if( leftIndex < right ) 237 quickSort( a, leftIndex, right ); 238 239 } 240 } 241 242 private void swap(int a[], int i, int j) 243 { 244 int T; 245 T = a[i]; 246 a[i] = a[j]; 247 a[j] = T; 248 } 249 250 251 252 void compress() { 253 int limit = ncon; 254 int c[] = con; 255 quickSort(con, 0, ncon - 1); 256 int d = 0; 257 int pp1 = -1; 258 for (int i = 0; i < limit; i++) { 259 int p1 = c[i]; 260 if (pp1 != p1) { 261 c[d] = p1; 262 d++; 263 } 264 pp1 = p1; 265 } 266 ncon = d; 267 } 268 269 static Color gr[]; 270 271 275 void paint(Graphics g) { 276 if (vert == null || nvert <= 0) 277 return; 278 transform(); 279 if (gr == null) { 280 gr = new Color [16]; 281 for (int i = 0; i < 16; i++) { 282 int grey = (int) (170*(1-Math.pow(i/15.0, 2.3))); 283 gr[i] = new Color (grey, grey, grey); 284 } 285 } 286 int lg = 0; 287 int lim = ncon; 288 int c[] = con; 289 int v[] = tvert; 290 if (lim <= 0 || nvert <= 0) 291 return; 292 for (int i = 0; i < lim; i++) { 293 int T = c[i]; 294 int p1 = ((T >> 16) & 0xFFFF) * 3; 295 int p2 = (T & 0xFFFF) * 3; 296 int grey = v[p1 + 2] + v[p2 + 2]; 297 if (grey < 0) 298 grey = 0; 299 if (grey > 15) 300 grey = 15; 301 if (grey != lg) { 302 lg = grey; 303 g.setColor(gr[grey]); 304 } 305 g.drawLine(v[p1], v[p1 + 1], 306 v[p2], v[p2 + 1]); 307 } 308 } 309 310 311 void findBB() { 312 if (nvert <= 0) 313 return; 314 float v[] = vert; 315 float xmin = v[0], xmax = xmin; 316 float ymin = v[1], ymax = ymin; 317 float zmin = v[2], zmax = zmin; 318 for (int i = nvert * 3; (i -= 3) > 0;) { 319 float x = v[i]; 320 if (x < xmin) 321 xmin = x; 322 if (x > xmax) 323 xmax = x; 324 float y = v[i + 1]; 325 if (y < ymin) 326 ymin = y; 327 if (y > ymax) 328 ymax = y; 329 float z = v[i + 2]; 330 if (z < zmin) 331 zmin = z; 332 if (z > zmax) 333 zmax = z; 334 } 335 this.xmax = xmax; 336 this.xmin = xmin; 337 this.ymax = ymax; 338 this.ymin = ymin; 339 this.zmax = zmax; 340 this.zmin = zmin; 341 } 342 } 343 344 345 public class ThreeD extends Applet  346 implements Runnable , MouseListener, MouseMotionListener { 347 Model3D md; 348 boolean painted = true; 349 float xfac; 350 int prevx, prevy; 351 float xtheta, ytheta; 352 float scalefudge = 1; 353 Matrix3D amat = new Matrix3D(), tmat = new Matrix3D(); 354 String mdname = null; 355 String message = null; 356 357 public void init() { 358 mdname = getParameter("model"); 359 try { 360 scalefudge = Float.valueOf(getParameter("scale")).floatValue(); 361 }catch(Exception e){}; 362 amat.yrot(20); 363 amat.xrot(20); 364 if (mdname == null) 365 mdname = "model.obj"; 366 resize(getSize().width <= 20 ? 400 : getSize().width, 367 getSize().height <= 20 ? 400 : getSize().height); 368 addMouseListener(this); 369 addMouseMotionListener(this); 370 } 371 372 public void destroy() { 373 removeMouseListener(this); 374 removeMouseMotionListener(this); 375 } 376 377 public void run() { 378 InputStream is = null; 379 try { 380 Thread.currentThread().setPriority(Thread.MIN_PRIORITY); 381 is = new URL (getDocumentBase(), mdname).openStream(); 382 Model3D m = new Model3D (is); 383 md = m; 384 m.findBB(); 385 m.compress(); 386 float xw = m.xmax - m.xmin; 387 float yw = m.ymax - m.ymin; 388 float zw = m.zmax - m.zmin; 389 if (yw > xw) 390 xw = yw; 391 if (zw > xw) 392 xw = zw; 393 float f1 = getSize().width / xw; 394 float f2 = getSize().height / xw; 395 xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge; 396 } catch(Exception e) { 397 md = null; 398 message = e.toString(); 399 } 400 try { 401 if (is != null) 402 is.close(); 403 } catch(Exception e) { 404 } 405 repaint(); 406 } 407 408 public void start() { 409 if (md == null && message == null) 410 new Thread (this).start(); 411 } 412 413 public void stop() { 414 } 415 416 public void mouseClicked(MouseEvent e) { 417 } 418 419 public void mousePressed(MouseEvent e) { 420 prevx = e.getX(); 421 prevy = e.getY(); 422 e.consume(); 423 } 424 425 public void mouseReleased(MouseEvent e) { 426 } 427 428 public void mouseEntered(MouseEvent e) { 429 } 430 431 public void mouseExited(MouseEvent e) { 432 } 433 434 public void mouseDragged(MouseEvent e) { 435 int x = e.getX(); 436 int y = e.getY(); 437 438 tmat.unit(); 439 float xtheta = (prevy - y) * 360.0f / getSize().width; 440 float ytheta = (x - prevx) * 360.0f / getSize().height; 441 tmat.xrot(xtheta); 442 tmat.yrot(ytheta); 443 amat.mult(tmat); 444 if (painted) { 445 painted = false; 446 repaint(); 447 } 448 prevx = x; 449 prevy = y; 450 e.consume(); 451 } 452 453 public void mouseMoved(MouseEvent e) { 454 } 455 456 public void paint(Graphics g) { 457 if (md != null) { 458 md.mat.unit(); 459 md.mat.translate(-(md.xmin + md.xmax) / 2, 460 -(md.ymin + md.ymax) / 2, 461 -(md.zmin + md.zmax) / 2); 462 md.mat.mult(amat); 463 md.mat.scale(xfac, -xfac, 16 * xfac / getSize().width); 464 md.mat.translate(getSize().width / 2, getSize().height / 2, 8); 465 md.transformed = false; 466 md.paint(g); 467 setPainted(); 468 } else if (message != null) { 469 g.drawString("Error in model:", 3, 20); 470 g.drawString(message, 10, 40); 471 } 472 } 473 474 private synchronized void setPainted() { 475 painted = true; 476 notifyAll(); 477 } 478 484 public String getAppletInfo() { 485 return "Title: ThreeD \nAuthor: James Gosling? \nAn applet to put a 3D model into a page."; 486 } 487 488 public String [][] getParameterInfo() { 489 String [][] info = { 490 {"model", "path string", "The path to the model to be displayed."}, 491 {"scale", "float", "The scale of the model. Default is 1."} 492 }; 493 return info; 494 } 495 } 496
| Popular Tags
|