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

Last change on this file since 128 was 124, checked in by Sam Hocevar, 15 years ago
  • Get rid of ugly tabs and trailing spaces everywhere.
File size: 8.9 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.hpp"
13#include "specs.hpp"
14#include "timage.hpp"
15#include "timing.hpp"
16#include "filter.hpp"
17#include "video.hpp"
18#include "jrand.hpp"
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 *)jmalloc(t*4,"morph movers");
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 *)jmalloc(sizeof(stepper)*m->t,"smorph steps");
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 *)jmalloc(w*h,"hole image");
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.