use simpler rcs tags
[btb/d2x.git] / 3d / interp.c
1 /* $Id: interp.c,v 1.5 2002-07-17 21:55:19 bradleyb 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  * Polygon object interpreter
17  * 
18  * Old Log:
19  *
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.5 2002-07-17 21:55:19 bradleyb 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
53 #define OP_EOF                          0       //eof
54 #define OP_DEFPOINTS            1       //defpoints
55 #define OP_FLATPOLY             2       //flat-shaded polygon
56 #define OP_TMAPPOLY             3       //texture-mapped polygon
57 #define OP_SORTNORM             4       //sort by normal
58 #define OP_RODBM                        5       //rod bitmap
59 #define OP_SUBCALL              6       //call a subobject
60 #define OP_DEFP_START   7       //defpoints with start
61 #define OP_GLOW                 8       //glow value for next poly
62
63 #define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table))
64
65 #define MAX_POINTS_PER_POLY             25
66
67 short   highest_texture_num;
68 int     g3d_interp_outline;
69
70 g3s_point *Interp_point_list=NULL;
71
72 #define MAX_INTERP_COLORS 100
73
74 //this is a table of mappings from RGB15 to palette colors
75 struct {short pal_entry,rgb15;} interp_color_table[MAX_INTERP_COLORS];
76
77 int n_interp_colors=0;
78
79 //gives the interpreter an array of points to use
80 void g3_set_interp_points(g3s_point *pointlist)
81 {
82         Interp_point_list = pointlist;
83 }
84
85 #define w(p)  (*((short *) (p)))
86 #define wp(p)  ((short *) (p))
87 #define vp(p)  ((vms_vector *) (p))
88
89 void rotate_point_list(g3s_point *dest,vms_vector *src,int n)
90 {
91         while (n--)
92                 g3_rotate_point(dest++,src++);
93 }
94
95 vms_angvec zero_angles = {0,0,0};
96
97 g3s_point *point_list[MAX_POINTS_PER_POLY];
98
99 int glow_num = -1;
100
101 //calls the object interpreter to render an object.  The object renderer
102 //is really a seperate pipeline. returns true if drew
103 bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values)
104 {
105         ubyte *p = model_ptr;
106
107         glow_num = -1;          //glow off by default
108
109         while (w(p) != OP_EOF)
110
111                 switch (w(p)) {
112
113                         case OP_DEFPOINTS: {
114                                 int n = w(p+2);
115
116                                 rotate_point_list(Interp_point_list,vp(p+4),n);
117                                 p += n*sizeof(struct vms_vector) + 4;
118
119                                 break;
120                         }
121
122                         case OP_DEFP_START: {
123                                 int n = w(p+2);
124                                 int s = w(p+4);
125
126                                 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
127                                 p += n*sizeof(struct vms_vector) + 8;
128
129                                 break;
130                         }
131
132                         case OP_FLATPOLY: {
133                                 int nv = w(p+2);
134
135                                 Assert( nv < MAX_POINTS_PER_POLY );
136                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
137                                         int i;
138                                         short c;
139                                         unsigned char cc;
140                                         int l;
141
142 //                                      DPH: Now we treat this color as 15bpp
143 //                                      gr_setcolor(w(p+28));
144                                         
145                                         //l = (32 * model_light) >> 16;
146                                         l = f2i(fixmul(i2f(32), model_light));
147                                         if (l<0) l = 0;
148                                         else if (l>32) l = 32;
149                                         cc = gr_find_closest_color_15bpp(w(p+28));
150                                         c = gr_fade_table[(l<<8)|cc];
151                                         gr_setcolor(c);
152
153                                         for (i=0;i<nv;i++)
154                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
155
156                                         g3_draw_poly(nv,point_list);
157                                 }
158
159                                 p += 30 + ((nv&~1)+1)*2;
160                                         
161                                 break;
162                         }
163
164                         case OP_TMAPPOLY: {
165                                 int nv = w(p+2);
166                                 g3s_uvl *uvl_list;
167
168                                 Assert( nv < MAX_POINTS_PER_POLY );
169                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
170                                         int i;
171                                         fix light;
172
173                                         //calculate light from surface normal
174
175                                         if (glow_num < 0) {                     //no glow
176
177                                                 light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
178                                                 light = f1_0/4 + (light*3)/4;
179                                                 light = fixmul(light,model_light);
180                                         }
181                                         else {                          //yes glow
182                                                 light = glow_values[glow_num];
183                                                 glow_num = -1;
184                                         }
185
186                                         //now poke light into l values
187
188                                         uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
189
190                                         for (i=0;i<nv;i++)
191                                                 uvl_list[i].l = light;
192
193                                         for (i=0;i<nv;i++)
194                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
195
196                                         g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
197                                 }
198
199                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
200                                         
201                                 break;
202                         }
203
204                         case OP_SORTNORM:
205
206                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
207
208                                         //draw back then front
209
210                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
211                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
212
213                                 }
214                                 else {                  //not facing.  draw front then back
215
216                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
217                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
218                                 }
219
220                                 p += 32;
221
222                                 break;
223
224
225                         case OP_RODBM: {
226                                 g3s_point rod_bot_p,rod_top_p;
227
228                                 g3_rotate_point(&rod_bot_p,vp(p+20));
229                                 g3_rotate_point(&rod_top_p,vp(p+4));
230
231                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
232
233                                 p+=36;
234                                 break;
235                         }
236
237                         case OP_SUBCALL: {
238                                 vms_angvec *a;
239
240                                 if (anim_angles)
241                                         a = &anim_angles[w(p+2)];
242                                 else
243                                         a = &zero_angles;
244
245                                 g3_start_instance_angles(vp(p+4),a);
246
247                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
248
249                                 g3_done_instance();
250
251                                 p += 20;
252
253                                 break;
254
255                         }
256
257                         case OP_GLOW:
258
259                                 if (glow_values)
260                                         glow_num = w(p+2);
261                                 p += 4;
262                                 break;
263
264                         default:
265                         ;
266                 }
267         return 1;
268 }
269
270 extern int gr_find_closest_color_15bpp( int rgb );
271
272 #ifndef NDEBUG
273 int nest_count;
274 #endif
275
276 //alternate interpreter for morphing object
277 bool g3_draw_morphing_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,vms_vector *new_points)
278 {
279         ubyte *p = model_ptr;
280         fix *glow_values = NULL;
281
282         glow_num = -1;          //glow off by default
283
284         while (w(p) != OP_EOF)
285
286                 switch (w(p)) {
287
288                         case OP_DEFPOINTS: {
289                                 int n = w(p+2);
290
291                                 rotate_point_list(Interp_point_list,new_points,n);
292                                 p += n*sizeof(struct vms_vector) + 4;
293
294                                 break;
295                         }
296
297                         case OP_DEFP_START: {
298                                 int n = w(p+2);
299                                 int s = w(p+4);
300
301                                 rotate_point_list(&Interp_point_list[s],new_points,n);
302                                 p += n*sizeof(struct vms_vector) + 8;
303
304                                 break;
305                         }
306
307                         case OP_FLATPOLY: {
308                                 int nv = w(p+2);
309                                 int i,ntris;
310
311                                 gr_setcolor(w(p+28));
312                                 
313                                 for (i=0;i<2;i++)
314                                         point_list[i] = Interp_point_list + wp(p+30)[i];
315
316                                 for (ntris=nv-2;ntris;ntris--) {
317
318                                         point_list[2] = Interp_point_list + wp(p+30)[i++];
319
320                                         g3_check_and_draw_poly(3,point_list,NULL,NULL);
321
322                                         point_list[1] = point_list[2];
323
324                                 }
325
326                                 p += 30 + ((nv&~1)+1)*2;
327                                         
328                                 break;
329                         }
330
331                         case OP_TMAPPOLY: {
332                                 int nv = w(p+2);
333                                 g3s_uvl *uvl_list;
334                                 g3s_uvl morph_uvls[3];
335                                 int i,ntris;
336                                 fix light;
337
338                                 //calculate light from surface normal
339
340                                 if (glow_num < 0) {                     //no glow
341
342                                         light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
343                                         light = f1_0/4 + (light*3)/4;
344                                         light = fixmul(light,model_light);
345                                 }
346                                 else {                          //yes glow
347                                         light = glow_values[glow_num];
348                                         glow_num = -1;
349                                 }
350
351                                 //now poke light into l values
352
353                                 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
354
355                                 for (i=0;i<3;i++)
356                                         morph_uvls[i].l = light;
357
358                                 for (i=0;i<2;i++) {
359                                         point_list[i] = Interp_point_list + wp(p+30)[i];
360
361                                         morph_uvls[i].u = uvl_list[i].u;
362                                         morph_uvls[i].v = uvl_list[i].v;
363                                 }
364
365                                 for (ntris=nv-2;ntris;ntris--) {
366
367                                         point_list[2] = Interp_point_list + wp(p+30)[i];
368                                         morph_uvls[2].u = uvl_list[i].u;
369                                         morph_uvls[2].v = uvl_list[i].v;
370                                         i++;
371
372                                         g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
373
374                                         point_list[1] = point_list[2];
375                                         morph_uvls[1].u = morph_uvls[2].u;
376                                         morph_uvls[1].v = morph_uvls[2].v;
377
378                                 }
379
380                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
381
382                                 break;
383                         }
384
385                         case OP_SORTNORM:
386
387                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
388
389                                         //draw back then front
390
391                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
392                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
393
394                                 }
395                                 else {                  //not facing.  draw front then back
396
397                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
398                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
399                                 }
400
401                                 p += 32;
402
403                                 break;
404
405
406                         case OP_RODBM: {
407                                 g3s_point rod_bot_p,rod_top_p;
408
409                                 g3_rotate_point(&rod_bot_p,vp(p+20));
410                                 g3_rotate_point(&rod_top_p,vp(p+4));
411
412                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
413
414                                 p+=36;
415                                 break;
416                         }
417
418                         case OP_SUBCALL: {
419                                 vms_angvec *a;
420
421                                 if (anim_angles)
422                                         a = &anim_angles[w(p+2)];
423                                 else
424                                         a = &zero_angles;
425
426                                 g3_start_instance_angles(vp(p+4),a);
427
428                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
429
430                                 g3_done_instance();
431
432                                 p += 20;
433
434                                 break;
435
436                         }
437
438                         case OP_GLOW:
439
440                                 if (glow_values)
441                                         glow_num = w(p+2);
442                                 p += 4;
443                                 break;
444                 }
445
446         return 1;
447 }
448
449 void init_model_sub(ubyte *p)
450 {
451         Assert(++nest_count < 1000);
452
453         while (w(p) != OP_EOF) {
454
455                 switch (w(p)) {
456
457                         case OP_DEFPOINTS: {
458                                 int n = w(p+2);
459                                 p += n*sizeof(struct vms_vector) + 4;
460                                 break;
461                         }
462
463                         case OP_DEFP_START: {
464                                 int n = w(p+2);
465                                 p += n*sizeof(struct vms_vector) + 8;
466                                 break;
467                         }
468
469                         case OP_FLATPOLY: {
470                                 int nv = w(p+2);
471
472                                 Assert(nv > 2);         //must have 3 or more points
473
474 //                              *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
475
476                                 p += 30 + ((nv&~1)+1)*2;
477                                         
478                                 break;
479                         }
480
481                         case OP_TMAPPOLY: {
482                                 int nv = w(p+2);
483
484                                 Assert(nv > 2);         //must have 3 or more points
485
486                                 if (w(p+28) > highest_texture_num)
487                                         highest_texture_num = w(p+28);
488
489                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
490                                         
491                                 break;
492                         }
493
494                         case OP_SORTNORM:
495
496                                 init_model_sub(p+w(p+28));
497                                 init_model_sub(p+w(p+30));
498                                 p += 32;
499
500                                 break;
501
502
503                         case OP_RODBM:
504                                 p += 36;
505                                 break;
506
507
508                         case OP_SUBCALL: {
509                                 init_model_sub(p+w(p+16));
510                                 p += 20;
511                                 break;
512
513                         }
514
515                         case OP_GLOW:
516                                 p += 4;
517                                 break;
518                         default:
519                                 Assert(0);
520                 }
521         }
522 }
523
524 //init code for bitmap models
525 void g3_init_polygon_model(void *model_ptr)
526 {
527         #ifndef NDEBUG
528         nest_count = 0;
529         #endif
530
531         highest_texture_num = -1;
532
533         init_model_sub((ubyte *) model_ptr);
534 }
535