source: abuse/trunk/src/imlib/morph.cpp @ 494

Last change on this file since 494 was 494, checked in by Sam Hocevar, 12 years ago

style: remove trailing spaces, fix copyright statements.

File size: 25.4 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11/* FIXME: this file is unused */
12
13#include "config.h"
14
15#include "morph.h"
16
17long trans(long x1, long x2, long frame)
18{
19  return (((x2-x1)<<5)*frame+(x1<<8))>>8;
20}
21
22
23void jmorph::show_step_frame(image *screen, int x, int y, int frame_on,
24                   color_filter *fli, palette *pal)
25{
26  short x1,y1,x2,y2;
27  unsigned char r1,g1,b1,r2,g2,b2;
28  screen->get_clip(x1,y1,x2,y2);
29
30  int i;
31  long xx,yy;
32
33  if (small)
34  {
35    morph_point8 *m8=(morph_point8 *)p;
36    screen->lock();
37    for (i=0; i<total; i++,m8++)
38    {
39      xx=x+trans(m8->x1,m8->x2,frame_on);
40      yy=y+trans(m8->y1,m8->y2,frame_on);
41
42      if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
43      {
44    pal->get(m8->start_color,r1,g1,b1);
45    pal->get(m8->end_color,r2,g2,b2);
46
47    long r=trans(r1,r2,frame_on)>>3,
48             g=trans(g1,g2,frame_on)>>3,
49         b=trans(b1,b2,frame_on)>>3;
50
51        *(screen->scan_line(yy)+xx)=fli->lookup_color(r,g,b);
52      }
53    }
54    screen->unlock();
55  }
56}
57
58
59void patched_morph::show_frame(image *screen, int x, int y,
60                   int frame_on, color_filter *fli, palette *pal)
61{
62  jmorph::show_step_frame(screen,x,y,frame_on,fli,pal);
63  int tot=pats[frame_on].patches,xx,yy;
64  unsigned char *p=pats[frame_on].patch_data;
65  short cx1,cy1,cx2,cy2;
66  screen->get_clip(cx1,cy1,cx2,cy2);
67  screen->lock();
68  while (tot--)
69  {
70    xx=*(p++)+x;
71    if (xx<cx1 || xx>cx2)
72      p+=2;
73    else
74    {
75      yy=*(p++)+y;
76      if (yy<cy1 || yy>cy2)
77        p++;
78      else
79    *(screen->scan_line(yy)+xx)=*(p++);
80    }
81  }
82  screen->unlock();
83}
84
85void patched_morph::show_8(image *screen, int x, int y, int frame_on, color_filter *fli, palette *pal)
86{
87  jmorph::show_8(screen,x,y,frame_on,fli,pal);
88  int tot=pats[frame_on].patches,xx,yy;
89  unsigned char *p=pats[frame_on].patch_data;
90  short cx1,cy1,cx2,cy2;
91  screen->get_clip(cx1,cy1,cx2,cy2);
92  screen->lock();
93  while (tot--)
94  {
95    xx=*(p++)+x;
96    if (xx<cx1 || xx>cx2)
97      p+=2;
98    else
99    {
100      yy=*(p++)+y;
101      if (yy<cy1 || yy>cy2)
102        p++;
103      else
104    *(screen->scan_line(yy)+xx)=*(p++);
105    }
106  }
107  screen->unlock();
108}
109
110
111
112
113patched_morph::patched_morph(image *i1, image *hint1, image *i2, image *hint2, int aneal_steps,
114            color_filter *fli, palette *pal, int frames) : jmorph(i1,hint1,i2,hint2,aneal_steps)
115{
116  int i,j,w,h,x,y,tot,r,g,b,mark_color,dist;
117  unsigned char *cur_patch,*sl,ored,og,ob;
118
119  frames=9;
120
121  patches=frames;
122  pats=(morph_patch *)malloc(sizeof(morph_patch)*patches);
123  w=max(bound_x2(0),bound_x2(1));
124  h=max(bound_y2(0),bound_y2(1));
125  image *im=new image(w,h);
126
127
128  for (i=0; i<patches; i++)
129  {
130    pats[i].patch_data=NULL;
131    pats[i].patches=0;
132    if (i!=0 && i!=patches-1)
133    {
134      im->clear();
135      jmorph::show_step_frame(im,0,0,i,fli,pal);
136      for (j=0; j<4; j++)
137      {
138    for (y=0; y<h; y++)
139          for (sl=im->scan_line(y),x=0; x<w; x++,sl++)
140      {
141        mark_color=-1;
142
143        tot=r=g=b=0;
144        if (x!=0 && *(sl-1))
145        { tot++;
146          r+=pal->red(*(sl-1));
147          g+=pal->green(*(sl-1));
148          b+=pal->blue(*(sl-1));
149        }
150        if (x!=w-1 && *(sl+1))
151        { tot++;
152          r+=pal->red(*(sl+1));
153          g+=pal->green(*(sl+1));
154          b+=pal->blue(*(sl+1));
155        }
156        if (y!=0 && im->pixel(x,y-1))
157        { tot++;
158          r+=pal->red(im->pixel(x,y-1));
159          g+=pal->green(im->pixel(x,y-1));
160          b+=pal->blue(im->pixel(x,y-1));
161        }
162        if (y!=h-1 && im->pixel(x,y+1))
163        { tot++;
164          r+=pal->red(im->pixel(x,y+1));
165          g+=pal->green(im->pixel(x,y+1));
166          b+=pal->blue(im->pixel(x,y+1));
167        }
168
169        if (*sl && tot==0)  // kill any separate pixels
170          mark_color=0;
171        else if (*sl)
172        {
173          pal->get(*sl,ored,og,ob);       // see if we need to blur this on in
174          r/=tot;
175          g/=tot;
176          b/=tot;
177
178          dist=((int)ored-r)*((int)ored-r)+((int)og-g)*((int)og-g)+((int)ob-b)*((int)ob-b);
179          if (i>0 && i<patches-1 && dist>3000)
180          {
181//        printf("adding blur at %d %d to frame %d, dist=%d\n",x,y,i,dist);
182        mark_color=fli->lookup_color(r>>3,g>>3,b>>3);
183          }
184        }
185        else if (*sl==0 && tot>=3)
186          mark_color=fli->lookup_color((r/tot)>>3,(g/tot)>>3,(b/tot)>>3);
187        if (mark_color>=0)
188        {
189          pats[i].patches++;
190          pats[i].patch_data=(unsigned char *)realloc(pats[i].patch_data,3*pats[i].patches);
191          cur_patch=pats[i].patch_data+  (pats[i].patches-1)*3;
192          *(cur_patch++)=x;
193          *(cur_patch++)=y;
194          *sl=mark_color;
195          *(cur_patch++)=*sl;
196        }
197      }
198      }
199    }
200  }
201  delete im;
202
203}
204
205
206void jmorph::show_8(image *screen, int x, int y, int frame_on, color_filter *fli, palette *pal)
207{
208  int pixelx,pixely,i;
209  short cx1,cy1,cx2,cy2;
210  unsigned char r,g,b;
211  unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr();
212  screen->get_clip(cx1,cy1,cx2,cy2);
213
214  if (small)
215  {
216    morph_point8 *p_on=(morph_point8 *)p;
217    for (i=0; i<total; i++,p_on++)
218    {
219      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/8+p_on->x1+x;
220      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/8+p_on->y1+y;
221      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
222      {
223        scolor=addr+((int)p_on->start_color)*3;
224        ecolor=addr+((int)p_on->end_color)*3;
225        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
226        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
227        b=((int)(*ecolor)-(int)(*scolor))*frame_on/8+*scolor;
228        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
229      }
230    }
231  }
232  else
233  {
234    morph_point16 *p_on=(morph_point16 *)p;
235    for (i=0; i<total; i++,p_on++)
236    {
237      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/8+p_on->x1+x;
238      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/8+p_on->y1+y;
239      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
240      {
241        scolor=addr+((int)p_on->start_color)*3;
242        ecolor=addr+((int)p_on->end_color)*3;
243        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
244        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/8+*scolor; scolor++;
245        b=((int)(*ecolor)-(int)(*scolor))*frame_on/8+*scolor;
246        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
247      }
248    }
249  }
250}
251
252
253void jmorph::add_filler(int frames)
254{
255  int w=max(bound_x2(0),bound_x2(1)),h=max(bound_y2(0),bound_y2(1)),
256      i,pixelx,pixely,k,l,frame_on;
257  morph_point8 **middle_map,*other;
258  unsigned char *end_map;
259  CONDITION(small,"add filler not defined for 16bit morphs\n");
260
261  if (frames<3) return ;
262
263
264  // create an image of pointers
265  middle_map=(morph_point8 **)malloc(w*h*sizeof(morph_point8 *));
266  // maps all the ending pixels
267  end_map=(unsigned char *)malloc(w*h);
268
269  for (frame_on=2; frame_on<frames-1; frame_on++)
270  {
271    memset(middle_map,0,w*h*sizeof(morph_point8 *));            // initialize them middle pointers NULL
272    memset(end_map,0,w*h);                                      // clear all end pixels
273
274    morph_point8 *p_on=(morph_point8 *)p;    // p is the array of morph points
275    for (i=0; i<total; i++,p_on++)
276    {
277      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long) frame_on  /(long) frames  +p_on->x1;
278      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long) frame_on  /(long) frames  +p_on->y1;
279
280      middle_map[pixelx+pixely*w]=p_on;      // map this poisiton back to the morph point
281      end_map[p_on->x2+p_on->y2*w]=p_on->end_color;        // note an ending map here
282    }
283
284
285    int skipped=0;
286
287    for (pixely=0; pixely<h; pixely++)
288    {
289      for (pixelx=0; pixelx<w; pixelx++)
290      {
291    if (middle_map[pixelx+pixely*w]==NULL)  // we are checking for 'duds'  (misplaced black pixels)
292    {
293      int tot;
294      if (pixelx>0) if (middle_map[pixelx-1+pixely*w]) tot=1; else tot=0;
295      if (pixelx<w-1) if (middle_map[pixelx+1+pixely*w]) tot++;
296      if (pixely>0) if (middle_map[pixelx+(pixely-1)*w]) tot++;
297      if (pixely<h-1) if (middle_map[pixelx+(pixely+1)*w]) tot++;
298
299      if (tot>=3)                   // it is surronded by 3 non black squares, this is a dud
300      {
301        int distance,shortest_distance,shortest_end_x,shortest_end_y;
302        morph_point8 *shortest=NULL;
303
304        for (k=0; k<w; k++)
305             for (l=0; l<h; l++)
306          {
307                other=middle_map[k+(l)*w];
308        if (other)
309        {
310          int end_x=frames*(pixelx-other->x1)/frame_on+other->x1,
311              end_y=frames*(pixely-other->y1)/frame_on+other->y1;
312          if (end_x>=0 && end_y>=0 && end_x<w && end_y<h && end_map[end_x+end_y*w])
313          {
314                    distance=(other->x1-end_x)*(other->x1-end_x)+
315                     (other->y1-end_y)*(other->y1-end_y);
316            if (!shortest || shortest_distance>distance)
317            {
318              shortest_distance=distance;
319              shortest=other;
320              shortest_end_x=end_x;
321              shortest_end_y=end_y;
322            }
323          }
324        }
325          }
326        if (shortest)
327        {
328          total++;
329          p=(void *)realloc(p,sizeof(morph_point8)*total);
330          morph_point8 *mod=((morph_point8 *)p)+total-1;
331          mod->x1=shortest->x1;
332          mod->y1=shortest->y1;
333          mod->start_color=shortest->start_color;
334
335          mod->x2=shortest_end_x;
336          mod->y2=shortest_end_y;
337          mod->end_color=end_map[shortest_end_x+shortest_end_y*w];
338        }
339        else
340        {
341            skipped++;
342          printf("skiped so far : %d (frame %d)\n",skipped,frame_on);
343        }
344
345
346      }
347    }
348      }
349    }
350  }
351
352  free(middle_map);
353  free(end_map);
354
355}
356
357
358
359jmorph::jmorph(spec_entry *e, bFILE *fp)
360{
361  int i;
362  fp->seek(e->offset,0);
363  fp->read(&total,4);
364  total=long_to_local(total);
365  if (e->type==SPEC_MORPH_POINTS_8 || e->type==SPEC_PATCHED_MORPH)
366  {
367    p=(void *)malloc(sizeof(morph_point8)*total);
368    fp->read(p,sizeof(morph_point8)*total);
369    small=1;
370  }
371  else
372  {
373    p=(void *)malloc(sizeof(morph_point16)*total);
374
375    for (i=0; i<total; i++)
376    {
377      ((morph_point16 *)p+i)->x1=fp->read_uint16();
378      ((morph_point16 *)p+i)->y1=fp->read_uint16();
379      ((morph_point16 *)p+i)->x2=fp->read_uint16();
380      ((morph_point16 *)p+i)->y2=fp->read_uint16();
381      fp->read( &((morph_point16 *)p+i)->start_color,1);
382      fp->read( &((morph_point16 *)p+i)->end_color,1);
383    }
384
385    small=0;
386  }
387  w[0]=fp->read_uint16();
388  h[0]=fp->read_uint16();
389  w[1]=fp->read_uint16();
390  h[1]=fp->read_uint16();
391}
392
393void jmorph::show_frame(image *screen, int x, int y,
394                      int frames, int frame_on, color_filter *fli, palette *pal)
395{
396  int pixelx,pixely,i;
397  short cx1,cy1,cx2,cy2;
398  unsigned char r,g,b;
399  unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr();
400  screen->get_clip(cx1,cy1,cx2,cy2);
401
402  if (small)
403  {
404    morph_point8 *p_on=(morph_point8 *)p;
405    for (i=0; i<total; i++,p_on++)
406    {
407      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
408      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
409      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
410      {
411        scolor=addr+((int)p_on->start_color)*3;
412        ecolor=addr+((int)p_on->end_color)*3;
413        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
414        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
415        b=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
416        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
417      }
418    }
419  }
420  else
421  {
422    morph_point16 *p_on=(morph_point16 *)p;
423    for (i=0; i<total; i++,p_on++)
424    {
425      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
426      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
427      if (pixelx>=cx1 && pixely>=cy1 && pixelx<=cx2 && pixely<=cy2)
428      {
429        scolor=addr+((int)p_on->start_color)*3;
430        ecolor=addr+((int)p_on->end_color)*3;
431        r=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
432        g=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++;
433        b=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
434        *(screen->scan_line(pixely)+pixelx)=fli->lookup_color(r>>3,g>>3,b>>3);
435      }
436    }
437  }
438}
439
440void jmorph::show_24frame(unsigned char *screen, int width, int height,
441                  int x, int y, int frames, int frame_on, palette *pal)
442{
443    int pixelx,pixely,i;
444  unsigned char *scolor,*ecolor,*addr=(unsigned char *)pal->addr(),*pix;
445
446  if (small)
447  {
448    morph_point8 *p_on=(morph_point8 *)p;
449    for (i=0; i<total; i++,p_on++)
450    {
451      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
452      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
453
454      if (pixelx>=0 && pixely>=0 && pixelx<width && pixely<height)
455      {
456        scolor=addr+((int)p_on->start_color)*3;
457        ecolor=addr+((int)p_on->end_color)*3;
458        pix=screen+pixelx*3+pixely*3*width;
459        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;
460        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;
461        *pix=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
462      }
463    }
464  }
465  else
466  {
467    morph_point16 *p_on=(morph_point16 *)p;
468    for (i=0; i<total; i++,p_on++)
469    {
470      pixelx=(long)((int)p_on->x2-(int)p_on->x1)*(long)frame_on/(long)frames+p_on->x1+x;
471      pixely=(long)((int)p_on->y2-(int)p_on->y1)*(long)frame_on/(long)frames+p_on->y1+y;
472
473      if (pixelx>=0 && pixely>=0 && pixelx<width && pixely<height)
474      {
475        scolor=addr+((int)p_on->start_color)*3;
476        ecolor=addr+((int)p_on->end_color)*3;
477        pix=screen+pixelx*3+pixely*3*width;
478        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;
479        *pix=(((int)*(ecolor++))-((int)*scolor))*frame_on/frames+*scolor; scolor++; pix++;
480        *pix=((int)(*ecolor)-(int)(*scolor))*frame_on/frames+*scolor;
481      }
482    }
483  }
484}
485
486
487jmorph::jmorph(image *i1, image *hint1, image *i2, image *hint2,
488                          int aneal_steps)
489{
490  w[0]=i1->width();
491  h[0]=i1->height();
492  w[1]=i2->width();
493  h[1]=i2->height();
494
495  struct { int start,end; } crange[256];
496  int hint_hist1[256],hint_hist2[256],x,y,total_hints=0,randp,cur_pix,
497      last=0,first=0,i,j,k,findx1,findy1,findx2,findy2,total1,total2,points;
498  unsigned char *sl,color;
499  void *plist;
500
501
502  CONDITION(i1->width()==hint1->width() && i1->height()==hint1->height() &&
503            i2->width()==hint2->width() && i2->height()==hint2->height(),
504            "Image sizes do not correspond with hint sizes");
505  if (i1->width()>255 || i2->width()>255 || i1->height()>255 || i2->height()>255)
506    small=0;
507  else small=1;
508
509  memset(hint_hist1,0,sizeof(hint_hist1));
510  memset(hint_hist2,0,sizeof(hint_hist2));
511  total=0;
512
513  // first found out how many hints we have to follow
514  for (y=0; y<hint1->height(); y++)
515  { sl=hint1->scan_line(y);
516    for (x=hint1->width(); x; x--,sl++)
517      if (*sl) hint_hist1[*sl]++;
518  }
519  for (y=0; y<hint2->height(); y++)
520  { sl=hint2->scan_line(y);
521    for (x=hint2->width(); x; x--,sl++)
522      if (*sl) hint_hist2[*sl]++;
523  }
524
525  // check the user and see if the mask match up
526  for (x=0; x<256; x++)
527  {
528    if ((hint_hist1[x]!=0 && hint_hist2[x]==0) ||
529        (hint_hist1[x]==0 && hint_hist2[x]!=0))
530    { printf("Color %d used for hinting is prent in one hint mask, but not the other\n",x);
531      exit(1);
532    } else if (hint_hist1[x])
533    {
534      if (!first) first=x;
535      total_hints++;
536      if (hint_hist1[x]>hint_hist2[x])
537        y=hint_hist1[x];
538      else
539        y=hint_hist2[x];
540      total+=y;
541      crange[x].start=last;
542      crange[x].end=last+y-1;
543      last+=y;
544    }
545  }
546  if (small)
547    plist=(void *)malloc(sizeof(morph_point8)*total);
548  else
549    plist=(void *)malloc(sizeof(morph_point16)*total);
550  CHECK(plist);
551  for (i=0,color=0; i<total_hints; i++)
552  {
553    color++; while (!hint_hist1[color]) color++;
554    findx1=findx2=-1; findy1=findy2=0;
555    total1=hint_hist1[color];
556    total2=hint_hist2[color];
557    if (total1>total2) points=total1; else points=total2;
558    for (j=0; j<points; j++)
559    {
560      if (total1)  // are there any more pixels left in this image?
561      { total1--;
562        do {
563          findx1++;
564          if (findx1>=hint1->width()) { findx1=0; findy1++; }
565        } while (hint1->pixel(findx1,findy1)!=color);
566      }
567      else
568      {
569        randp=rand()%j+crange[color].start;
570        if (small)
571        { findx1=((morph_point8 *)plist)[randp].x1;
572          findy1=((morph_point8 *)plist)[randp].y1;
573        } else
574        { findx1=((morph_point16 *)plist)[randp].x1;
575          findy1=((morph_point16 *)plist)[randp].y1;
576        }
577      }
578      if (total2)  // are there any more pixels left in this image?
579      {
580        total2--;
581        do {
582          findx2++;
583          if (findx2>=hint2->width()) { findx2=0; findy2++; }
584        } while (hint2->pixel(findx2,findy2)!=color);
585      }
586      else
587      {
588        randp=rand()%j+crange[color].start;
589        if (small)
590        { findx2=((morph_point8 *)plist)[randp].x2;
591          findy2=((morph_point8 *)plist)[randp].y2;
592        } else
593        { findx2=((morph_point16 *)plist)[randp].x2;
594          findy2=((morph_point16 *)plist)[randp].y2;
595        }
596      }
597      cur_pix=j+crange[color].start;
598      CHECK(cur_pix<total);
599
600      if (small)
601      {
602        ((morph_point8 *)plist)[cur_pix].x1=findx1;
603        ((morph_point8 *)plist)[cur_pix].x2=findx2;
604        ((morph_point8 *)plist)[cur_pix].y1=findy1;
605        ((morph_point8 *)plist)[cur_pix].y2=findy2;
606        ((morph_point8 *)plist)[cur_pix].start_color=i1->pixel(findx1,findy1);
607        ((morph_point8 *)plist)[cur_pix].end_color=i2->pixel(findx2,findy2);
608      }
609      else
610      {
611        ((morph_point16 *)plist)[cur_pix].x1=findx1;
612        ((morph_point16 *)plist)[cur_pix].x2=findx2;
613        ((morph_point16 *)plist)[cur_pix].y1=findy1;
614        ((morph_point16 *)plist)[cur_pix].y2=findy2;
615        ((morph_point16 *)plist)[cur_pix].start_color=i1->pixel(findx1,findy1);
616        ((morph_point16 *)plist)[cur_pix].end_color=i2->pixel(findx2,findy2);
617      }
618    }
619  }
620  int swap_point,distance,new_distance,hint_color,first_point,range,start;
621
622  int sx2,sy2,sec;
623  for (i=0; i<aneal_steps; i++)
624  {
625    for (j=0,first_point=0; j<total_hints; j++)
626    {
627      if (small)
628        hint_color=hint1->pixel(((morph_point8 *)plist)[first_point].x1,((morph_point8 *)plist)[first_point].y1);
629      else
630        hint_color=hint1->pixel(((morph_point16 *)plist)[first_point].x1,((morph_point16 *)plist)[first_point].y1);
631      start=crange[hint_color].start;
632      range=crange[hint_color].end-start+1;
633      for(k=crange[hint_color].start; k<=crange[hint_color].end; k++)
634      {
635        swap_point=rand()%range+start;
636        if (small)
637        {
638          morph_point8 *pk,*ps;
639          pk=(morph_point8 *)plist+k;
640          ps=(morph_point8 *)plist+swap_point;
641
642          distance=(pk->x2-pk->x1)*(pk->x2-pk->x1)+(pk->y2-pk->y1)*(pk->y2-pk->y1)+
643                   (ps->x2-ps->x1)*(ps->x2-ps->x1)+(ps->y2-ps->y1)*(ps->y2-ps->y1);
644          new_distance=(ps->x2-pk->x1)*(ps->x2-pk->x1)+(ps->y2-pk->y1)*(ps->y2-pk->y1)+
645                       (pk->x2-ps->x1)*(pk->x2-ps->x1)+(pk->y2-ps->y1)*(pk->y2-ps->y1);
646          if (new_distance<distance)
647          {
648            sx2=pk->x2;         sy2=pk->y2;
649            sec=pk->end_color;
650            pk->x2=ps->x2;      pk->y2=ps->y2;
651            pk->end_color=ps->end_color;
652            ps->x2=sx2;         ps->y2=sy2;
653            ps->end_color=sec;
654          }
655        } else
656        {
657          morph_point16 *pk,*ps;
658          pk=(morph_point16 *)plist+k;
659          ps=(morph_point16 *)plist+swap_point;
660
661          distance=(pk->x2-pk->x1)*(pk->x2-pk->x1)+(pk->y2-pk->y1)*(pk->y2-pk->y1)+
662                   (ps->x2-ps->x1)*(ps->x2-ps->x1)+(ps->y2-ps->y1)*(ps->y2-ps->y1);
663          new_distance=(ps->x2-pk->x1)*(ps->x2-pk->x1)+(ps->y2-pk->y1)*(ps->y2-pk->y1)+
664                       (pk->x2-ps->x1)*(pk->x2-ps->x1)+(pk->y2-ps->y1)*(pk->y2-ps->y1);
665          if (new_distance<distance)
666          {
667            sx2=pk->x2;         sy2=pk->y2;
668            sec=pk->end_color;
669            pk->x2=ps->x2;      pk->y2=ps->y2;
670            pk->end_color=ps->end_color;
671            ps->x2=sx2;         ps->y2=sy2;
672            ps->end_color=sec;
673          }
674        }
675      }
676      first_point=crange[hint_color].end+1;
677    }
678  }
679  p=plist;
680}
681
682int morph_width;
683
684int morph8_compare(const void *p1, const void *p2)
685{
686  int pos1=((morph_point8 *)p1)->x1+((morph_point8 *)p1)->y1*morph_width;
687  int pos2=((morph_point8 *)p2)->x1+((morph_point8 *)p2)->y1*morph_width;
688  if (pos1<pos2) return -1;
689  else if (pos1==pos2) return 0;
690  else return 1;
691
692}
693
694
695int jmorph::write(bFILE *fp)
696{
697  int i;
698
699
700  fp->write_uint32(total);
701  if (small)
702  {
703
704    // if the points are put in order then they can be compressed easier
705    morph_width=max(bound_x2(0),bound_x2(1));      // global used by qsort compare routine
706    qsort(p,total,sizeof(morph_point8),morph8_compare);
707
708    fp->write(p,sizeof(morph_point8)*total);
709  }
710  else
711  {
712    for (i=0; i<total; i++)
713    { fp->write_uint16(((morph_point16 *)p+i)->x1);
714      fp->write_uint16(((morph_point16 *)p+i)->y1);
715      fp->write_uint16(((morph_point16 *)p+i)->x2);
716      fp->write_uint16(((morph_point16 *)p+i)->y2);
717      fp->write( &((morph_point16 *)p+i)->start_color,1);
718      fp->write( &((morph_point16 *)p+i)->end_color,1);
719    }
720  }
721  fp->write_uint16(w[0]);
722  fp->write_uint16(h[0]);
723  fp->write_uint16(w[1]);
724  fp->write_uint16(h[1]);
725  return 1;
726}
727
728
729
730
731step_morph::step_morph(patched_morph *mor, palette *pal, int frame_direction, int face_direction)
732{
733  int i;
734  pm=mor;
735
736  total=mor->total_points();
737  points=(step_struct *)malloc(sizeof(step_struct)*total);
738
739  dir=frame_direction;
740  face_dir=face_direction;
741
742  if (dir>0)
743    frame_on=0;
744  else
745    frame_on=mor->patches-1;
746
747  if (mor->small_morph())
748  {
749      int x1,y1,x2,y2;
750
751
752      if (frame_direction>0)
753      {
754    morph_point8 *m8=mor->small_points();
755
756    for (i=0; i<total; i++,m8++)
757    {
758      x1=(int)m8->x1;
759      x2=(int)m8->x2;
760
761      y1=(int)m8->y1;
762      y2=(int)m8->y2;
763
764      points[i].x=x1<<8;
765      points[i].y=y1<<8;
766      points[i].dx=(x2-x1)<<5;
767      points[i].dy=(y2-y1)<<5;
768
769      unsigned char r1,g1,b1,r2,g2,b2;
770      pal->get(m8->start_color,r1,g1,b1);
771      pal->get(m8->end_color,r2,g2,b2);
772      points[i].r=r1<<8;
773      points[i].g=g1<<8;
774      points[i].b=b1<<8;
775
776      points[i].dr=(long)((int)r2-(int)r1)<<5;
777      points[i].dg=(long)((int)g2-(int)g1)<<5;
778      points[i].db=(long)((int)b2-(int)b1)<<5;
779    }
780      }
781      else
782      {
783    morph_point8 *m8=mor->small_points();
784    for (i=0; i<total; i++,m8++)
785    {
786      x1=(int)m8->x1;
787      x2=(int)m8->x2;
788
789      y1=(int)m8->y1;
790      y2=(int)m8->y2;
791
792      points[i].x=x2<<8;
793      points[i].y=y2<<8;
794      points[i].dx=(x1-x2)<<5;
795      points[i].dy=(y1-y2)<<5;
796
797      unsigned char r1,g1,b1,r2,g2,b2;
798      pal->get(m8->start_color,r2,g2,b2);
799      pal->get(m8->end_color,r1,g1,b1);
800      points[i].r=r1<<8;
801      points[i].g=g1<<8;
802      points[i].b=b1<<8;
803
804      points[i].dr=(long)((int)r2-(int)r1)<<5;
805      points[i].dg=(long)((int)g2-(int)g1)<<5;
806      points[i].db=(long)((int)b2-(int)b1)<<5;
807    }
808      }
809  }
810
811
812}
813
814void step_morph::show_frame(image *screen, int x, int y,  color_filter *fli)
815{
816  short x1,y1,x2,y2;
817  screen->get_clip(x1,y1,x2,y2);
818
819  int i,px,py,ww=max(pm->bound_x2(0),pm->bound_x2(1))-1;
820  step_struct *ss;
821
822  morph_patch *pat=pm->pats+frame_on;
823  int j,tp=pat->patches;
824  unsigned char *sl=pat->patch_data;
825
826  if (face_dir>0)
827  {
828    for (i=0,ss=points; i<total; i++,ss++)
829    {
830      px=x+(ss->x>>(16-8));
831      py=y+(ss->y>>(16-8));
832      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
833        *(screen->scan_line(py)+px)=fli->lookup_color(ss->r>>(19-8),ss->g>>(19-8),ss->b>>(19-8));
834
835      ss->x+=ss->dx;
836      ss->y+=ss->dy;
837      ss->r+=ss->dr;
838      ss->g+=ss->dg;
839      ss->b+=ss->db;
840    }
841
842    for (j=0; j<tp; j++,sl++)
843    {
844      px=x+*(sl++);
845      py=y+*(sl++);
846      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
847        *(screen->scan_line(py)+px)=*sl;
848    }
849  } else
850  {
851    for (i=0,ss=points; i<total; i++,ss++)
852    {
853      px=x+ww-(ss->x>>(16-8));
854      py=y+(ss->y>>(16-8));
855      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
856        *(screen->scan_line(py)+px)=fli->lookup_color(ss->r>>(19-8),ss->g>>(19-8),ss->b>>(19-8));
857
858      ss->x+=ss->dx;
859      ss->y+=ss->dy;
860      ss->r+=ss->dr;
861      ss->g+=ss->dg;
862      ss->b+=ss->db;
863    }
864
865    for (j=0; j<tp; j++,sl++)
866    {
867      px=x+(ww-(int)(*(sl++)));
868      py=y+*(sl++);
869      if (px>=x1 && px<=x2 && py>=y1 && py<=y2)
870        *(screen->scan_line(py)+px)=*sl;
871    }
872  }
873
874  frame_on+=dir;
875
876}
877
878void step_morph::reverse_direction()
879{
880  step_struct *s=points;
881  int i;
882  for (i=0; i<total; i++,s++)
883  {
884    s->dx=-s->dx;
885    s->dy=-s->dy;
886    s->dr=-s->dr;
887    s->dg=-s->dg;
888    s->db=-s->db;
889  }
890  dir=-dir;
891
892}
893
894
895patched_morph::patched_morph(spec_entry *e, bFILE *fp) : jmorph(e,fp)
896{
897  int i;
898
899  patches=fp->read_uint16();
900  pats=(morph_patch *)malloc(sizeof(morph_patch)*patches);
901
902  for (i=0; i<patches; i++)
903  {
904    pats[i].patches=fp->read_uint16();
905    if (pats[i].patches)
906    {
907      pats[i].patch_data=(unsigned char *)malloc(3*pats[i].patches);
908      fp->read(pats[i].patch_data,3*pats[i].patches);
909    }
910    else
911      pats[i].patch_data=NULL;
912  }
913}
914
915
Note: See TracBrowser for help on using the repository browser.