?? threed.java.bck
字號:
/* A set of classes to parse, represent and display 3D wireframe models represented in Wavefront .obj format. *//* I adapted this program, so that it doesn't read in a file any more, but gets the vertices and connections directly by an instance of the 'RoboProto' class. The orignal program is from the book 'Hooked on Java'.*/package RoboPackII;import java.applet.Applet;import java.awt.Graphics;import java.awt.Color;import java.awt.Event;import java.awt.*;class FileFormatException extends Exception { public FileFormatException(String s) { super(s); }}/** The representation of a 3D model */class Model3D { float[] vert; int tvert[]; int nvert = 0, maxvert; int[] con; int ncon = 0, maxcon; boolean transformed; Matrix3D mat; RoboProto rob; float xmin, xmax, ymin, ymax, zmin, zmax; Model3D (RoboProto datarob) { mat = new Matrix3D (); mat.xrot(20); mat.yrot(30); rob = datarob; maxvert = rob.numberOfPoints; maxcon = rob.numberOfEdges; vert = new float[maxvert * 3]; con = new int[maxcon]; for (int i = 0; i < maxvert; i++) addVert((float) rob.PL[i].x, (float) rob.PL[i].y, (float) rob.PL[i].z); for (int i = 0; i < maxcon; i++) add((int) rob.el[i].p1, (int) rob.el[i].p2); } /** Add a vertex to this model */ int addVert(float x, float y, float z) { int i = nvert; if (i >= maxvert) if (vert == null) { maxvert = 100; vert = new float[maxvert * 3]; } else { maxvert *= 2; float nv[] = new float[maxvert * 3]; System.arraycopy(vert, 0, nv, 0, vert.length); vert = nv; } i *= 3; vert[i] = x; vert[i + 1] = y; vert[i + 2] = z; return nvert++; } /** Add a line from vertex p1 to vertex p2 */ void add(int p1, int p2) { int i = ncon; if (p1 >= nvert || p2 >= nvert) return; if (i >= maxcon) if (con == null) { maxcon = 100; con = new int[maxcon]; } else { maxcon *= 2; int nv[] = new int[maxcon]; System.arraycopy(con, 0, nv, 0, con.length); con = nv; } if (p1 > p2) { int t = p1; p1 = p2; p2 = t; } con[i] = (p1 << 16) | p2; ncon = i + 1; } /** Transform all the points in this model */ void transform() { if (transformed || nvert <= 0) return; if (tvert == null || tvert.length < nvert * 3) tvert = new int[nvert*3]; mat.transform(vert, tvert, nvert); transformed = true; } private void sort(int lo0, int hi0) { int a[] = con; int lo = lo0; int hi = hi0; if (lo >= hi) return; int mid = a[(lo + hi) / 2]; while (lo < hi) { while (lo < hi && a[lo] < mid) { lo++; } while (lo < hi && a[hi] >= mid) { hi--; } if (lo < hi) { int T = a[lo]; a[lo] = a[hi]; a[hi] = T; } } if (hi < lo) { int T = hi; hi = lo; lo = T; } sort(lo0, lo); sort(lo == lo0 ? lo + 1 : lo, hi0); } /** eliminate duplicate lines */ void compress() { int limit = ncon; int c[] = con; sort(0, ncon - 1); int d = 0; int pp1 = -1; for (int i = 0; i < limit; i++) { int p1 = c[i]; if (pp1 != p1) { c[d] = p1; d++; } pp1 = p1; } ncon = d; } static Color gr[]; /** Paint this model to a graphics context. It uses the matrix associated with this model to map from model space to screen space. The next version of the browser should have double buffering, which will make this *much* nicer */ void paint(Graphics g) { if (vert == null || nvert <= 0) return; transform(); if (gr == null) { gr = new Color[16]; for (int i = 0; i < 16; i++) { int grey = (int) (170*(1-Math.pow(i/15.0, 2.3))); gr[i] = new Color(grey, grey, grey); } } int lg = 0; int lim = ncon; int c[] = con; int v[] = tvert; if (lim <= 0 || nvert <= 0) return; g.clearRect(0, 0, 499, 499); g.drawRect(2, 2, 490, 496); for (int i = 0; i < lim; i++) { int T = c[i]; int p1 = ((T >> 16) & 0xFFFF) * 3; int p2 = (T & 0xFFFF) * 3; int grey = v[p1 + 2] + v[p2 + 2]; if (grey < 0) grey = 0; if (grey > 15) grey = 15; if (grey != lg) { lg = grey; g.setColor(gr[grey]); } g.drawLine(v[p1], v[p1 + 1], v[p2], v[p2 + 1]); } } /** Find the bounding box of this model */ void findBB() { if (nvert <= 0) return; float v[] = vert; float xmin = v[0], xmax = xmin; float ymin = v[1], ymax = ymin; float zmin = v[2], zmax = zmin; for (int i = nvert * 3; (i -= 3) > 0;) { float x = v[i]; if (x < xmin) xmin = x; if (x > xmax) xmax = x; float y = v[i + 1]; if (y < ymin) ymin = y; if (y > ymax) ymax = y; float z = v[i + 2]; if (z < zmin) zmin = z; if (z > zmax) zmax = z; } this.xmax = xmax; this.xmin = xmin; this.ymax = ymax; this.ymin = ymin; this.zmax = zmax; this.zmin = zmin; }}/** A class to put a 3D model into a page */class ThreeD implements Runnable { Canvas goalCanvas; // the wireframe gets painted into this canvas RoboProto rob; // 'rob' is needed as a reference for 'Model3D' Model3D md; boolean painted = true; float xfac; int prevx, prevy; float xtheta, ytheta; float scalefudge = 0.5f; Matrix3D amat = new Matrix3D(), tmat = new Matrix3D(); String message = null; float f1 = 1, f2 = 1; //variables for the determination of the scale factor public ThreeD(Canvas inCanvas, RoboProto dataRobot) { // the canvas has to be 500x500 pixels large goalCanvas = inCanvas; rob = dataRobot; amat.yrot(5); amat.xrot(5); } public void setScale(float newScale) { if (newScale > 0) { scalefudge = newScale; xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge; } } public void run() { try { Thread.currentThread().setPriority(Thread.MIN_PRIORITY); Model3D m = new Model3D (rob); md = m; m.findBB(); m.compress(); float xw = m.xmax - m.xmin; float yw = m.ymax - m.ymin; float zw = m.zmax - m.zmin; if (yw > xw) xw = yw; if (zw > xw) xw = zw; f1 = goalCanvas.size().width / xw; // the model gets adapted f2 = goalCanvas.size().height / xw;// to the canvas size xfac = 0.7f * (f1 < f2 ? f1 : f2) * scalefudge; } catch(Exception e) { md = null; message = e.toString(); } this.repaint(); } public void start() { if (md == null && message == null) { new Thread(this).start(); repaint(); } } public void stop() { } public void setVert(int no, Points newCoordinates){ if ((no >= 0) && (no < rob.numberOfPoints)) { md.vert[3 * no] = (float)newCoordinates.x; md.vert[3 * no + 1] = (float)newCoordinates.y; md.vert[3 * no + 2] = (float)newCoordinates.z; md.transformed = false; } } public boolean mouseDown(Event e, int x, int y) { prevx = x; prevy = y; return true; } public boolean mouseDrag(Event e, int x, int y) { tmat.unit(); float xtheta = (prevy - y) * 360.0f / goalCanvas.size().width; float ytheta = (x - prevx) * 360.0f / goalCanvas.size().height; if (rob.rotateEverywhere) tmat.xrot(xtheta); // else this rotation is prohibited tmat.yrot(ytheta); amat.mult(tmat); if (painted) { painted = false; this.repaint(); } prevx = x; prevy = y; return true; } public void repaint() { this.paint(goalCanvas.getGraphics()); } public void paint(Graphics g) { // this g is the graphics of the canvas if (md != null) { md.mat.unit(); md.mat.translate(-(md.xmin + md.xmax) / 2, -(md.ymin + md.ymax) / 2, -(md.zmin + md.zmax) / 2); md.mat.mult(amat); md.mat.scale(xfac, -xfac, 16 * xfac / goalCanvas.size().width); md.mat.translate(goalCanvas.size().width / 2, goalCanvas.size().height / 2, 8); md.transformed = false; md.paint(g); setPainted(); } else if (message != null) { g.drawString("Error in model:", 3, 20); g.drawString(message, 10, 40); } } private synchronized void setPainted() { painted = true; notifyAll(); }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -