simplify and eliminate redundant swap macros. maschaffner@gmx.ch and btb
[btb/d2x.git] / 3d / interp.c
1 /* $Id: interp.c,v 1.8 2002-10-28 20:57:11 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Polygon object interpreter
18  *
19  * Old Log:
20  * Revision 1.4  1995/10/10  22:20:09  allender
21  * new morphing code from Matt
22  *
23  * Revision 1.3  1995/08/31  15:40:24  allender
24  * swap color data correctly
25  *
26  * Revision 1.2  1995/05/11  13:06:38  allender
27  * fix int --> short problem
28  *
29  * Revision 1.1  1995/05/05  08:51:41  allender
30  * Initial revision
31  *
32  * Revision 1.1  1995/04/17  06:44:33  matt
33  * Initial revision
34  *
35  *
36  */
37
38 #ifdef HAVE_CONFIG_H
39 #include <conf.h>
40 #endif
41
42 #ifdef RCS
43 static char rcsid[] = "$Id: interp.c,v 1.8 2002-10-28 20:57:11 btb Exp $";
44 #endif
45
46 #include <stdlib.h>
47 #include "error.h"
48
49 #include "3d.h"
50 #include "globvars.h"
51 #include "gr.h"
52 #include "byteswap.h"
53
54 #define OP_EOF          0   //eof
55 #define OP_DEFPOINTS    1   //defpoints
56 #define OP_FLATPOLY     2   //flat-shaded polygon
57 #define OP_TMAPPOLY     3   //texture-mapped polygon
58 #define OP_SORTNORM     4   //sort by normal
59 #define OP_RODBM        5   //rod bitmap
60 #define OP_SUBCALL      6   //call a subobject
61 #define OP_DEFP_START   7   //defpoints with start
62 #define OP_GLOW         8   //glow value for next poly
63
64 #define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table))
65
66 #define MAX_POINTS_PER_POLY 25
67
68 short highest_texture_num;
69 int g3d_interp_outline;
70
71 g3s_point *Interp_point_list = NULL;
72
73 #define MAX_INTERP_COLORS 100
74
75 //this is a table of mappings from RGB15 to palette colors
76 struct {short pal_entry,rgb15;} interp_color_table[MAX_INTERP_COLORS];
77
78 int n_interp_colors=0;
79
80 //gives the interpreter an array of points to use
81 void g3_set_interp_points(g3s_point *pointlist)
82 {
83         Interp_point_list = pointlist;
84 }
85
86 #define w(p)  (*((short *) (p)))
87 #define wp(p)  ((short *) (p))
88 #define vp(p)  ((vms_vector *) (p))
89
90 void rotate_point_list(g3s_point *dest,vms_vector *src,int n)
91 {
92         while (n--)
93                 g3_rotate_point(dest++,src++);
94 }
95
96 vms_angvec zero_angles = {0,0,0};
97
98 g3s_point *point_list[MAX_POINTS_PER_POLY];
99
100 int glow_num = -1;
101
102 #ifdef WORDS_BIGENDIAN
103 void short_swap(short *s)
104 {
105         *s = SWAPSHORT(*s);
106 }
107
108 void vms_vector_swap(vms_vector *v)
109 {
110         v->x = (fix)SWAPINT((int)v->x);
111         v->y = (fix)SWAPINT((int)v->y);
112         v->z = (fix)SWAPINT((int)v->z);
113 }
114
115 void swap_polygon_model_data(ubyte *data)
116 {
117         int i;
118         short n;
119         g3s_uvl *uvl_val;
120         ubyte *p = data;
121
122         short_swap(wp(p));
123
124         while (w(p) != OP_EOF) {
125                 switch (w(p)) {
126                         case OP_DEFPOINTS:
127                                 short_swap(wp(p + 2));
128                                 n = w(p+2);
129                                 for (i = 0; i < n; i++)
130                                         vms_vector_swap(vp((p + 4) + (i * sizeof(vms_vector))));
131                                 p += n*sizeof(struct vms_vector) + 4;
132                                 break;
133
134                         case OP_DEFP_START:
135                                 short_swap(wp(p + 2));
136                                 short_swap(wp(p + 4));
137                                 n = w(p+2);
138                                 for (i = 0; i < n; i++)
139                                         vms_vector_swap(vp((p + 8) + (i * sizeof(vms_vector))));
140                                 p += n*sizeof(struct vms_vector) + 8;
141                                 break;
142
143                         case OP_FLATPOLY:
144                                 short_swap(wp(p+2));
145                                 n = w(p+2);
146                                 vms_vector_swap(vp(p + 4));
147                                 vms_vector_swap(vp(p + 16));
148                                 short_swap(wp(p+28));
149 #ifdef MACINTOSH
150                                 // swap the colors 0 and 255 here!!!!
151                                 if (w(p+28) == 0)
152                                         w(p+28) = 255;
153                                 else if (w(p+28) == 255)
154                                         w(p+28) = 0;
155 #endif
156                                 for (i=0; i < n; i++)
157                                         short_swap(wp(p + 30 + (i * 2)));
158                                 p += 30 + ((n&~1)+1)*2;
159                                 break;
160
161                         case OP_TMAPPOLY:
162                                 short_swap(wp(p+2));
163                                 n = w(p+2);
164                                 vms_vector_swap(vp(p + 4));
165                                 vms_vector_swap(vp(p + 16));
166                                 for (i=0;i<n;i++) {
167                                         uvl_val = (g3s_uvl *)((p+30+((n&~1)+1)*2) + (i * sizeof(g3s_uvl)));
168                                         uvl_val->u = (fix)SWAPINT((int)uvl_val->u);
169                                         uvl_val->v = (fix)SWAPINT((int)uvl_val->v);
170                                 }
171                                 short_swap(wp(p+28));
172                                 for (i=0;i<n;i++)
173                                         short_swap(wp(p + 30 + (i * 2)));
174                                 p += 30 + ((n&~1)+1)*2 + n*12;
175                                 break;
176
177                         case OP_SORTNORM:
178                                 vms_vector_swap(vp(p + 4));
179                                 vms_vector_swap(vp(p + 16));
180                                 short_swap(wp(p + 28));
181                                 short_swap(wp(p + 30));
182                                 swap_polygon_model_data(p + w(p+28));
183                                 swap_polygon_model_data(p + w(p+30));
184                                 p += 32;
185                                 break;
186
187                         case OP_RODBM:
188                                 vms_vector_swap(vp(p + 20));
189                                 vms_vector_swap(vp(p + 4));
190                                 short_swap(wp(p+2));
191                                 *((int *)(p + 16)) = SWAPINT(*((int *)(p + 16)));
192                                 *((int *)(p + 32)) = SWAPINT(*((int *)(p + 32)));
193                                 p+=36;
194                                 break;
195
196                         case OP_SUBCALL:
197                                 short_swap(wp(p+2));
198                                 vms_vector_swap(vp(p+4));
199                                 short_swap(wp(p+16));
200                                 swap_polygon_model_data(p + w(p+16));
201                                 p += 20;
202                                 break;
203
204                         case OP_GLOW:
205                                 short_swap(wp(p + 2));
206                                 p += 4;
207                                 break;
208
209                         default:
210                                 Int3();
211                 }
212                 short_swap(wp(p));
213         }
214 }
215 #endif
216
217 //calls the object interpreter to render an object.  The object renderer
218 //is really a seperate pipeline. returns true if drew
219 bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values)
220 {
221         ubyte *p = model_ptr;
222
223         glow_num = -1;          //glow off by default
224
225         while (w(p) != OP_EOF)
226
227                 switch (w(p)) {
228
229                         case OP_DEFPOINTS: {
230                                 int n = w(p+2);
231
232                                 rotate_point_list(Interp_point_list,vp(p+4),n);
233                                 p += n*sizeof(struct vms_vector) + 4;
234
235                                 break;
236                         }
237
238                         case OP_DEFP_START: {
239                                 int n = w(p+2);
240                                 int s = w(p+4);
241
242                                 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
243                                 p += n*sizeof(struct vms_vector) + 8;
244
245                                 break;
246                         }
247
248                         case OP_FLATPOLY: {
249                                 int nv = w(p+2);
250
251                                 Assert( nv < MAX_POINTS_PER_POLY );
252                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
253                                         int i;
254                                         short c;
255                                         unsigned char cc;
256                                         int l;
257
258 //                                      DPH: Now we treat this color as 15bpp
259 //                                      gr_setcolor(w(p+28));
260                                         
261                                         //l = (32 * model_light) >> 16;
262                                         l = f2i(fixmul(i2f(32), model_light));
263                                         if (l<0) l = 0;
264                                         else if (l>32) l = 32;
265                                         cc = gr_find_closest_color_15bpp(w(p+28));
266                                         c = gr_fade_table[(l<<8)|cc];
267                                         gr_setcolor(c);
268
269                                         for (i=0;i<nv;i++)
270                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
271
272                                         g3_draw_poly(nv,point_list);
273                                 }
274
275                                 p += 30 + ((nv&~1)+1)*2;
276                                         
277                                 break;
278                         }
279
280                         case OP_TMAPPOLY: {
281                                 int nv = w(p+2);
282                                 g3s_uvl *uvl_list;
283
284                                 Assert( nv < MAX_POINTS_PER_POLY );
285                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
286                                         int i;
287                                         fix light;
288
289                                         //calculate light from surface normal
290
291                                         if (glow_num < 0) {                     //no glow
292
293                                                 light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
294                                                 light = f1_0/4 + (light*3)/4;
295                                                 light = fixmul(light,model_light);
296                                         }
297                                         else {                          //yes glow
298                                                 light = glow_values[glow_num];
299                                                 glow_num = -1;
300                                         }
301
302                                         //now poke light into l values
303
304                                         uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
305
306                                         for (i=0;i<nv;i++)
307                                                 uvl_list[i].l = light;
308
309                                         for (i=0;i<nv;i++)
310                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
311
312                                         g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
313                                 }
314
315                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
316                                         
317                                 break;
318                         }
319
320                         case OP_SORTNORM:
321
322                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
323
324                                         //draw back then front
325
326                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
327                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
328
329                                 }
330                                 else {                  //not facing.  draw front then back
331
332                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
333                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
334                                 }
335
336                                 p += 32;
337
338                                 break;
339
340
341                         case OP_RODBM: {
342                                 g3s_point rod_bot_p,rod_top_p;
343
344                                 g3_rotate_point(&rod_bot_p,vp(p+20));
345                                 g3_rotate_point(&rod_top_p,vp(p+4));
346
347                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
348
349                                 p+=36;
350                                 break;
351                         }
352
353                         case OP_SUBCALL: {
354                                 vms_angvec *a;
355
356                                 if (anim_angles)
357                                         a = &anim_angles[w(p+2)];
358                                 else
359                                         a = &zero_angles;
360
361                                 g3_start_instance_angles(vp(p+4),a);
362
363                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
364
365                                 g3_done_instance();
366
367                                 p += 20;
368
369                                 break;
370
371                         }
372
373                         case OP_GLOW:
374
375                                 if (glow_values)
376                                         glow_num = w(p+2);
377                                 p += 4;
378                                 break;
379
380                         default:
381                         ;
382                 }
383         return 1;
384 }
385
386 extern int gr_find_closest_color_15bpp( int rgb );
387
388 #ifndef NDEBUG
389 int nest_count;
390 #endif
391
392 //alternate interpreter for morphing object
393 bool g3_draw_morphing_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,vms_vector *new_points)
394 {
395         ubyte *p = model_ptr;
396         fix *glow_values = NULL;
397
398         glow_num = -1;          //glow off by default
399
400         while (w(p) != OP_EOF)
401
402                 switch (w(p)) {
403
404                         case OP_DEFPOINTS: {
405                                 int n = w(p+2);
406
407                                 rotate_point_list(Interp_point_list,new_points,n);
408                                 p += n*sizeof(struct vms_vector) + 4;
409
410                                 break;
411                         }
412
413                         case OP_DEFP_START: {
414                                 int n = w(p+2);
415                                 int s = w(p+4);
416
417                                 rotate_point_list(&Interp_point_list[s],new_points,n);
418                                 p += n*sizeof(struct vms_vector) + 8;
419
420                                 break;
421                         }
422
423                         case OP_FLATPOLY: {
424                                 int nv = w(p+2);
425                                 int i,ntris;
426
427                                 gr_setcolor(w(p+28));
428                                 
429                                 for (i=0;i<2;i++)
430                                         point_list[i] = Interp_point_list + wp(p+30)[i];
431
432                                 for (ntris=nv-2;ntris;ntris--) {
433
434                                         point_list[2] = Interp_point_list + wp(p+30)[i++];
435
436                                         g3_check_and_draw_poly(3,point_list,NULL,NULL);
437
438                                         point_list[1] = point_list[2];
439
440                                 }
441
442                                 p += 30 + ((nv&~1)+1)*2;
443                                         
444                                 break;
445                         }
446
447                         case OP_TMAPPOLY: {
448                                 int nv = w(p+2);
449                                 g3s_uvl *uvl_list;
450                                 g3s_uvl morph_uvls[3];
451                                 int i,ntris;
452                                 fix light;
453
454                                 //calculate light from surface normal
455
456                                 if (glow_num < 0) {                     //no glow
457
458                                         light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
459                                         light = f1_0/4 + (light*3)/4;
460                                         light = fixmul(light,model_light);
461                                 }
462                                 else {                          //yes glow
463                                         light = glow_values[glow_num];
464                                         glow_num = -1;
465                                 }
466
467                                 //now poke light into l values
468
469                                 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
470
471                                 for (i=0;i<3;i++)
472                                         morph_uvls[i].l = light;
473
474                                 for (i=0;i<2;i++) {
475                                         point_list[i] = Interp_point_list + wp(p+30)[i];
476
477                                         morph_uvls[i].u = uvl_list[i].u;
478                                         morph_uvls[i].v = uvl_list[i].v;
479                                 }
480
481                                 for (ntris=nv-2;ntris;ntris--) {
482
483                                         point_list[2] = Interp_point_list + wp(p+30)[i];
484                                         morph_uvls[2].u = uvl_list[i].u;
485                                         morph_uvls[2].v = uvl_list[i].v;
486                                         i++;
487
488                                         g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
489
490                                         point_list[1] = point_list[2];
491                                         morph_uvls[1].u = morph_uvls[2].u;
492                                         morph_uvls[1].v = morph_uvls[2].v;
493
494                                 }
495
496                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
497
498                                 break;
499                         }
500
501                         case OP_SORTNORM:
502
503                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
504
505                                         //draw back then front
506
507                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
508                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
509
510                                 }
511                                 else {                  //not facing.  draw front then back
512
513                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
514                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
515                                 }
516
517                                 p += 32;
518
519                                 break;
520
521
522                         case OP_RODBM: {
523                                 g3s_point rod_bot_p,rod_top_p;
524
525                                 g3_rotate_point(&rod_bot_p,vp(p+20));
526                                 g3_rotate_point(&rod_top_p,vp(p+4));
527
528                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
529
530                                 p+=36;
531                                 break;
532                         }
533
534                         case OP_SUBCALL: {
535                                 vms_angvec *a;
536
537                                 if (anim_angles)
538                                         a = &anim_angles[w(p+2)];
539                                 else
540                                         a = &zero_angles;
541
542                                 g3_start_instance_angles(vp(p+4),a);
543
544                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
545
546                                 g3_done_instance();
547
548                                 p += 20;
549
550                                 break;
551
552                         }
553
554                         case OP_GLOW:
555
556                                 if (glow_values)
557                                         glow_num = w(p+2);
558                                 p += 4;
559                                 break;
560                 }
561
562         return 1;
563 }
564
565 void init_model_sub(ubyte *p)
566 {
567         Assert(++nest_count < 1000);
568
569         while (w(p) != OP_EOF) {
570
571                 switch (w(p)) {
572
573                         case OP_DEFPOINTS: {
574                                 int n = w(p+2);
575                                 p += n*sizeof(struct vms_vector) + 4;
576                                 break;
577                         }
578
579                         case OP_DEFP_START: {
580                                 int n = w(p+2);
581                                 p += n*sizeof(struct vms_vector) + 8;
582                                 break;
583                         }
584
585                         case OP_FLATPOLY: {
586                                 int nv = w(p+2);
587
588                                 Assert(nv > 2);         //must have 3 or more points
589
590 //                              *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
591
592                                 p += 30 + ((nv&~1)+1)*2;
593                                         
594                                 break;
595                         }
596
597                         case OP_TMAPPOLY: {
598                                 int nv = w(p+2);
599
600                                 Assert(nv > 2);         //must have 3 or more points
601
602                                 if (w(p+28) > highest_texture_num)
603                                         highest_texture_num = w(p+28);
604
605                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
606                                         
607                                 break;
608                         }
609
610                         case OP_SORTNORM:
611
612                                 init_model_sub(p+w(p+28));
613                                 init_model_sub(p+w(p+30));
614                                 p += 32;
615
616                                 break;
617
618
619                         case OP_RODBM:
620                                 p += 36;
621                                 break;
622
623
624                         case OP_SUBCALL: {
625                                 init_model_sub(p+w(p+16));
626                                 p += 20;
627                                 break;
628
629                         }
630
631                         case OP_GLOW:
632                                 p += 4;
633                                 break;
634                         default:
635                                 Assert(0);
636                 }
637         }
638 }
639
640 //init code for bitmap models
641 void g3_init_polygon_model(void *model_ptr)
642 {
643         #ifndef NDEBUG
644         nest_count = 0;
645         #endif
646
647         highest_texture_num = -1;
648
649         init_model_sub((ubyte *) model_ptr);
650 }
651