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

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

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

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