forwarding build fix when MUIA_Scrollgroup_AutoBars is defined (NicJA).
[AROS-Contrib.git] / Demo / Voxel / voxel.c
blob4f64e7c76269821bcf91a2de72d3c792caceaef2
1 #include <dos/dos.h>
2 #include <intuition/intuition.h>
3 #include <graphics/gfx.h>
4 #include <cybergraphx/cybergraphics.h>
5 #include <proto/exec.h>
6 #include <proto/dos.h>
7 #include <proto/graphics.h>
8 #include <proto/cybergraphics.h>
9 #include <proto/intuition.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <math.h>
16 #undef PI
17 #define PI 3.141592654
18 #define SCREENWIDTH 640
19 #define SCREENHEIGHT 400
20 #define MAPWIDTH 512
21 #define MAPHEIGHT 512
22 #define CLOUDWIDTH 640
23 #define CLOUDHEIGHT 400
25 #define MAPSHIFT 9 /* 2^9==512==MAPWIDTH */
26 #define voxel_dist 3000
29 /* stegerg */
30 #define CHECKMAPRANGE 1
31 #define PIXELWIDTH 2
32 #define MAXVIEWLENGTH SCREENWIDTH
33 #define RESIZEABLE 1
35 /*************************************************************/
37 struct IntuitionBase *IntuitionBase;
38 struct GfxBase *GfxBase;
39 struct Library *CyberGfxBase;
40 struct Screen *scr;
41 struct Window *win;
42 struct RastPort *rp;
44 ULONG cgfx_coltab[256];
46 int screenwidth = SCREENWIDTH;
47 int screenheight = SCREENHEIGHT - 1;
48 int resizescale = 1 << 16;
50 /**************************VARS*******************************/
51 float sintab[360],costab[360];
52 char *buffer, /* Offscreen Buffer */
53 *map; /* Height Map */
54 unsigned char *color, /* Color Map */
55 *clouds; /* Cloud Bitmap */
56 char ende;
57 char scancode;
58 char Keys[128];
59 #if 0
60 void (__interrupt __far *old09h)();
61 void __interrupt __far new09h();
62 #endif
63 int hoehe,richt,xc,yc,direction,voxel_stretch=50;
64 int horizon,maxy,
65 view_length,view_size,flyheight = 100,
66 y_old,offtab[SCREENHEIGHT],
67 xtab[SCREENWIDTH][MAXVIEWLENGTH],voxtab[SCREENWIDTH];
69 /************************************************************/
72 /**************************PCX-STRUCTS***********************/
73 typedef struct{
74 short x,y;} Tpcxsize;
77 typedef struct{
78 unsigned char id,version,encoding,bpp;
79 short x1,y1,x2,y2,hres,vres;
80 unsigned char colors[48];
81 unsigned char vmode,planes;
82 short bpl,palinfo;
83 unsigned char fillbytes[58];
84 } PCXHeader;
86 /************************************************************/
89 /*****************BUILD TABLES*******************************/
91 void intvars()
93 horizon=150,
94 maxy=(screenheight-1),
95 view_length=(screenwidth/5),
96 view_size=(screenwidth/PIXELWIDTH)-1;
98 resizescale = (screenheight << 16) / SCREENHEIGHT;
102 void make_trig()
104 float i;
105 for(i=0;i<=359;i++)sintab[(int)i]=sin(i/(180)*PI);
106 for(i=0;i<=359;i++)costab[(int)i]=cos(i/(180)*PI);
110 void gentab()
112 int i, j;
114 for(j=1;j<=view_length;j++)voxtab[j]=horizon+voxel_dist/j;
115 for(j=0;j<screenheight;j++)offtab[j]=j*SCREENWIDTH;
116 for(i=0;i<=view_size;i++)
117 for(j=1;j<=view_length;j++)
118 xtab[i][j]=i*j /view_size-(j>>1);
119 make_trig();
123 float sinus(int a)
125 a+=360;
126 a=a%360;
127 return sintab[(int)a];
130 float cosinus(int a)
132 a+=360;
133 a=a%360;
134 return costab[(int)a];
138 /************************PCX LOADER**************************/
140 Tpcxsize getpcxsize(char *d)
142 Tpcxsize k;
143 PCXHeader pc;
144 FILE *f=fopen(d,"rb");
145 memset(&pc,0,sizeof(pc));
146 fread(&pc,sizeof(pc),1,f);
147 fclose(f);
148 k.x=pc.x2+1;
149 k.y=pc.y2+1;
150 return k;
153 long filesize(FILE *n)
155 long org=ftell(n), size;
156 fseek(n,-0L,SEEK_END);
157 size=ftell(n);
158 fseek(n,org,SEEK_SET);
159 return size;
162 void loadpcx(char *name,char *po)
164 FILE *f;
165 int g,m,i,z;
166 unsigned char *cimage;
167 unsigned char header[128];
169 Tpcxsize sz=getpcxsize(name);
170 f=fopen(name,"rb");
171 cimage=(char *)malloc(filesize(f));
172 fread(&header,128,1,f);
174 fread(&*cimage,filesize(f)-896,1,f);
175 fclose(f);
176 z=0;
177 g=0;
179 if(cimage[z]<192) po[g]=cimage[z];
180 if(cimage[z]>=192){m=cimage[z]-192;
181 z++;
182 for(i=1;i<=m;i++) po[g+i-1]=cimage[z];
183 g=g+m-1;}
184 z++;
185 g++;
186 }while(g<sz.x*sz.y);
187 free(cimage);
192 void loadpcxpal(char *name,unsigned char pal[768])
194 FILE *f;
195 int i;
197 f=fopen(name,"rb");
198 fseek(f,filesize(f)-768,SEEK_SET);
199 fread(pal,768,1,f);
200 for(i=0;i<768;i++) pal[i]/=4;
203 /***********************************************************/
206 void setpal(unsigned char palp[])
208 unsigned int pcount;
209 for(pcount=0;pcount<256;pcount++){
210 cgfx_coltab[pcount] = (palp[pcount * 3] << 18) +
211 (palp[pcount * 3 + 1] << 10) +
212 (palp[pcount * 3 + 2] << 2);
217 void adjust(char *b)
219 int x,y,f;
220 for(y=0;y<MAPHEIGHT;y++)
221 for(x=0;x<MAPWIDTH;x++){
222 f=b[(x-1)+y*MAPWIDTH]+\
223 b[(x-2)+y*MAPWIDTH]+\
224 b[(x+1)+y*MAPWIDTH]+\
225 b[(x+2)+y*MAPWIDTH]+\
226 b[x+(y-1)*MAPWIDTH]+\
227 b[x+(y-2)*MAPWIDTH]+\
228 b[x+(y+1)*MAPWIDTH]+\
229 b[x+(y+2)*MAPWIDTH];
230 if(f!=0)b[x+y*MAPWIDTH]=f>>3;}
235 /*****************MAIN VOXEL PROCS**************************/
237 # if 1
239 static inline void innerloop(int x, int start,int col)
241 UBYTE *dest = buffer + x + start * SCREENWIDTH;
242 int count = y_old + 1 - start;
244 #if PIXELWIDTH==4
245 #define PIXELTYPE int
246 col += (col << 24) + (col << 16) + (col << 8);
247 #elif PIXELWIDTH==2
248 #define PIXELTYPE short
249 col += (col << 8);
250 #elif PIXELWIDTH==1
251 #define PIXELTYPE char
252 #else
253 #error "PIXELWIDTH must be 1,2 or 4"
254 #endif
256 while(--count)
258 *(PIXELTYPE *)dest = col;
259 dest += SCREENWIDTH;
263 #else
265 void innerloop(int x,int start,int col); /* draws 4pix vline */
266 #pragma aux innerloop= \
267 "mov edi,[buffer]"\
268 "add edi,ebx "\
269 "mov ecx,[y_old] "\
270 "inc ecx "\
271 "sub ecx,edx "\
272 "imul edx,640 "\
273 "add edi,edx "\
274 "mov ah,al "\
275 "push ax "\
276 "shl eax,16 "\
277 "pop ax "\
278 "l1: "\
279 "mov [edi],eax "\
280 "add edi,640 "\
281 "loop l1 "\
282 modify [edi ecx] \
283 parm[ebx][edx][eax];
285 #endif
287 void draw_voxel(int x,int e,int f,int c)
289 int y,h;
290 f-=hoehe;
291 h=f*voxel_stretch /e;
292 #if RESIZEABLE
293 y=((voxtab[e]-h) * resizescale) >> 16;
294 #else
295 y=voxtab[e]-h;
296 #endif
297 if(y>0&&y<y_old){
298 innerloop(x,y,c);
299 y_old=y;
304 void voxel_spacing(int xp,int yp,int r)
306 int i,j=0,offset,x,co,si,nx,ny;
307 int f,c;
309 r-=90;
310 co=cosinus(r)*1024;
311 si=sinus(r)*1024;
313 hoehe=map[xp+yp*MAPWIDTH]+flyheight;
315 for(i=0;i<=view_size;i++){
316 y_old=screenheight-1;
317 for(j=1;j<=view_length;j++){
318 x=xtab[i][j];
319 nx=(x*co >> 10)-(j*si >> 10);
320 ny=(x*si >> 10)+(j*co >> 10);
321 #if CHECKMAPRANGE
322 offset=((nx+xp) & (MAPWIDTH - 1)) + (((ny+yp) & (MAPHEIGHT - 1))<<MAPSHIFT);
323 #else
324 offset=(nx+xp)+((ny+yp)<<MAPSHIFT);
325 #endif
326 f=map[offset];
327 c=color[offset];
328 draw_voxel(i*PIXELWIDTH,j,f,c);
333 /***********************************************************/
335 #define KC_LEFT 0x4F
336 #define KC_RIGHT 0x4E
337 #define KC_UP 0x4C
338 #define KC_DOWN 0x4D
339 #define KC_NUMPAD8 0x3E
340 #define KC_NUMPAD2 0x1E
341 #define KC_NUMPADPLUS 0x5E
342 #define KC_NUMPADMINUS 0x4A
343 #define KC_NUMPADMINUS2 0x5D
344 #define KC_ESC 0x45
345 #define KC_RETURN 0x44
347 void control()
349 if(Keys[KC_DOWN]){
350 xc-=cosinus(richt)*4;
351 yc-=sinus(richt)*4;
353 if(Keys[KC_UP]){
354 xc+=cosinus(richt)*4;
355 yc+=sinus(richt)*4;
357 if(Keys[KC_RIGHT]){richt-=4;direction-=4;if(richt<0)richt+=360;if(direction<0) direction+=SCREENWIDTH;}
358 if(Keys[KC_LEFT]){richt+=4;direction+=4;if(richt>=360)richt-=360;if(direction>=SCREENWIDTH)direction-=SCREENWIDTH;}
359 if(Keys[KC_NUMPAD2])flyheight--;
360 if(Keys[KC_NUMPAD8])flyheight++;
361 if(Keys[KC_RETURN])adjust(map);
362 if(Keys[KC_NUMPADMINUS] || Keys[KC_NUMPADMINUS2])voxel_stretch++;
363 if(Keys[KC_NUMPADPLUS])voxel_stretch--;
364 if(Keys[KC_ESC]) ende=1;
367 /***********************************************************/
369 void cleanup(char *msg)
371 if (msg)
373 printf("voxel: %s\n",msg);
376 if (win) CloseWindow(win);
378 if (scr) UnlockPubScreen(0, scr);
380 if (CyberGfxBase) CloseLibrary(CyberGfxBase);
381 if (GfxBase) CloseLibrary((struct Library *)GfxBase);
382 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
384 exit(0);
387 void openlibs(void)
389 if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39)))
391 cleanup("Can't open intuition.library V39!");
394 if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 39)))
396 cleanup("Can't open graphics.library V39!");
399 if (!(CyberGfxBase = OpenLibrary("cybergraphics.library",0)))
401 cleanup("Can't open cybergraphics.library!");
405 void getvisual(void)
407 if (!(scr = LockPubScreen(NULL)))
409 cleanup("Can't lock pub screen!");
412 if (GetBitMapAttr(scr->RastPort.BitMap, BMA_DEPTH) <= 8)
414 cleanup("Need hi or true color screen!");
418 void makewin(void)
420 win = OpenWindowTags(NULL, WA_CustomScreen, (IPTR)scr,
421 WA_InnerWidth, SCREENWIDTH,
422 WA_InnerHeight, SCREENHEIGHT - 1,
423 WA_Title, (IPTR)"Voxel",
424 WA_DragBar, TRUE,
425 WA_DepthGadget, TRUE,
426 WA_CloseGadget, TRUE,
427 RESIZEABLE ?
428 WA_SizeGadget :
429 TAG_IGNORE , TRUE,
430 RESIZEABLE ?
431 WA_SizeBBottom:
432 TAG_IGNORE , TRUE,
433 WA_Activate, TRUE,
434 WA_IDCMP, IDCMP_CLOSEWINDOW |
435 (RESIZEABLE * IDCMP_NEWSIZE) |
436 IDCMP_RAWKEY,
437 TAG_DONE);
439 if (!win) cleanup("Can't open window");
441 #if RESIZEABLE
442 WindowLimits(win, 320 + win->BorderLeft + win->BorderRight,
443 200 + win->BorderTop + win->BorderBottom,
444 SCREENWIDTH + win->BorderLeft + win->BorderRight,
445 SCREENHEIGHT - 1 + win->BorderTop + win->BorderBottom);
447 #endif
449 rp = win->RPort;
452 void getevents(void)
454 struct IntuiMessage *msg;
456 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
458 switch(msg->Class)
460 case IDCMP_CLOSEWINDOW:
461 ende = TRUE;
462 break;
464 case IDCMP_RAWKEY:
466 WORD code = msg->Code & ~IECODE_UP_PREFIX;
468 Keys[code] = (code == msg->Code) ? 1 : 0;
471 break;
473 #if RESIZEABLE
475 case IDCMP_NEWSIZE:
477 screenwidth = win->Width - win->BorderLeft - win->BorderRight;
478 screenheight = win->Height - win->BorderTop - win->BorderBottom;
479 intvars();
480 gentab();
482 break;
483 #endif
485 ReplyMsg((struct Message *)msg);
488 /********************MAIN PROC******************************/
490 int main(int argc, char **argv)
492 int frame=0, u;
493 unsigned char pal[768];
495 openlibs();
496 getvisual();
498 intvars();
499 gentab();
500 buffer=(char*)malloc(SCREENWIDTH*(SCREENHEIGHT + 1));
501 map=(char*)malloc(MAPWIDTH*MAPHEIGHT);
502 color=(char*)malloc(MAPWIDTH*MAPHEIGHT);
503 clouds=(char*)malloc(CLOUDWIDTH*CLOUDHEIGHT);
504 if(color==0||buffer==0||map==0||clouds==0){
505 printf("no mem... -sorry!\n");exit(0);
507 loadpcx("demoh.pcx",map);
508 loadpcx("democ.pcx",color);
509 loadpcx("clouds.pcx",clouds);
510 loadpcxpal("democ.pcx",pal);
511 for(u=0;u<7;u++)adjust(map);
512 setpal(pal);
513 xc=160,yc=100,direction=0;
515 makewin();
518 getevents();
519 control();
520 memcpy(buffer,clouds + CLOUDWIDTH - direction,SCREENWIDTH*screenheight);
521 voxel_spacing(xc,yc,richt);
523 WriteLUTPixelArray(buffer,
526 SCREENWIDTH,
528 cgfx_coltab,
529 win->BorderLeft,
530 win->BorderTop,
531 screenwidth,
532 screenheight,
533 CTABFMT_XRGB8);
534 WaitTOF();
535 frame++;
536 }while(!ende);
538 cleanup(0);
540 return 0;