package automenta.vivisect.face; import java.awt.Color; import java.awt.Graphics; import java.awt.event.KeyEvent; import java.util.StringTokenizer; import java.util.Vector; public class FaceGUI extends BaseClass { private static final long serialVersionUID = 1L; HumanoidFacePanel f; boolean firstVertices; boolean isVectors; boolean addNoise; boolean doShade; boolean shiftAxis; int nVertices; int nShapes; int nFlexes; int keyFlex[]; double keyValue[]; double flexValue[][]; double flexTarget[][]; double jitterAmpl[]; double jitterFreq[]; boolean firstTime; boolean kludge; final int POLYGON = 0; final int POLYLINE = 1; final int CIRCLE = 2; double flexData[][][]; int flexShape[][]; int flexSymmetry[]; double pts[][][]; int shape[][][]; double vertexArray[][]; double t; double blinkValue; double spin; int noRotateIndex; boolean leftArrow; boolean rightArrow; int prevKey; long lastTime; int frameCount; int dispCount; Vector<Color> colorVector; Vector flexNamesVector; Vector flexVector; Vector flx; Vector ixyz; Vector flexSymmetryVector; Vector shapesVector; Vector shapeVector; Vector face; Vector typeVector; Vector vertexVector; public final int pupil; public final int eyeBall; private float eyeballSize = 16; private float pupilSize = 8; public FaceGUI() { super(); firstVertices = true; isVectors = false; doShade = false; addNoise = true; shiftAxis = false; keyFlex = new int[256]; keyValue = new double[256]; firstTime = true; kludge = true; noRotateIndex = 1000; leftArrow = false; rightArrow = false; prevKey = -1; colorVector = new Vector(); flexNamesVector = new Vector(); flexVector = new Vector(); flexSymmetryVector = new Vector(); shapesVector = new Vector(); typeVector = new Vector(); vertexVector = new Vector(); setBackground(Color.white); lastTime = System.currentTimeMillis(); frameCount = 0; dispCount = 0; vertices("14,99,0"); vertices("27,85,0 30,70,0 15,30,-12 19,31.5,10 6.1,16.8,44.5"); // 1- 5 face vertices("5,70,44 12,72,42 22,68,35 12,70,42 5,68,44.5"); // 6-10 brows vertices("6,60,43.7 12,62,44 19,60,38 12,58,43 2,45,52"); // 11-15 eyes/nose vertices("5,44,47 1,42.5,49 4,38,50 8,30.2,46 3,23.5,46"); // 16-20 nose/lips vertices("2.1,35,48 5,31,47 1.5,29,47 12,60,37 14.1,62.1,37"); // 21-25 mouth/eyeballs vertices("13.15,61.15,37 7,34,44 7,29.2,42 4,47,48 26.5,55,14"); // 26-30 teeth,nostrils,cheeks,hair vertices("28,30,0 12,95,27 22,80,24 12,99,13 16,36,33"); // 31-35 forehead,face,headtop vertices("2,48.5,52.5 5,20.7,46.5 3,23,45 15,36,39 22,51,37"); // 36-40 misc vertices("13.6,26,38 10,84,34 6,22,20 22,35,15 12,97,-5"); // 41-45 vertices("15,91,-17 18,80,-26 16,60,-29 10,40,-23 30,52,-4"); // 46-50 vertices("16,86,39 20,-40,-23 23.3,51.3,7 26.5,50.7,7 23,59,9"); // 51-55 vertices("26,61,7 27.6,59.5,7"); // 56-57 noRotate(); vertices("13,50,0 16,16,0 40,7,0 40,0,0"); // 58-61 neck,shoulders polygons(.1, 0, 0, "58,59 59,60 60,61"); polygons(0, 0, 0, "15,16,17"); polygons(0, 0, 0, "39,41"); polygons(.56, .56, .56, "11,29,36"); polygons(.5, .5, .5, "15,29,16"); polygons(0, 0, 0, "3,49 49,48 48,47 47,46 46,45 1,45,46 1,46,47 50,47,48 48,49,3 30,3,4"); polygons(0, 0, 0, "34,32 34,1,33,32 1,30,33 45,34 34,45,1 50,1,47 50,48,3 50,3,30 50,30,1"); polygons(0, 0, 0, "32,51 51,42 32,33,51 51,33,42"); circles(.56, .56, .56, "53,54"); polygons(.56, .56, .56, "54,53,55,56,57"); polygons(.50, .50, .50, "54,53,55,57"); polygons(0, 0, 0, "18,27 28,20"); polygons(0, 0, 0, "11,12,13,14"); eyeBall = circles(.9, .9, .9, "24,25"); pupil = circles(0, 0, 0, "24,26"); polygons(.56, .56, .56, "16,29,11"); polygons(.50, .50, .50, "13,12,9,8 12,11,10,9 5,43 5,4,43"); polygons(0, 0, 0, "6,7,9,10 7,8,9"); polygons(.56, .56, .56, "39,40,41 4,41,40 4,5,41 5,37,41 37,19,41 19,39,41 19,37,38,20"); polygons(.56, .56, .56, "6,10 10,11 11,36 36,15 17,18 20,38 38,37 37,5"); polygons(.56, .56, .56, "17,16,18 29,15,36"); polygons(.56, .56, .56, "42,6 42,7,6 42,33,8,7"); polygons(.56, .56, .56, "30,4,40 30,40,8 13,8,40 8,33,30 11,14,16"); polygons(.56, .56, .56, "40,16,14 13,40,14 40,39,16 16,39,18 18,39,19"); polygons(.4, .4, .45, "15,17 18,21 23,20 18,19,22,21 23,22,19,20"); polylines(0, 0, 0, "11,12,13,14,11"); flex("sayAh", "19 20 21 22 23 4 5 28 16 37 38 39 41", "0,-3,-.6 0,-6,-1.2 0,.3 -1,-2.8,-.6 .6,-5.9,-1.2 1,-1.5,-.3 0,-4,-.8 0,-4.8,-1 .2,-.3 0,-5,-.8 0,-5,-1 0,-1,-.2 0,-5,-1"); flex("blink", "12 14", "0,-2 0,2"); flex("brows", "6 7 8 9 10 13 1 2 42", "-1,4 0,1 0,-2.3 0,1 0,4 0,-1 .4,.2 0,-1 -.5,1"); flex("lookX", "24 25 26", "2.8 3 3"); assymetric(); flex("lookY", "24 25 26", "0,2 0,2 0,2"); flex("lids", "12 14 60", "0,2 0,2 0,3"); flex("sayOo", "18 19 20 21 22 23 3 4 18 27 28 39 41", ".5,.2 4,-.5,2 .5 1.6 4.7,.2,1 1.6 .2 .25,.4 .4 4 4 3 2"); flex("smile", "19 21 22 23 4 27 28 39 41", "0,4.2 -.8,1 -.8,2.6 -.8,1 0,1 0,1 0,.7 0,3 0,2"); flex("sneer", "18 21 16 17 29 27 39", "-1.5,2 -1.5,2 -.2,1 -.3 0,.8 0,.6 0,.4"); map("'", "brows", 1); map("_", "brows", 0); map("`", "brows", -1); map("@", "blink", -.9); map("+", "blink", 0); map("=", "blink", .5); map("-", "blink", 1); map("t", "lids", 1); map("c", "lids", 0); map("b", "lids", -1); map("l", "lookX", -1); map(".", "lookX", 0); map("r", "lookX", 1); map("u", "lookY", 1); map(":", "lookY", 0); map("d", "lookY", -1); map("<", "turn", 1); map("!", "turn", 0); map(">", "turn", -1); map("^", "nod", 1); map("~", "nod", 0); map("v", "nod", -1); map("\\", "tilt", -1); map("|", "tilt", 0); map("/", "tilt", 1); map("m", "sayAh", -1); map("e", "sayAh", -.5); map("o", "sayAh", 0); map("O", "sayAh", .5); map("P", "sayOo", .8); map("p", "sayOo", .4); map("a", "sayOo", 0); map("w", "sayOo", -.4); map("W", "sayOo", -.7); map("S", "smile", 1.5); map("s", "smile", 1); map("n", "smile", 0); map("f", "smile", -.7); map("i", "sneer", -.5); map("x", "sneer", 0); map("h", "sneer", .5); map("z", "sneer", 1); } public void setPupil(float radius, float r, float g, float b, float a) { colorVector.set(pupil, new Color(r, g, b, a)); pupilSize = radius; } public void setEyeball(float radius, float r, float g, float b, float a) { colorVector.set(eyeBall, new Color(r, g, b, a)); eyeballSize = radius; } public void map(String s, String s1, double d) { for (int i = 0; i < flexNamesVector.size(); i++) { if (((String) flexNamesVector.elementAt(i)).equals(s1)) { char c = s.charAt(0); keyFlex[c] = i; keyValue[c] = d; return; } } } public void toggleShade() { doShade = isVectors ? true : !doShade; if (isVectors) { toggleVectors(); } } public void toggleNoise() { addNoise = !addNoise; } public void toggleVectors() { isVectors = !isVectors; } public void noRotate() { noRotateIndex = vertexVector.size() / 3; } public int polygons(double d, double d1, double d2, String s) { return addFaces(0, d, d1, d2, s); } public void polylines(double d, double d1, double d2, String s) { addFaces(1, d, d1, d2, s); } public int circles(double d, double d1, double d2, String s) { return addFaces(2, d, d1, d2, s); } public void vertices(String s) { if (firstVertices) { firstVertices = false; flex("turn", "", ""); flex("nod", "", ""); flex("tilt", "", ""); } if (s != null) { StringTokenizer stringtokenizer1; for (StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens(); vertexVector.addElement(new Double(stringtokenizer1.nextToken()))) { stringtokenizer1 = new StringTokenizer(stringtokenizer.nextToken(), ","); vertexVector.addElement(new Double(stringtokenizer1.nextToken())); vertexVector.addElement(new Double(stringtokenizer1.nextToken())); } } } int type(int i) { return ((Integer) typeVector.elementAt(i)).intValue(); } Color color(int i, boolean flag) { if (flag) { return Color.black; } else { return (Color) colorVector.elementAt(i); } } Vector shapes(int i) { return (Vector) shapesVector.elementAt(i); } public int addFaces(int i, double d, double d1, double d2, String s) { int index = typeVector.size(); typeVector.addElement(new Integer(i)); colorVector.addElement(new Color((float) d1, (float) d1, (float) d1)); shapesVector.addElement(shapeVector = new Vector()); if (s != null) { for (StringTokenizer stringtokenizer = new StringTokenizer(s); stringtokenizer.hasMoreTokens();) { shapeVector.addElement(face = new Vector()); for (StringTokenizer stringtokenizer1 = new StringTokenizer(stringtokenizer.nextToken(), ","); stringtokenizer1.hasMoreTokens(); face.addElement(new Integer(stringtokenizer1.nextToken()))); } } return index; } public void assymetric() { int i = flexVector.size() - 1; flexSymmetryVector.setElementAt(new Integer(1), i); } public void flex(String s, String s1, String s2) { flexNamesVector.addElement(s); flexSymmetryVector.addElement(new Integer(-1)); flexVector.addElement(flx = new Vector()); for (StringTokenizer stringtokenizer = new StringTokenizer(s1); stringtokenizer.hasMoreTokens(); ixyz.addElement(new Integer(stringtokenizer.nextToken()))) { flx.addElement(ixyz = new Vector()); } int i = 0; for (StringTokenizer stringtokenizer1 = new StringTokenizer(s2); stringtokenizer1.hasMoreTokens();) { ixyz = (Vector) flx.elementAt(i++); for (StringTokenizer stringtokenizer2 = new StringTokenizer(stringtokenizer1.nextToken(), ","); stringtokenizer2.hasMoreTokens(); ixyz.addElement(new Double(stringtokenizer2.nextToken()))); } } public double[][] getTargets() { double ad[][] = new double[2][flexTarget[0].length]; for (int i = 0; i < 2; i++) { System.arraycopy(flexTarget[i], 0, ad[i], 0, flexTarget[0].length); } return ad; } public void setTargets(double ad[][]) { for (int i = 0; i < 2; i++) { System.arraycopy(ad[i], 0, flexTarget[i], 0, flexTarget[0].length); } } // // public void openAnim() // { // if(f != null) // if(!f.isShowing()) // f = null; // else // f.toFront(); // if(f == null) // f = new GraphAppFrame("Animator", this, getCodeBase().toString(), null); // } @Override public void keyReleased(KeyEvent e) { super.keyReleased(e); //To change body of generated methods, choose Tools | Templates. } @Override public void keyPressed(KeyEvent e) { super.keyPressed(e); int i = e.getKeyChar(); System.out.println(i); switch (i) { case '2': leftArrow = true; prevKey = -1; break; case '3': rightArrow = true; prevKey = -1; break; case '{': // '{' spin++; break; case '}': // '}' spin--; break; case '1': // '\t' toggleNoise(); break; default: if (i != prevKey) { setFlex(i); leftArrow = false; rightArrow = false; } prevKey = i; break; } } int ai[] = new int[100]; int ai1[] = new int[100]; int ai2[] = new int[100]; @Override public void render(Graphics g) { try { boolean flag = firstTime; float f1 = 0.9019608F; super.bgcolor = new Color(50,50,50); //isVectors ? Color.white : new Color(f1, f1, f1); if (firstTime) { firstTime = false; nVertices = vertexVector.size() / 3; vertexArray = new double[nVertices][3]; for (int i = 0; i < nVertices; i++) { for (int k = 0; k < 3; k++) { vertexArray[i][k] = ((Double) vertexVector.elementAt(3 * i + k)).doubleValue(); } } nShapes = shapesVector.size(); shape = new int[nShapes][][]; for (int l = 0; l < nShapes; l++) { shapeVector = shapes(l); shape[l] = new int[shapeVector.size()][]; for (int j1 = 0; j1 < shape[l].length; j1++) { face = (Vector) shapeVector.elementAt(j1); shape[l][j1] = new int[face.size()]; for (int i2 = 0; i2 < shape[l][j1].length; i2++) { shape[l][j1][i2] = ((Integer) face.elementAt(i2)).intValue(); } } } nFlexes = flexVector.size(); flexData = new double[nFlexes][][]; flexShape = new int[nFlexes][]; flexSymmetry = new int[nFlexes]; flexTarget = new double[2][nFlexes]; flexValue = new double[2][nFlexes]; for (int k1 = 0; k1 < nFlexes; k1++) { flx = (Vector) flexVector.elementAt(k1); flexData[k1] = new double[flx.size()][]; flexShape[k1] = new int[flx.size()]; flexSymmetry[k1] = ((Integer) flexSymmetryVector.elementAt(k1)).intValue(); for (int j2 = 0; j2 < flexShape[k1].length; j2++) { ixyz = (Vector) flx.elementAt(j2); flexShape[k1][j2] = ((Integer) ixyz.elementAt(0)).intValue(); flexData[k1][j2] = new double[3]; for (int k2 = 1; k2 < ixyz.size(); k2++) { flexData[k1][j2][k2 - 1] = ((Double) ixyz.elementAt(k2)).doubleValue(); } } } flexTarget[0][3] = flexTarget[1][3] = -1D; double ad[] = { 0.080000000000000002D, 0.040000000000000001D, 0, 0, 0, 0.10000000000000001D, 0.070000000000000007D, 0.070000000000000007D, 0.14999999999999999D }; double ad1[] = { 0.25D, 0.25D, 0, 0, 0, 0.5D, 0.5D, 0.5D, 0.5D }; jitterAmpl = new double[nFlexes]; jitterFreq = new double[nFlexes]; for (int l2 = 0; l2 < ad.length && l2 < nFlexes; l2++) { jitterAmpl[l2] = ad[l2]; jitterFreq[l2] = ad1[l2]; } pts = new double[2][nVertices][3]; } int j = flexValue[0].length; for (int i1 = 0; i1 < 2; i1++) { for (int l1 = 0; l1 < j; l1++) { if (flexTarget[i1][l1] != flexValue[i1][l1] || addNoise && jitterAmpl[l1] != 0.0D) { flag = true; } } } if (!flag) { return; } double d = 0.94999999999999996D; double d1 = 1.0D; long l3 = System.currentTimeMillis(); long l4 = l3 - lastTime; double d2 = (d1 * 1000D) / (double) l4; double d3 = 1.0D - Math.pow(1.0D - d, 1.0D / d2); frameCount++; long l5 = l3 / 1000L - lastTime / 1000L; if (l5 > 0L) { dispCount = (int) ((long) frameCount / l5); frameCount = 0; } lastTime = l3; for (int i3 = 0; i3 < 2; i3++) { for (int j3 = 0; j3 < j; j3++) { flexValue[i3][j3] += d3 * (flexTarget[i3][j3] - flexValue[i3][j3]); if (addNoise && jitterAmpl[j3] != 0.0D) { flexValue[i3][j3] += jitterAmpl[j3] * ImprovMath.noise(jitterFreq[j3] * t + (double) (10 * j3)); } t += 0.0050000000000000001D; } } blinkValue = addNoise ? pulse(t / 2D + ImprovMath.noise(t / 1.5D) + 0.5D * ImprovMath.noise(t / 3D), 0.050000000000000003D) : 0.0D; doRender(g, flexValue, blinkValue, isVectors, doShade, shiftAxis); } catch (Exception e) { System.err.println(e); e.printStackTrace(); } } void doRender(Graphics g, double ad[][], double d, boolean flag, boolean flag1, boolean flag2) { try { synchronized (pts) { for (int i = 0; i < 2; i++) { for (int j = 0; j < vertexArray.length; j++) { pts[i][j][0] = vertexArray[j][0]; pts[i][j][1] = vertexArray[j][1]; pts[i][j][2] = vertexArray[j][2]; if (i == 1) { pts[i][j][0] = -pts[i][j][0]; } } } for (int k = 0; k < nFlexes; k++) { for (int l = 0; l < flexShape[k].length; l++) { int i1 = flexShape[k][l]; double d2 = ad[0][k]; double d4 = ad[1][k]; if (k == 4 && d == 1.0D) { d2 = d4 = 1.0D; } pts[0][i1][0] += d2 * flexData[k][l][0] * (double) flexSymmetry[k]; pts[1][i1][0] += d4 * flexData[k][l][0]; pts[0][i1][1] += d2 * flexData[k][l][1]; pts[1][i1][1] += d4 * flexData[k][l][1]; pts[0][i1][2] += d2 * flexData[k][l][2]; pts[1][i1][2] += d4 * flexData[k][l][2]; } } double d1 = ad[0][0]; double d3 = ad[0][1]; double d5 = ad[0][2]; if (kludge) { kludge = false; } double d6 = -0.20000000000000001D * d1 - 0.10000000000000001D * spin; d6 = (d6 + 3.1415926535897931D + 3141.5926535897929D) % 6.2831853071795862D - 3.1415926535897931D; Matrix3D matrix3d = new Matrix3D(); matrix3d.scale((double) super.height / 110D, (double) (-super.height) / 110D, (double) super.height / 110D); matrix3d.translate(35D, -80D, flag2 ? 20 : 5); matrix3d.rotateX(-0.20000000000000001D * d3); matrix3d.rotateY(d6); matrix3d.rotateZ(-0.20000000000000001D * d5); matrix3d.translate(0.0D, -30D, flag2 ? -20 : -5); Matrix3D matrix3d1 = new Matrix3D(); matrix3d1.scale((double) super.height / 110D, (double) (-super.height) / 110D, (double) super.height / 110D); matrix3d1.translate(35D, -110D, 0.0D); Vector3D vector3d = new Vector3D(); int j1 = d6 >= 0.0D ? 0 : 1; for (int k1 = 0; k1 <= 1;) { for (int l1 = 0; l1 < shape.length; l1++) { int i2 = type(l1); g.setColor(color(l1, flag)); for (int j2 = 0; j2 < shape[l1].length; j2++) { int k2 = shape[l1][j2].length; if (i2 != 0 || k2 != 2 || k1 != 1) { for (int l2 = 0; l2 < k2; l2++) { int i3 = shape[l1][j2][l2]; vector3d.set(pts[j1][i3][0], pts[j1][i3][1], pts[j1][i3][2]); vector3d.transform(i3 >= noRotateIndex ? ((MatrixN) (matrix3d1)) : ((MatrixN) (matrix3d))); ai[l2] = (int) vector3d.get(0); ai1[l2] = (int) vector3d.get(1); if (flag1) { ai2[l2] = (int) vector3d.get(2); } } if (i2 == 0 && k2 == 2) { k2 = 4; for (int j3 = 0; j3 < 2; j3++) { int l3 = shape[l1][j2][j3]; vector3d.set(pts[1 - j1][l3][0], pts[1 - j1][l3][1], pts[1 - j1][l3][2]); vector3d.transform(l3 >= noRotateIndex ? ((MatrixN) (matrix3d1)) : ((MatrixN) (matrix3d))); ai[3 - j3] = (int) vector3d.get(0); ai1[3 - j3] = (int) vector3d.get(1); if (flag1) { ai2[3 - j3] = (int) vector3d.get(2); } } } switch (i2) { default: break; case 2: // '\002' /*if (Math.abs(d6) > 2D || d6 > 0.90000000000000002D && j1 == 0 || d6 < -0.90000000000000002D && j1 == 1) { break; }*/ int k3 = ai[0] - ai[1]; int i4 = ai1[0] - ai1[1]; //byte byte0 = ((byte) (k3 * k3 + i4 * i4 < 51 ? 6 : 12)); //HACK remove the ear circles, whatever they are if ((l1!=13) && (l1!=14)) continue; float radius = l1 == 14 ? pupilSize : eyeballSize; float rscale = super.height/220f; int cr = (int)(radius * rscale); int cx = ai[0] - cr/2; int cy = ai1[0] - cr/2; if (flag) { g.drawOval(cx, cy, cr, cr); } else { g.fillOval(cx, cy, cr, cr); } break; case 1: // '\001' if (!flag && Math.abs(d6) <= 2D && (d6 <= 1.1000000000000001D || j1 != 0) && (d6 >= -1.1000000000000001D || j1 != 1)) { g.drawPolygon(ai, ai1, k2); } break; case 0: // '\0' if (flag && !((Color) colorVector.elementAt(l1)).equals(Color.black) && shape[l1][j2][0] < noRotateIndex) { ai[k2] = ai[0]; ai1[k2] = ai1[0]; g.drawPolygon(ai, ai1, k2 + 1); } if (flag || (area(ai, ai1, k2) > 0) != (j1 == 0)) { break; } if (flag1) { Color color1 = color(l1, flag); int j4 = color1.getRed(); int k4 = color1.getGreen(); int l4 = color1.getBlue(); int i5 = getShade(ai, ai1, ai2); j4 = Math.min(255, i5 * j4 >> 8); k4 = Math.min(255, i5 * k4 >> 8); l4 = Math.min(255, i5 * l4 >> 8); g.setColor(new Color(j4, k4, l4)); } g.fillPolygon(ai, ai1, k2); break; } } } } k1++; j1 = 1 - j1; } } } catch (Exception e) { } } void setFlex(int i) { try { if (!leftArrow) { flexTarget[0][keyFlex[i]] = keyValue[i]; } if (!rightArrow) { flexTarget[1][keyFlex[i]] = keyValue[i]; } } catch (Exception e) { e.printStackTrace(); } } int area(int ai[], int ai1[], int i) { int j = 0; for (int l = 0; l < i; l++) { int k = (l + 1) % i; j += (ai[l] - ai[k]) * (ai1[l] + ai1[k]); } return j / 2; } double pulse(double d, double d1) { return (double) (d - (double) (int) d >= d1 ? 0 : 1); } int getShade(int ai[], int ai1[], int ai2[]) { int i = ai[1] - ai[0]; int j = ai1[1] - ai1[0]; int k = ai2[1] - ai2[0]; int l = ai[2] - ai[1]; int i1 = ai1[2] - ai1[1]; int j1 = ai2[2] - ai2[1]; int k1 = j * j1 - k * i1; int l1 = k * l - i * j1; int i2 = i * i1 - j * l; int j2 = (k1 - l1 / 2) + i2; j2 = (8 * j2 * j2) / (k1 * k1 + l1 * l1 + i2 * i2); return 192 + 8 * j2; } } //package nars.gui.output.face; // //import java.awt.Color; //import java.awt.Event; //import java.awt.Graphics; //import java.awt.Image; //import static java.lang.Thread.sleep; //import java.util.StringTokenizer; //import java.util.Vector; // ///** @author http://cs.nyu.edu/~lhs215/multimedia/face/ */ //public class Face2bApplet extends Animator //{ // //---- PUBLIC INTERFACE: // // // MAP A KEY TO A FLEX VALUE // // public void map(String s, String flexName, double f) { // for (int i = 0 ; i < flexNamesVector.size() ; i++) // if (((String)flexNamesVector.elementAt(i)).equals(flexName)) { // char key = s.charAt(0); // keyFlex[(int)key] = i; // keyValue[(int)key] = f; // return; // } // } // // // ALL THIS PARSING STUFF GOES IN THE "MOVING" OBJECT // // public void set(String s) { // for (int i = 0 ; i < s.length() ; i++) // if (s.charAt(i) == '[') // leftArrow = true; // else if (s.charAt(i) == ']') // rightArrow = true; // else if (s.charAt(i) >= '0' && s.charAt(i) <= '9') // sleep(100 * (s.charAt(i) - '0')); // else { // setFlex((int)s.charAt(i)); // leftArrow = rightArrow = false; // } // } // public void toggleShade() { // doShade = isVectors ? true : !doShade; // if (isVectors) // toggleVectors(); // } // public void toggleNoise() { addNoise = ! addNoise; } // public void toggleVectors() { isVectors = ! isVectors; } // public void noRotate() { noRotateIndex = vertexVector.size() / 3; } // // public void polygons (double r, double g, double b, String str) // { addFaces(POLYGON, r,g,b, str); } // public void polylines(double r, double g, double b, String str) // { addFaces(POLYLINE, r,g,b, str); } // public void circles (double r, double g, double b, String str) // { addFaces(CIRCLE, r,g,b, str); } // // // PARSE ITEMS OF THE FORM vertices("x,y,z x,y,z ...") // // public void vertices(String str) // { // StringTokenizer arg, word; // // if (firstVertices) { // firstVertices = false; // flex("turn","1","",""); // flex("nod" ,"1","",""); // flex("tilt","1","",""); // } // // if (str != null) // for (arg = new StringTokenizer(str) ; arg.hasMoreTokens() ; ) { // word = new StringTokenizer(arg.nextToken(), ","); // vertexVector.addElement(new Double(word.nextToken())); // vertexVector.addElement(new Double(word.nextToken())); // vertexVector.addElement(new Double(word.nextToken())); // } // } // // // PARSE SHAPE SPECIFIERS: addFaces(type, r, g, b, "a,b,c d,e,f,g ...") // // WHERE a,b,c,d,e,f... ARE VERTEX INDICES. // // int type(int i) { return ((Integer)typeVector.elementAt(i)).intValue(); } // Color color(int i, boolean vec) { return vec ? Color.black : (Color)colorVector.elementAt(i); } // Vector shapes(int i) { return (Vector)shapesVector.elementAt(i); } // // public void addFaces(int type, double r, double g, double b, String str) // { // StringTokenizer fs, f; // // typeVector.addElement(new Integer(type)); // colorVector.addElement(new Color((float)r,(float)g,(float)b)); // shapesVector.addElement(shapeVector = new Vector()); // if (str != null) // for (fs = new StringTokenizer(str) ; fs.hasMoreTokens() ; ) { // shapeVector.addElement(face = new Vector()); // for (f=new StringTokenizer(fs.nextToken(),","); f.hasMoreTokens(); ) // face.addElement(new Integer(f.nextToken())); // } // } // // // SPECIFY THAT THE FLEX WE'VE JUST SPECIFIED IS HORIZONTALLY ASSYMETRIC // // public void assymetric() { // int lastFlex = flexVector.size()-1; // flexSymmetryVector.setElementAt(new Integer(1), lastFlex); // } // // // PARSE FLEX SPECIFIERS OF THE FORM: // // flex("name", "settle_time", "a b c ...", "x,y,z x,y,z x,y,z ...") // // // WHERE a,b,c... ARE VERTEX INDICES, and x,y,z ARE DISPLACEMENTS. // // public void flex(String name, String settle, String id, String xyz) { // StringTokenizer s, t; // // flexNamesVector.addElement(name); // flexSettleVector.addElement(new Double(settle)); // flexSymmetryVector.addElement(new Integer(-1)); // flexVector.addElement(flx = new Vector()); // for (s = new StringTokenizer(id) ; s.hasMoreTokens() ; ) { // flx.addElement(ixyz = new Vector()); // ixyz.addElement(new Integer(s.nextToken())); // } // int i = 0; // for (s = new StringTokenizer(xyz) ; s.hasMoreTokens() ; ) { // ixyz = (Vector)flx.elementAt(i++); // for (t=new StringTokenizer(s.nextToken(), ",") ; t.hasMoreTokens() ; ) // ixyz.addElement(new Double(t.nextToken())); // } // } // // // CSP: // // getTargets() return current flex targets for Animation applet // // setTargets() sets the targets // // getSnapshotImage() returns an image of size w by h described // // by the values in flexVals // // openAnim() opens the animation applet in a frame // // // // public double[][] getTargets() { // double[][] retVal = new double[2][flexTarget[0].length]; // for(int s = 0; s < 2; s++) // for(int v = 0; v < flexTarget[0].length; v++) // retVal[s][v] = flexTarget[s][v]; // return retVal; // } // // public void setTargets(double[][] inVal) { // for(int s = 0; s < 2; s++) // for(int v = 0; v < flexTarget[0].length; v++) // flexTarget[s][v] = inVal[s][v]; // } // // public Image getSnapshotImage(double[][] flexVals) { // Image temp = createImage(bounds().width, bounds().height); // Graphics tempg = temp.getGraphics(); // doRender(tempg, flexVals, 0, false, false, false); // // tempg.dispose(); // return temp; // } // // public void init() { // super.init(); // setBackground(Color.white); // lastTime = System.currentTimeMillis(); // frameCount = 0; // dispCount = 0; // } // // GraphAnimFrame f = null; // // public void openAnim() { // if(f != null) // if(!f.isShowing()) { // f = null; // } else { // f.toFront(); // } // if(f == null) { // f = new GraphAnimFrame("Animator", this); // } // } // // public void getFaceFrame() { // if(f != null) // f.getGraphanim().getFaceFrame(); // } // // public void startAnim() { // if(f != null) // f.getGraphanim().startAnim(); // } // // // end CSP // // public boolean keyUp(Event e, int key) { // switch (key) { // case Event.LEFT: // leftArrow = true; // prevKey = -1; // break; // case Event.RIGHT: // rightArrow = true; // prevKey = -1; // break; // case '{': // spin++; // break; // case '}': // spin--; // break; // case '\t': // toggleNoise(); // break; // default: // if (key != prevKey) { // setFlex(key); // leftArrow = false; // rightArrow = false; // } // prevKey = key; // break; // } // return true; // } // // boolean okToRender = false; // public void enableRender() { okToRender = true; } // // //--- RENDERING ROUTINE, CALLED EVERY FRAME // // public void render(Graphics g) { // // //the JavaScript turns on rendering when it's done with init stuff // if (!okToRender) // return; // // //firstTime is set elsewhere to true for the first rendering, false after // boolean changed = firstTime; // // //float of gray color - don't know why it's not named // float c = (float)128 / 255; // //background is white for wireframe, gray for rendered // bgcolor = isVectors ? Color.white : new Color(c,c,c); // // // INITIALIZATION OF THE "MOVING" OBJECT HAPPENS HERE // // if (firstTime) { // firstTime = false; // // //set up keymaps, seems to overlap with javascript to do same // createKeyMaps(); // //set nVertices to number of vertices - 1/3 of number of coords read // nVertices = vertexVector.size()/3; // // //set up an array to hold the vertices // vertexArray = new double[nVertices][3]; // //load it // for (int v = 0 ; v < nVertices ; v++) // for (int j = 0 ; j < 3 ; j++) // vertexArray[v][j] = // ((Double)vertexVector.elementAt(3*v + j)).doubleValue(); // // //set nShapes to number of shapes read from Javascript // nShapes = shapesVector.size(); // // //set up an array to hold shape data // shape = new int[nShapes][][]; // for (int i = 0 ; i < nShapes ; i++) { // //put the shape we're looking at in a temporary var // //shapes(i) reads the ith shape from shapesVector // //create the array for shape i - an array of length // //number_of_faces_in_shape, each containing number_of_vertices // //_in_face integers identifying the appropriate vertices // //not sure what a face with only two vertices means // shapeVector = shapes(i); // shape[i] = new int[shapeVector.size()][]; // for (int j = 0 ; j < shape[i].length ; j++) { // face = (Vector)shapeVector.elementAt(j); // shape[i][j] = new int[face.size()]; // for (int k = 0 ; k < shape[i][j].length ; k++) // shape[i][j][k] = ((Integer)face.elementAt(k)).intValue(); // } // } // // nFlexes = flexVector.size(); // // flexData = new double[nFlexes][][]; // flexShape = new int [nFlexes][]; // flexSymmetry = new int [nFlexes]; // flexTarget = new double[2][nFlexes]; // flexValue = new double[2][nFlexes]; // flexSettle = new double[nFlexes]; // // for (int f = 0 ; f < nFlexes ; f++) { // flx = (Vector)flexVector.elementAt(f); // flexData [f] = new double[flx.size()][]; // flexShape [f] = new int[flx.size()]; // flexSymmetry[f] = // ((Integer)flexSymmetryVector.elementAt(f)).intValue(); // for (int j = 0 ; j < flexShape[f].length ; j++) { // ixyz = (Vector)flx.elementAt(j); // flexShape[f][j] = ((Integer)ixyz.elementAt(0)).intValue(); // flexData [f][j] = new double[3]; // for (int k = 1 ; k < ixyz.size() ; k++) // flexData[f][j][k-1] = // ((Double)ixyz.elementAt(k)).doubleValue(); // } // flexSettle[f] = ((Double)flexSettleVector.elementAt(f)).doubleValue(); // } // // flexTarget[0][3] = flexTarget[1][3] = -1; // // double[] jtrAmpl = {.08,.04,0, 0,0,.1,.07,.07,.15}; // double[] jtrFreq = {.25,.25,0, 0,0,.5,.5 ,.5 ,.5 }; // // jitterAmpl = new double[nFlexes]; // jitterFreq = new double[nFlexes]; // // for (int f = 0 ; f < jtrAmpl.length && f < nFlexes ; f++) { // jitterAmpl[f] = jtrAmpl[f]; // jitterFreq[f] = jtrFreq[f]; // } // // pts = new double[2][nVertices][3]; // } // // // FRAME-BY-FRAME STUFF FOR THE "MOVING" OBJECT HAPPENS HERE // // int nFlexes = flexValue[0].length; // /* The background is blanked anyway - if we don't draw, the face disappears // for (int s = 0 ; s < 2 ; s++) // for (int f = 0 ; f < nFlexes ; f++) // if (flexTarget[s][f] != flexValue[s][f] || (addNoise && jitterAmpl[f] != 0)) // changed = true; // if (! changed) // return; // */ // // // CSP: do frame rate stuff // // calculate frame rate based on elapsed time since last render // // find per-frame movement to accomplish move_p percent of movement // // in move_t seconds // // changed by lsanders to have separate settling times // // double move_p = 0.95; //move 95% of the way during the settling time // // long currTime = System.currentTimeMillis(); // double secdiff = (currTime - lastTime)/1000.0; // // /* // frameCount++; // long secdiff = currTime/1000 - lastTime/1000; // if(secdiff > 0) { // dispCount = (int)(frameCount / secdiff); // frameCount = 0; // // System.out.println("frames: " + dispCount); // } // // */ // lastTime = currTime; // // end CSP // // double uipf, move_inc; // for (int s = 0 ; s < 2 ; s++) // for (int f = 0 ; f < nFlexes ; f++) { // uipf = secdiff/flexSettle[f]; //what percentage of settle time has passed // move_inc = 1.0 - Math.pow((1.0 - move_p), uipf); // // flexValue[s][f] += move_inc * (flexTarget[s][f] - flexValue[s][f]); // if (addNoise && jitterAmpl[f] != 0) // flexValue[s][f] += // jitterAmpl[f] * ImprovMath.noise(jitterFreq[f] * t + 10 * f); // t += .005; // } // // blinkValue = //!addNoise ? 0 : // pulse(t/2 + ImprovMath.noise(t/1.5) + .5*ImprovMath.noise(t/3), .05); // // doRender(g, flexValue, blinkValue, isVectors, doShade, shiftAxis); // // // g.setColor(Color.white); // // g.drawString("frames: " + dispCount + ", inc: " + move_inc, 25, 380); // } // // void doRender(Graphics g, double[][] flexValueLocal, double blinkValueLocal, // boolean isVectorsLocal, boolean doShadeLocal, boolean shiftAxisLocal) { // synchronized(pts) { // int[] x = new int[100]; // int[] y = new int[100]; // int[] z = new int[100]; // // // temporary storage for vertices, split out by face side // for (int s = 0 ; s < 2 ; s++) // for (int v = 0 ; v < vertexArray.length ; v++) { // pts[s][v][0] = vertexArray[v][0]; // pts[s][v][1] = vertexArray[v][1]; // pts[s][v][2] = vertexArray[v][2]; // if (s == 1) // pts[s][v][0] = -pts[s][v][0]; // } // // // calculate flex effects on vertices // for (int f = 0 ; f < nFlexes ; f++) // for (int j = 0 ; j < flexShape[f].length ; j++) { // int n = flexShape[f][j]; // double L = flexValueLocal[0][f]; // double R = flexValueLocal[1][f]; // if (f == 4 && blinkValueLocal == 1) // L = R = 1; // pts[0][n][0] += L * flexData[f][j][0] * flexSymmetry[f]; // pts[1][n][0] += R * flexData[f][j][0]; // pts[0][n][1] += L * flexData[f][j][1]; // pts[1][n][1] += R * flexData[f][j][1]; // pts[0][n][2] += L * flexData[f][j][2]; // pts[1][n][2] += R * flexData[f][j][2]; // } // // // COMPUTE TRANSFORMATION MATRICES // // double rotY = flexValueLocal[0][0]; // double rotX = flexValueLocal[0][1]; // double rotZ = flexValueLocal[0][2]; // // // CSP: I don't know why, but weird errors occur if this is not here // if(kludge) { // System.out.println("first time"); // kludge = false; // } // // double theta = -.2*rotY - .1*spin; // theta = ((theta + Math.PI + 1000 * Math.PI) % (2*Math.PI)) - Math.PI; // // Matrix3D m1 = new Matrix3D(); // m1.scale(height/110.,-height/110.,height/110.); // m1.translate(35,-80,shiftAxisLocal ? 20 : 5); // m1.rotateX(-.2*rotX); // m1.rotateY(theta); // m1.rotateZ(-.2*rotZ); // m1.translate(0,-30,shiftAxisLocal ? -20 : -5); // // Matrix3D m2 = new Matrix3D(); // m2.scale(height/110.,-height/110.,height/110.); // m2.translate(35,-110,0); // // Vector3D v = new Vector3D(); // // // RENDER THE TWO SIDES OF FACE // // int s = (theta < 0) ? 1 : 0; // which side is rendered first depends on head rotation // for (int _s = 0 ; _s <= 1 ; _s++, s = 1-s) // for (int i = 0 ; i < shape.length ; i++) { // // int type = type(i); // g.setColor(color(i, isVectorsLocal)); // // for (int j = 0 ; j < shape[i].length ; j++) { // // int nk = shape[i][j].length; // if (type == POLYGON && nk == 2 && _s == 1) // continue; // // for (int k = 0 ; k < nk ; k++) { // int n = shape[i][j][k]; // v.set(pts[s][n][0], pts[s][n][1], pts[s][n][2]); // v.transform(n < noRotateIndex ? m1 : m2); // x[k] = (int)v.get(0); // y[k] = (int)v.get(1); // if (doShadeLocal) // z[k] = (int)v.get(2); // } // // if (type == POLYGON && nk == 2) { // nk = 4; // for (int k = 0 ; k < 2 ; k++) { // int n = shape[i][j][k]; // v.set(pts[1-s][n][0],pts[1-s][n][1],pts[1-s][n][2]); // v.transform(n < noRotateIndex ? m1 : m2); // x[3-k] = (int)v.get(0); // y[3-k] = (int)v.get(1); // if (doShadeLocal) // z[3-k] = (int)v.get(2); // } // } // // switch (type) { // case CIRCLE: // if (Math.abs(theta)>2 || theta>.9 && s==0 || theta<-.9 && s==1) // break; // int dx = x[0]-x[1], dy = y[0]-y[1], r = dx*dx + dy*dy >= 51 ? 12 : 6; // if (isVectorsLocal) // g.drawOval(x[0]-r, y[0]-r, 2*r, 2*r); // else // g.fillOval(x[0]-r, y[0]-r, 2*r, 2*r); // break; // case POLYLINE: // if (!isVectorsLocal && !(Math.abs(theta)>2 || theta>1.1 && s==0 || theta<-1.1 && s==1)) // g.drawPolygon(x, y, nk); // break; // case POLYGON: // if (isVectorsLocal && !((Color)colorVector.elementAt(i)).equals(Color.black) // && shape[i][j][0] < noRotateIndex) { // x[nk] = x[0]; // y[nk] = y[0]; // g.drawPolygon(x, y, nk+1); // } // if (!isVectorsLocal && (area(x, y, nk) > 0) == (s == 0)) { // if (doShadeLocal) { // Color color = color(i, isVectorsLocal); // int R = color.getRed(), G = color.getGreen(), B = color.getBlue(); // int S = getShade(x,y,z); // R = Math.min(255, S*R >> 8); // G = Math.min(255, S*G >> 8); // B = Math.min(255, S*B >> 8); // g.setColor(new Color(R, G, B)); // } // g.fillPolygon(x, y, nk); // } // break; // } // } // } // } // } // // //---- INTERNAL METHODS // // void setFlex(int key) { // if (! leftArrow) // flexTarget[0][keyFlex[key]] = keyValue[key]; // if (! rightArrow) // flexTarget[1][keyFlex[key]] = keyValue[key]; // } // // int area(int[] x, int[] y, int n) { // int area = 0; // int j; // for (int i = 0 ; i < n ; i++) { // j = (i+1) % n; // area += (x[i] - x[j]) * (y[i] + y[j]); // } // return area / 2; // } // // double pulse(double t,double epsilon) { return (t-(int)t)<epsilon ? 1 : 0; } // // //---- INTERNAL VARIABLES // // // vertices are combined into polygons, polylines, and circles // // vertices are grouped together into flexes, and given offsetx which are multiplied by -1 to 1 // // boolean firstVertices = true, isVectors = false, addNoise = true, doShade = false, shiftAxis = false; // // int nVertices, nShapes, nFlexes; // // int[] keyFlex = new int[256]; // double[] keyValue = new double[256]; // // double[][] flexValue, flexTarget; // double[] jitterAmpl, jitterFreq, flexSettle; // // boolean firstTime = true; // boolean kludge = true; // CSP: see kludge comment in doRender() // // final int POLYGON = 0; // final int POLYLINE = 1; // final int CIRCLE = 2; // // double[][][] flexData; // array of double[3] offsets for each vertex of each shape // int[][] flexShape; // array of vertices which make up shapes // int flexSymmetry[]; // double[][][] pts; // int[][][] shape; // array of vertices of subparts of shapes // double[][] vertexArray; // array of double[3] of vertices // // double t = 0, blinkValue = 0; // int spin = 0, noRotateIndex = 1000; // // boolean leftArrow = false, rightArrow = false; // // int prevKey = -1; // // long lastTime; // int frameCount, dispCount; // ////---- INTERNAL VECTORS USED WHILE PARSING // // Vector colorVector = new Vector(); // Vector flexNamesVector = new Vector(); // list of flexes // Vector flexSettleVector = new Vector(); // list of settle times // Vector flexVector = new Vector(), flx, ixyz; // Vector of Vectors; inner vector first value is vertex, rest are flex offsets // Vector flexSymmetryVector = new Vector(); // Vector shapesVector = new Vector(), shapeVector, face; // list of shapes; Vector of Vector of Vectors // Vector typeVector = new Vector(); // Vector vertexVector = new Vector(); // list of vertices; each x, y, z triple is 3 entries; converted to vertexArray // // void createKeyMaps() { // map("'","brows", 1); map("_","brows", 0); map("`","brows", -1); // map("@","blink",-.9); map("+","blink", 0); map("=","blink", .5); // map("-","blink", 1); // map("t","lids" , 1); map("c","lids" , 0); map("b","lids" , -1); // // map("l","lookX", -1); map(".","lookX", 0); map("r","lookX", 1); // map("u","lookY", 1); map(":","lookY", 0); map("d","lookY", -1); // map("<","turn" , 1); map("!","turn" , 0); map(">","turn" , -1); // map("^","nod" , 1); map("~","nod" , 0); map("v","nod" , -1); // map("\\","tilt", -1); map("|","tilt" , 0); map("/","tilt" , 1); // // map("m","sayAh", -1); map("e","sayAh",-.5); map("o","sayAh", 0); // map("O","sayAh", .5); // map("p","sayOo", .8); map("a","sayOo", 0); map("w","sayOo",-.7); // map("s","smile", 1); map("n","smile", 0); map("f","smile",-.7); // map("i","sneer",-.5); map("x","sneer", 0); map("h","sneer", .5); // map("z","sneer", 1); // } // // // 3D Shading // // int getShade(int[] x, int[] y, int[] z) { // int ax = x[1] - x[0], ay = y[1] - y[0], az = z[1] - z[0]; // int bx = x[2] - x[1], by = y[2] - y[1], bz = z[2] - z[1]; // int cx = ay * bz - az * by, cy = az * bx - ax * bz, cz = ax * by - ay * bx; // int N = cx - cy/2 + cz; // N = 8 * N * N / (cx*cx + cy*cy + cz*cz); // return 192 + 8 * N; // } // // // Routines for dianostic printout // // void printVertices() { // System.out.println("VERTICES:"); // for (int v = 0 ; v < nVertices ; v++) { // System.out.print(" " + v + ": "); // for (int j = 0 ; j < 3 ; j++) { // System.out.print(vertexArray[v][j]); // if (j < 2) // System.out.print(","); // } // System.out.println(); // } // System.out.println(); // } // // void printFaces() { // System.out.println("FACES:"); // for (int i = 0 ; i < nShapes ; i++) { // System.out.print(" {"); // for (int j = 0 ; j < shape[i].length ; j++) { // System.out.print(" "); // for (int k = 0 ; k < shape[i][j].length ; k++) { // System.out.print(shape[i][j][k]); // if (k < shape[i][j].length-1) // System.out.print(","); // } // } // System.out.println("}"); // } // System.out.println(); // } // // void printShapes() { // System.out.println("SHAPES:"); // for (int i = 0 ; i < nShapes ; i++) { // System.out.println(); // for (int j = 0 ; j < shape[i].length ; j++) { // System.out.print("{"); // for (int k = 0 ; k < shape[i][j].length ; k++) { // int n = shape[i][j][k]; // System.out.print(vertexArray[n][0] + " " + // vertexArray[n][1] + " " + // vertexArray[n][2]); // if (k < shape[i][j].length-1) // System.out.print(" "); // } // System.out.println("}"); // } // } // System.out.println(); // } //} //