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