source: abuse/branches/lol/src/imlib/supmorph.cpp @ 732

Last change on this file since 732 was 732, checked in by Sam Hocevar, 8 years ago

build: SDL2 compilation fixes.

File size: 8.5 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2013 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, by
8 *  Jonathan Clark, or by Sam Hocevar.
9 */
10
11#if HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "common.h"
16
17#include "imlib/supmorph.h"
18#include "imlib/specs.h"
19#include "imlib/transimage.h"
20#include "imlib/filter.h"
21#include "imlib/video.h"
22
23#define p_swap(x,y) { x^=y; y^=x; x^=y; }
24#define p_dist(x1,y1,x2,y2) (((int)(x1)-(int)x2)*((int)(x1)-(int)x2)+      \
25                             ((int)(y1)-(int)y2)*((int)(y1)-(int)y2))
26
27super_morph::super_morph(TransImage *hint1, TransImage *hint2,
28             int aneal_steps, void (*stat_fun)(int))
29{
30  int x,y,w1=hint1->Size().x,
31          h1=hint1->Size().y,
32          w2=hint2->Size().x,
33          h2=hint2->Size().y;
34  if (w1>w2) w=w1; else w=w2;
35  if (h1>h2) h=h1; else h=h2;
36  unsigned char *dp;
37
38  /************************ count up the number of hints ****************************/
39  unsigned short hints1[256],hints2[256];
40  memset(hints1,0,256*2);
41  memset(hints2,0,256*2);
42
43  dp=hint1->Data();
44  for (y=0; y<h1; y++)
45  {
46    x=0;
47    while (x<w1)
48    {
49      x+=*dp;      // skip over space
50      dp++;
51      if (x<w1)
52      {
53    int rl=*(dp++);
54    while (rl--) { hints1[*(dp++)]++; x++; }
55      }
56    }
57  }
58
59  // hint2 image2
60  dp=hint2->Data();
61  for (y=0; y<h2; y++)
62  {
63    x=0;
64    while (x<w2)
65    {
66      x+=*dp;      // skip over space
67      dp++;
68      if (x<w2)
69      {
70    int rl=*(dp++);
71    while (rl--) { hints2[*(dp++)]++; x++; }
72      }
73    }
74  }
75
76
77  /****************** now sum up hints and alloc memory for movers *************/
78  unsigned short start1[256],start2[256],
79                 totals[256],
80                 start=0,*h1p=hints1,*h2p=hints2;
81  unsigned char hint_color[256],total_hints=0;
82
83  for (y=0; y<256; y++,h1p++,h2p++)
84    if (*h1p)
85    {
86      if (*h2p==0)
87      {
88    t=0;
89    return ;
90      }
91      start1[y]=start2[y]=start;       // specify start of hint range
92      if (*h1p>*h2p)
93        totals[y]=*h1p;
94      else totals[y]=*h2p;
95      start+=totals[y];
96      hint_color[total_hints++]=y;
97    }
98
99  t=start;
100  movers=(unsigned char *)malloc(t*4);
101
102
103  /**************** Now scan the images again setup hints *********************/
104  dp=hint1->Data();
105  for (y=0; y<h1; y++)
106  {
107    x=0;
108    while (x<w1)
109    {
110      x+=*dp;      // skip over space
111      dp++;
112      if (x<w1)
113      {
114    int rl=*(dp++);
115    while (rl--)
116    {
117      int maddr=(start1[*(dp++)]++)*4;
118      movers[(maddr++)]=x;
119      movers[maddr]=y;
120      x++;
121    }
122      }
123    }
124  }
125
126  dp=hint2->Data();
127  for (y=0; y<h2; y++)
128  {
129    x=0;
130    while (x<w2)
131    {
132      x+=*dp;      // skip over space
133      dp++;
134      if (x<w2)
135      {
136    int rl=*(dp++);
137    while (rl--)
138    {
139      int maddr=(start2[*(dp++)]++)*4+2;
140      movers[(maddr++)]=x;
141      movers[maddr]=y;
142      x++;
143    }
144      }
145    }
146  }
147
148  /********* if hint sizes don't match duplicate the smaller until sizes are equal **********/
149  for (start=0,x=0; x<total_hints; x++)
150  {
151    y=hint_color[x];
152    int dups;
153    for (dp=movers+start1[y]*4,dups=totals[y]-hints1[y]; dups; dups--)
154    {
155      *dp=*(dp-4); dp++;      // copy previous x,y position
156      *dp=*(dp-4); dp++;
157      dp+=2;
158    }
159    start1[y]-=2*totals[y]-hints1[y];        // set the start back to the begining of hint range
160  }
161
162  for (start=0,x=0; x<total_hints; x++)
163  {
164    y=hint_color[x];
165    int dups;
166    for (dp=movers+start2[y]*4+2,dups=totals[y]-hints2[y]; dups; dups--)
167    {
168      *dp=*(dp-4); dp++;      // copy previous x,y position
169      *dp=*(dp-4); dp++;
170      dp+=2;
171    }
172    start2[y]-=hints2[y];        // set the start back to the begining of hint range
173  }
174
175
176  /******* Now apply simulated annealing to solve for a smaller total distance ********/
177  for (y=0; y<aneal_steps; y++)
178  {
179    if (stat_fun)
180      stat_fun(y);
181    dp=movers;
182    for (x=0; x<total_hints; x++)
183    {
184      int hc=hint_color[x];
185      int a,z=totals[hc];
186      unsigned char *range_start=dp;
187      for (a=0; a<z; a++,dp+=4)
188      {
189    unsigned char *swap = range_start + rand(z) * 4;
190    int d_old=p_dist(dp[0],dp[1],dp[2],dp[3])+p_dist(swap[0],swap[1],swap[2],swap[3]);
191    int d_new=p_dist(dp[0],dp[1],swap[2],swap[3])+p_dist(swap[0],swap[1],dp[2],dp[3]);
192    if (d_new<d_old)
193    {
194      unsigned char s;
195      s=swap[2]; swap[2]=dp[2]; dp[2]=s;
196      s=swap[3]; swap[3]=dp[3]; dp[3]=s;
197    }
198      }
199    }
200  }
201}
202
203smorph_player::smorph_player(super_morph *m, Palette *pal, AImage *i1, AImage *i2, int frames, int dir)
204{
205  unsigned char *d = m->movers;
206  stepper *p = steps = (stepper *)malloc(sizeof(stepper)*m->t);
207  f_left=frames;
208  frames--;
209  t=m->t;
210  w=m->w; h=m->h;
211
212  for (int i = 0; i < t; i++, p++)
213  {
214    int x1 = *d++;
215    int y1 = *d++;
216    int x2 = *d++;
217    int y2 = *d++;
218
219    u8vec3 c1 = pal->GetColor(*(i1->scan_line(y1) + x1));
220    u8vec3 c2 = pal->GetColor(*(i2->scan_line(y2) + x2));
221
222    p->r = c1.r <<16;
223    p->g = c1.g <<16;
224    p->b = c1.b <<16;
225
226    p->dr = (long)(((int)c2.r - (int)c1.r) << 16) / frames;
227    p->dg = (long)(((int)c2.g - (int)c1.g) << 16) / frames;
228    p->db = (long)(((int)c2.b - (int)c1.b) << 16) / frames;
229
230    if (dir<0)
231    {
232      x1=w-x1-1;
233      x2=w-x2-1;
234    }
235    p->dx=((x2-x1)<<16)/frames;
236    p->dy=((y2-y1)<<16)/frames;
237    p->x=x1<<16;
238    p->y=y1<<16;
239  }
240
241  hole=(unsigned char *)malloc(w*h);
242}
243
244int smorph_player::show(AImage *screen, int x, int y, ColorFilter *fil, Palette *pal,
245            int blur_threshold)
246{
247    if (!f_left)
248        return 0;
249
250    int i;
251    ivec2 caa, cbb;
252    screen->GetClip(caa, cbb);
253    screen->AddDirty(ivec2(x, y), ivec2(x + w, y + h));
254    stepper *ss;
255    memset(hole,0,w*h);
256    for (ss=steps,i=0; i<t; i++,ss++)
257    {
258      int ix = ss->x >> 16;
259      int iy = ss->y >> 16;
260      int px = ix + x;
261      int py = iy + y;
262      if (px>=caa.x && px < cbb.x && py>=caa.y && py < cbb.y)
263      {
264        int n = fil->Lookup(u8vec3(ss->r >> 19, ss->g >> 19, ss->b >> 19));
265        hole[ix+iy*w]=*(screen->scan_line(py)+px) = n;
266      }
267      ss->x+=ss->dx;
268      ss->y+=ss->dy;
269      ss->r+=ss->dr;
270      ss->g+=ss->dg;
271      ss->b+=ss->db;
272    }
273    f_left--;
274    if (!f_left)    // skip hole fills and smoothing on last frame
275      return 1;
276
277    unsigned char *ll=hole+1,*tl=hole+w+1,*nl=hole+w*2+1;
278    for (int iy = 1; iy < h - 1; iy++)    // now scan the for holes to fill
279    {
280      for (int ix = 1; ix < w - 1; ix++, ll++, tl++, nl++)
281      {
282    if (x+ix>=caa.x && x+ix < cbb.x && y+iy>=caa.y && y+iy < cbb.y)
283    {
284      int t=0;
285      ivec3 rgb(0);
286/*      if (*(tl-1)) t++;
287      if (*(tl+1)) t++;
288      if (*ll) t++;
289      if (*nl) t++; */
290
291      if (*(tl-1)) { t++; rgb += (ivec3)pal->GetColor(*(tl - 1)); }
292      if (*(tl+1)) { t++; rgb += (ivec3)pal->GetColor(*(tl + 1)); }
293      if (*(ll)) { t++; rgb += (ivec3)pal->GetColor(*ll); }
294      if (*(nl)) { t++; rgb += (ivec3)pal->GetColor(*nl); }
295
296      if (t)
297          rgb /= t;
298
299      if (*tl)
300      {
301        if (t)
302        {
303          ivec3 color = (ivec3)pal->GetColor(*tl);
304          int dist = sqlength(color - rgb);
305          if (dist > blur_threshold)
306            *(tl)=*(screen->scan_line(y+iy)+x+ix) = fil->Lookup(u8vec3(rgb / 8));
307        } else
308            *(tl) = *(screen->scan_line(y+iy)+x+ix)=0; // kill single pixels
309      }
310      else if (t>=3)
311        *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->Lookup(u8vec3(rgb / 8));
312    }
313      }
314      ll+=2;
315      tl+=2;
316      nl+=2;
317    }
318    return 1;
319}
320
321
322
323
324/*void free_up_memory() { printf("you're screwed\n"); }
325
326main(int argc, char **argv)
327{
328  image_init();
329  FILE *fp=fopen("art/mrphmask.spe","rb");
330  SpecDir sd(fp);
331  AImage *h1=new AImage(sd.find("20 h"),fp),
332        *h2=new AImage(sd.find("1h"),fp),
333        *i1=new AImage(sd.find("20"),fp),
334        *i2=new AImage(sd.find("1"),fp);
335  palette *pal=new palette(sd.find(SPEC_PALETTE),fp);
336  color_filter *fil=new color_filter(sd.find(SPEC_COLOR_TABLE),fp);
337
338  int steps=atoi(argv[1]);
339  if (steps<2) steps=50;
340  TransImage *hh1=new TransImage(h1,"hint1"),*hh2=new TransImage(h2,"hint2");
341
342  Timer t;
343  super_morph sm(hh1,hh2,steps);
344  int frames=atoi(argv[2]);
345  if (frames<2) frames=16;
346  smorph_player sp(&sm,pal,i1,i2,frames,-1);
347  printf("time = %lf\n", t.Get());
348
349  CreateScreen(argc,argv);
350  pal->Load();
351  i1->put_image(screen,30,30);
352  update_dirty(screen);
353  sleep(2);
354  while (sp.show(screen,30,30,fil,pal))
355  { update_dirty(screen);
356    screen->bar(30,30,30+sp.w,30+sp.h,0);
357  }
358  sleep(2);
359  DestroyScreen();
360}*/
361
362
Note: See TracBrowser for help on using the repository browser.