/***********************************************************

/* A program to generate symbolic walkers as dynamic, three dimensional /* color graphic displays. We, the viewers, move into the seen in a

/* straight line, while our "gaze" is on this walker

/*

/*

/* The basis for this code was a program written by James E. Cutting,

/* published in Behavior Research Methods & Instrumentation (1978, Vol. /* 10 (1), 91-94), under the * title of "A program to generate synthetic /* walkers as * dynamic point-light displays." The orginal program was * /* written in FORTAN 77 on a 32K Hewlett-Packard HP-100 * L-Series P /* for a Tektronix 604 monitor display driven by a Data General Nova.

/*

/* Modifications by J.E.C. beginning 23 Sept 91

/* latest 18 Mar 92, Laurence Kaplan adaptation

/*

/***********************************************************/

/* attach the code to the 'C' libraries it requires */ #include <stdio.h>

/* standard input & output */

#include <values.h>

#include <gl.h> /* graphics library */

#include <math.h> /* math functions */

#include <device.h> /* interactive device */

#include <time.h>

#include <sys/types.h> /* } */

#include <sys/times.h>

#include <sys/time.h> /* } time/timing functions */

#include <sys/param.h> /* } */

#include <fmclient.h>

/* define the global constants */

/* math */

#define PI 3.1415926

#define RAD 0.017453292 /* degree to radian conversion constant */

#define DEG 57.29577951 /* radian to degree conversion constant */

/* body */

#define TORSO 85.0 /* height or length of torso */

#define SW 25.0 /* shoulder width */

#define HW 15.0 /* hip width */

/* walker object */

#define NUM_STEPS 6 /* number of steps to be taken by walker */

#define Z1 0.0 /* where in z-plane walker is to walk */

/* colors */

#define GROUND 1 /* color of ground plane in bkgnd scenery */

#define FIXTREE 9

#define TREECOLOR 10

/* viewing */

#define VISANG 300 /* cone of vision */

#define EYE_HT 255.0

/* forest */

#define NUMTR 60

#define NTRI 9 /* 8 plus 1 */

/* declare global variables */

/* the coords for cube object from which walker is created */

long side[6][4][3] ={{-1,-1,1}, {1,-1,1}, {1,1,1}, {-1,1,1},

{1,-1,1}, {1,-1,-1}, {1,1,-1}, {1,1,1},

{1,-1,-1}, {-1,-1,-1}, {-1,1,-1}, {1,1,-1},

{-1,-1,-1}, {-1,-1,1}, {-1,1,1}, {-1,1,-1},

{-1,1,1}, {1,1,1}, {1,1,-1}, {-1,1,-1},

{-1,-1,-1}, {1,-1,-1}, {1,-1,1}, {-1,-1,1}};

/* variables used by time functions */

struct tms t1;

long time1,time2;

double tim, starttim;

struct timeval tp;

struct timezone tzp;

float x,y,z,xx,zz,xx1,zz1;

int REDO,TRI,RESP,SDIR,SX,SZ,GRID,TREES,INCR,t,tt,tmod,j,OUT; char fname[20];

FILE *fp,*fopen();

Coord rno[NUMTR][3];

int afile[NTRI][6];

int tord[NTRI];

int tinfo[NTRI][3] ={0,0,0,

/* x z angle */

-4943, 0, 0,

/* in front and behind */

4943, 0, 180,

0, -4943, 90,

/*on either side*/

0, 4943, 270,

3445, -3445, 135,

/*in front and to the side*/

3445, 3445, 225,

-3445, -3445, 45,

/*behind and to the side*/

-3445, 3445, 315};

/* the graphical objects that make up the walker and scenery */ Object cube,Groundplane,Floorgrid,Tree1,Cylinder;

