/* * FlightBox.java * * (C) 2004-2005, Alex S. */ import java.awt.*; import java.util.*; /** * main class of the whole thing */ public class FlightBox extends BufferedApplet { pMatrix matrix = new pMatrix(); pMatrix pmatrix = new pMatrix(); pMap map; // angle, mouse state private double m_anglex,m_angley; private int m_mousex,m_mousey; // used for java's fillpoly thingie... (and some quick & dirty clipping) private int[] x; private int[] y; private int[] z; // clippping ... private int[] cx; private int[] cy; private int[] cz; private int[][] screen_edges; boolean[] keys; // viewers direction/location pEntity player; double acceleration = 0; double friction = 0; double force = 0; double speed = 0; double frametime = 0; long lastframe = System.currentTimeMillis(); /** * initialize things */ public void init(){ super.init(); //map = pMapGen.generateCubes(7); map = pMapGen.generateRoundedCubes(32,7); map.buildBSP(); // pEntity[696.536252532293,3252.2114602859024,-3252.8875039509153; [0.2761343203503068,<0.5567707004151814,-0.7533427659789588,-0.21501372335517446>]] player = new pEntity(696.536252532293,3252.2114602859024,-3252.8875039509153, new pQuaternion(0.2761343203503068,0.5567707004151814,-0.7533427659789588,-0.21501372335517446)); //player.x = 1000; //player.y = 1000; //player.z = 1000; keys = new boolean[0x1000]; for (int i=0;i'] || keys['.'] || keys['x']) { force = -70; } else { force = 0; } friction = (double)0.1; acceleration = acceleration + friction * (0 - acceleration); acceleration = Math.min(1000,acceleration + force); // should be force * direction vector speed = speed + friction * (0 - speed); speed = Math.min(2000,speed + acceleration * frametime); speed = Math.max(speed,-1000); double distance = Math.round(speed * frametime); pQuaternion tmpq = new pQuaternion(0,0,0,-1); //tmpq = player.orientation.mult(tmpq).mult(player.orientation.conjugate()); tmpq = player.orientation.conjugate().mult(tmpq).mult(player.orientation); //System.out.println("<"+tmpq.x+","+tmpq.y+","+tmpq.z+">\n"); if (distance != 0) { double[] eye = {player.x,player.y,player.z}; double[] neweye = { player.x + distance * tmpq.x, player.y + distance * tmpq.y, player.z + distance * tmpq.z }; //System.out.println("("+player.x+","+player.y+","+player.z+") => "); for(int i=0;i<5;i++){ map.traceSphere(eye,neweye,24); /* if(!map.outputStartsOut){ System.out.println("Starting location is inside!"); } if(map.outputAllSolid){ System.out.println("Starting and ending inside."); } if(map.outputStartsOut && map.outputFraction < 1){ System.out.println("Moving into object."); } */ if(map.outputFraction > 0){ //double d = map.outputPlane.eval(neweye); //System.out.println("Final position: "+d+" away frm plane."); player.x += (neweye[0] - player.x) * map.outputFraction; player.y += (neweye[1] - player.y) * map.outputFraction; player.z += (neweye[2] - player.z) * map.outputFraction; //System.out.println(" -> ("+player.x+","+player.y+","+player.z+") => "); break; } double d = map.outputPlane.eval(neweye); //System.out.println("Moved "+d+" into the plane."); //EndPosition += Polygon.Normal*(CollRadius-EndSideValue) neweye[0] += map.outputPlane.p[0] * ((24+pMap.EPSILON)-d); neweye[1] += map.outputPlane.p[1] * ((24+pMap.EPSILON)-d); neweye[2] += map.outputPlane.p[2] * ((24+pMap.EPSILON)-d); d = map.outputPlane.eval(neweye); ///System.out.println("Handled move; now "+d+" away from the plane."); } damage = true; } } /** * recompute various things when screen size changes */ public void recompute(Rectangle r){ screen_edges = new int[4][3]; int W = r.width-1; int H = r.height-1; int lines[][] = { {0,0,0,H}, {0,H,W,H}, {W,H,W,0}, {W,0,0,0} }; int x1 = 0; int y1 = 1; int x2 = 2; int y2 = 3; for (int i=0;i 0) { allnegative = false; } else { allpositive = false; if (clipz > -10000) { alloutofrange = false; } else { allinrange = false; } } } //System.out.println(""); // trivial rejection if (allpositive) { //System.out.println("\tall positive"); return; } if (alloutofrange) { //System.out.println("\tall out of range."); return; } if (!allnegative) { int[] arr = {0,0,-1,0}; n = SutherlandHodgmanPolygonClip3D(x,y,z,n,cx,cy,cz,arr); if (n == 0) { //System.out.println("all z clipped"); return; } for (k=0;k 0) pRenderFace(face,g); } } /** * render everything in a bsp tree using painter's algorithm (back to front) */ public void pTreeRender(pBSPNode node,Graphics g){ if (node.type != pBSPNode.TREENODE) return; // just render everything here. if (node.plane.eval(player.x,player.y,player.z) >= 0) { pTreeRender(node.back,g); pRenderFaces(node.faces,g); pTreeRender(node.front,g); } else { pTreeRender(node.front,g); pRenderFaces(node.faces,g); pTreeRender(node.back,g); } } /** * function that gets called whenever something needs to be * rendered. */ public void render(Graphics g) { handleMotion(); if (damage) { g.setColor(Color.lightGray); g.fillRect(0, 0, bounds().width, bounds().height); matrix.push(); pMatrix camera = new pMatrix(player.orientation.to4x4matrix()); matrix.mult(camera); matrix.translate(-player.x,-player.y,-player.z); pTreeRender(map.bsp,g); matrix.pop(); //g.drawString("("+player.x+","+player.y+","+player.z+")",10,10); //System.out.println("camera: "+player); } } /** * mouse event handler: let the user move things */ public boolean mouseDown(Event evt, int x, int y){ m_mousex = x; m_mousey = y; return true; } public boolean mouseUp(Event evt, int x, int y){ return true; } /** * mouse event handler: let the user move things */ public boolean mouseDrag(Event evt, int x, int y){ m_angley += (double)0.015 * (double)(x - m_mousex); m_anglex += (double)0.015 * (double)(m_mousey - y); m_mousex = x; m_mousey = y; return true; } public boolean keyDown(Event evt,int key){ //System.out.println("keyDown: "+key); if (key < 0x1000) keys[key] = true; return true; } public boolean keyUp(Event evt,int key){ //System.out.println("keyUp: "+key); if (key < 0x1000) keys[key] = false; return true; } /** * edge is in Ax + By + D = 0 format. * * dx = x2 - x1; * dy = y2 - y1; * A = dy * B = -dx * D = -(A * x1 + B * y1) */ private int SutherlandHodgmanPolygonClip(int[] ix,int[] iy,int n,int[] ox,int[] oy,int[] edge){ int A,B,D,p,s,k,l,olen,x,y; long d1,d2; // these -need- to be long (some of these values get -very- large. A = edge[0]; B = edge[1]; D = edge[2]; olen = 0; s = n - 1; for (p=0;p= 0 ) { // p is inside if ( (l = ix[s] * A + iy[s] * B + D) >= 0 ) { // s in inside ox[olen] = ix[p]; oy[olen] = iy[p]; olen++; } else { // find intersection d1 = -l; d2 = (d1 + k); ox[olen] = (int)(ix[s] + ( d1 * ( ix[p] - ix[s] ) ) / d2); oy[olen] = (int)(iy[s] + ( d1 * ( iy[p] - iy[s] ) ) / d2); olen++; ox[olen] = ix[p]; oy[olen] = iy[p]; olen++; } } else { if ( (l = ix[s] * A + iy[s] * B + D) >= 0 ) { // s in inside d1 = -k; d2 = (d1 + l); ox[olen] = (int)(ix[p] + ( d1 * ( ix[s] - ix[p] ) ) / d2); oy[olen] = (int)(iy[p] + ( d1 * ( iy[s] - iy[p] ) ) / d2); olen++; } } s = p; } return olen; } /** * edge is Ax + By + Cz + D = 0 */ private int SutherlandHodgmanPolygonClip3D(int[] ix,int[] iy,int[] iz,int n,int[] ox,int[] oy,int[] oz,int[] edge){ int A,B,C,D,p,s,k,l,olen,x,y; long d1,d2; // these -need- to be long (some of these values get -very- large. A = edge[0]; B = edge[1]; C = edge[2]; D = edge[3]; olen = 0; s = n - 1; for (p=0;p= 0 ) { // p is inside if ( (l = ix[s] * A + iy[s] * B + iz[s] * C + D) >= 0 ) { // s in inside ox[olen] = ix[p]; oy[olen] = iy[p]; oz[olen] = iz[p]; olen++; } else { // find intersection d1 = -l; d2 = (d1 + k); ox[olen] = (int)(ix[s] + ( d1 * ( ix[p] - ix[s] ) ) / d2); oy[olen] = (int)(iy[s] + ( d1 * ( iy[p] - iy[s] ) ) / d2); oz[olen] = (int)(iz[s] + ( d1 * ( iz[p] - iz[s] ) ) / d2); olen++; ox[olen] = ix[p]; oy[olen] = iy[p]; oz[olen] = iz[p]; olen++; } } else { if ( (l = ix[s] * A + iy[s] * B + iz[s] * C + D) >= 0 ) { // s in inside d1 = -k; d2 = (d1 + l); ox[olen] = (int)(ix[p] + ( d1 * ( ix[s] - ix[p] ) ) / d2); oy[olen] = (int)(iy[p] + ( d1 * ( iy[s] - iy[p] ) ) / d2); oz[olen] = (int)(iz[p] + ( d1 * ( iz[s] - iz[p] ) ) / d2); olen++; } } s = p; } return olen; } }