⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bbsjava1.txt

📁 标 题: Java example(1) 发信站: BBS 水木清华站
💻 TXT
字号:
BBS水木清华站∶精华区
发信人: VolVis (arthur), 信区: Java 
标  题: Java example(1) 
发信站: BBS 水木清华站 (Fri Dec 25 13:36:27 1998) WWW-POST 
 
Dear Everyone:  
 
I just have read a java program to draw a 3d face was written by Daeron  
Meyer, The Geometry Center, University of Minnesota. I do think it is a good  
program to illustrate the java appletview and the 3d Graphics although it  
only draw a polygon without clipping and lingting. It inludes three class:  
Viewer3D, Matrix3D and OOGL_OFF. The most important class is OOGL_OFF, I  
will  
explain it and the other 2 class in the java program.The last part was one  
OFF  
format file and one html file.I hope it will be helpful to you.  
 
 
Yours VolVis  
Information Department of Peking University  
The following will give you a detailed explaination about the class OOGL_OFF  
(1) findBB() is to calculate the bounding box of the object  
    why? the answer is to put all the vertices in a box, so the coordinate  
    transform can the (0,0,0) to be the object center.  
(2) paint() is the most function in the class OOGL_OFF, for it using the  
    Painter's algorithm to paint the scenes. Do you know the Painter's  
    algorithm? The algorithm is to align the object in the reverse erder of  
    their distance from the eye. As common, the eye is placed in minus z  
axis,  
    so the sort the object according to object parameter depth. The the  
farther  
    object will be painted earlier, and the nearest object will be painted  
the  
    latest. Perhaps, the nearer object will hide the farther object. Let's  
see  
    the java program: At first, it will allocate the color for the face  
    gr[i] = new Color(face[i].cr, face[i].cg, face[i].cb) 0 <= i <= number  
of  
    faces. then quick sort the faces by the qs function whose algorithm is  
    the same asthe dividing method in data structure. At last paint the  
    faces by the function g.fillPolygon(vx, vy, face[i].nverts) and paint  
the  
    edges by the function g.drawLine(vx[v], vy[v], vx[v+1], vy[v+1])  
(3) the readObject function is to read the faces from the OFF file. The  
first  
    line of OFF file is the tag OFF, the following is number of vertices ,  
    number of faces, and number of edges. Then the three dimensional data of  
    vertices is following them. The next thing is data of faces, including  
the  
    number of vertices in the face, the vertex index, and the color of face.  
i  
    In the OFF file, you can add any comment with the head #. Now, if you  
are  
    familiar with the java, you can read the OFF file either. But I have to  
    remind you that the class StreamTokenizer is a good way to do this work.  
 
/**  
 *  
 * Author: Daeron Meyer  
 * Copyright (c) 1995 by The Geometry Center, University of Minnesota  
 * Distributed under the terms of the GNU Library General Public License  
 * 12-14-95  
 *  
 */  
 
import java.applet.Applet;  
import java.awt.Graphics;  
import java.awt.Color;  
import java.awt.Event;  
import java.lang.*;  
import java.io.StreamTokenizer;  
import java.io.InputStream;  
import java.io.IOException;  
import java.net.URL;  
 
/**  
 *  class Face: your basic storage class for polygonal face information.  
 */  
 
class Face {  
 
  public int nverts; // number of vertices  
  public int index[]; // array of indices  
  public int cr, cg, cb; // face color in RGB  
  public int zdepth; // z depth of furthest vertex  
 
  Face () {  
    nverts = 0;  
    index = null;  
    cr = 255; cg = 255; cb = 255;  
  }  
 
  Face (int nv) {  
    nverts = nv;  
    index = new int[nv];  
    cr = 255; cg = 255; cb = 255;  
  }  
 
  public void numVerts(int nv) {  
    nverts = nv;  
    index = new int[nv];  
  }  
}  
 
/**  
 *  class OOGL_OFF: a class for parsing, storing and rendering OFF 3D models  
 *  
 *  For more information about OFF files and other OOGL (Object Oriented  
 *  Graphics Library) file formats, check the following URL:  
 *  
 *  http://www.geom.umn.edu/software/geomview/docs/oogltour.html  
 */  
 
public class OOGL_OFF {  
 
