//made by Hu Pan 2004.9.8
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class polygonModeling extends Applet implements KeyListener, ActionListener{
private Image offScreenImage;
private Ticker t;
private paste[] Paste;
private model[] models;
private int numOfVisiblePolygons;
private vector cameraPosition; // the change of camera position with respect of (0,0,0);
private vector viewDirection; // the view direction of the camera
private boolean seeThrough;
private double xzRotate, yzRotate;
private boolean UP_TYPED, DOWN_TYPED, RIGHT_TYPED, LEFT_TYPED, MOVE_FOWARD, MOVE_BACKWORD, SLIDE_LEFT, SLIDE_RIGHT;
private double forward, backward, slideLeft, slideRight;
int time;
public void init(){
Paste = new paste[10000000];
models = new model[6];
models[0] = new desk(new vector(-18,-18,45));
models[1] = new book(new vector(-7,-1.97,46.1));
models[2] = new lamp(new vector(2,-1.97,56));
models[3] = new chair(new vector(-10,-20,32));
models[4] = new pencil(new vector(0,-1.9, 46));
models[5] = new floor(new vector(-28,-17.9,25)); //back ground
cameraPosition = new vector(0,0,0);
viewDirection = new vector(0,0,1);
addKeyListener(this);
requestFocus();
t = new Ticker(35);
t.addActionListener(this);
t.start();
}
public void actionPerformed(ActionEvent e){
//============================control=============================================
if(MOVE_FOWARD){
if(forward < 0.5)
forward += 0.05;
cameraPosition = cameraPosition.subtract(viewDirection.unit().scale(forward));
} else
forward = 0;
if(MOVE_BACKWORD){
if(backward < 0.5)
backward += 0.05;
cameraPosition = cameraPosition.add(viewDirection.unit().scale(backward));
} else
backward = 0;
if(SLIDE_LEFT){
if(slideLeft<0.5)
slideLeft += 0.05;
vector left = viewDirection.cross(new vector(-viewDirection.x, -1000000, -viewDirection.z));
cameraPosition = cameraPosition.add(left.unit().scale(slideLeft));
} else
slideLeft = 0;
if(SLIDE_RIGHT){
if(slideRight<0.5)
slideRight += 0.05;
vector right = viewDirection.cross(new vector(viewDirection.x, 1000000, viewDirection.z));
cameraPosition = cameraPosition.add(right.unit().scale(slideRight));
} else
slideRight = 0;
if(UP_TYPED){
if(yzRotate < Math.PI/2){
yzRotate+=0.03;
if(yzRotate > Math.PI/2)
yzRotate = Math.PI/2 - 0.001;
}
}
if(DOWN_TYPED){
if(yzRotate > -Math.PI/2){
yzRotate-=0.03;
if(yzRotate < -Math.PI/2)
yzRotate = -Math.PI/2 + 0.001;
}
}
if(LEFT_TYPED){
viewDirection = viewDirection.rotate_XZ(0.03);
xzRotate-=0.03;
}
if(RIGHT_TYPED){
xzRotate+=0.03;
viewDirection = viewDirection.rotate_XZ(-0.03);
}
viewDirection = viewDirection.rotate_vertical(yzRotate);
//=================================end control============================================
//update the models' vertics accordiong to the user's move (camera's orientation)
for(int i = 0; i < models.length; i++)
models[i].update(cameraPosition, xzRotate, yzRotate);
//sort models so that they are drawn in the right order
sortModels();
//load polygons of the models
numOfVisiblePolygons = 0;
for(int i = 0; i < models.length-1; i++){
int start = numOfVisiblePolygons;
for(int j = 0; j < models[i].getPolygon().length; j++){
if(models[i].getPolygon()[j].visible){
Paste[numOfVisiblePolygons] = models[i].getPolygon()[j];
numOfVisiblePolygons++;
}
}
//sort polygons of the model so that they are drawn in the right order;
sortPolygon(start, numOfVisiblePolygons);
}
repaint();
}
//sort models
private void sortModels(){
for(int i = 1; i < models.length-1; i++){
for(int j = 0; j <models.length - i-1; j++){
if(compare1(models[j], models[j+1])){
model temp = models[j+1];
models[j+1] = models[j];
models[j] = temp;
}
}
}
}
//sort polygons
private boolean compare1(model a, model b){
paste[] aPaste = a.getBoundary();
paste[] bPaste = b.getBoundary();
vector difference = a.getCentre().subtract(b.getCentre());
boolean insideA = true;
boolean insideB = true;
vector origin = new vector(0,0,0);
for(int i = 0; i < 6; i++){
if(origin.subtract(aPaste[i].centre).dot(aPaste[i].normal) > 0)
insideA = false;
}
for(int i = 0; i < 6; i++){
if(origin.subtract(bPaste[i].centre).dot(bPaste[i].normal) > 0)
insideB = false;
}
if(insideA)
return true;
if(insideB)
return false;
boolean bCantBeSeen = true;
for(int i = 0; i < 6; i++){
if(bPaste[i].visible){
bCantBeSeen = false;
break;
}
}
if(bCantBeSeen)
return true;
paste comparebleA = aPaste[0];
for(int i = 0; i < 6; i++){
if(aPaste[i].visible){
comparebleA = aPaste[i];
break;
}
}
for(int i = 0; i < 6; i++){
if(aPaste[i].visible){
if(Math.abs(comparebleA.normal.dot(difference)) < Math.abs(aPaste[i].normal.dot(difference)))
comparebleA = aPaste[i];
}
}
paste comparebleB = bPaste[0];
for(int i = 0; i < 6; i++){
if(bPaste[i].visible){
comparebleB = bPaste[i];
break;
}
}
for(int i = 0; i < 6; i++){
if(bPaste[i].visible){
if(Math.abs(comparebleB.normal.dot(difference)) < Math.abs(bPaste[i].normal.dot(difference)))
comparebleB = bPaste[i];
}
}
try{
if(compare2(comparebleA, comparebleB))
return true;
}catch(Exception e){}
return false;
}
//sort polygon
private void sortPolygon(int start, int finish){
for(int i = start + 1; i < finish; i++){
for(int j = start; j <finish - 1; j++){
if(compare2(Paste[j], Paste[j+1])){
paste temp = Paste[j+1];
Paste[j+1] = Paste[j];
Paste[j] = temp;
}
}
}
}
//check if polygon a is completely inside the plane spand by polygon b (use painter's method)
public boolean compare2(paste a, paste b){
if(a.zMax < b.zMin)
return true;
if(a.zMin > b.zMax)
return false;
if(a.points[0].z < b.points[0].z && a.points[1].z < b.points[1].z && a.points[2].z < b.points[2].z && a.points[3].z < b.points[3].z)
return true;
boolean inside = true;
for(int i = 0; i < b.points.length; i++){
if(b.points[i].subtract(a.centre).unit().dot(a.normal) > 0.0001 ){
inside = false;
break;
}
}
if(inside)
return true;
inside = true;
for(int i = 0; i <a.points.length; i++){
if(a.points[i].subtract(b.centre).unit().dot(b.normal) < -0.0001 ){
inside = false;
break;
}
}
if(inside)
return true;
return false;
}
public void paint(Graphics g){
// draw back ground polygons first which always need to be draw at first
for(int i = 0; i < models[models.length-1].getPolygon().length; i++){
if(models[models.length-1].getPolygon()[i].visible){
if(!seeThrough)
models[models.length-1].getPolygon()[i].draw(g);
}
}
//then draw the polygon that are sorted
for(int i = 0; i < numOfVisiblePolygons; i++){
try{
if(Paste[i].innerPaste != null){
for(int j = 0; j < Paste[i].innerPaste.length; j++){
Paste[i].innerPaste[j].wireFrameOn = seeThrough;
Paste[i].innerPaste[j].draw(g);
}
}
else{
Paste[i].wireFrameOn = seeThrough;
Paste[i].draw(g);
}
}catch(Exception e){}
}
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP)
UP_TYPED = true;
else if(e.getKeyCode() == KeyEvent.VK_DOWN)
DOWN_TYPED = true;
else if(e.getKeyCode() == KeyEvent.VK_LEFT)
LEFT_TYPED = true;
else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
RIGHT_TYPED = true;
else if(e.getKeyChar() == 'w')
MOVE_FOWARD = true;
else if(e.getKe