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