//
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);
}
}