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