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