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