/* * PuppetApplet.java * * (C) 2004-2005, Alex S. */ import java.awt.*; import java.util.*; /* class BodyNode { public Vector children; public pMatrix matrix; public BodyNode(){ children = new Vector(); matrix = new pMatrix(); } } */ public class PuppetApplet extends BufferedApplet { pMatrix matrix = new pMatrix(); pMatrix pmatrix = new pMatrix(); // points/colors that are rendered. Vector points = new Vector(); Vector colors = new Vector(); // for z sorting float[] avgz; int[] polyorder; // pre-computed points. Vector cube = new Vector(); // current rendering color Color currentColor = Color.red; // angle, mouse state private float 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; // screen rectangle int minx,maxx,miny,maxy; boolean[] keys; float[][][] globe; /** * make a globe sphere mesh * * @param m Horizontal splits. * @param m Vertical Splits. */ public float[][][] globeMesh(int m,int n){ float mesh[][][] = new float[m][n][3]; for (int i = 0 ; i < m ; i++){ for (int j = 0 ; j < n ; j++) { double u = i / (m - 1.0); double v = j / (n - 1.0); double theta = 2 * Math.PI * u; double phi = Math.PI * v - Math.PI/2; mesh[i][j][0] = (float)(Math.cos(theta) * Math.cos(phi)); mesh[i][j][1] = (float)(Math.sin(theta) * Math.cos(phi)); mesh[i][j][2] = (float)Math.sin(phi); } } return mesh; } /** * dumps phere to rendering pipeline */ public void dumpGlobe(){ int i,j; float[][][] mesh = globe; for(i=0;i=0 && avgz[j] > e2;j--) { avgz[j+1] = avgz[j]; polyorder[j+1] = polyorder[j]; } polyorder[j+1] = e1; avgz[j+1] = e2; } } pMatrix camera = new pMatrix(); float acceleration = 0; float friction = 0; float force = 0; float speed = 0; float frametime = 0; long lastframe = System.currentTimeMillis(); public void handleMotion(){ long currentframe = System.currentTimeMillis(); frametime = (currentframe - lastframe) / (float)1000.0; lastframe = currentframe; if(m_anglex != 0 || m_angley != 0){ pMatrix nm = new pMatrix(); nm.rotatex(m_anglex); nm.rotatey(m_angley); nm.mult(camera); camera = nm; m_anglex = m_angley = 0; damage = true; } if(keys[127] || keys['q']){ // del key pMatrix nm = new pMatrix(); nm.rotatez((float)Math.PI/100); nm.mult(camera); camera = nm; damage = true; } if(keys[1025] || keys['e']){ // ins key pMatrix nm = new pMatrix(); nm.rotatez((float)-Math.PI/100); nm.mult(camera); camera = nm; damage = true; } if(keys[1006] || keys['a']){ // left key pMatrix nm = new pMatrix(); nm.rotatey((float)-Math.PI/100); nm.mult(camera); camera = nm; damage = true; } if(keys[1007] || keys['d']){ // right key pMatrix nm = new pMatrix(); nm.rotatey((float)Math.PI/100); nm.mult(camera); camera = nm; damage = true; } if(keys[1004] || keys['w']){ // up key pMatrix nm = new pMatrix(); nm.rotatex((float)Math.PI/100); nm.mult(camera); camera = nm; damage = true; } if(keys[1005] || keys['s']){ // down key pMatrix nm = new pMatrix(); nm.rotatex((float)-Math.PI/100); nm.mult(camera); camera = nm; damage = true; } if(keys['<'] || keys[','] || keys['z']){ //System.out.println("< is pressed"); force = 100; }else if(keys['>'] || keys['.'] || keys['x']){ force = -70; }else{ force = 0; } friction = (float)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(200,speed + acceleration * frametime); speed = Math.max(speed,-100); float distance = Math.round(speed * frametime); if(distance != 0){ pMatrix nm = new pMatrix(); nm.translate(0,0,distance); nm.mult(camera); /* // todo: collision detection pMatrix inverse = camera.inverse(); float[] vec = {0,0,0,1}; vec = inverse.mult(vec); */ camera = nm; damage = true; } } /** * recompute various things when screen size changes */ public void recompute(Rectangle r){ screen_edges = new int[4][3]; int W = r.width - 10; int H = r.height - 10; int lines[][] = { {10,10,10,H}, {10,H,W,H}, {W,H,W,10}, {W,10,10,10} }; int x1 = 0; int y1 = 1; int x2 = 2; int y2 = 3; for(int i=0;i 0) { int clipz,n = 4; for (k=0; k < n; k++) { float[] point = (float[])points.elementAt(poly+k); //point = pmatrix.mult(point); x[k] = (int)(point[0]); // / point[3]); y[k] = (int)(point[1]); // / point[3]); z[k] = clipz = (int)(point[2]); // / point[3]); // clipping // trivial cases, all points have positive or all negative z if (clipz > 0){ allnegative = false; }else{ allpositive = false; if(clipz > -1000){ alloutofrange = false; }else{ allinrange = false; } } } // trivial rejection if (allpositive) continue; if (alloutofrange) continue; if (!allnegative){ int[] arr = {0,0,-1,0}; n = SutherlandHodgmanPolygonClip3D(x,y,z,n,cx,cy,cz,arr); if(n == 0) continue; for(k=0;k= 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; } }