//
import render.*; public class Doll extends Actor { static public boolean debug = false; static Material shadowColor = new Material(); static Material shinyBlack = new Material(); static Material matteBlack = new Material(); static Material copper = new Material(); static Material gold = new Material(); static Material silver = new Material(); static Material violet = new Material(); Material skinColor = silver; Material eyeColor = shinyBlack; Material hairColor = matteBlack; boolean isGirl = false; static { // THE FOLLOWING COLORS ARE DECLARED STATIC BECAUSE // THEY WILL BE THE SAME FOR ALL DOLLS double f=1.3,r=f*.8,g=f*.6,b=f*.24,S=1.5,A=.5; gold.setAmbient(A*r,A*g,A*b); gold.setDiffuse(r,g,b,2); gold.setSpecular(S*r,S*g,S*b,10); r = .7; g = .7; b = .8; silver.setAmbient(A*r,A*g,A*b); silver.setDiffuse(r,g,b,2); silver.setSpecular(S*r,S*g,S*b,10); r = .8; g = .5; b = .3; S = 2; A=.6; copper.setAmbient(A*r,A*g,A*b); copper.setDiffuse(r,g,b,2); copper.setSpecular(S*r,S*g,S*b,10); r = 1; g = 0; b = .7; S = 1.5; A=.5; violet.setAmbient(A*r,A*g,A*b); violet.setDiffuse(r,g,b,2); violet.setSpecular(S*r,S*g,S*b,10); shinyBlack.setAmbient(0,0,0); shinyBlack.setDiffuse(0,0,0); shinyBlack.setSpecular(1.5,1.5,1.5,10); matteBlack.setAmbient(0,0,0); matteBlack.setDiffuse(.3,.3,.3,2); matteBlack.setSpecular(.7,.7,.7,3); shadowColor.setAmbient(0,0,0); shadowColor.setDiffuse(0,0,0); shadowColor.setSpecular(0,0,0,1); shadowColor.setTransparency(.8); } // ALL THE PARTS OF THE DOLL public Geometry shadow, head, hair, body, nose, leftEye, rightEye, torso; public Geometry leftShoulder, rightShoulder, leftArm, rightArm, leftHand, rightHand; double height = 2; // HOW TALL IS THE DOLL? double leftArmAngle = 0; // LEFT ARM SWING ANGLE double rightArmAngle = 0; // RIGHT ARM SWING ANGLE // DECLARE ALL THE PARTS OF THE DOLL AND SET DEFAULT PROPORTIONS public Doll() { super(); shadow = add(); shadow.add().disk(10); shadow.add().disk(10); shadow.setMaterial(shadowColor); head = parts.add().ball(5); hair = head.add(); hair.add().globe(16, 8, .15,.85, .25,1).setDoubleSided(true); nose = head.add().ball(3); leftEye = head.add().ball(2); rightEye = head.add().ball(2); body = parts.add(); torso = body.add().pill(10,.8,.2); leftShoulder = body.add(); leftShoulder.add().ball(3); leftShoulder.add().cylinder(5); leftShoulder.child[1].matrix.translate(0,0,1); leftShoulder.child[1].matrix.scale(.5,.5,1); rightShoulder = body.add(); rightShoulder.add().ball(3); rightShoulder.add().cylinder(5); rightShoulder.child[1].matrix.translate(0,0,-1); rightShoulder.child[1].matrix.scale(.5,.5,1); leftArm = body.add().cylinder(8); rightArm = body.add().cylinder(8); leftHand = body.add().ball(3); rightHand = body.add().ball(3); } public Doll setGirl() { isGirl = true; return this; } public Doll setSkin(Material m) { skinColor = m; return this; } public Doll setSkin(double f) { skinColor = new Material(); f = .5 + .5*f; double r = .8*f, g = .6*Math.pow(f,1.5), b = .5*f*f; skinColor.setAmbient(r/2,g/2,b/2); skinColor.setDiffuse(r,g,b); skinColor.setSpecular(g/2,g/2,g/2,5); return this; } public Doll setHeight(double h) { height = h; isNewPose = true; return this; } // GAZING AT OTHER OBJECTS double prevLookAngle = 0; Geometry prevLookObject = null; boolean atLookAngle = false; public boolean setGaze(Geometry g) { super.setGaze(g); if (g != prevLookObject) { atLookAngle = false; prevLookObject = g; return false; } atLookAngle |= Math.abs(prevLookAngle - getLookAngle(g)) < .02; return atLookAngle; } double getLookAngle(Geometry object) { double t = 0; if (object != null) { Matrix A = matrix, B = object.matrix; t = Math.atan2(A.get(2,3) - B.get(2,3), B.get(0,3) - A.get(0,3)); t = (t - theta) / (2 * Math.PI); } return gw * 2*Math.PI * Math.max(-.25, Math.min(.25, t<-.5 ? t+1 : t>.5 ? t-1 : t)); } // FACING OTHER OBJECTS double getFacingAngle(Geometry object) { double t = 0; if (object != null) { Matrix A = matrix, B = object.matrix; t = Math.atan2(A.get(2,3) - B.get(2,3), B.get(0,3) - A.get(0,3)); t = (t - theta) / (2 * Math.PI); } return 2*Math.PI * Math.max(-.25, Math.min(.25, t<-.5 ? t+1 : t>.5 ? t-1 : t)) + theta; } // SETTING ARM POSITIONS public boolean setLeftArmAngle(double angle) { boolean isDone = isNear(angle, leftArmAngle); leftArmAngle = angle; return isDone; } public double getLeftArmAngle() { return leftArmAngle; } public boolean setRightArmAngle(double angle) { boolean isDone = isNear(angle, rightArmAngle); rightArmAngle = angle; return isDone; } public double getRightArmAngle() { return rightArmAngle; } double dTime = 0, prevTime = 0; public void animate(double time) { dTime = time - prevTime; prevTime = time; isNewLocation = true; isNewPose = true; super.animate(time); } public double animateLooking() { double lookAngle = getLookAngle(gazeObject); if (! atLookAngle) lookAngle = prevLookAngle + 2 * dTime * (lookAngle - prevLookAngle); prevLookAngle = lookAngle; return lookAngle; } public void computePose() { super.computePose(); double h = (height-1)/2; head.matrix.identity(); head.matrix.translate(0,height-.5,0); head.matrix.rotateY(animateLooking()); head.matrix.scale(.5,.5,.5); hair.matrix.identity(); if (isGirl) { hair.matrix.rotateX(-Math.PI/2); hair.matrix.rotateZ(-.2); hair.matrix.scale(1.15,1.15,1.15); } else hair.matrix.scale(0,0,0); nose.matrix.identity(); nose.matrix.translate(1,0,0); nose.matrix.scale(.5,.4,.4); leftEye.matrix.identity(); leftEye.matrix.translate(.7,.5,-.37); leftEye.matrix.scale(.3,.3,.3); rightEye.matrix.identity(); rightEye.matrix.translate(.7,.5,.37); rightEye.matrix.scale(.3,.3,.3); body.matrix.identity(); body.matrix.translate(0,h,0); torso.matrix.identity(); torso.matrix.scale(.5,h,.5); torso.matrix.rotateX(Math.PI/2); leftShoulder.matrix.identity(); leftShoulder.matrix.translate(0,.5*h+.2*h*h,-.72); leftArm.matrix.copy(leftShoulder.matrix); leftShoulder.matrix.scale(.2,.2,.2); leftArm.matrix.rotateZ(leftArmAngle); leftArm.matrix.translate(0,-h/2,0); leftHand.matrix.copy(leftArm.matrix); leftHand.matrix.translate(0,-h/2,0); leftHand.matrix.scale(.185,.185,.185); leftArm.matrix.scale(.2,h/2,.2); leftArm.matrix.rotateX(Math.PI/2); rightShoulder.matrix.identity(); rightShoulder.matrix.translate(0,.5*h+.2*h*h,.72); rightArm.matrix.copy(rightShoulder.matrix); rightShoulder.matrix.scale(.2,.2,.2); rightArm.matrix.rotateZ(rightArmAngle); rightArm.matrix.translate(0,-h/2,0); rightHand.matrix.copy(rightArm.matrix); rightHand.matrix.translate(0,-h/2,0); rightHand.matrix.scale(.185,.185,.185); rightArm.matrix.scale(.2,h/2,.2); rightArm.matrix.rotateX(Math.PI/2); head.setMaterial(skinColor); hair.setMaterial(hairColor); leftEye.setMaterial(eyeColor); rightEye.setMaterial(eyeColor); leftHand.setMaterial(skinColor); rightHand.setMaterial(skinColor); shadow.matrix.identity(); shadow.matrix.rotateY(Math.PI/4); shadow.matrix.translate(0,.04,-.045 * height); shadow.matrix.scale(.7,.02,.5 +.045 * height); shadow.matrix.rotateX(-Math.PI/2); shadow.child[1].matrix.identity(); shadow.child[1].matrix.translate(0,0,2); shadow.child[1].matrix.scale(.94,.88,1); } }