/***************************************************************************

* MAIN function/procedure of the program *

***************************************************************************/ main () {

/* declare functions */

void initialize_variables (),

setup_windows_graphics_devices (),

setup_underdraw(),

make_objects (),

ankle_table (),

get_hips (),

get_ankles (),

get_shoulders (),

get_wrists (),

get_knees (),

get_elbows (),

get_midpoint (),

clear_screen (),

draw_corpse (),

draw_head (),

draw_part (),

draw_torso (),

get_angle (),

locomotion (),

stop_and_wait (),

clean_up ();

/* declare variables */

float humor,ulna,tibia,femur,leg, /* lengths of body parts */

step, hstep, /* length of step, half-step */ hex, hey, /* hip ellipses, x&y axes */

sex, sey, /* shoulder ellipses,x&y-axes*/

sher, /* shoulder excursion as multiple of hip */

time, /* cmsec per frame */

bounce, /* up & down mvt of body */

swf, /* femur swing */

swh, /* humor swing, f(sholder swing&step */

swu, /* ulna swing */

swt, /* tibia swing, 25=atan(foot/tibia) */

femfo, /* forward tilt of femur pendulum */

delay, /* degrees pre- and post-femur swing that tibia

swings due to foot & to compound pendulum */

cosff, /* y correction for hip */

xlean, ylean, /* upper body lean, f(speed), 2 deg modal */ xinit, yinit, /* initial x & y values in screen units */ falfo, /* mvt falling forwards w/in overlay period

due to tibia swing and foot */

sia[541]; /* ankle table, broad w-shaped, 0-540 deg. */

int ip, ist; /* used for SWAPINTERVAL */

char ss[10];

int c,k;

fmfonthandle f;

fmfonthandle fsized;

/* printf("filename = ");

scanf("%s",fname);

*/

/* main routines */

/* initialize the variables */

initialize_variables (&humor,&ulna,&femur,&tibia,&leg,&step,

&sher,&time,&hex,&hey,&sex,&sey,&swf,&swh, &swu,&swt,&hstep,&bounce,&delay,&xlean,&ylean, &xinit,&yinit,&falfo,&femfo,&cosff,&ip,&ist);

/* set up the windows, the graphics configuration, objects, etc. */ setup_windows_graphics_devices ();

/* generate the ankle table */

ankle_table (delay,sia);

rnorder();

/*for (t=1; t<NTRI; t++) printf("%5d",tord[t]);*/ color(BLACK);

clear();

swapbuffers();

for (TRI=1; TRI<NTRI; TRI++){

frontbuffer(TRUE);

color(WHITE);

ortho2 (0,1280,0,1009);

cmov2i(520,530);

sprintf(ss,"%d",TRI);

fminit();

f = fmfindfont("Times-Roman");

fsized = fmscalefont(f,36);

fmsetfont(fsized);

fmprstr("TRIAL");

cmov2i(700,530);

fmprstr(ss);

sleep(1);

frontbuffer(FALSE);

if (REDO == 0)

generatecoords();

qreset();

/* main loop(s) for the walker(s) */

t=tord[TRI];

xx=tinfo[t][0];

zz=tinfo[t][1];

SDIR=tinfo[t][2];

setup_underdraw();

locomotion (humor,ulna,femur,tibia,leg,step,

sher,time,hex,hey,sex,sey,swf,swh,

swu,swt,hstep,bounce,delay,xlean,ylean,

xinit,yinit,falfo,femfo,cosff,sia,ip,ist);

/* clean up the underlay plane so desktop/workspace isn't messed up */

qreset ();

while(qtest()) {}

processinput();

clean_up ();

clearscreen();

swapbuffers();

qreset();

sleep(1);

if (OUT == 1)

break;

afile[t][0]=xx;

afile[t][1]=zz;

afile[t][2]=SDIR;

afile[t][3]=RESP;

afile[t][4]=1;

if(t%2==(RESP-1)) afile[t][4]=0;

/* printf("%3d %3d ",TRI,t);

for (j=0; j<5; j++)

printf("%6d",afile[t][j]);

printf("\n");

*/

}

fp=fopen(fname,"w");

for (TRI=1; TRI<NTRI; TRI++){

for (j=0; j<5; j++)

fprintf(fp,"%6d",afile[TRI][j]);

fprintf(fp,"\n");

}

fclose(fp);

clearscreen ();

clear ();

}

/*********************************************************************

/* initialize the variables *

**********************************************************************void initialize_variables (humor,ulna,femur,tibia,leg,step,

sher,time,hex,hey,sex,sey,swf,swh,

swu,swt,hstep,bounce,delay,xlean,ylean,

xinit,yinit,falfo,femfo,cosff,ip,ist)

/* all of these values are R/W, and are explained in declarations above */

