📄 用java编程画3d的一张动画人物的脸.txt
字号:
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 + -