formatting
[btb/d2x.git] / 3d / interp.c
1 /* $Id: interp.c,v 1.11 2003-01-03 00:57:00 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.11 2003-01-03 00:57:00 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
226 #include <string.h> // for memcpy
227
228 typedef struct chunk { // pointer-thing to next chunk of model_data
229         ubyte *old_base; // where the offset sets off from (relative to beginning of model_data)
230         ubyte *new_base; // where the base is in the aligned structure
231         short offset; // how much to add to base to get the address of the offset
232         short correction; // how much the value of the offset must be shifted for alignment
233 } chunk;
234
235 ubyte * old_dest(chunk o) // return where the chunk is (in unaligned structure)
236 {
237         return o.old_base + INTEL_SHORT(w(o.old_base + o.offset));
238 }
239
240 ubyte * new_dest(chunk o) // return where the chunk is (in aligned structure)
241 {
242         return o.new_base + INTEL_SHORT(w(o.old_base + o.offset)) + o.correction;
243 }
244
245 #define MAX_CHUNKS 100 // increase if insufficent
246
247 int no_chunks; // the number of chunks currently in array
248 chunk *chunk_list;
249
250 void add_chunk(ubyte *old_base, ubyte *new_base, int offset) {
251         Assert(no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this
252         chunk_list[no_chunks].old_base = old_base;
253         chunk_list[no_chunks].new_base = new_base;
254         chunk_list[no_chunks].offset = offset;
255         chunk_list[no_chunks].correction = 0;
256         no_chunks++;
257 }
258
259 chunk get_first_chunk() // return chunk (from old structure) with smallest address, removing it from array
260 {
261         int i, first_index = 0;
262         chunk first;
263
264         Assert(no_chunks >= 1);
265         // find index of chunk with smallest address:
266         for (i = 1; i < no_chunks; i++)
267                 if (old_dest(chunk_list[i]) < old_dest(chunk_list[first_index]))
268                         first_index = i;
269         // assign it:
270         first = chunk_list[first_index];
271         // remove it from array:
272         no_chunks--;
273         for (i = first_index; i < no_chunks; i++)
274                 chunk_list[i] = chunk_list[i + 1];
275         return first;
276 }
277
278 /*
279  * find out what chunks the chunk "data" points to, return length of current chunk
280  */
281 int get_chunks(ubyte *data, ubyte *new_data)
282 {
283         short n;
284         ubyte *p = data;
285
286         while (INTEL_SHORT(w(p)) != OP_EOF) {
287                 switch (INTEL_SHORT(w(p))) {
288                 case OP_DEFPOINTS:
289                         n = INTEL_SHORT(w(p+2));
290                         p += n*sizeof(struct vms_vector) + 4;
291                         break;
292                 case OP_DEFP_START:
293                         n = INTEL_SHORT(w(p+2));
294                         p += n*sizeof(struct vms_vector) + 8;
295                         break;
296                 case OP_FLATPOLY:
297                         n = INTEL_SHORT(w(p+2));
298                         p += 30 + ((n&~1)+1)*2;
299                         break;
300                 case OP_TMAPPOLY:
301                         n = INTEL_SHORT(w(p+2));
302                         p += 30 + ((n&~1)+1)*2 + n*12;
303                         break;
304                 case OP_SORTNORM:
305                         add_chunk(p, p - data + new_data, 28);
306                         add_chunk(p, p - data + new_data, 30);
307                         p += 32;
308                         break;
309                 case OP_RODBM:
310                         p+=36;
311                         break;
312                 case OP_SUBCALL:
313                         add_chunk(p, p - data + new_data, 16);
314                         p+=20;
315                         break;
316                 case OP_GLOW:
317                         p += 4;
318                         break;
319                 default:
320                         Error("invalid polygon model\n");
321                 }
322         }
323         return p + 2 - data;
324 }
325
326 #define SHIFT_SPACE 500 // increase if insufficent
327
328 void align_polygon_model_data(polymodel *pm)
329 {
330         int i, chunk_len;
331         int total_correction = 0;
332         ubyte *cur_old, *cur_new;
333         chunk cur_ch;
334         chunk cl[MAX_CHUNKS]; // we need the chunk_list only in this function
335         int tmp_size = pm->model_data_size + SHIFT_SPACE;
336         ubyte *tmp = d_malloc(tmp_size); // where we build the aligned version of pm->model_data
337
338         Assert(tmp != NULL);
339         chunk_list = cl; // so other functions can access it
340         no_chunks = 0;
341         //start with first chunk (is always aligned!)
342         cur_old = pm->model_data;
343         cur_new = tmp;
344         chunk_len = get_chunks(cur_old, cur_new);
345         memcpy(cur_new, cur_old, chunk_len);
346         while (no_chunks > 0) {
347                 cur_ch = get_first_chunk();
348                 if ((u_int32_t)new_dest(cur_ch) % 4L != 0) { // if (new) address unaligned
349                         short to_shift = 4 - (u_int32_t)new_dest(cur_ch) % 4L; // how much to align
350
351                         // correct chunks' addresses
352                         cur_ch.correction += to_shift;
353                         for (i = 0; i < no_chunks; i++)
354                                 chunk_list[i].correction += to_shift;
355                         total_correction += to_shift;
356                         Assert((u_int32_t)new_dest(cur_ch) % 4L == 0);
357                         Assert(total_correction <= SHIFT_SPACE); // if you get this, increase SHIFT_SPACE
358                 }
359                 //write (corrected) chunk for current chunk:
360                 w(cur_ch.new_base + cur_ch.offset)
361                   = INTEL_SHORT(cur_ch.correction
362                   + INTEL_SHORT(w(cur_ch.old_base + cur_ch.offset)));
363                 //write (correctly aligned) chunk:
364                 cur_old = old_dest(cur_ch);
365                 cur_new = new_dest(cur_ch);
366                 chunk_len = get_chunks(cur_old, cur_new);
367                 memcpy(cur_new, cur_old, chunk_len);
368                 //correct submodel_ptr's for pm, too
369                 for (i = 0; i < MAX_SUBMODELS; i++)
370                         if (pm->model_data + pm->submodel_ptrs[i] >= cur_old
371                             && pm->model_data + pm->submodel_ptrs[i] < cur_old + chunk_len)
372                                 pm->submodel_ptrs[i] += (cur_new - tmp) - (cur_old - pm->model_data);
373         }
374         d_free(pm->model_data);
375         pm->model_data_size += total_correction;
376         pm->model_data = d_malloc(pm->model_data_size);
377         Assert(pm->model_data != NULL);
378         memcpy(pm->model_data, tmp, pm->model_data_size);
379         d_free(tmp);
380 }
381
382 #endif //def WORDS_NEED_ALIGNMENT
383
384 void verify(ubyte *data)
385 {
386         short n;
387         ubyte *p = data;
388
389         while (w(p) != OP_EOF) {
390                 switch (w(p)) {
391                 case OP_DEFPOINTS:
392                         n = (w(p+2));
393                         p += n*sizeof(struct vms_vector) + 4;
394                         break;
395                 case OP_DEFP_START:
396                         n = (w(p+2));
397                         p += n*sizeof(struct vms_vector) + 8;
398                         break;
399                 case OP_FLATPOLY:
400                         n = (w(p+2));
401                         p += 30 + ((n&~1)+1)*2;
402                         break;
403                 case OP_TMAPPOLY:
404                         n = (w(p+2));
405                         p += 30 + ((n&~1)+1)*2 + n*12;
406                         break;
407                 case OP_SORTNORM:
408                         verify(p + w(p + 28));
409                         verify(p + w(p + 30));
410                         p += 32;
411                         break;
412                 case OP_RODBM:
413                         p+=36;
414                         break;
415                 case OP_SUBCALL:
416                         verify(p + w(p + 16));
417                         p+=20;
418                         break;
419                 case OP_GLOW:
420                         p += 4;
421                         break;
422                 default:
423                         Error("invalid polygon model\n");
424                 }
425         }
426 }
427
428
429 //calls the object interpreter to render an object.  The object renderer
430 //is really a seperate pipeline. returns true if drew
431 bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values)
432 {
433         ubyte *p = model_ptr;
434
435         glow_num = -1;          //glow off by default
436
437         while (w(p) != OP_EOF)
438
439                 switch (w(p)) {
440
441                         case OP_DEFPOINTS: {
442                                 int n = w(p+2);
443
444                                 rotate_point_list(Interp_point_list,vp(p+4),n);
445                                 p += n*sizeof(struct vms_vector) + 4;
446
447                                 break;
448                         }
449
450                         case OP_DEFP_START: {
451                                 int n = w(p+2);
452                                 int s = w(p+4);
453
454                                 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
455                                 p += n*sizeof(struct vms_vector) + 8;
456
457                                 break;
458                         }
459
460                         case OP_FLATPOLY: {
461                                 int nv = w(p+2);
462
463                                 Assert( nv < MAX_POINTS_PER_POLY );
464                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
465                                         int i;
466                                         short c;
467                                         unsigned char cc;
468                                         int l;
469
470 //                                      DPH: Now we treat this color as 15bpp
471 //                                      gr_setcolor(w(p+28));
472                                         
473                                         //l = (32 * model_light) >> 16;
474                                         l = f2i(fixmul(i2f(32), model_light));
475                                         if (l<0) l = 0;
476                                         else if (l>32) l = 32;
477                                         cc = gr_find_closest_color_15bpp(w(p+28));
478                                         c = gr_fade_table[(l<<8)|cc];
479                                         gr_setcolor(c);
480
481                                         for (i=0;i<nv;i++)
482                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
483
484                                         g3_draw_poly(nv,point_list);
485                                 }
486
487                                 p += 30 + ((nv&~1)+1)*2;
488                                         
489                                 break;
490                         }
491
492                         case OP_TMAPPOLY: {
493                                 int nv = w(p+2);
494                                 g3s_uvl *uvl_list;
495
496                                 Assert( nv < MAX_POINTS_PER_POLY );
497                                 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
498                                         int i;
499                                         fix light;
500
501                                         //calculate light from surface normal
502
503                                         if (glow_num < 0) {                     //no glow
504
505                                                 light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
506                                                 light = f1_0/4 + (light*3)/4;
507                                                 light = fixmul(light,model_light);
508                                         }
509                                         else {                          //yes glow
510                                                 light = glow_values[glow_num];
511                                                 glow_num = -1;
512                                         }
513
514                                         //now poke light into l values
515
516                                         uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
517
518                                         for (i=0;i<nv;i++)
519                                                 uvl_list[i].l = light;
520
521                                         for (i=0;i<nv;i++)
522                                                 point_list[i] = Interp_point_list + wp(p+30)[i];
523
524                                         g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
525                                 }
526
527                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
528                                         
529                                 break;
530                         }
531
532                         case OP_SORTNORM:
533
534                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
535
536                                         //draw back then front
537
538                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
539                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
540
541                                 }
542                                 else {                  //not facing.  draw front then back
543
544                                         g3_draw_polygon_model(p+w(p+28),model_bitmaps,anim_angles,model_light,glow_values);
545                                         g3_draw_polygon_model(p+w(p+30),model_bitmaps,anim_angles,model_light,glow_values);
546                                 }
547
548                                 p += 32;
549
550                                 break;
551
552
553                         case OP_RODBM: {
554                                 g3s_point rod_bot_p,rod_top_p;
555
556                                 g3_rotate_point(&rod_bot_p,vp(p+20));
557                                 g3_rotate_point(&rod_top_p,vp(p+4));
558
559                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
560
561                                 p+=36;
562                                 break;
563                         }
564
565                         case OP_SUBCALL: {
566                                 vms_angvec *a;
567
568                                 if (anim_angles)
569                                         a = &anim_angles[w(p+2)];
570                                 else
571                                         a = &zero_angles;
572
573                                 g3_start_instance_angles(vp(p+4),a);
574
575                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
576
577                                 g3_done_instance();
578
579                                 p += 20;
580
581                                 break;
582
583                         }
584
585                         case OP_GLOW:
586
587                                 if (glow_values)
588                                         glow_num = w(p+2);
589                                 p += 4;
590                                 break;
591
592                         default:
593                                 Error("invalid polygon model\n");
594                 }
595         return 1;
596 }
597
598 extern int gr_find_closest_color_15bpp( int rgb );
599
600 #ifndef NDEBUG
601 int nest_count;
602 #endif
603
604 //alternate interpreter for morphing object
605 bool g3_draw_morphing_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,vms_vector *new_points)
606 {
607         ubyte *p = model_ptr;
608         fix *glow_values = NULL;
609
610         glow_num = -1;          //glow off by default
611
612         while (w(p) != OP_EOF)
613
614                 switch (w(p)) {
615
616                         case OP_DEFPOINTS: {
617                                 int n = w(p+2);
618
619                                 rotate_point_list(Interp_point_list,new_points,n);
620                                 p += n*sizeof(struct vms_vector) + 4;
621
622                                 break;
623                         }
624
625                         case OP_DEFP_START: {
626                                 int n = w(p+2);
627                                 int s = w(p+4);
628
629                                 rotate_point_list(&Interp_point_list[s],new_points,n);
630                                 p += n*sizeof(struct vms_vector) + 8;
631
632                                 break;
633                         }
634
635                         case OP_FLATPOLY: {
636                                 int nv = w(p+2);
637                                 int i,ntris;
638
639                                 gr_setcolor(w(p+28));
640                                 
641                                 for (i=0;i<2;i++)
642                                         point_list[i] = Interp_point_list + wp(p+30)[i];
643
644                                 for (ntris=nv-2;ntris;ntris--) {
645
646                                         point_list[2] = Interp_point_list + wp(p+30)[i++];
647
648                                         g3_check_and_draw_poly(3,point_list,NULL,NULL);
649
650                                         point_list[1] = point_list[2];
651
652                                 }
653
654                                 p += 30 + ((nv&~1)+1)*2;
655                                         
656                                 break;
657                         }
658
659                         case OP_TMAPPOLY: {
660                                 int nv = w(p+2);
661                                 g3s_uvl *uvl_list;
662                                 g3s_uvl morph_uvls[3];
663                                 int i,ntris;
664                                 fix light;
665
666                                 //calculate light from surface normal
667
668                                 if (glow_num < 0) {                     //no glow
669
670                                         light = -vm_vec_dot(&View_matrix.fvec,vp(p+16));
671                                         light = f1_0/4 + (light*3)/4;
672                                         light = fixmul(light,model_light);
673                                 }
674                                 else {                          //yes glow
675                                         light = glow_values[glow_num];
676                                         glow_num = -1;
677                                 }
678
679                                 //now poke light into l values
680
681                                 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
682
683                                 for (i=0;i<3;i++)
684                                         morph_uvls[i].l = light;
685
686                                 for (i=0;i<2;i++) {
687                                         point_list[i] = Interp_point_list + wp(p+30)[i];
688
689                                         morph_uvls[i].u = uvl_list[i].u;
690                                         morph_uvls[i].v = uvl_list[i].v;
691                                 }
692
693                                 for (ntris=nv-2;ntris;ntris--) {
694
695                                         point_list[2] = Interp_point_list + wp(p+30)[i];
696                                         morph_uvls[2].u = uvl_list[i].u;
697                                         morph_uvls[2].v = uvl_list[i].v;
698                                         i++;
699
700                                         g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
701
702                                         point_list[1] = point_list[2];
703                                         morph_uvls[1].u = morph_uvls[2].u;
704                                         morph_uvls[1].v = morph_uvls[2].v;
705
706                                 }
707
708                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
709
710                                 break;
711                         }
712
713                         case OP_SORTNORM:
714
715                                 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) {             //facing
716
717                                         //draw back then front
718
719                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
720                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
721
722                                 }
723                                 else {                  //not facing.  draw front then back
724
725                                         g3_draw_morphing_model(p+w(p+28),model_bitmaps,anim_angles,model_light,new_points);
726                                         g3_draw_morphing_model(p+w(p+30),model_bitmaps,anim_angles,model_light,new_points);
727                                 }
728
729                                 p += 32;
730
731                                 break;
732
733
734                         case OP_RODBM: {
735                                 g3s_point rod_bot_p,rod_top_p;
736
737                                 g3_rotate_point(&rod_bot_p,vp(p+20));
738                                 g3_rotate_point(&rod_top_p,vp(p+4));
739
740                                 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
741
742                                 p+=36;
743                                 break;
744                         }
745
746                         case OP_SUBCALL: {
747                                 vms_angvec *a;
748
749                                 if (anim_angles)
750                                         a = &anim_angles[w(p+2)];
751                                 else
752                                         a = &zero_angles;
753
754                                 g3_start_instance_angles(vp(p+4),a);
755
756                                 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
757
758                                 g3_done_instance();
759
760                                 p += 20;
761
762                                 break;
763
764                         }
765
766                         case OP_GLOW:
767
768                                 if (glow_values)
769                                         glow_num = w(p+2);
770                                 p += 4;
771                                 break;
772                 }
773
774         return 1;
775 }
776
777 void init_model_sub(ubyte *p)
778 {
779         Assert(++nest_count < 1000);
780
781         while (w(p) != OP_EOF) {
782
783                 switch (w(p)) {
784
785                         case OP_DEFPOINTS: {
786                                 int n = w(p+2);
787                                 p += n*sizeof(struct vms_vector) + 4;
788                                 break;
789                         }
790
791                         case OP_DEFP_START: {
792                                 int n = w(p+2);
793                                 p += n*sizeof(struct vms_vector) + 8;
794                                 break;
795                         }
796
797                         case OP_FLATPOLY: {
798                                 int nv = w(p+2);
799
800                                 Assert(nv > 2);         //must have 3 or more points
801
802 //                              *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
803
804                                 p += 30 + ((nv&~1)+1)*2;
805                                         
806                                 break;
807                         }
808
809                         case OP_TMAPPOLY: {
810                                 int nv = w(p+2);
811
812                                 Assert(nv > 2);         //must have 3 or more points
813
814                                 if (w(p+28) > highest_texture_num)
815                                         highest_texture_num = w(p+28);
816
817                                 p += 30 + ((nv&~1)+1)*2 + nv*12;
818                                         
819                                 break;
820                         }
821
822                         case OP_SORTNORM:
823
824                                 init_model_sub(p+w(p+28));
825                                 init_model_sub(p+w(p+30));
826                                 p += 32;
827
828                                 break;
829
830
831                         case OP_RODBM:
832                                 p += 36;
833                                 break;
834
835
836                         case OP_SUBCALL: {
837                                 init_model_sub(p+w(p+16));
838                                 p += 20;
839                                 break;
840
841                         }
842
843                         case OP_GLOW:
844                                 p += 4;
845                                 break;
846                         default:
847                                 Error("invalid polygon model\n");
848                 }
849         }
850 }
851
852 //init code for bitmap models
853 void g3_init_polygon_model(void *model_ptr)
854 {
855         #ifndef NDEBUG
856         nest_count = 0;
857         #endif
858
859         highest_texture_num = -1;
860
861         init_model_sub((ubyte *) model_ptr);
862 }