float *humor,*ulna,*femur,*tibia,*leg,*step,*sher,

*time,*hex,*hey,*sex,*sey,*swf,*swh,*swu,*swt, *hstep,*bounce,*delay,*xlean,*ylean,*xinit,*yinit, *falfo,*femfo,*cosff;

int *ip,*ist;

{

float a, temp; /* for temporary storage */

*step=TORSO*0.975;

*hex=1.0;

*sher=3.0;

*hex=(*hex)*0.03*(*step);

*hey=(*hex)/1.5;

*sex=(*sher)*(*hex);

*sey=(*sex)/5.0;

*humor=TORSO*0.59; /* length of upper arm */

*ulna=TORSO*0.56; /* length of forearm */

*femur=TORSO*0.77; /* length of upper leg */

*tibia=TORSO*0.77; /* length lower leg */

*leg=(*femur)+(*tibia)+0.3*TORSO; /* adjust for ankle to heel length */

/* half step without torso torque */

*hstep=(*step)/2.0-(*hex);

/* up & down mvt of body due to step size and hip roll */ *bounce=((*leg)-sqrt((*leg)*(*leg)-(*hstep)*(*hstep))-(*hey))/2.0;

temp=(*hstep)/sqrt((*leg)*(*leg)-(*hstep)*(*hstep)); *swf=atan(temp);

*swh=0.24*((*step)-4.0*(*sex))*RAD;

*swu=1.65*(*swh);

*swt=25.0*RAD+(*swf)+5.0*(*hey)*RAD;

*femfo=RAD*0.04*(*step);

*cosff= (*leg)*(cos((*swf)-(*femfo))-cos((*swf)+(*femfo)))/2.0;

*xlean=TORSO*sin(-.0*RAD); /* no lean */ *ylean=TORSO*cos(-.0*RAD);

*xinit= -1060.0; /*changed*/

*yinit=130.0; /*changed from Laurence's program*/

*falfo=0.0;

REDO=0; /* to repeat a trial */

OUT=0; /* to break out of system */

}

/*********************************************************************

* create the objects from which the sequence is to be made *

/********************************************************************* void make_objects ()

{

int i,j; /* used in "Floorgrid" object */

makeobj (cube=genobj());

/* 1.05-1.07 s/cyc w/ polygons only

1.06-1.10 s/cyc w/ closedlines only

1.08-1.40 s/cyc w/ both */

color (YELLOW);

for (j=0;j<6;j++)

{

bgnpolygon ();

v3i (side[j][0]);

v3i (side[j][1]);

v3i (side[j][2]);

v3i (side[j][3]);

endpolygon ();

}

color (BLACK);

for (j=0;j<6;j++)

{

bgnclosedline ();

v3i (side[j][0]);

v3i (side[j][1]);

v3i (side[j][2]);

v3i (side[j][3]);

endclosedline ();

}

closeobj ();

makeobj (Groundplane=genobj());

pmv(-20000.0,0.0,-20000.0);

pdr(-20000.0,0.0,20000.0);

pdr(20000.0,0.0,20000.0);

pdr(20000.0,0.0,-20000.0);

pclos();

closeobj ();

makeobj (Floorgrid=genobj());

for (i= -13000;i<=13000;i+=1500)

{

movei (i,0.0,13500);

drawi (i,0.0,-13500);

movei (13500,0.0,i);

drawi (-13500,0.0,i);

}

closeobj ();

makeobj(Cylinder=genobj());

move(0.0,0.0,0.0);

draw(0.0,20.0,0.0);

closeobj();

makeobj(Tree1);

move(0.0,0.0,0.0);

scale(1.6,1.6,1.6);

callobj(Cylinder);

translate(0.0,20.0,0.0);

rotate(250,'z');

scale(0.8,0.8,0.8);

callobj(Cylinder);

rotate(-400,'z');

rotate(250,'x');

scale(0.9,0.9,0.9);

callobj(Cylinder);

translate(0.0,15.0,0.0);

scale(0.8,0.8,0.8);

rotate(-850,'x');

callobj(Cylinder);

