////////////////////////////////////////////////////////////////////// // // File: human.cc // // builds a character hierarchy // ////////////////////////////////////////////////////////////////////// #ifndef BUILDH #include "build.h" #endif /* BUILDH */ // {{{ Human #define RGB_SKIN (ulong)0xffd28e80 // #define RGB_SKIN (ulong)0x8f4f4f80 Node * buildHuman() { const double total_mass = 75., head_mass = .0792 * total_mass, pelvis_mass = .16 * total_mass, // pelvis+abdomen = 26.39% abdomen_mass = .26 * total_mass - pelvis_mass, spine_mass = .10 * total_mass, scapula_mass = .05 * total_mass, bicep_mass = .0275 * total_mass, forearm_mass = .016 * total_mass, hand_mass = .0612 * total_mass, thigh_mass = .105 * total_mass, shin_mass = .046 * total_mass, foot_mass = .014 * total_mass, leg_fat = .04, foot_len = .18, heel_len = .02, ankle_height = .105, shin_len = .405, thigh_len = .425, trunk_fat = .08, trunk_width = .22, pelvis_len = .14, abdomen_len = .30, hip_shoulder_len = .52, full_spine_len = hip_shoulder_len-pelvis_len/2-abdomen_len, spine_len = full_spine_len + .07, neck_len = .04, head_len = .19, head_width = .14, arm_fat = .03, shoulder_width = .41, scapula_len = sqrt(full_spine_len*full_spine_len + shoulder_width*shoulder_width/4), shrug_angle = -atan2(shoulder_width/2, full_spine_len), bicep_len = .31, forearm_len = .25, hand_len = .18; // {{{ Body Primitives // ============================ legs ============================ // the lfoot_prim primitive should be read in the following way: // a cube of edge length 2 centered at the origin, has mass foot_mass, // and is first translated in the x direction, then scaled and // then translated again so that the origin is at the ankle. Primitive *lfoot_prim = new PrimCube(ConstDof::var(foot_mass), new XformChain(0, 0, new Translate(-heel_len, -ankle_height, 0.), new Scale(foot_len/2,.02,foot_len/4), new Translate(1., 0., 0.), NULL), RGB_SKIN); Primitive *rfoot_prim = lfoot_prim->clone(RGB_SKIN); // the lshin_prim primitive should be read in the following // way: a sphere of radius 1 centered at the origin, has mass // shin_mass, and is first translated in the -y direction, then // scaled to be of length shin_len and of certain "fattness". Primitive *lshin_prim = new PrimSphere(ConstDof::var(shin_mass), new XformChain(0, 0, new Scale(leg_fat, shin_len/2, leg_fat), new Translate(0., -1., 0.), NULL), RGB_SKIN); Primitive *rshin_prim = lshin_prim->clone(RGB_SKIN); Primitive *lthigh_prim = new PrimSphere(ConstDof::var(thigh_mass), new XformChain(0, 0, new Scale(leg_fat*1.75, thigh_len/2, leg_fat*1.75), new Translate(0., -1., 0.), NULL), RGB_SKIN); Primitive *rthigh_prim = lthigh_prim->clone(RGB_SKIN); // ============================ arms ============================ Primitive *lhand_prim = new PrimSphere(ConstDof::var(hand_mass), new XformChain(0, 0, new Scale(arm_fat, hand_len/2, arm_fat/4), new Translate(0., -1., 0.), NULL), RGB_SKIN); Primitive *rhand_prim = lhand_prim->clone(RGB_SKIN); Primitive *lforearm_prim = new PrimSphere(ConstDof::var(forearm_mass), new XformChain(0, 0, new Scale(arm_fat, forearm_len/2, arm_fat), new Translate(0., -1., 0.), NULL), RGB_SKIN); Primitive *rforearm_prim = lforearm_prim->clone(RGB_SKIN); Primitive *lbicep_prim = new PrimSphere(ConstDof::var(bicep_mass), new XformChain(0, 0, new Scale(arm_fat*1.75, bicep_len/2, arm_fat*1.75), new Translate(0., -1., 0.), NULL), RGB_SKIN); Primitive *rbicep_prim = lbicep_prim->clone(RGB_SKIN); // =========================== trunk =========================== Primitive *pelvis_prim = new PrimSphere(ConstDof::var(pelvis_mass), new XformChain(0, 0, new Scale(trunk_fat*1.33,pelvis_len/2,trunk_width/2*1.5), NULL), RGB_SKIN); Primitive *abdomen_prim = new PrimSphere(ConstDof::var(abdomen_mass), new XformChain(0, 0, new Translate(0., pelvis_len/2, 0.), new Scale(trunk_fat,abdomen_len/2,trunk_width/2), new Translate(0., 1., 0.), NULL), RGB_SKIN); Primitive *lscapula_prim = new PrimSphere(ConstDof::var(scapula_mass), new XformChain(0, 0, new Scale(trunk_fat, scapula_len/2, trunk_fat), new Translate(0., 1., 0.), NULL), RGB_SKIN); Primitive *rscapula_prim = lscapula_prim->clone(RGB_SKIN); Primitive *spine_prim = new PrimSphere(ConstDof::var(spine_mass), new XformChain(0, 0, new Scale(trunk_fat*.66, spine_len/2, trunk_fat*.66), new Translate(0., 1., 0.), NULL), RGB_SKIN); Primitive *head_prim = new PrimSphere(ConstDof::var(head_mass), new XformChain(0, 0, new Scale(head_width/2, head_len/2, head_width/2), new Translate(0., 1.+neck_len/head_len*.5, 0.), NULL), RGB_SKIN); // }}} // {{{ Dofs // ANGLE_DOF(name, min, max, init_value) ANGLE_DOF(lankle, 0, 135 DEGREES, 0 DEGREES); ANGLE_DOF(lknee, 0, M_PI, M_PI/2); ANGLE_DOF(lankletwist, -M_PI/2, M_PI/2, 0); BALL_JOINT(lhip); BALL_JOINT(pelvis); BALL_JOINT(spine); BALL_JOINT(stomach); BALL_JOINT(neck); ANGLE_DOF(lshrug, -20 DEGREES, 20 DEGREES, 0); ANGLE_DOF(lslouch, -20 DEGREES, 20 DEGREES, 0); BALL_JOINT(lshoulder); ANGLE_DOF(lelbow, 0, M_PI, 0); ANGLE_DOF(lelbowtwist, -M_PI/2, M_PI/2, 0); ANGLE_DOF(lwrist, -M_PI/2, M_PI/2, 0); Dof *rhip_x = lhip_x->clone("rhip_x"); Dof *rhip_y = lhip_y->clone("rhip_y"); Dof *rhip_z = lhip_z->clone("rhip_z"); Dof *rhip_w = lhip_w->clone("rhip_w"); Dof *rknee = lknee->clone("rknee"); Dof *rankle = lankle->clone("rankle"); Dof *rankletwist = lankletwist->clone("rankletwist"); Dof *rshoulder_x = lshoulder_x->clone("rshoulder_x"); Dof *rshoulder_y = lshoulder_y->clone("rshoulder_y"); Dof *rshoulder_z = lshoulder_z->clone("rshoulder_z"); Dof *rshoulder_w = lshoulder_w->clone("rshoulder_w"); Dof* relbow = lelbow->clone("relbow"); Dof* relbowtwist = lelbowtwist->clone("relbowtwist"); Dof* rwrist = lwrist->clone("rwrist"); Dof* rshrug = lshrug->clone("rshrug"); Dof* rslouch = lslouch->clone("rslouch"); // }}} // {{{ Human hierarchy // Read the transformation constructions from the back. // For example the pelvis node takes the pelvis primitive // and applies a quaternion rotation (ball joint) to it // followed by a global translation. So translation is // the outermost (the last applied) transformation. Node *pelvis = new Node("Pelvis", new XformChain(0, 0, new Translate(pelvis_tx,pelvis_ty,pelvis_tz), new RotateQuat(pelvis_x,pelvis_y,pelvis_z,pelvis_w), NULL), pelvis_prim ); RotateQuat *lhip_quat; Node *lthigh = new Node("LeftThigh", new XformChain(0, 0, new Translate(0., -pelvis_len/2, -trunk_width/2.), (lhip_quat = new RotateQuat(lhip_x,lhip_y,lhip_z,lhip_w)), NULL), lthigh_prim ); pelvis->addChild(lthigh); Node *rthigh = new Node("RightThigh", new XformChain(0, 0, new Translate(0., -pelvis_len/2, trunk_width/2.), new RotateQuat(rhip_x,rhip_y,rhip_z,rhip_w), NULL), rthigh_prim ); pelvis->addChild(rthigh); Node *lshin = new Node("LeftShin", new XformChain(0, 0, new Translate(0., -thigh_len, 0.), // -M_PI is the constant offset // added to the value of lknee new RotateEuler(Zaxis, -M_PI, lknee), NULL), lshin_prim ); lthigh->addChild(lshin); Node *rshin = new Node("RightShin", new XformChain(0, 0, new Translate(0., -thigh_len, 0.), new RotateEuler(Zaxis, -M_PI, rknee), NULL), rshin_prim ); rthigh->addChild(rshin); Node *lfoot = new Node("LeftFoot", new XformChain(0, 0, new Translate(0., -shin_len, 0.), new RotateEuler(Zaxis, -80 DEGREES, lankle), new RotateEuler(Yaxis, 0., lankletwist), NULL), lfoot_prim ); lshin->addChild(lfoot); Node *rfoot = new Node("RightFoot", new XformChain(0, 0, new Translate(0., -shin_len, 0.), new RotateEuler(Zaxis, -80 DEGREES, rankle), new RotateEuler(Yaxis, 0., rankletwist), NULL), rfoot_prim ); rshin->addChild(rfoot); Node *abdomen = new Node("Abdomen", new RotateQuat(stomach_x,stomach_y,stomach_z,stomach_w), abdomen_prim ); pelvis->addChild(abdomen); Node *spine = new Node("Spine", new XformChain(0, 0, new Translate(0., abdomen_len, 0.), new RotateQuat(spine_x,spine_y,spine_z,spine_w), NULL), spine_prim ); abdomen->addChild(spine); Node *head = new Node("Head", new XformChain(0, 0, new Translate(0., spine_len, 0.), new RotateQuat(neck_x,neck_y,neck_z,neck_w), NULL), head_prim ); spine->addChild(head); Node *lscapula = new Node("LeftScapula", new XformChain(0, 0, new RotateEuler(Zaxis, 0, lslouch), new RotateEuler(Xaxis, shrug_angle, lshrug), NULL), lscapula_prim ); spine->addChild(lscapula); Node *rscapula = new Node("RightScapula", new XformChain(0, 0, new RotateEuler(Zaxis, 0, rslouch), new RotateEuler(Xaxis, -shrug_angle, rshrug), NULL), rscapula_prim ); spine->addChild(rscapula); Node *lbicep = new Node("LeftBicep", new XformChain(0, 0, new Translate(0., scapula_len, 0.), new RotateQuat(lshoulder_x,lshoulder_y,lshoulder_z,lshoulder_w), NULL), lbicep_prim ); lscapula->addChild(lbicep); Node *rbicep = new Node("RightBicep", new XformChain(0, 0, new Translate(0., scapula_len, 0.), new RotateQuat(rshoulder_x,rshoulder_y,rshoulder_z,rshoulder_w), NULL), rbicep_prim ); rscapula->addChild(rbicep); Node *lforearm = new Node("LeftForearm", new XformChain(0, 0, new Translate(0., -bicep_len, 0.), new RotateEuler(Zaxis, 0., lelbow), new RotateEuler(Yaxis, 0., lelbowtwist), NULL), lforearm_prim ); lbicep->addChild(lforearm); Node *rforearm = new Node("RightForearm", new XformChain(0, 0, new Translate(0., -bicep_len, 0.), new RotateEuler(Zaxis, 0., relbow), new RotateEuler(Yaxis, 0., relbowtwist), NULL), rforearm_prim ); rbicep->addChild(rforearm); Node *lhand = new Node("LeftHand", new XformChain(0, 0, new Translate(0., -forearm_len, 0.), new RotateEuler(Xaxis, 0., lwrist), NULL), lhand_prim ); lforearm->addChild(lhand); Node *rhand = new Node("RightHand", new XformChain(0, 0, new Translate(0., -forearm_len, 0.), new RotateEuler(Xaxis, 0., rwrist), NULL), rhand_prim ); rforearm->addChild(rhand); // }}} Node *root = pelvis; // Marker specification: // Marker(node, name, xpos, ypos, zpos) // node -- a local frame to which the marker belongs // name -- name of the marker // xpos,ypos,zpos -- local displacements for the marker position MARKER(lfoot, lfoot_in, .13, -ankle_height, .06); MARKER(lfoot, lfoot_out, .13, -ankle_height, -.06); MARKER(rfoot, rfoot_in, .13, -ankle_height, -.06); MARKER(rfoot, rfoot_out, .13, -ankle_height, .06); MARKER(lshin, lankle, -.05, -shin_len+.01, .0); MARKER(rshin, rankle, -.05, -shin_len+.01, .0); MARKER(lthigh, lknee, -.01, -thigh_len+.008, -.06); MARKER(rthigh, rknee, -.01, -thigh_len+.0, .06); MARKER(pelvis, lhip, -.0, -pelvis_len/2-0.01, -.21); MARKER(pelvis, rhip, -.0, -pelvis_len/2, .21); MARKER(pelvis, tail, -.12, +.01, .0); MARKER(spine, chest, .11, full_spine_len-.035, .0); MARKER(spine, neck, -.04, spine_len+.01, .0); MARKER(lscapula, lshldr, -.05, scapula_len, -.015); MARKER(rscapula, rshldr, -.05, scapula_len, .015); MARKER(lbicep, lelbow, .01, -bicep_len+.01, -.06); MARKER(rbicep, relbow, .01, -bicep_len+.01, .06); MARKER(lforearm, lwrist_front,.04, -forearm_len, -.0); MARKER(lforearm, lwrist_back, -.04, -forearm_len, -.0); MARKER(rforearm, rwrist_front, .04, -forearm_len, -.0); MARKER(rforearm, rwrist_back, -.04, -forearm_len, -.0); MARKER(lhand, lknuckle, -.00, -.08, -.03); MARKER(rhand, rknuckle, -.00, -.08, .03); MARKER(head, head_lear, -.00, neck_len+head_len-.11, -.07); MARKER(head, head_rear, -.00, neck_len+head_len-.11, .07); MARKER(head, head_top, -.00, neck_len+head_len, .00); return root; }