/* * PuppetApplet.java * * (C) 2004, Alex S. */ import java.awt.*; import java.util.Vector; 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 double[] avgz; int[] polyorder; // pre-computed points. Vector curve_points = new Vector(); Vector object_points = new Vector(); // current rendering color Color currentColor = Color.red; // angle, mouse state private double m_anglex,m_angley; private int m_mousex,m_mousey; private double[][][] mesh; private double[][][] sphere; private double[][][] losphere; public double m_angledx = 0; public double m_angledy = Math.PI/128; public int renderSpheres = 1; public boolean dragged = false; /** * make a globe sphere mesh * * @param m Horizontal splits. * @param m Vertical Splits. */ public double[][][] globeMesh(int m,int n){ double mesh[][][] = new double[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.0 * Math.PI * u; double phi = Math.PI * v - Math.PI/2.0; mesh[i][j][0] = Math.cos(theta) * Math.cos(phi); mesh[i][j][1] = Math.sin(theta) * Math.cos(phi); mesh[i][j][2] = Math.sin(phi); } } return mesh; } /** * dumps phere to rendering pipeline */ public void dumpSphere(){ int i,j; double[][][] mesh = sphere; for(i=0;i= 1) time = 0; matrix.push(); // 1 //matrix.rotatez(0); matrix.rotatez(0.1*(Math.sin(time*3 * Math.PI*2)+Math.cos(time*3 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,.4,0); matrix.push(); matrix.scale(.3,.4,.3); dumpLoSphere(); matrix.pop(); matrix.translate(0,.4,0); // 2 (stomach) //matrix.rotatez(0); matrix.rotatez(-0.1*(Math.sin(time*3 * Math.PI*2)+Math.cos(time*3 * Math.PI*2))); matrix.rotatex(-0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatey(-0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,1,0); matrix.push(); matrix.scale(.5,1,.3); dumpLoSphere(); matrix.pop(); matrix.translate(0,1,0); // 3 (neck) matrix.push(); //matrix.rotatex(0); matrix.rotatez(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*3 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*8 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*5 * Math.PI*2)+Math.cos(time*7 * Math.PI*2))); matrix.translate(0,.2,0); matrix.push(); matrix.scale(.1,.2,.1); dumpLoSphere(); matrix.pop(); matrix.translate(0,.2,0); // 4 (head) //matrix.rotatez(0); matrix.rotatez(0.2*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.translate(0,.6,0); matrix.push(); matrix.scale(.3,.6,.3); dumpLoSphere(); matrix.pop(); matrix.pop(); // 5 (left arm) matrix.push(); //matrix.rotatez(0); // SHOULDER JOINT matrix.translate(-0.4,0,0); matrix.push(); matrix.scale(.4,.1,.1); dumpLoSphere(); matrix.pop(); matrix.translate(-0.4,0,0); //matrix.rotatez(0); // SHOULDER JOINT matrix.rotatez(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-0.7,0); matrix.push(); matrix.scale(.2,0.7,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-0.7,0); //matrix.rotatez(0); // ELBOW JOINT matrix.rotatez(-0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(-0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatey(-0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-0.7,0); matrix.push(); matrix.scale(.2,0.7,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-0.7,0); //matrix.rotatex(0); // WRIST JOINT matrix.rotatez(0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*5 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*3 * Math.PI*2)+Math.cos(time*3 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*5 * Math.PI*2))); matrix.translate(0,-.4,0); matrix.push(); matrix.scale(.2,.4,.2); dumpLoSphere(); matrix.pop(); matrix.pop(); // 6 (right arm) matrix.push(); //matrix.rotatez(0); // SHOULDER JOINT matrix.translate(0.4,0,0); matrix.push(); matrix.scale(.4,.1,.1); dumpLoSphere(); matrix.pop(); matrix.translate(0.4,0,0); //matrix.rotatez(0); // SHOULDER JOINT matrix.rotatez(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-0.7,0); matrix.push(); matrix.scale(.2,0.7,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-0.7,0); //matrix.rotatez(0); // ELBOW JOINT matrix.rotatez(-0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(-0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatey(-0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-0.7,0); matrix.push(); matrix.scale(.2,0.7,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-0.7,0); //matrix.rotatex(0); // WRIST JOINT matrix.rotatez(0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*3 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*1 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.translate(0,-.4,0); matrix.push(); matrix.scale(.2,.4,.2); dumpLoSphere(); matrix.pop(); matrix.pop(); matrix.pop(); // 5 (left leg) matrix.push(); //matrix.rotatez(0); matrix.translate(-0.2,0,0); matrix.push(); matrix.scale(.2,.1,.1); dumpLoSphere(); matrix.pop(); matrix.translate(-0.2,0,0); //matrix.rotatez(0); matrix.rotatez(0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*3 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-1,0); matrix.push(); matrix.scale(.2,1,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-1,0); //matrix.rotatez(0); matrix.rotatez(-0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(-0.1*(Math.sin(time*3 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatey(-0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-1,0); matrix.push(); matrix.scale(.2,1,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-1,0); //matrix.rotatex(-Math.PI); matrix.rotatez(0.01*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.rotatex(-Math.PI + 0.01*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.rotatey(0.01*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.translate(0,-.2,-.5); matrix.push(); matrix.scale(.2,.1,.5); dumpLoSphere(); matrix.pop(); matrix.pop(); // 6 (right leg) matrix.push(); //matrix.rotatez(0); matrix.translate(0.2,0,0); matrix.push(); matrix.scale(.2,.1,.1); dumpLoSphere(); matrix.pop(); matrix.translate(0.2,0,0); //matrix.rotatez(0); matrix.rotatez(0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatey(0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-1,0); matrix.push(); matrix.scale(.2,1,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-1,0); //matrix.rotatez(0); matrix.rotatez(-0.1*(Math.sin(time*2 * Math.PI*2)+Math.cos(time*4 * Math.PI*2))); matrix.rotatex(-0.1*(Math.sin(time*4 * Math.PI*2)+Math.cos(time*6 * Math.PI*2))); matrix.rotatey(-0.1*(Math.sin(time*6 * Math.PI*2)+Math.cos(time*2 * Math.PI*2))); matrix.translate(0,-1,0); matrix.push(); matrix.scale(.2,1,.2); dumpLoSphere(); matrix.pop(); matrix.translate(0,-1,0); //matrix.rotatex(-Math.PI); matrix.rotatez(0.01*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.rotatex(-Math.PI + 0.01*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.rotatey(0.01*(Math.sin(time * Math.PI*2)+Math.cos(time * Math.PI*2))); matrix.translate(0,-.2,-.5); matrix.push(); matrix.scale(.2,.1,.5); dumpLoSphere(); matrix.pop(); matrix.pop(); } /** * dumps the scene */ public void dumpScene(){ currentColor = Color.yellow; matrix.rotatey(Math.PI); matrix.rotatex(Math.PI); dumpModel(); } /** * sort via average z */ public void sort(){ int i,j; int e1; double e2; for(i=1;i=0 && avgz[j] > e2;j--){ avgz[j+1] = avgz[j]; polyorder[j+1] = polyorder[j]; } polyorder[j+1] = e1; avgz[j+1] = e2; } } /** * function that gets called whenever something needs to be * rendered. */ public void render(Graphics g) { if (true || damage) { m_angley += m_angledy; m_anglex += m_angledx; g.setColor(Color.lightGray); g.fillRect(0, 0, bounds().width, bounds().height); g.setColor(Color.gray); g.fillRect(0, (int)(bounds().height*3.0/4.0), bounds().width, bounds().height); matrix.push(); matrix.translate(0,0,-144); matrix.scale(10); matrix.rotatey(m_angley); matrix.rotatex(m_anglex); dumpScene(); // calculate average z for all points. avgz = new double[points.size() / 4]; polyorder = new int[points.size() / 4]; int k,i=0,j=points.size(); double[] plane = new double[4]; for(i=0;i 0){ for(k=0;k<4;k++){ double[] point = (double[])points.elementAt(poly+k); point = pmatrix.mult(point); x[k] = (int)(point[0] / point[3]); y[k] = (int)(point[1] / point[3]); } Color c = (Color)colors.elementAt(poly); double color1 = dotProduct(plane,new double[]{0,0,-1}); if(color1 >= 0){ g.setColor( new Color( (float)(((c.getRed()+50) * color1)/306.0), (float)(((c.getGreen()+50) * color1)/306.0), (float)(((c.getBlue()+50) * color1)/306.0) ) ); g.fillPolygon(x,y,x.length); //g.setColor(c); //g.drawPolygon(x,y,x.length); } } } avgz = null; polyorder = null; matrix.pop(); points.removeAllElements(); colors.removeAllElements(); } } /** * given 2 points, find their difference */ void vectorSubtract (double[] va, double[] vb, double[] out){ out[0] = va[0]-vb[0]; out[1] = va[1]-vb[1]; out[2] = va[2]-vb[2]; } /** * cross product of two vectors */ void crossProduct(double[] v1, double[] v2, double[] cross ) { cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; } /** * normalize */ double vectorNormalize(double[] in, double[] out ) { double length, ilength; length = Math.sqrt(in[0]*in[0] + in[1]*in[1] + in[2]*in[2]); if (length == 0){ return 0; } ilength = 1.0/length; out[0] = in[0]*ilength; out[1] = in[1]*ilength; out[2] = in[2]*ilength; return length; } /** * dot product */ double dotProduct (double[] v1, double[] v2){ return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; } /** * gets plane equation from three points on plane */ boolean planeFromPoints(double[] plane, double[] a, double[] b,double[] c,double[] d ){ double[] d1 = new double[4]; double[] d2 = new double[4]; vectorSubtract( b, a, d1 ); if(dotProduct(d1,d1) < 0.02){ vectorSubtract( c, a, d1 ); vectorSubtract( d, a, d2 ); }else{ vectorSubtract( c, a, d2 ); if(dotProduct(d2,d2) < 0.02){ vectorSubtract( d, a, d2 ); } } crossProduct( d2, d1, plane ); if ( vectorNormalize( plane, plane ) == 0 ) { return false; } plane[3] = dotProduct( a, plane ); return true; } /** * mouse event handler: let the user move things */ public boolean mouseDown(Event evt, int x, int y){ dragged = false; m_angledx = 0; m_angledy = 0; return true; } public boolean mouseUp(Event evt, int x, int y){ if(!dragged) renderSpheres ^= 1; dragged = false; m_angledx = 0; m_angledy = Math.PI/128; return true; } /** * mouse event handler: let the user move things */ public boolean mouseDrag(Event evt, int x, int y){ dragged = true; if((m_mousey - y) < 0) m_anglex += Math.PI/45; if((m_mousey - y) > 0) m_anglex -= Math.PI/45; if((m_mousex - x) < 0) m_angley -= Math.PI/45; if((m_mousex - x) > 0) m_angley += Math.PI/45; m_mousex = x; m_mousey = y; damage = true; return true; } }