translate(0.0,8.0,0.0);

scale(0.8,0.8,0.8);

rotate(500,'z');

callobj(Cylinder);/**/

translate(-10.0,-8.0,-25.0);

rotate(1800,'x');

rotate(1400,'z');

callobj(Cylinder);

translate(0.0,15.0,0.0);

rotate(1200,'z');

scale(0.5,0.5,0.5);

callobj(Cylinder);/**/

translate(21.0,17.0,-46.0);

rotate(-1350,'z');

scale(2.0,2.0,2.0);

callobj(Cylinder);

translate(0.0,18.0,0.0);

rotate(-400,'z');/*b*/

rotate(-600,'x');

scale(0.6,0.6,0.6);

callobj(Cylinder);/*e*/

move(0.0,0.0,0.0);

closeobj();

}

/*********************************************************************

* setup windows, graphical configurations, devices, and call objects *

*********************************************************************/ void setup_windows_graphics_devices ()

{

prefposition (0,1280,0,1009); /* define window size and placement */ winopen ("walker in a forest"); /* call and name the window */

underlay (2);

doublebuffer (); /* double buffer mode for animation */

gconfig ();

/*swapinterval (7);*/

backface (TRUE); /* Remove counter-clockwise drawn */

zbuffer (TRUE); /* backfacing characters & activate */

zclear (); /* z-buffering for speed & acuracy */

qdevice (ESCKEY); /* queue the ESC key */

qdevice (LEFTMOUSE);

qdevice (MIDDLEMOUSE);

qdevice (RIGHTMOUSE);

make_objects (); /* generate the graphical objects */

mapcolor (TREECOLOR,227,128,101);

mapcolor (FIXTREE,227,144,67);

drawmode(UNDERDRAW); /*added by Peter to fix ground plane*/

mapcolor (GROUND,90,73,47); /*added by Peter to fix ground plane*/

drawmode(NORMALDRAW); /*added by Peter to fix ground plane*/

}

/*********************************************************************

* set up underdraw *

*********************************************************************/ void setup_underdraw ()

{

drawmode (UNDERDRAW);

perspective (VISANG,1.0,0.1,20000.0);

lookat (0.0,EYE_HT,0.0,0.0,0.0,20000.0,0.0); color(GROUND);

callobj (Groundplane);

drawmode (NORMALDRAW);

}

/*********************************************************************

* generate the ankle table, broad w-shaped, 0-540 degrees *

*********************************************************************/ void ankle_table (delay,sia)

float delay, /* R/W pre- and post- femur swing of tibia */

sia[]; /* R/W ankle table */

{

int i,j; /* counters */

float n, a, z; /* for temporary storage */

for (i=0;i<=180;i++)

{

sia[i]=0.0;

sia[i+360]=0.0;

}

n=360.0+delay;

i=0;

/* symmetric about 270 degrees */

for (j=270;j<=n;j++)

{

z=(float)i;

a=(2.0*z-2.0*delay*z/(90.0+delay))*RAD;

a=(cos(a)+1.0)/2.0;

sia[j]=a;

sia[j-2*i]=a;

i++;

}

for (i=360;i<=n;i++)

sia[i-360]=sia[i];

n=180.0-delay;

for (i=n;i<=180;i++)

sia[i+360]=sia[i];

}

/*********************************************************************

* determine the right and left hip locations in the x and y axes *

*********************************************************************/ void get_hips (x,y,cosa,sina,cosff,hex,hey,xhipr,yhipr,xhipl,yhipl) float x,y,cosa,sina,cosff,hex,hey,*xhipr,*yhipr,*xhipl,*yhipl; {

float hx,hy;

hx=hex*cosa;

hy=hey*sina-cosff*sina;

*xhipr=x+hx;

*yhipr=y+hy;

*xhipl=x-hx;

*yhipl=y-hy;

}

/*********************************************************************

* determine the right and left knee locations in the x and y axes *

*********************************************************************/ void get_knees (swf,cosa,femfo,femur,xhipr,yhipr,xhipl,yhipl,

xkner,ykner,xknel,yknel)

float swf,cosa,femfo,femur,xhipr,yhipr,xhipl,yhipl,

*xkner,*ykner,*xknel,*yknel;

