ff826dcc11f3112ddf20255ec67f06e159df1e56
[btb/d2x.git] / 3d / interp.c
1 /* $Id: interp.c,v 1.12 2003-02-13 22:02:29 btb 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  *
17  * Polygon object interpreter
18  *
19  * Old Log:
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.12 2003-02-13 22:02:29 btb Exp $";
44 #endif
45
46 #include <stdlib.h>
47 #include "error.h"
48
49 #include "interp.h"
50 #include "globvars.h"
51 #include "gr.h"
52 #include "byteswap.h"
53 #include "u_mem.h"
54
55 #define OP_EOF          0   //eof
56 #define OP_DEFPOINTS    1   //defpoints
57 #define OP_FLATPOLY     2   //flat-shaded polygon
58 #define OP_TMAPPOLY     3   //texture-mapped polygon
59 #define OP_SORTNORM     4   //sort by normal
60 #define OP_RODBM        5   //rod bitmap
61 #define OP_SUBCALL      6   //call a subobject
62 #define OP_DEFP_START   7   //defpoints with start
63 #define OP_GLOW         8   //glow value for next poly
64
65 //#define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table))
66
67 #define MAX_POINTS_PER_POLY 25
68
69 short highest_texture_num;
70 int g3d_interp_outline;
71
72 g3s_point *Interp_point_list = NULL;
73
74 #define MAX_INTERP_COLORS 100
75
76 //this is a table of mappings from RGB15 to palette colors
77 struct {short pal_entry,rgb15;} interp_color_table[MAX_INTERP_COLORS];
78
79 int n_interp_colors=0;
80
81 //gives the interpreter an array of points to use
82 void g3_set_interp_points(g3s_point *pointlist)
83 {
84         Interp_point_list = pointlist;
85 }
86
87 #define w(p)  (*((short *) (p)))
88 #define wp(p)  ((short *) (p))
89 #define fp(p)  ((fix *) (p))
90 #define vp(p)  ((vms_vector *) (p))
91
92 void rotate_point_list(g3s_point *dest,vms_vector *src,int n)
93 {
94         while (n--)
95                 g3_rotate_point(dest++,src++);
96 }
97
98 vms_angvec zero_angles = {0,0,0};
99
100 g3s_point *point_list[MAX_POINTS_PER_POLY];
101
102 int glow_num = -1;
103
104 #ifdef WORDS_BIGENDIAN
105 void short_swap(short *s)
106 {
107         *s = SWAPSHORT(*s);
108 }
109
110 void fix_swap(fix *f)
111 {
112         *f = (fix)SWAPINT((int)*f);
113 }
114
115 void vms_vector_swap(vms_vector *v)
116 {
117         fix_swap(fp(&v->x));
118         fix_swap(fp(&v->y));
119         fix_swap(fp(&v->z));
120 }
121
122 void swap_polygon_model_data(ubyte *data)
123 {
124         int i;
125         short n;
126         g3s_uvl *uvl_val;
127         ubyte *p = data;
128
129         short_swap(wp(p));
130
131         while (w(p) != OP_EOF) {
132                 switch (w(p)) {
133                         case OP_DEFPOINTS:
134                                 short_swap(wp(p + 2));
135                                 n = w(p+2);
136                                 for (i = 0; i < n; i++)
137                                         vms_vector_swap(vp((p + 4) + (i * sizeof(vms_vector))));
138                                 p += n*sizeof(struct vms_vector) + 4;
139                                 break;
140
141                         case OP_DEFP_START:
142                                 short_swap(wp(p + 2));
143                                 short_swap(wp(p + 4));
144                                 n = w(p+2);
145                                 for (i = 0; i < n; i++)
146                                         vms_vector_swap(vp((p + 8) + (i * sizeof(vms_vector))));
147                                 p += n*sizeof(struct vms_vector) + 8;
148                                 break;
149
150                         case OP_FLATPOLY:
151                                 short_swap(wp(p+2));
152                                 n = w(p+2);
153                                 vms_vector_swap(vp(p + 4));
154                                 vms_vector_swap(vp(p + 16));
155                                 short_swap(wp(p+28));
156 #ifdef MACINTOSH
157                                 // swap the colors 0 and 255 here!!!!
158                                 if (w(p+28) == 0)
159                                         w(p+28) = 255;
160                                 else if (w(p+28) == 255)
161                                         w(p+28) = 0;
162 #endif
163                                 for (i=0; i < n; i++)
164                                         short_swap(wp(p + 30 + (i * 2)));
165                                 p += 30 + ((n&~1)+1)*2;
166                                 break;
167
168                         case OP_TMAPPOLY:
169                                 short_swap(wp(p+2));
170                                 n = w(p+2);
171                                 vms_vector_swap(vp(p + 4));
172                                 vms_vector_swap(vp(p + 16));
173                                 for (i=0;i<n;i++) {
174                                         uvl_val = (g3s_uvl *)((p+30+((n&~1)+1)*2) + (i * sizeof(g3s_uvl)));
175                                         fix_swap(&uvl_val->u);
176                                         fix_swap(&uvl_val->v);
177                                 }
178                                 short_swap(wp(p+28));
179                                 for (i=0;i<n;i++)
180                                         short_swap(wp(p + 30 + (i * 2)));
181                                 p += 30 + ((n&~1)+1)*2 + n*12;
182                                 break;
183
184                         case OP_SORTNORM:
185                                 vms_vector_swap(vp(p + 4));
186                                 vms_vector_swap(vp(p + 16));
187                                 short_swap(wp(p + 28));
188                                 short_swap(wp(p + 30));
189                                 swap_polygon_model_data(p + w(p+28));
190                                 swap_polygon_model_data(p + w(p+30));
191                                 p += 32;
192                                 break;
193
194                         case OP_RODBM:
195                                 vms_vector_swap(vp(p + 20));
196                                 vms_vector_swap(vp(p + 4));
197                                 short_swap(wp(p+2));
198                                 fix_swap(fp(p + 16));
199                                 fix_swap(fp(p + 32));
200                                 p+=36;
201                                 break;
202
203                         case OP_SUBCALL:
204                                 short_swap(wp(p+2));
205                                 vms_vector_swap(vp(p+4));
206                                 short_swap(wp(p+16));
207                                 swap_polygon_model_data(p + w(p+16));
208                                 p += 20;
209                                 break;
210
211                         case OP_GLOW:
212                                 short_swap(wp(p + 2));
213                                 p += 4;
214                                 break;
215
216                         default:
217                                 Error("invalid polygon model\n"); //Int3();
218                 }
219                 short_swap(wp(p));
220         }
221 }
222 #endif
223
224 #ifdef WORDS_NEED_ALIGNMENT
225 void add_chunk(ubyte *old_base, ubyte *new_base, int offset,
226                chunk *chunk_list, int *no_chunks)
227 {
228         Assert(*no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this
229         chunk_list[*no_chunks].old_base = old_base;
230         chunk_list[*no_chunks].new_base = new_base;
231         chunk_list[*no_chunks].offset = offset;
232         chunk_list[*no_chunks].correction = 0;
233         (*no_chunks)++;
234 }
235
236 /*
237  * finds what chunks the data points to, adds them to the chunk_list, 
238  * and returns the length of the current chunk
239  */
240 int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no)
241 {
242         short n;
243         ubyte *p = data;
244
245         while (INTEL_SHORT(w(p)) != OP_EOF) {
246                 switch (INTEL_SHORT(w(p))) {
247                 case OP_DEFPOINTS:
248                         n = INTEL_SHORT(w(p+2));
249                         p += n*sizeof(struct vms_vector) + 4;
250                         break;
251                 case OP_DEFP_START:
252                         n = INTEL_SHORT(w(p+2));
253                         p += n*sizeof(struct vms_vector) + 8;
254                         break;
255                 case OP_FLATPOLY:
256                         n = INTEL_SHORT(w(p+2));
257                         p += 30 + ((n&~1)+1)*2;
258                         break;
259                 case OP_TMAPPOLY:
260                         n = INTEL_SHORT(w(p+2));
261                         p += 30 + ((n&~1)+1)*2 + n*12;
262                         break;
263                 case OP_SORTNORM:
264                         add_chunk(p, p - data + new_data, 28, list, no);
265                         add_chunk(p, p - data + new_data, 30, list, no);
266                         p += 32;
267                         break;
268                 case OP_RODBM:
269                         p+=36;
270                         break;
271                 case OP_SUBCALL:
272                         add_chunk(p, p - data + new_data, 16, list, no);
273                         p+=20;
274                         break;
275                 case OP_GLOW:
276                         p += 4;
277                         break;
278                 default:
279                         Error("invalid polygon model\n");
280                 }
281         }
282         return p + 2 - data;
283 }
284 #endif //def WORDS_NEED_ALIGNMENT
285
286 void verify(ubyte *data)
287 {
288         short n;
289         ubyte *p = data;
290
291         while (w(p) != OP_EOF) {
292                 switch (w(p)) {
293                 case OP_DEFPOINTS:
294                         n = (w(p+2));
295                         p += n*sizeof(struct vms_vector) + 4;
296                         break;
297                 case OP_DEFP_START:
298                         n = (w(p+2));
299                         p += n*sizeof(struct vms_vector) + 8;
300                         break;
301                 case OP_FLATPOLY:
302                         n = (w(p+2));
303                         p += 30 + ((n&~1)+1)*2;
304                         break;
305                 case OP_TMAPPOLY:
306                         n = (w(p+2));
307                         p += 30 + ((n&~1)+1)*2 + n*12;
308                         break;
309                 case OP_SORTNORM:
310                         verify(p + w(p + 28));
311                         verify(p + w(p + 30));
312                         p += 32;
313                         break;
314                 case OP_RODBM:
315                         p+=36;
316                         break;
317                 case OP_SUBCALL:
318                         verify(p + w(p + 16));
319                         p+=20;
320                         break;
321                 case OP_GLOW:
322                         p += 4;
323                         break;
324                 default:
325                         Error("invalid polygon model\n");
326                 }
327         }
328 }
329
330
331 //calls the object interpreter to render an object.  The object renderer
332 //is really a seperate pipeline. returns true if drew
333 bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values)
334 {
335         ubyte *p = model_ptr;
336
337         glow_num = -1;          //glow off by default
338
339         while (w(p) != OP_EOF)
340
341                 switch (w(p)) {
342
343                         case OP_DEFPOINTS: {
344                                 int n = w(p+2);
345
346                                 rotate_point_list(Interp_point_list,vp(p+4),n);
347                                 p += n*sizeof(struct vms_vector) + 4;
348
349                                 break;
350                         }
351
352                         case OP_DEFP_START: {
353                                 int n = w(p+2);
354                                 int s = w(p+4);
355
356                                 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
357                                 p += n*sizeof(struct vms_vector) + 8;
358
359                                 break;
360                         }
361
362                         case OP_FLATPOLY: {
363                                 int nv = w(p+2);
364
365                                 Assert( nv < MAX_POINTS_PER_POLY );
366                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
367                                         int i;
368                                         short c;
369                                         unsigned char cc;
370                                         int l;
371
372 //                                      DPH: Now we treat this color as 15bpp
373 //                                      gr_setcolor(w(p+28));
374                                         
375                                         //l = (32 * model_light) >> 16;
376                                         l = f2i(fixmul(i2f(32), model_light));
377                                         if (l<0) l = 0;
378                                         else if (l>32) l = 32;
379                                         cc = gr_find_closest_color_15bpp(w(p+28));
380                                         c = gr_fade_table[(l<<8)|cc];
381                                         gr_setcolor(c);
382
383                                         for (i=0;i<nv;i++)
384                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
385
386                                         g3_draw_poly(nv,point_list);
387                                 }
388
389                                 p += 30 + ((nv&~1)+1)*2;
390                                         
391                                 break;
392                         }
393
394                         case OP_TMAPPOLY: {
395                                 int nv = w(p+2);
396                                 g3s_uvl *uvl_list;
397
398                                 Assert( nv < MAX_POINTS_PER_POLY );
399                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
400                                         int i;
401                                         fix light;
402
403                                         //calculate light from surface normal
404
405                                         if (glow_num < 0) {                     //no glow
406
407                                                 light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
408                                                 light = f1_0/4 + (light*3)/4;
409                                                 light = fixmul(light,model_light);
410                                         }
411                                         else {                          //yes glow
412                                                 light = glow_values[glow_num];
413                                                 glow_num = -1;
414                                         }
415
416                                         //now poke light into l values
417
418                                         uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
419
420                                         for (i=0;i<nv;i++)
421                                                 uvl_list[i].l = light;
422
423                                         for (i=0;i<nv;i++)
424                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
425
426                                         g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
427                                 }
428
429                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
430                                         
431                                 break;
432                         }
433
434                         case OP_SORTNORM:
435
436                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
437
438                                         //draw back then front
439
440                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
441                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
442
443                                 }
444                                 else {                  //not facing.  draw front then back
445
446                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
447                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
448                                 }
449
450                                 p += 32;
451
452                                 break;
453
454
455                         case OP_RODBM: {
456                                 g3s_point rod_bot_p,rod_top_p;
457
458                                 g3_rotate_point(&rod_bot_p,vp(p+20));
459                                 g3_rotate_point(&rod_top_p,vp(p+4));
460
461                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
462
463                                 p+=36;
464                                 break;
465                         }
466
467                         case OP_SUBCALL: {
468                                 vms_angvec *a;
469
470                                 if (anim_angles)
471                                         a = &anim_angles[w(p+2)];
472                                 else
473                                         a = &zero_angles;
474
475                                 g3_start_instance_angles(vp(p+4),a);
476
477                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
478
479                                 g3_done_instance();
480
481                                 p += 20;
482
483                                 break;
484
485                         }
486
487                         case OP_GLOW:
488
489                                 if (glow_values)
490                                         glow_num = w(p+2);
491                                 p += 4;
492                                 break;
493
494                         default:
495                                 Error("invalid polygon model\n");
496                 }
497         return 1;
498 }
499
500 extern int gr_find_closest_color_15bpp( int rgb );
501
502 #ifndef NDEBUG
503 int nest_count;
504 #endif
505
506 //alternate interpreter for morphing object
507 bool g3_draw_morphing_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,vms_vector *new_points)
508 {
509         ubyte *p = model_ptr;
510         fix *glow_values = NULL;
511
512         glow_num = -1;          //glow off by default
513
514         while (w(p) != OP_EOF)
515
516                 switch (w(p)) {
517
518                         case OP_DEFPOINTS: {
519                                 int n = w(p+2);
520
521                                 rotate_point_list(Interp_point_list,new_points,n);
522                                 p += n*sizeof(struct vms_vector) + 4;
523
524                                 break;
525                         }
526
527                         case OP_DEFP_START: {
528                                 int n = w(p+2);
529                                 int s = w(p+4);
530
531                                 rotate_point_list(&Interp_point_list[s],new_points,n);
532                                 p += n*sizeof(struct vms_vector) + 8;
533
534                                 break;
535                         }
536
537                         case OP_FLATPOLY: {
538                                 int nv = w(p+2);
539                                 int i,ntris;
540
541                                 gr_setcolor(w(p+28));
542                                 
543                                 for (i=0;i<2;i++)
544                                         point_list[i] = Interp_point_list + wp(p+30)[i];
545
546                                 for (ntris=nv-2;ntris;ntris--) {
547
548                                         point_list[2] = Interp_point_list + wp(p+30)[i++];
549
550                                         g3_check_and_draw_poly(3,point_list,NULL,NULL);
551
552                                         point_list[1] = point_list[2];
553
554                                 }
555
556                                 p += 30 + ((nv&~1)+1)*2;
557                                         
558                                 break;
559                         }
560
561                         case OP_TMAPPOLY: {
562                                 int nv = w(p+2);
563                                 g3s_uvl *uvl_list;
564                                 g3s_uvl morph_uvls[3];
565                                 int i,ntris;
566                                 fix light;
567
568                                 //calculate light from surface normal
569
570                                 if (glow_num < 0) {                     //no glow
571
572                                         light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
573                                         light = f1_0/4 + (light*3)/4;
574                                         light = fixmul(light,model_light);
575                                 }
576                                 else {                          //yes glow
577                                         light = glow_values[glow_num];
578                                         glow_num = -1;
579                                 }
580
581                                 //now poke light into l values
582
583                                 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
584
585                                 for (i=0;i<3;i++)
586                                         morph_uvls[i].l = light;
587
588                                 for (i=0;i<2;i++) {
589                                         point_list[i] = Interp_point_list + wp(p+30)[i];
590
591                                         morph_uvls[i].u = uvl_list[i].u;
592                                         morph_uvls[i].v = uvl_list[i].v;
593                                 }
594
595                                 for (ntris=nv-2;ntris;ntris--) {
596
597                                         point_list[2] = Interp_point_list + wp(p+30)[i];
598                                         morph_uvls[2].u = uvl_list[i].u;
599                                         morph_uvls[2].v = uvl_list[i].v;
600                                         i++;
601
602                                         g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
603
604                                         point_list[1] = point_list[2];
605                                         morph_uvls[1].u = morph_uvls[2].u;
606                                         morph_uvls[1].v = morph_uvls[2].v;
607
608                                 }
609
610                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
611
612                                 break;
613                         }
614
615                         case OP_SORTNORM:
616
617                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
618
619                                         //draw back then front
620
621                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
622                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
623
624                                 }
625                                 else {                  //not facing.  draw front then back
626
627                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
628                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
629                                 }
630
631                                 p += 32;
632
633                                 break;
634
635
636                         case OP_RODBM: {
637                                 g3s_point rod_bot_p,rod_top_p;
638
639                                 g3_rotate_point(&rod_bot_p,vp(p+20));
640                                 g3_rotate_point(&rod_top_p,vp(p+4));
641
642                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
643
644                                 p+=36;
645                                 break;
646                         }
647
648                         case OP_SUBCALL: {
649                                 vms_angvec *a;
650
651                                 if (anim_angles)
652                                         a = &anim_angles[w(p+2)];
653                                 else
654                                         a = &zero_angles;
655
656                                 g3_start_instance_angles(vp(p+4),a);
657
658                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
659
660                                 g3_done_instance();
661
662                                 p += 20;
663
664                                 break;
665
666                         }
667
668                         case OP_GLOW:
669
670                                 if (glow_values)
671                                         glow_num = w(p+2);
672                                 p += 4;
673                                 break;
674                 }
675
676         return 1;
677 }
678
679 void init_model_sub(ubyte *p)
680 {
681         Assert(++nest_count < 1000);
682
683         while (w(p) != OP_EOF) {
684
685                 switch (w(p)) {
686
687                         case OP_DEFPOINTS: {
688                                 int n = w(p+2);
689                                 p += n*sizeof(struct vms_vector) + 4;
690                                 break;
691                         }
692
693                         case OP_DEFP_START: {
694                                 int n = w(p+2);
695                                 p += n*sizeof(struct vms_vector) + 8;
696                                 break;
697                         }
698
699                         case OP_FLATPOLY: {
700                                 int nv = w(p+2);
701
702                                 Assert(nv > 2);         //must have 3 or more points
703
704 //                              *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
705
706                                 p += 30 + ((nv&~1)+1)*2;
707                                         
708                                 break;
709                         }
710
711                         case OP_TMAPPOLY: {
712                                 int nv = w(p+2);
713
714                                 Assert(nv > 2);         //must have 3 or more points
715
716                                 if (w(p+28) > highest_texture_num)
717                                         highest_texture_num = w(p+28);
718
719                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
720                                         
721                                 break;
722                         }
723
724                         case OP_SORTNORM:
725
726                                 init_model_sub(p+w(p+28));
727                                 init_model_sub(p+w(p+30));
728                                 p += 32;
729
730                                 break;
731
732
733                         case OP_RODBM:
734                                 p += 36;
735                                 break;
736
737
738                         case OP_SUBCALL: {
739                                 init_model_sub(p+w(p+16));
740                                 p += 20;
741                                 break;
742
743                         }
744
745                         case OP_GLOW:
746                                 p += 4;
747                                 break;
748                         default:
749                                 Error("invalid polygon model\n");
750                 }
751         }
752 }
753
754 //init code for bitmap models
755 void g3_init_polygon_model(void *model_ptr)
756 {
757         #ifndef NDEBUG
758         nest_count = 0;
759         #endif
760
761         highest_texture_num = -1;
762
763         init_model_sub((ubyte *) model_ptr);
764 }