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

Last change on this file since 481 was 481, checked in by Sam Hocevar, 11 years ago

Fuck the history, I'm renaming all .hpp files to .h for my own sanity.

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