  Face face[]; // array of faces  
  boolean transformed, gothead;  
  Matrix3D mat; // applied 3D transformation  
  public float xmin, xmax, // bounding box parameters  
ymin, ymax,  
zmin, zmax;  
  float vert[]; // array of vertex coordinates  
  int nverts, nfaces, nedges, // # of vertices, faces, edges  
vx[], vy[], // coords for rendering faces  
tvert[], // transformed vertices  
findex[]; // indices into face list  
  Color gr[]; // face colors  
  final int MAX_VERTS = 100; // assume each polygonal face  
// has less than 100 vertices.  
    
  OOGL_OFF () {  
    mat = new Matrix3D();  
    vx = new int[MAX_VERTS];  
    vy = new int[MAX_VERTS];  
    nverts = 0;  
    nedges = 0;  
    nfaces = 0;  
    vert = null;  
    gr = null;  
    mat.xrot(0); mat.yrot(0);  
  }  
 
  OOGL_OFF (URL loc) { // read object from any URL  
 
    this();  
    try {  
      readObject(loc.openStream());  
    } catch (IOException e) {  
      System.out.println(e.getMessage());  
    }  
 
  }  
    
  OOGL_OFF (InputStream is) { // read object from a stream  
 
    this();  
    try {  
      readObject(is);  
    } catch (IOException e) {  
      System.out.println(e.getMessage());  
    }  
 
  }  
 
 
/* This method parses an OFF file. */  
 
  void readObject(InputStream is) throws IOException {  
 
    StreamTokenizer stream = new StreamTokenizer (is);  
 
    stream.eolIsSignificant(true);  
    stream.commentChar('#');  
    gothead = false;  
 
  scanhead: // read the header  
 
    while (!gothead) {  
 
      switch (stream.nextToken()) {  
 
      default:  
break scanhead;  
 
      case StreamTokenizer.TT_EOL:  
break;  
 
      case StreamTokenizer.TT_WORD:  
 
if ("OFF".equals(stream.sval)) {  
            
          System.out.println(stream.sval);  
 
  nverts = 0; nfaces = 0; nedges = 0;  
  while (stream.nextToken() == StreamTokenizer.TT_EOL) {};  
 
  if (stream.ttype == StreamTokenizer.TT_NUMBER) {  
 
    nverts = (int)stream.nval;  
    if (stream.nextToken() == StreamTokenizer.TT_NUMBER) {  
 
      nfaces = (int)stream.nval;  
      if (stream.nextToken() == StreamTokenizer.TT_NUMBER) {  
 
nedges = (int)stream.nval;  
gothead = true;  
 
      } else throw new IOException("Can't read OFF file");  
 
    } else throw new IOException("Can't read OFF file");  
 
  } else throw new IOException("Can't read OFF file");  
 
}  
break;  
 
      case StreamTokenizer.TT_NUMBER:  
break;  
 
      }  
 
    }  
 
    vert = new float[nverts * 3];  
    face = new Face[nfaces]; findex = new int[nfaces];  
 
    for (int i = 0; i < nfaces; i++) { findex[i] = i; }  
 
    int num = 0;   
    int coordnum = 0;  
 
  scanverts: // read the vertices  
 
    while (num < nverts) {  
 
      switch (stream.nextToken()) {  
 
        default:  
  break;  
 
case StreamTokenizer.TT_EOL:  
  if (coordnum > 2) {  
    coordnum = 0; num++;  
  }  
  break;  
 
case StreamTokenizer.TT_NUMBER:  
  if (coordnum < 3) {  
    vert[num*3 + coordnum] = (float)stream.nval;  
    coordnum++;  
  }  
 
      }  
 
    }  
 
    num = 0; coordnum = 0;  
    boolean gotnum = false;  
 
  scanfaces: // read the faces  
 
    while (num < nfaces) {  
 
      switch (stream.nextToken()) {  
 
        default:  
  break;  
 
case StreamTokenizer.TT_EOL:  
  if (gotnum) { num++; }  
  gotnum = false;  
  break;  
 
case StreamTokenizer.TT_NUMBER:  
  if (!gotnum) {  
 
    face[num] = new Face();  
    face[num].numVerts((int)stream.nval);  
    gotnum = true; coordnum = 0;  
 
  } else if (coordnum < face[num].nverts) {  
 
    face[num].index[coordnum] = 3 * (int)stream.nval;  
    coordnum++;  
 
  } else {  
 
    face[num].cr = 255; face[num].cg = 255; face[num].cb = 255;  
    float val = (float)stream.nval;  
 
    if (val <= 1) { val *= 255; }  
 
    face[num].cr = (int)val;  
 
    if (stream.nextToken() != StreamTokenizer.TT_EOL) {  
 
      val = (float)stream.nval;  
      if (val <= 1) { val *= 255; }  
      face[num].cg = (int)val;  
 
      if (stream.nextToken() != StreamTokenizer.TT_EOL) {  
 
val = (float)stream.nval;  
        if (val <= 1) { val *= 255; }  
face[num].cb = (int)val;  
 
      } else {  
 
face[num].cr = 255; face[num].cg = 255; face[num].cb = 255;  
num++; gotnum = false;  
 
      }  
 
    } else {  
 
face[num].cr = 255; face[num].cg = 255; face[num].cb = 255;  
num++; gotnum = false;  
 
      }  
  }  
 
  break;  
 
      }  
 
    }  
       
 
  }  
 
 
/* transform all points in model */  
 