{

float a,z;

a=swf*cosa+femfo;

z=swf*cosa-femfo;

*xkner=xhipr+femur*sin(a);

*ykner=yhipr-femur*cos(a);

*xknel=xhipl-femur*sin(z);

*yknel=yhipl-femur*cos(z);

}

/*********************************************************************

* determine the right and left shoulder locations in the x and y axes *

*********************************************************************/ void get_shoulders (x,y,sex,sey,cosa,sina,xlean,ylean,

xshor,yshor,xshol,yshol)

float x,y,sex,sey,cosa,sina,xlean,ylean,

*xshor,*yshor,*xshol,*yshol;

{

float hx,hy;

hx=sex*cosa;

hy=sey*sina;

*xshor=x+xlean-hx;

*yshor=y+ylean-hy;

*xshol=x+xlean+hx;

*yshol=y+ylean+hy;

}

/*********************************************************************

* determine the right and left elbows locations in the x and y axes *

*********************************************************************/ void get_elbows (humor,cosa,swh,xshor,yshor,xshol,yshol,

xelbr,yelbr,xelbl,yelbl)

float humor,cosa,swh,xshor,yshor,xshol,yshol,

*xelbr,*yelbr,*xelbl,*yelbl;

{

float hx,hy;

hx=humor*sin(swh*cosa);

hy=humor*cos(swh*cosa);

*xelbr=xshor-hx;

*yelbr=yshor-hy;

*xelbl=xshol+hx;

*yelbl=yshol-hy;

}

/*********************************************************************

* determine the right and left ankles locations in the x and y axes *

*********************************************************************/ void get_ankles (swf,swt,cosa,sina1,sina2,femfo,tibia,

xkner,ykner,xknel,yknel,

xankr,yankr,xankl,yankl)

float swf,swt,cosa,sina1,sina2,femfo,tibia,xkner,ykner,xknel,yknel,

*xankr,*yankr,*xankl,*yankl;

{

float a,z;

a=swf*cosa+femfo-swt*sina1;

z= -swf*cosa+femfo-swt*sina2;

*xankr=xkner+tibia*sin(a);

*yankr=ykner-tibia*cos(a);

*xankl=xknel+tibia*sin(z);

*yankl=yknel-tibia*cos(z);

}

/*********************************************************************

* determine the right and left wrists locations in the x and y axes *

*********************************************************************/ void get_wrists (swh,swu,cosa,cos2a,ulna,xelbr,yelbr,xelbl,yelbl,

xwrir,ywrir,xwril,ywril)

float swh,swu,cosa,cos2a,ulna,xelbr,yelbr,xelbl,yelbl,

*xwrir,*ywrir,*xwril,*ywril;

{

float hx,hy,a,z;

hx=swh*cosa;

hy=swh*(cos2a+1.0)/2.0;

a=swu*(cosa-1.0)/2.0;

z=swu*(cosa+1.0)/2.0;

*xwrir=xelbr-ulna*sin(hx+a);

*ywrir=yelbr-ulna*cos(hy-a);

*xwril=xelbl+ulna*sin(hx+z);

*ywril=yelbl-ulna*cos(hy+z);

}

/********************************************************************

* render the walker to the buffering being drawn to *

*********************************************************************/ void draw_corpse (xhead,yhead,xshor,yshor,xshol,yshol,

xelbr,yelbr,xelbl,yelbl,xwrir,ywrir,

xwril,ywril,xhipr,yhipr,xhipl,yhipl,

xkner,ykner,xknel,yknel,xankr,yankr,

xankl,yankl,

ulna,humor,femur,tibia,

beta,shape,z)

float xhead,yhead,

xshor,yshor,xshol,yshol,

xelbr,yelbr,xelbl,yelbl,

xwrir,ywrir,xwril,ywril,

xhipr,yhipr,xhipl,yhipl,

xkner,ykner,xknel,yknel,

xankr,yankr,xankl,yankl,

ulna,humor,femur,tibia;

Angle beta;

Object shape;

float z;

