#include #include "skeleton.h" /* animate primitives */ int strokes(line_ptr line) { int n; n = 1; while(line->next!=NULL) { n++; line = line->next; } return(n); } void addsegs(line_ptr seg,int n,int req) { int rs,rt,i,j,k=0,l; int x1,y1,dx,dy; if(n/POINTS != req/POINTS) seg->pts=(struct pts *)realloc((void *)seg->pts, sizeof(struct pts)*POINTS*(req/POINTS+1), sizeof(struct pts)*POINTS*(n/POINTS+1)); seg->number = req+1; if(n==0) { x1 = seg->pts->p[0][0]; y1 = seg->pts->p[0][1]; for(i=1;i<=req;i++) { seg->pts->p[i][0]=x1; seg->pts->p[i][1]=y1; } return; } rt = req/n; rs = req%n; for(i=n;i>=0;i--) { if(i>rs) j = rs + rt*i; else j = (rt+1)*i; seg->pts->p[j][0] = seg->pts->p[i][0]; seg->pts->p[j][1] = seg->pts->p[i][1]; if(i!=n) { x1 = seg->pts->p[j][0]; y1 = seg->pts->p[j][1]; dx = seg->pts->p[k][0] - seg->pts->p[j][0]; dy = seg->pts->p[k][1] - seg->pts->p[j][1]; for(l=1;lpts->p[j+l][0] = (dx*l)/(k-j)+x1; seg->pts->p[j+l][1] = (dy*l)/(k-j)+y1; } } k = j; } } void breakstroke(line_ptr seg,int n) { int step; line_ptr newseg; if(n<=1) return; if(seg->number-1number-1,n); step = (seg->number-1)/n; for(;n>1;n--) { newseg = cutseg(seg,step); newseg->next = seg->next; seg->next = newseg; seg = newseg; } } void addstrokes(line_ptr line,int n,int req) { int rs,rt,i; line_ptr nextline; rt = req/n; rs = req%n; for(i=1;i<=rs;i++) { nextline = line->next; breakstroke(line,rt+1); line = nextline; } while(line!=NULL) { nextline = line->next; breakstroke(line,rt); line = nextline; } } void preprocess(line_ptr l1,line_ptr l2) { int n1,n2; if((l1==NULL)||(l2==NULL)) return; n1 = strokes(l1); n2 = strokes(l2); if(n1>n2) addstrokes(l2,n2,n1); else if(n2>n1) addstrokes(l1,n1,n2); while(l1!=NULL) { n1 = l1->number-1; n2 = l2->number-1; if(n1>n2) addsegs(l2,n2,n1); else if(n2>n1) addsegs(l1,n1,n2); l1 = l1->next; l2 = l2->next; } } int relative(int x ,int y ,int x1,int y1,int x2,int y2, int x3,int y3,int x4,int y4,int *l,int *w) { double L,W,dist2,tdist2; int a,b,c,d,e,f,g,h; int A,B,C; int temp,cross1,cross2; a = x-x1; b = x2-x1; c = y-y1; d = y2-y1; e = x-x3; f = x4-x3; g = y-y3; h = y4-y3; cross1 = a*d - c*b; /* psuedo cross products */ cross2 = e*h - g*f; if((cross1>0 && cross2>0)||(cross1<0 && cross2<0)) return(FALSE); cross1 = (a-e)*c - (c-g)*a; /* another cross product */ cross2 = (x4-x2)*(y-y2) - (y4-y2)*(x-x2); if((cross1>0 && cross2>0)||(cross1<0 && cross2<0)) return(FALSE); A = b*h - d*f; B = c*f + d*e - a*h - b*g; /* I won't soon forget this one */ C = a*g - c*e; if(A==0) { if(B!=0) L = -(double)C/B; else { return(FALSE); } } else { temp = B*B - 4*A*C; if(temp<0) { return(FALSE); } L = ((double)(-B) - sqrt((double)temp))/(2*A); if(L>1.0 || L<0.0) L = ((double)(-B) + sqrt((double)temp))/(2*A); if(L>1.0 || L<0.0) { return(FALSE); } } tdist2 = (a-e-(b-f)*L)*(a-e-(b-f)*L) + (c-g-(d-h)*L)*(c-g-(d-h)*L); if(tdist2==0.0) { return(FALSE); } dist2 = (a-b*L)*(a-b*L) + (c-d*L)*(c-d*L); W = sqrt(dist2/tdist2); if(W>1.0 || W<0.0) { return(FALSE); } *l = (int)(L*256); *w = (int)(W*256); return(TRUE); } line_ptr makerelative(obj_ptr object) { int i,j,k,p; int l,w; line_ptr seg,rel,head; seg = object->image; rel = head = NULL; while(seg!=NULL) { p = 0; for(i=0;inumber;i++) { for(j=0;jskeleton->number;j++) { for(k=0;k<=1;k++) { if((j*2+k+2outline->number) && (j+1skeleton->number)) { if(relative(seg->pts->p[i][0],seg->pts->p[i][1], object->skeleton->pts->p[j][0], object->skeleton->pts->p[j][1], object->skeleton->pts->p[j+1][0], object->skeleton->pts->p[j+1][1], object->outline->pts->p[j*2+k][0], object->outline->pts->p[j*2+k][1], object->outline->pts->p[j*2+k+2][0], object->outline->pts->p[j*2+k+2][1], &l,&w)==TRUE) { if(rel==NULL) { rel=(line_ptr)malloc(sizeof(struct line)); rel->pts=(struct pts *) malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1)); head = rel; rel->next = NULL; rel->linec = seg->linec; rel->fillc = seg->fillc; } else if(p==0) { rel->next=(line_ptr)malloc(sizeof(struct line)); rel = rel->next; rel->pts=(struct pts *) malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1)); rel->next = NULL; rel->linec = seg->linec; rel->fillc = seg->fillc; } rel->pts->p[p][0] = l+(j<<8); rel->pts->p[p][1] = ((k)?(-1):(1))*w; p++; k = 1; j = object->skeleton->number; } } } } } if(p!=0) { rel->number=p; if((p-1)/POINTS!=(seg->number-1)/POINTS) rel->pts=(struct pts *) realloc((void *)rel->pts, sizeof(struct pts)*POINTS*((p-1)/POINTS+1), sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1)); if(p==1) { rel->pts->p[1][0] = rel->pts->p[0][0]; rel->pts->p[1][1] = rel->pts->p[0][1]; } } seg = seg->next; } return(head); } void makeimage(obj_ptr object,line_ptr relative) { int i,j,k,p; int l,w,x1,y1,x2,y2; line_ptr seg,derel; seg = relative; derel = NULL; deleteline(object->image); while(seg!=NULL) { p = 0; for(i=0;inumber;i++) { l = seg->pts->p[i][0]; w = seg->pts->p[i][1]; j = l>>8; k = ((w<0)?(1):(0)); l = l - (j<<8); w = abs(w); if((j+1skeleton->number) && (k+j*2+2outline->number)) { x1 = ((object->skeleton->pts->p[j+1][0] - object->skeleton->pts->p[j][0]) * l)/256 + object->skeleton->pts->p[j][0]; y1 = ((object->skeleton->pts->p[j+1][1] - object->skeleton->pts->p[j][1]) * l)/256 + object->skeleton->pts->p[j][1]; x2 = ((object->outline->pts->p[j*2+k+2][0] - object->outline->pts->p[j*2+k][0]) * l)/256 + object->outline->pts->p[j*2+k][0]; y2 = ((object->outline->pts->p[j*2+k+2][1] - object->outline->pts->p[j*2+k][1]) * l)/256 + object->outline->pts->p[j*2+k][1]; x1 = ((x2-x1) * w)/256 + x1; y1 = ((y2-y1) * w)/256 + y1; if(derel==NULL) { derel=(line_ptr)malloc(sizeof(struct line)); derel->pts=(struct pts *) malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1)); derel->next = NULL; derel->linec = seg->linec; derel->fillc = seg->fillc; object->image = derel; } else if(p==0) { derel->next=(line_ptr)malloc(sizeof(struct line)); derel = derel->next; derel->pts=(struct pts *) malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1)); derel->next = NULL; derel->linec = seg->linec; derel->linec = seg->linec; derel->fillc = seg->fillc; } derel->pts->p[p][0] = x1; derel->pts->p[p][1] = y1; p++; } } if(p!=0) { derel->number=p; if((p-1)/POINTS!=(seg->number-1)/POINTS) derel->pts=(struct pts *) realloc((void *)derel->pts, sizeof(struct pts)*POINTS*((p-1)/POINTS+1), sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1)); setbox(derel); if(p==1) { derel->pts->p[1][0] = derel->pts->p[0][0]; derel->pts->p[1][1] = derel->pts->p[0][1]; } } seg = seg->next; } } void inbetween(int xi,int yi,int xo,int yo,int frame,int frames, int law,int *x,int *y) { if((law & XACCEL) && (law & XDECEL)) *x = (int)((xo-xi)*(1.0-cos((double)PI*frame/frames))/2)+xi; else if(law & XACCEL) *x = (int)((xo-xi)*(1.0-cos((double)PI*frame/frames/2)))+xi; else if(law & XDECEL) *x = (int)((xo-xi)*sin((double)PI*frame/frames/2))+xi; else *x = (int)((xo-xi)*(double)frame/frames)+xi; if((law & YACCEL) && (law & YDECEL)) *y = (int)((yo-yi)*(1.0-cos((double)PI*frame/frames))/2)+yi; else if(law & YACCEL) *y = (int)((yo-yi)*(1.0-cos((double)PI*frame/frames/2)))+yi; else if(law & YDECEL) *y = (int)((yo-yi)*sin((double)PI*frame/frames/2))+yi; else *y = (int)((yo-yi)*(double)frame/frames)+yi; } line_ptr imagebetween(line_ptr linein,line_ptr lineout, int frame,int frames,int law) { line_ptr start, line; int i; int x,y,n; start = NULL; while(linein!=NULL && lineout!=NULL) { if(linein->number>lineout->number) n = lineout->number; else n = linein->number; for(i=0;ipts->p[i][0],linein->pts->p[i][1], lineout->pts->p[i][0],lineout->pts->p[i][1], frame,frames,law,&x,&y); if(start==NULL) { line = (line_ptr)malloc(sizeof(struct line)); line->pts = malloc(sizeof(struct pts)*POINTS*((n-1)/POINTS+1)); line->linec = linein->linec; line->fillc = linein->fillc; line->next = NULL; start = line; } else if(i==0) { line->next = (line_ptr)malloc(sizeof(struct line)); line = line->next; line->pts = malloc(sizeof(struct pts)*POINTS*((n-1)/POINTS+1)); line->linec = linein->linec; line->fillc = linein->fillc; line->next = NULL; } line->pts->p[i][0] = x; line->pts->p[i][1] = y; } line->number = n; setbox(line); if(n==1) { line->pts->p[1][0] = line->pts->p[0][0]; line->pts->p[1][1] = line->pts->p[0][1]; } linein = linein->next; lineout = lineout->next; } return(start); } obj_ptr findtype(obj_ptr object,int flags,int *n) { *n = 0; if(flags!=0) { while((object!=NULL)&&((object->entry&flags)!=flags)) { object=object->next; (*n)++; } } else { while((object!=NULL)&&(object->entry==0)) { object=object->next; (*n)++; } } return(object); } obj_ptr findtypeback(obj_ptr object,int flags,int *n) { *n = 0; if(flags!=0) { while((object!=NULL)&&((object->entry&flags)!=flags)) { object=object->prev; (*n)++; } } else { while((object!=NULL)&&(object->entry==0)) { object=object->prev; (*n)++; } } return(object); } /* void makeoutline(obj_ptr with,obj_ptr without) { double length,a1i,a1f,a2i,a2f,aoi,aof; int x10,y10,x11,y11,x12,y12,x1o,y1o,x20,y20,x21,y21,x22,y22,x2o,y2o; int i; deleteline(without->outline); without->outline = NULL; for(i=0;ioutline->number;i++) { x10 = with->skeleton->pts->p[i/2][0]; y10 = with->skeleton->pts->p[i/2][1]; x1o = with->outline->pts->p[i][0]; y1o = with->outline->pts->p[i][1]; if(i>1) { x11 = with->skeleton->pts->p[i/2-1][0]; y11 = with->skeleton->pts->p[i/2-1][1]; } if(ioutline->number-2) { x12 = with->skeleton->pts->p[i/2+1][0]; y12 = with->skeleton->pts->p[i/2+1][1]; } x20 = without->skeleton->pts->p[i/2][0]; y20 = without->skeleton->pts->p[i/2][1]; if(i!=0) { x21 = without->skeleton->pts->p[i/2-1][0]; y21 = without->skeleton->pts->p[i/2-1][1]; } if(i!=with->outline->number-1) { x22 = without->skeleton->pts->p[i/2+1][0]; y22 = without->skeleton->pts->p[i/2+1][1]; } length = sqrt((double)(x10-x11)*(x10-x11) + (double)(y10-y11)*(y10-y11)); a1i = atan2((double)(x11-x10),(double)(y11-y10)); a2i = atan2((double)(x12-x10),(double)(y12-y10)); aoi = atan2((double)(x1o-x10),(double)(y1o-y10)); a1f = atan2((double)(x21-x20),(double)(y21-y20)); a2f = atan2((double)(x22-x20),(double)(y22-y20)); if(i==0) aof = aoi + (a2f-a2i); else if(i==with->outline->number-1) aof = aoi + (a1f-a1i); else aof = aoi + ((a1f-a1i) + (a2f-a2i))/2; x2o = x21 + (int)(length*cos(aof)); y2o = y21 + (int)(length*sin(aof)); without->outline = addpoint(without->outline,x2o,y2o); } } void derelative(obj_ptr firstimage,int n) { obj_ptr nextskel,image; int f,acc,i; nextskel = findtype(firstimage->next,SKELETON,&f); f = f + 1; acc = f; while(nextskel!=NULL && acc < n) { if(nextskel->entry & XOUTLINE != XOUTLINE) makeoutline(firstimage,nextskel); image = firstimage->next; for(i=1;i<=f;i++) { image->skeleton = imagebetween(firstimage->skeleton, nextskel->skeleton,i,f,firstimage->ilaw); image->outline = imagebetween(firstimage->outline, nextskel->outline,i,f,firstimage->ilaw); makeimage(image); image = image->next; } firstimage = nextskel; nextskel = findtype(firstimage->next,SKELETON,&f); acc = acc + f; } } */ void animate(obj_ptr object) { obj_ptr firstimage, nextimage, firstskel, nextskel, image; line_ptr firstrel,nextrel, rel, firstcopy, nextcopy; int f,n,i,j; int skelable; if(object==NULL) return; firstrel = nextrel = NULL; firstimage = findtype(object,IMAGE,&f); if(firstimage==NULL) return; if((firstimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE)) { skelable=TRUE; firstrel = makerelative(firstimage); } else { skelable = FALSE; } nextimage = findtype(firstimage->next,IMAGE,&n); while(nextimage!=NULL) { if(skelable==TRUE) { if((nextimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE)) { nextrel = makerelative(nextimage); nextcopy = copyline(nextrel); firstcopy = copyline(firstrel); preprocess(firstcopy,nextcopy); } else { skelable = FALSE; } j = 0; firstskel = firstimage; nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f); while((j+f<=n) && (nextskel!=NULL)) { if((skelable==TRUE) && (nextskel!=nextimage)) { rel = imagebetween(firstcopy, nextcopy,j+f+1,n+1,firstskel->ilaw); makeimage(nextskel,rel); deleteline(rel); } else if(nextskel!=nextimage) { makeimage(nextskel,firstrel); } image = firstskel->next; for(i=1;i<=f;i++) { deleteline(image->skeleton); image->skeleton = imagebetween(firstskel->skeleton, nextskel->skeleton,i,f+1,firstskel->ilaw); deleteline(image->outline); image->outline = imagebetween(firstskel->outline, nextskel->outline,i,f+1,firstskel->ilaw); if(skelable==TRUE) { rel = imagebetween(firstcopy, nextcopy,j+i,n+1,firstskel->ilaw); makeimage(image,rel); deleteline(rel); } else { makeimage(image,firstrel); } image = image->next; } j = j+f+1; firstskel = nextskel; nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f); } if(skelable==TRUE) { deleteline(firstcopy); deleteline(nextcopy); } else nextrel=NULL; deleteline(firstrel); firstrel = nextrel; if(jimage); nextcopy = copyline(nextimage->image); preprocess(firstcopy,nextcopy); image = firstskel->next; for(i=1;i<=n;i++) { deleteline(image->image); image->image = imagebetween(firstcopy, nextcopy,i,n+1,firstskel->ilaw); image = image->next; } deleteline(firstcopy); deleteline(nextcopy); } } else { /* inbetweening of images */ firstcopy = copyline(firstimage->image); nextcopy = copyline(nextimage->image); preprocess(firstcopy,nextcopy); image = firstimage->next; for(i=1;i<=n;i++) { deleteline(image->image); image->image = imagebetween(firstcopy, nextcopy,i,n+1,firstimage->ilaw); image = image->next; } deleteline(firstcopy); deleteline(nextcopy); if((nextimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE)) { skelable = TRUE; deleteline(firstrel); firstrel = makerelative(nextimage); } } firstimage = nextimage; nextimage = findtype(firstimage->next,IMAGE,&n); } if((firstimage->next!=NULL) && (skelable==TRUE)) { firstskel = firstimage; nextskel = findtype(firstimage->next,SKELETON|XOUTLINE,&f); while(nextskel!=NULL) { makeimage(nextskel,firstrel); image = firstskel->next; for(i=1;i<=f;i++) { deleteline(image->skeleton); image->skeleton = imagebetween(firstskel->skeleton, nextskel->skeleton,i,f+1,firstskel->ilaw); deleteline(image->outline); image->outline = imagebetween(firstskel->outline, nextskel->outline,i,f+1,firstskel->ilaw); makeimage(image,firstrel); image = image->next; } firstskel = nextskel; nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f); } } deleteline(firstrel); }