// HOW TO WALK ALONG A PATH // // Technique developed by Rune S. Johansen // Render as animation with clock going from 0 to 1 and // with at least 100 frames. // A quick scene camera {location 10*y look_at 0 rotate -60*x angle 12 translate 0.2*y} light_source {<1,2,-1>*1000, color 0.5 shadowless} light_source {<1,2,-1>*1000, color 0.5} plane {y, 0 pigment {checker rgb 1.1, rgb 0.9 scale 0.2}} #default {texture {pigment {color <0.9,1.1,1.2>}}} // The path to follow: #macro WalkPath (Time) vrotate(Time*x,180*Time*y) #end #declare Time = -1+2*clock; #declare PrevTime = floor(Time*5)/5; #declare NextTime = floor(Time*5+1)/5; #declare CurPoint = WalkPath(Time); #declare PrevPoint = WalkPath(PrevTime); #declare NextPoint = WalkPath(NextTime); #declare CurForward = vnormalize(WalkPath(Time +0.001)-CurPoint ); #declare PrevForward = vnormalize(WalkPath(PrevTime+0.001)-PrevPoint); #declare NextForward = vnormalize(WalkPath(NextTime+0.001)-NextPoint); #declare CycleTime = ((Time-PrevTime)/(NextTime-PrevTime)); #declare CycleValue = min(1,max(0,CycleTime*2-0.5)); #declare FootPoint = ( +PrevPoint*(1-CycleValue) +NextPoint*( CycleValue) +sin(CycleValue*pi)*0.1*y ); #declare FootForward = vnormalize( +PrevForward*(1-CycleValue) +NextForward*( CycleValue) ); // A simple representation of a foot. cone { FootPoint-0.1*FootForward, 0.06, FootPoint+0.2*FootForward, 0.04 } // The "body" sphere {CurPoint+0.55*y, 0.06} // The following is just some inverse kinematics calculations // taken directly from the "Goodies Page" on my website: // http://rsj.mobilixnet.dk/3d/goodies/goodies.html // Specify HipPoint and AnklePoint, and the entire leg will follow. // // You also need to specify the length of the thigh and the shin as // well as the direction in which the knee should be pointing. // // Note that the KneeDirection should always be adjusted to fit your // needs. If your are making an animation where the knee points in // many different directions, the KneeDirection should be animated // accordingly. #declare HipPoint = CurPoint+0.55*y; #declare AnklePoint = FootPoint-0.1*FootForward; #declare ThighLength = 0.25; #declare ShinLength = 0.35; #declare KneeDirection = (CurForward+FootForward)/2; // Now specify the objects used for the thigh and the shin. #declare ThighObject = sphere {0, 1 scale <0.05,0.25/2,0.05> translate <0,-0.25/2,0>} #declare ShinObject = sphere {0, 1 scale <0.05,0.35/2,0.05> translate <0,-0.35/2,0>} // Knee calculates the point of the knee given these input: // pA: Point of the ankle. // pH: Point of the hip. // LT: Length of thigh. // LS: Length of shin. // vD: Direction in which the knee is pointing. #macro Knee(pA,pH,LT,LS,vD) // by Tor Olav Kristensen #local vB=pA-pH; #local LB=vlength(vB); #if(LB>LT+LS) #error "Ankle and hip are too far apart.\n" #end #if(LB #end // Now do the calculations to find the transformations used to place // the thigh and shin. #declare KneeVector = Perpendiculize(KneeDirection,HipPoint-AnklePoint); #declare KneePoint = Knee(HipPoint,AnklePoint,ShinLength,ThighLength,KneeVector); #declare ThighY = vnormalize(HipPoint-KneePoint); #declare ThighZ = Perpendiculize(KneeVector,ThighY); #declare ThighX = vcross(ThighY,ThighZ); #declare ThighP = HipPoint; #declare ThighTransform = transform{Vectors2Matrix(ThighX,ThighY,ThighZ,ThighP)} #declare ShinY = vnormalize(KneePoint-AnklePoint); #declare ShinZ = Perpendiculize(KneeVector,ShinY); #declare ShinX = vcross(ShinY,ShinZ); #declare ShinP = KneePoint; #declare ShinTransform = transform{Vectors2Matrix(ShinX,ShinY,ShinZ,ShinP)} // And last, place the thigh and shin objects in the scene... object {ThighObject transform ThighTransform} object {ShinObject transform ShinTransform}