{

/* bones lengths added --get_part_length omitted */ draw_part (xshor,yshor,z+SW,xelbr,yelbr,z+SW,ulna,8.0,8.0,beta,shape); draw_part (xelbr,yelbr,z+SW,xwrir,ywrir,z+SW,humor,7.0,7.0,beta,shape); draw_part (xshol,yshol,z-SW,xelbl,yelbl,z-SW,ulna,8.0,8.0,beta,shape); draw_part (xelbl,yelbl,z-SW,xwril,ywril,z-SW,humor,7.0,7.0,beta,shape);

/* legs changed */

draw_part

(xhipr,yhipr,z+HW-4.0,xkner,ykner,z+HW-4.0,femur,12.0,12.0,beta,shape);

draw_part

(xkner,ykner,z+HW-4.0,xankr,yankr,z+HW-4.0,tibia,11.0,11.0,beta,shape);

draw_part

(xhipl,yhipl,z-HW+4.0,xknel,yknel,z-HW+4.0,femur,12.0,12.0,beta,shape);

draw_part

(xknel,yknel,z-HW+4.0,xankl,yankl,z-HW+4.0,tibia,11.0,11.0,beta,shape);

draw_torso ((xshor+xshol)/2.0,(yshor+yshol)/2.0,z,

(xhipr+xhipl)/2.0,(yhipr+yhipl)/2.0,z,beta,shape); draw_head (xhead-5.0,yhead-19.0,z,10.0,beta,shape); draw_head (xhead-9.0,yhead-40.0,z,5.0,beta,shape); /* neck added */ }

/*********************************************************************

* This is the main loop, in which the walker walks and the viewer moves * * through the "scenery" *

*********************************************************************/ void locomotion (humor,ulna,femur,tibia,leg,step,

sher,time,hex,hey,sex,sey,swf,swh,

swu,swt,hstep,bounce,delay,xlean,ylean,

xinit,yinit,falfo,femfo,cosff,sia,ip,ist) float humor,ulna,femur,tibia,leg,step,

sher,time,hex,hey,sex,sey,swf,swh,

swu,swt,hstep,bounce,delay,xlean,ylean,

xinit,yinit,falfo,femfo,cosff,sia[];

int ip,ist;

