/* * Also see ThreeD.java */ /* Modified by Håkan Johansson 2000-02-10 */ import java.applet.Applet; import java.awt.Graphics; import java.awt.*; import java.awt.event.*; import java.io.*; import java.lang.Math; import java.net.URL; class FileFormatException extends Exception { public FileFormatException(String s) { super(s); } } /** The representation of a 3D model */ class Model3D { float vert[]; int tvert[]; float vertnorm[]; float verthit[]; int tverthit[]; float verthitfrom[]; int tverthitfrom[]; float tverthitfromz[]; int nvert, maxvert; int con[]; int ncon, maxcon; int tri[]; float trinorm[]; float ttrinormz[]; int ntri, maxtri; boolean transformed; boolean transformedhit; boolean transformedtrinorm; Matrix3D mat; Matrix3D matnorm; volatile boolean pauseInitCalc; volatile boolean killInitCalc; float xmin, xmax, ymin, ymax, zmin, zmax; Model3D () { mat = new Matrix3D (); mat.xrot(20); mat.yrot(30); matnorm = new Matrix3D (); matnorm.xrot(20); matnorm.yrot(30); pauseInitCalc = false; killInitCalc = false; } /** Create a 3D model by parsing an input stream */ void ScanFile (InputStream is,BtnOrText msg) throws IOException, FileFormatException { StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(is))); st.eolIsSignificant(true); st.commentChar('#'); scan: while (true) { switch (st.nextToken()) { default: break scan; case StreamTokenizer.TT_EOL: break; case StreamTokenizer.TT_WORD: if ("v".equals(st.sval)) { double x = 0, y = 0, z = 0; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { x = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { y = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) z = st.nval; } } addVert((float) x, (float) y, (float) z); if (nvert % 100 == 0) msg.SetLabelText("Vert: "+nvert); while (st.ttype != StreamTokenizer.TT_EOL && st.ttype != StreamTokenizer.TT_EOF) st.nextToken(); } else if ("w".equals(st.sval)) { double x = 0, y = 0, z = 0, xn = 0, yn = 0, zn = 0; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { x = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { y = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { z = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { xn = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) { yn = st.nval; if (st.nextToken() == StreamTokenizer.TT_NUMBER) zn = st.nval; } } } } } addVert((float) x, (float) y, (float) z,(float) xn, (float) yn, (float) zn); if (nvert % 100 == 0) msg.SetLabelText("Vert: "+nvert); while (st.ttype != StreamTokenizer.TT_EOL && st.ttype != StreamTokenizer.TT_EOF) st.nextToken(); } else if ("f".equals(st.sval) || "fo".equals(st.sval) || "l".equals(st.sval)) { int start = -1; int prev = -1; int n = -1; while (true) if (st.nextToken() == StreamTokenizer.TT_NUMBER) { n = (int) st.nval; if (prev >= 0) add(prev - 1, n - 1); if (start < 0) start = n; prev = n; } else if (st.ttype == '/') st.nextToken(); else break; if (start >= 0) add(start - 1, prev - 1); if (st.ttype != StreamTokenizer.TT_EOL) break scan; } else { while (st.nextToken() != StreamTokenizer.TT_EOL && st.ttype != StreamTokenizer.TT_EOF); } } } is.close(); if (st.ttype != StreamTokenizer.TT_EOF) throw new FileFormatException(st.toString()); } static final int maxlines = 7; void CreateLines(double somedist,double maxdist,BtnOrText msg) { double maxdistsqr = maxdist*maxdist; double thismaxdist; double thismaxdistsqr; int todo = nvert*(nvert-1); int done = 0; int to[] = new int[maxlines+1]; float dist[] = new float[maxlines+1]; for (int i = 0; i < nvert; i++) { if (i % 10 == 0) { msg.SetLabelText("Lines: "+((done*100)/todo)+"%"); if (CalcWaitOrKill ()) return; } int numlines = 0; thismaxdist = maxdist; thismaxdistsqr = maxdistsqr; for (int j = 0; j < nvert; j++) if (j != i) { // see if dist i -> j is less than maxdist int p1 = i * 3; int p2 = j * 3; double xd, yd, zd; double dsqr; if (Math.abs(xd = vert[p1 ] - vert[p2 ]) < thismaxdist && Math.abs(yd = vert[p1+1] - vert[p2+1]) < thismaxdist && Math.abs(zd = vert[p1+2] - vert[p2+2]) < thismaxdist && (dsqr = (xd*xd+yd*yd+zd*zd)) < thismaxdistsqr) { //if (numlines < maxlines || // dsqr < dist[numlines-1]) // { int ins; for (ins = numlines; ins > 0 && dist[ins-1] > dsqr; ins--) { to[ins] = to[ins-1]; dist[ins] = dist[ins-1]; } to[ins] = j; dist[ins] = (float) dsqr; if (numlines < maxlines) numlines++; else { thismaxdistsqr = dist[maxlines-1]; thismaxdist = Math.sqrt(thismaxdistsqr); } // } } } for (int j = 0; j < numlines; j++) { if (j > 3 && dist[j] > somedist) break; add(i,to[j]); } done += nvert-1; } } void CreateTris(BtnOrText msg) { int con2[] = new int[ncon]; for (int i = 0; i < ncon; i++) con2[i] = (((con[i] & 0xFFFF) << 16) | ((con[i]>> 16) & 0xFFFF)); quickSort(con2, 0, ncon - 1,1); for (int i = 0; i < ncon; i++) { if (i % 10 == 0) { msg.SetLabelText("Tris: "+((i*100)/ncon)+"%"); if (CalcWaitOrKill ()) return; } int p1 = ((con[i]>> 16) & 0xFFFF); int p2 = (con[i] & 0xFFFF); // see if we can find two other lines, one ending at some other p3<(p1,p2) // and one ending at p4>(p1,p2) // note that p1> 16) & 0xFFFF) == p1) i3max++; if (i3max == i3min) continue; // no such lines found // we now have line i (p1,p2) p1 < p2 // and the lines i3min..i3max-1 (p3,p1) p3 < p1 for (int i3 = i3min; i3 < i3max; i3++) { int p3 = (con2[i3] & 0xFFFF); //if (((con2[i3] >> 16) & 0xFFFF) != p1) // System.out.println ("Fail A"); //if (p3 >= p1) // System.out.println ("Fail B"); //System.out.println ("("+p3+","+p1+","+p2+") maybe"); // look for lines (p3,p2) p3 < p2 int iconnectmin = findfirstindex(con,p3); //if (iconnectmin < ncon && ((con[iconnectmin] >> 16) & 0xFFFF) < p3) // System.out.println ("Fail C"); //if (iconnectmin > 0 && ((con[iconnectmin-1] >> 16) & 0xFFFF) >= p3) // System.out.println ("Fail D"); while (iconnectmin < ncon && ((con[iconnectmin] >> 16) & 0xFFFF) == p3) { if ((con[iconnectmin] & 0xFFFF) == p2) { //System.out.println ("("+p3+","+p1+","+p2+")"); addtri (p3,p1,p2); } /*else if ((con[iconnectmin] & 0xFFFF) > p2) { int p4 = (con[iconnectmin] & 0xFFFF); // now see if we can find the line p2,p4 // System.out.println ("("+p3+","+p1+","+p2+","+p4+") maybe"); if (existinlist(con,((p2<<16)|p4))) { //System.out.println ("("+p3+","+p1+","+ // p2+","+p4+")"); //addtri (p3,p1,p2); //addtri (p1,p2,p4); } }*/ iconnectmin++; } } /* // and one ending at p1 and one ending at p2 for (int ia = 0; ia < ncon; ia++) { int pa1 = ((con[ia]>> 16) & 0xFFFF); if (pa1 >= p1) break; if ((con[ia] & 0xFFFF) == p1) { for (int ib = 0; ib < ncon; ib++) { if (((con[ib] >> 16) & 0xFFFF) == pa1 && (con[ib] & 0xFFFF) == p2) addtri (pa1,p1,p2); } } } */ } } int findfirstindex (int list[],int lookfor) { int at = 0; int max = list.length-1; while (at <= max) { int tryat = (at + max) >> 1; if (((list[tryat] >> 16) & 0xFFFF) < lookfor) at = tryat+1; else if (((list[tryat] >> 16) & 0xFFFF) >= lookfor) max = tryat-1; } //if (at < list.length && ((list[at] >> 16) & 0xFFFF) < lookfor) // System.out.println ("Fail 1"); //if (at > 0 && ((list[at-1] >> 16) & 0xFFFF) >= lookfor) // System.out.println ("Fail 2"); return at; } boolean existinlist (int list[],int lookfor) { int at = 0; int max = list.length-1; while (at <= max) { int tryat = (at + max) >> 1; if (list[tryat] < lookfor) at = tryat+1; else if (list[tryat] >= lookfor) max = tryat-1; } return (at < list.length && list[at] == lookfor); } boolean CalcWaitOrKill() { if (pauseInitCalc) { try { synchronized (this) { System.out.println ("wait "+this); while (pauseInitCalc) wait(); } } catch (InterruptedException ex) { } } if (killInitCalc) return true; return false; } void CreateHit(BtnOrText msg) { verthit = new float[nvert*3*3]; verthitfrom = new float[nvert*3]; for (int i = 0, iv = 0, ivh = 0; i < nvert; i++, iv += 3, ivh += 9) { if (i % 10 == 0) { msg.SetLabelText("Hit: "+((i*100)/nvert)+"%"); if (CalcWaitOrKill ()) return; } double x = vert[iv], y = vert[iv+1], z = vert[iv+2]; double xn = vertnorm[iv], yn = vertnorm[iv+1], zn = vertnorm[iv+2]; double div = Math.sqrt(xn*xn+yn*yn+zn*zn); //System.out.println ("xn "+div); xn /= div; yn /= div; zn /= div; double x1 = 0, y1 = 0, z1 = 0; if (Math.abs(xn) > Math.abs(yn) && Math.abs(xn) > Math.abs(zn)) { y1 = -xn; x1 = yn; } else { z1 = -yn; y1 = zn; } div = Math.sqrt(x1*x1+y1*y1+z1*z1); //System.out.println (" x1 "+div); x1 /= div; y1 /= div; z1 /= div; double x2 = (y1 * zn - z1 * yn), y2 = (z1 * xn - x1 * zn), z2 = (x1 * yn - y1 * xn); verthit[ivh ] = (float) (x+.75*(-x1)); verthit[ivh+1] = (float) (y+.75*(-y1)); verthit[ivh+2] = (float) (z+.75*(-z1)); verthit[ivh+3] = (float) (x+.75*(.5*x1+.866*x2)); verthit[ivh+4] = (float) (y+.75*(.5*y1+.866*y2)); verthit[ivh+5] = (float) (z+.75*(.5*z1+.866*z2)); verthit[ivh+6] = (float) (x+.75*(.5*x1-.866*x2)); verthit[ivh+7] = (float) (y+.75*(.5*y1-.866*y2)); verthit[ivh+8] = (float) (z+.75*(.5*z1-.866*z2)); verthitfrom[iv ] = (float) (x+xn*1.5); verthitfrom[iv+1] = (float) (y+yn*1.5); verthitfrom[iv+2] = (float) (z+zn*1.5); // System.out.println("("+i+","+iv+","+ivh+")"); // System.out.println("("+x+","+y+","+z+") ("+zn+","+yn+","+zn+") "); } /* float vert[]; int tvert[]; float vertnorm[]; float verthit[]; int tverthit[]; float verthitfrom[]; int tverthitfrom[]; float tverthitfromz[]; */ } int addVert(float x, float y, float z) { return addVert(x,y,z,0,0,1); } /** Add a vertex to this model */ int addVert(float x, float y, float z,float xn, float yn, float zn) { int i = nvert; if (i >= maxvert) if (vert == null) { maxvert = 100; vert = new float[maxvert * 3]; vertnorm = new float[maxvert * 3]; } else { maxvert *= 2; float nv[] = new float[maxvert * 3]; System.arraycopy(vert, 0, nv, 0, vert.length); vert = nv; float nvn[] = new float[maxvert * 3]; System.arraycopy(vertnorm, 0, nvn, 0, vertnorm.length); vertnorm = nvn; } i *= 3; vert[i] = x; vert[i + 1] = y; vert[i + 2] = z; vertnorm[i] = xn; vertnorm[i + 1] = yn; vertnorm[i + 2] = zn; 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; } /** Add a tri from vertex p1,p2,p3 */ void addtri(int p1, int p2,int p3) { int i = ntri; if (p1 >= nvert || p2 >= nvert || p3 >= nvert) return; if (i >= maxtri) if (tri == null) { maxtri = 100; tri = new int[maxtri*3]; trinorm = new float[maxtri*3]; } else { maxtri *= 2; int nv[] = new int[maxtri*3]; System.arraycopy(tri, 0, nv, 0, tri.length); tri = nv; float fv[] = new float[maxtri*3]; System.arraycopy(trinorm, 0, fv, 0, trinorm.length); trinorm = fv; } if (p1 > p2) { int t = p1; p1 = p2; p2 = t; } if (p2 > p3) { int t = p2; p2 = p3; p3 = t; } if (p1 > p2) { int t = p1; p1 = p2; p2 = t; } tri[i*3] = p1; tri[i*3+1] = p2; tri[i*3+2] = p3; int j1 = p1*3, j2 = p2*3, j3 = p3*3; double x1 = vert[j2 ]-vert[j1 ], y1 = vert[j2+1]-vert[j1+1], z1 = vert[j2+2]-vert[j1+2]; double x2 = vert[j3 ]-vert[j1 ], y2 = vert[j3+1]-vert[j1+1], z2 = vert[j3+2]-vert[j1+2]; double x3 = (y1 * z2 - z1 * y2), y3 = (z1 * x2 - x1 * z2), z3 = (x1 * y2 - y1 * x2); double xn = vert[j1 ]+vert[j2 ]+vert[j3 ]; double yn = vert[j1+1]+vert[j2+1]+vert[j3+1]; double zn = vert[j1+2]+vert[j2+2]+vert[j3+2]; if (x3*xn+y3*yn+z3*zn < 0) { x3 = -x3; y3 = -y3; z3 = -z3; } double div = Math.sqrt(x3*x3+y3*y3+z3*z3); if (div < 1e-7) { x3=1;y3=0;z3=0; } else { x3 /= div; y3 /= div; z3 /= div; } trinorm[i*3 ] = (float) x3; trinorm[i*3+1] = (float) y3; trinorm[i*3+2] = (float) z3; // System.out.println (""+x3+" , "+y3+" , "+z3+"..."); ntri = i + 1; // System.out.println (""+p1+","+p2+","+p3+"..."); } /** 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]; //tvertnorm = new int[nvert*3]; } mat.transform(vert, tvert, nvert); //mat.transform(vertnorm, tvertnorm, nvert); transformed = true; } void transformtrinorm() { if (transformedtrinorm || nvert <= 0) return; if (ttrinormz == null || ttrinormz.length < ntri) { ttrinormz = new float[ntri]; } matnorm.transform(trinorm, ttrinormz, ntri); //mat.transform(vertnorm, tvertnorm, nvert); transformedtrinorm = true; } void transformhit() { if (transformedhit || nvert <= 0) return; if (tverthit == null || tverthit.length < nvert * 3) { tverthit = new int[nvert*3*3]; tverthitfrom = new int[nvert*3]; tverthitfromz = new float[nvert]; } mat.transform(verthit, tverthit, nvert*3); mat.transform(verthitfrom, tverthitfrom, nvert); matnorm.transform(vertnorm, tverthitfromz, nvert); transformedhit = true; } /* Quick Sort implementation */ private void quickSort(int a[], int left, int right,int objsize) { int T; int leftIndex = left; int rightIndex = right; int partionElement; if ( right > left) { partionElement = a[ (( left + right ) / 2)]; while( leftIndex <= rightIndex ) { while( ( leftIndex < right ) && ( a[leftIndex] < partionElement ) ) leftIndex += objsize; while( ( rightIndex > left ) && ( a[rightIndex] > partionElement ) ) rightIndex -= objsize; if( leftIndex <= rightIndex ) { for (int k = objsize, j = rightIndex; k != 0; k--, j++) { T = a[leftIndex]; a[leftIndex++] = a[j]; a[j] = T; } // swap(a, leftIndex, rightIndex,objsize); //leftIndex += objsize; rightIndex -= objsize; } } if( left < rightIndex ) quickSort( a, left, rightIndex,objsize ); if( leftIndex < right ) quickSort( a, leftIndex, right,objsize ); } } /* private void swap(int a[], int i, int j,int objsize) { int T; } */ /** eliminate duplicate lines */ void compress() { // System.out.println ("lines: "+ncon); int limit = ncon; int c[] = con; quickSort(con, 0, ncon - 1,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; // System.out.println ("lines: "+ncon); } 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 gp,Canvas cv,int paintmethod) { try { Dimension dim = cv.getSize(); int w = dim.width; int h = dim.height; if (vert == null || nvert <= 0) { gp.clearRect(0,0,w,h); return; } Image img = cv.createImage(w,h); Graphics g = img.getGraphics(); g.clearRect(0,0,w,h); 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 np = 0; // 3 for points, 5 for lines, 8 for tris, 13 for trilines int xyz[] = null; if (paintmethod == 0) { int v[] = tvert; np = 3; xyz = new int[nvert*3]; for (int i = 0; i < nvert; i++) { int p1 = i * 3; xyz[p1 ] = v[p1+2]*2; xyz[p1+1] = v[p1]; xyz[p1+2] = v[p1+1]; } } else if (paintmethod == 1 && ncon > 0) { transformhit(); int v[] = tvert; int vh[] = tverthit; int vhf[] = tverthitfrom; float vhfz[] = tverthitfromz; np = 13; xyz = new int[nvert*13]; for (int i = 0; i < nvert; i++) { int p1 = i * 3; int p2 = i * 9; int p3 = i * 13; xyz[p3 ] = v[p1+2]*2; xyz[p3+1 ] = 7 - (int) (6 * vhfz[i]); xyz[p3+2 ] = (vhfz[i] < 0) ? 1 : 0; xyz[p3+3 ] = v[p1 ]; xyz[p3+4 ] = v[p1+1]; xyz[p3+5 ] = vhf[p1 ]; xyz[p3+6 ] = vhf[p1+1]; xyz[p3+7 ] = vh[p2 ]; xyz[p3+8 ] = vh[p2+1]; xyz[p3+9 ] = vh[p2+3]; xyz[p3+10] = vh[p2+4]; xyz[p3+11] = vh[p2+6]; xyz[p3+12] = vh[p2+7]; } /* float vert[]; int tvert[]; float vertnorm[]; int tvertnorm[]; float verthit[]; int tverthit[]; float verthitfrom[]; int tverthitfrom[]; float tverthitfromz[]; float verthit[]; int tverthit[]; float verthitfrom[]; int tverthitfrom[]; float tverthitfromz[]; */ } else if (paintmethod == 2 && ncon > 0) { int c[] = con; int v[] = tvert; np = 5; xyz = new int[ncon*5]; for (int i = 0, i2 = 0; i < ncon; i++) { int T = c[i]; int p1 = ((T >> 16) & 0xFFFF) * 3; int p2 = (T & 0xFFFF) * 3; xyz[i2++] = v[p1 + 2] + v[p2 + 2]; xyz[i2++] = v[p1]; xyz[i2++] = v[p1+1]; xyz[i2++] = v[p2]; xyz[i2++] = v[p2+1]; } } else if (paintmethod == 3 && ntri > 0) { transformtrinorm(); int t[] = tri; int v[] = tvert; np = 8; xyz = new int[ntri*8]; for (int i = 0, i2 = 0, i3 = 0; i < ntri; i++) { int p1 = t[i3++]*3; int p2 = t[i3++]*3; int p3 = t[i3++]*3; // System.out.println (""+p1+","+p2+","+p3); xyz[i2++] = v[p1 + 2] + v[p2 + 2]; xyz[i2++] = 7 + (int) (6 * ttrinormz[i]); xyz[i2++] = v[p1]; xyz[i2++] = v[p1+1]; xyz[i2++] = v[p2]; xyz[i2++] = v[p2+1]; xyz[i2++] = v[p3]; xyz[i2++] = v[p3+1]; } } if (xyz != null) { quickSort(xyz,0,xyz.length-np,np); int lg = -1; if (np == 3) for (int i = 0; i < xyz.length; i += 3) { int grey = xyz[i]; if (grey < 0) grey = 0; if (grey > 15) grey = 15; if (grey != lg) { lg = grey; g.setColor(gr[grey]); } g.drawLine(xyz[i+1], xyz[i+2], xyz[i+1]+1, xyz[i+2]+1); } if (np == 5) for (int i = 0; i < xyz.length; i += 5) { int grey = xyz[i]; if (grey < 0) grey = 0; if (grey > 15) grey = 15; if (grey != lg) { lg = grey; g.setColor(gr[grey]); } g.drawLine(xyz[i+1], xyz[i+2], xyz[i+3], xyz[i+4]); } if (np == 8) { int x[] = new int[3]; int y[] = new int[3]; for (int i = 0; i < xyz.length; i += 8) { int grey = xyz[i+1]; if (grey < 0) grey = 0; if (grey > 15) grey = 15; if (grey != lg) { lg = grey; g.setColor(gr[grey]); } x[0] = xyz[i+2 ]; x[1] = xyz[i+4 ]; x[2] = xyz[i+6 ]; y[0] = xyz[i+3 ]; y[1] = xyz[i+5 ]; y[2] = xyz[i+7 ]; g.fillPolygon (x,y,3); } } if (np == 13) { int x[] = new int[3]; int y[] = new int[3]; for (int i = 0; i < xyz.length; i += 13) { if (xyz[i+2] != 0) { if (0 != lg) { lg = 0; g.setColor(gr[15]); } g.drawLine(xyz[i+3], xyz[i+4], xyz[i+5], xyz[i+6]); } int grey = xyz[i+1]; if (grey < 0) grey = 0; if (grey > 15) grey = 15; if (grey != lg) { lg = grey; g.setColor(gr[grey]); } x[0] = xyz[i+7 ]; x[1] = xyz[i+9 ]; x[2] = xyz[i+11]; y[0] = xyz[i+8 ]; y[1] = xyz[i+10]; y[2] = xyz[i+12]; g.fillPolygon (x,y,3); if (xyz[i+2] == 0) { if (0 != lg) { lg = 0; g.setColor(gr[15]); } g.drawLine(xyz[i+3], xyz[i+4], xyz[i+5], xyz[i+6]); } } } } gp.drawImage(img,0,0,null); } catch (Exception ex) { gp.drawString("Failure during drawing", 3, 20); ex.printStackTrace (); } } /** 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; } }