  void transform() {  
 
    if (transformed || nverts <= 0)  
      return;  
 
    if (tvert == null)  
      tvert = new int[nverts*3];  
 
    mat.transform(vert, tvert, nverts);  
    transformed = true;  
  }  
 
 
/**  
 *  The quick sort algorithm in this method is used for sorting faces  
 *  from back to front by z depth values.  
 */  
 
  void qs(int left, int right) {  
 
    int i, j, x, y;  
 
    i = left; j = right;  
    x = face[findex[(left+right)/2]].zdepth;  
 
    do {  
 
      while (face[findex[i]].zdepth > x && i < right) i++;  
      while (x > face[findex[j]].zdepth && j > left) j--;  
 
      if (i <= j) {  
y = findex[i];  
findex[i] = findex[j];  
findex[j] = y;  
i++; j--;  
      }  
 
    } while (i <= j);  
 
    if (left < j) qs(left, j);  
    if (i < right) qs(i, right);  
 
  }  
 
 
/* Paint myself to the graphics context. */  
 
  void paint(Graphics g) {  
 
    if (vert == null || nverts <= 0)  
      return;  
 
    transform();  
 
    if (gr == null) { // allocate colors if  
// they haven't been  
      gr = new Color[nfaces]; // allocated already  
 
      for (int i = 0; i < nfaces; i++) {  
 
gr[i] = new Color(face[i].cr, face[i].cg, face[i].cb);  
 
      }  
 
    }  
 
/**  
 *  Calculate the average z depth of faces and use this to sort them.  
 *  This is called the "Painter's algorithm" and although it works in  
 *  some case, does *not* always provide a correct ordering. Sometimes  
 *  a correct ordering is impossible, especially in the case of mutually  
 *  overlapping polygons.  
 */  
 
    for (int i = 0; i < nfaces; i++) {  
 
      face[i].zdepth = 0;  
 
      for (int c = 0; c < face[i].nverts; c++) {  
 
if (face[i].zdepth < tvert[face[i].index[c]+2])  
  face[i].zdepth = tvert[face[i].index[c]+2];  
      }  
 
    }  
 
    qs(0, nfaces-1); // quick sort the faces  
 
    for (int f = 0; f < nfaces; f++) {  
 
      int i = findex[f];  
      int v = 0;  
 
      for (int c = 0; c < face[i].nverts; c++) {  
vx[c] = tvert[face[i].index[c]];  
vy[c] = tvert[face[i].index[c]+1];  
      }  
 
      g.setColor(gr[i]);  
      g.fillPolygon(vx, vy, face[i].nverts); // draw each face  
 
      g.setColor(Color.black);  
 
      for (v = 0; v < (face[i].nverts-1); v++) {  
g.drawLine(vx[v], vy[v], vx[v+1], vy[v+1]); // draw the face edges  
      }  
 
      g.drawLine(vx[v], vy[v], vx[0], vy[0]);  
 
    }  
 
  }  
 
/* calculate the bounding box of our object: */  
 
  void findBB() {  
    if (nverts <= 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 = nverts * 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;  
 
  }  
 
}  
 
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -