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