{

int i,j,k,it,gridrot,tt,tmod;

float sina, sina1, sina2, cosa, cos2a, cosi, dum,

x, y, xf, zf,

xhead, yhead, /* } */

xhipr, yhipr, xhipl, yhipl, /* } */

xelbr, yelbr, xelbl, yelbl, /* } */

xkner, ykner, xknel, yknel, /* }x&y coords of body parts */

xshor, yshor, xshol, yshol, /* } */

xankr, yankr, xankl, yankl, /* } */

xwrir, ywrir, xwril, ywril, /* } */

n, /* a counter */

a1, /* for temporary storage */

yy, /* eyeheight of looker */

speed; /* time in secs. of each step cycle */

/* n is the counter used in the subject walker movement loop.

The subject walker starts walking at xx,zz=0.0 */

gridrot=(float)rand()*3600.0;

time1=times(&t1);

gettimeofday(&tp,&tzp);

tt=0;

tmod=0;

INCR=30;

xx1=xx;

zz1=zz;

/* This is the main loop for both walkers. Each step-cycle (j) is

two steps */

for (j=1;j<=NUM_STEPS;j++)

{

for (k=tmod;k<359;k+=INCR)

{

tim = starttim = ((double)tp.tv_sec) +

((double)tp.tv_usec)*0.000001;

/*n=step*2.0*INCR/360.0;*/

i=k+12.0*sin(2.0*k*RAD); /* surge factor */

sina=sin(i*RAD);

cosa=sin((i+90)*RAD);

cos2a=sin((i*2+90)*RAD);

sina1=sia[i];

sina2=sia[i+180];

if (i <= 180) cosi=cosa;

if (i > 180) cosi=sin((i-90)*RAD);

if ((i >= (180-delay)) & (i <= (180+delay)))

falfo=falfo+step*0.02/12;

if ((i >= (360-delay)) || (i <= delay))

falfo=falfo+step*0.02/12;

/* depends on increment in i */

x=xinit-cosi*step/2.0+falfo;

y=yinit-bounce*cos2a;

/* generate the coords of the walker object */

xhead=x+1.6*xlean+TORSO/15.0;

yhead=y+1.6*ylean;

get_hips (x,y,cosa,sina,cosff,hex,hey,&xhipr,&yhipr,

&xhipl,&yhipl);

get_knees (swf,cosa,femfo,femur,xhipr,yhipr,xhipl,

yhipl,&xkner,&ykner,&xknel,&yknel);

get_shoulders (x,y,sex,sey,cosa,sina,xlean,ylean,

&xshor,&yshor,&xshol,&yshol);

get_elbows (humor,cosa,swh,xshor,yshor,xshol,yshol,

&xelbr,&yelbr,&xelbl,&yelbl);

get_ankles (swf,swt,cosa,sina1,sina2,femfo,tibia,

xkner,ykner,xknel,yknel,

&xankr,&yankr,&xankl,&yankl);

get_wrists (swh,swu,cosa,cos2a,ulna,

xelbr,yelbr,xelbl,yelbl,

&xwrir,&ywrir,&xwril,&ywril);

/* draw the grid, walker object, then trees */

clearscreen ();

perspective (VISANG,1.0,0.1,30000.0);

lookat (xx1,EYE_HT,zz1,0.0,EYE_HT,0.0,0.0);

linewidth(1);

color (WHITE);

pushmatrix();

rotate(gridrot,'y');

callobj(Floorgrid);

popmatrix();

draw_corpse (xhead,yhead,xshor,yshor,xshol,yshol,

xelbr,yelbr,xelbl,yelbl,xwrir,ywrir,

xwril,ywril,xhipr,yhipr,xhipl,yhipl,

xkner,ykner,xknel,yknel,xankr,yankr,

xankl,yankl,

ulna,humor,femur,tibia,

0,cube,Z1);

drawtrees(xx,zz);

swapbuffers ();

gettimeofday(&tp,&tzp);

tim = ((double)tp.tv_sec) +

((double)tp.tv_usec)*0.000001;

tt=(float)(tim-starttim)*100*3;

/* printf ("frame %d = %d %f\n",k,tt,x);

*/

INCR = tt;

if((k+tt)>359) tmod=(k+tt)%360;

if ((k>=140) & (k<=180)){

xinit=xinit+step+falfo;

xx=xx+(step+falfo)*cos(SDIR*RAD);

zz=zz+(step+falfo)*sin(SDIR*RAD);

falfo=0;

if(k<(181-INCR)) k=181-INCR;}

}

xinit=xinit+step+falfo;

xx=xx+(step+falfo)*cos(SDIR*RAD);

zz=zz+(step+falfo)*sin(SDIR*RAD);

falfo=0;

}

time2=times(&t1);

/* printf (" duration = %d\n",(time2-time1));

*/

}

/*********************************************************************

* calculate the midpoint between two points in three dimensional space * *********************************************************************/ void get_midpoint (x1,y1,z1,x2,y2,z2,xm,ym,zm) float x1,y1,z1,x2,y2,z2,*xm,*ym,*zm;

{

*xm=(x1+x2)/2.0;

*ym=(y1+y2)/2.0;

*zm=(z1+z2)/2.0;

}

/*********************************************************************

* render a single body part *

*********************************************************************/ void draw_part (x1,y1,z1,x2,y2,z2,length,w,t,beta,shape) float x1,y1,z1,x2,y2,z2, /* R/O coords of joints of this body part */

w,t, /* R/O width and thickness of this body part */

length; /* from bone */

Angle beta; /* R/O Angle of walker's change of direction */

Object shape; /* R/O object used to make this body part */

{

float alpha, /* angle to which the object that the body

part is made freom is rotated */

xm,ym,zm; /* midpoint of the body part (midpoint

between the joints */

get_midpoint (x1,y1,z1,x2,y2,z2,&xm,&ym,&zm); get_angle (x1,y1,x2,y2,&alpha);

pushmatrix ();

rotate (beta*10,'Y'); /* change of direction */

translate (xm,ym,zm);

rotate (alpha*10,'Z');

scale (length/2.0,t/2.0,w/2.0); /* make the part the correct length,

width and thickness */

callobj (shape);

popmatrix ();

}

/*********************************************************************

* calculate the angle that a body part needs to be rotated *