1 /* $Id: interp.c,v 1.14 2003-03-19 19:21:34 btb Exp $ */
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.
17 * Polygon object interpreter
20 * Revision 1.4 1995/10/10 22:20:09 allender
21 * new morphing code from Matt
23 * Revision 1.3 1995/08/31 15:40:24 allender
24 * swap color data correctly
26 * Revision 1.2 1995/05/11 13:06:38 allender
27 * fix int --> short problem
29 * Revision 1.1 1995/05/05 08:51:41 allender
32 * Revision 1.1 1995/04/17 06:44:33 matt
43 static char rcsid[] = "$Id: interp.c,v 1.14 2003-03-19 19:21:34 btb Exp $";
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
65 //#define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table))
67 #define MAX_POINTS_PER_POLY 25
69 short highest_texture_num;
70 int g3d_interp_outline;
72 g3s_point *Interp_point_list = NULL;
74 #define MAX_INTERP_COLORS 100
76 //this is a table of mappings from RGB15 to palette colors
77 struct {short pal_entry,rgb15;} interp_color_table[MAX_INTERP_COLORS];
79 int n_interp_colors=0;
81 //gives the interpreter an array of points to use
82 void g3_set_interp_points(g3s_point *pointlist)
84 Interp_point_list = pointlist;
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))
92 void rotate_point_list(g3s_point *dest,vms_vector *src,int n)
95 g3_rotate_point(dest++,src++);
98 vms_angvec zero_angles = {0,0,0};
100 g3s_point *point_list[MAX_POINTS_PER_POLY];
104 #ifdef WORDS_BIGENDIAN
105 void short_swap(short *s)
110 void fix_swap(fix *f)
112 *f = (fix)SWAPINT((int)*f);
115 void vms_vector_swap(vms_vector *v)
122 void fixang_swap(fixang *f)
124 *f = (fixang)SWAPSHORT((short)*f);
127 void vms_angvec_swap(vms_angvec *v)
134 void swap_polygon_model_data(ubyte *data)
143 while (w(p) != OP_EOF) {
146 short_swap(wp(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;
154 short_swap(wp(p + 2));
155 short_swap(wp(p + 4));
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;
165 vms_vector_swap(vp(p + 4));
166 vms_vector_swap(vp(p + 16));
167 short_swap(wp(p+28));
169 // swap the colors 0 and 255 here!!!!
172 else if (w(p+28) == 255)
175 for (i=0; i < n; i++)
176 short_swap(wp(p + 30 + (i * 2)));
177 p += 30 + ((n&~1)+1)*2;
183 vms_vector_swap(vp(p + 4));
184 vms_vector_swap(vp(p + 16));
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);
190 short_swap(wp(p+28));
192 short_swap(wp(p + 30 + (i * 2)));
193 p += 30 + ((n&~1)+1)*2 + n*12;
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));
207 vms_vector_swap(vp(p + 20));
208 vms_vector_swap(vp(p + 4));
210 fix_swap(fp(p + 16));
211 fix_swap(fp(p + 32));
217 vms_vector_swap(vp(p+4));
218 short_swap(wp(p+16));
219 swap_polygon_model_data(p + w(p+16));
224 short_swap(wp(p + 2));
229 Error("invalid polygon model\n"); //Int3();
236 #ifdef WORDS_NEED_ALIGNMENT
237 void add_chunk(ubyte *old_base, ubyte *new_base, int offset,
238 chunk *chunk_list, int *no_chunks)
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;
249 * finds what chunks the data points to, adds them to the chunk_list,
250 * and returns the length of the current chunk
252 int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no)
257 while (INTEL_SHORT(w(p)) != OP_EOF) {
258 switch (INTEL_SHORT(w(p))) {
260 n = INTEL_SHORT(w(p+2));
261 p += n*sizeof(struct vms_vector) + 4;
264 n = INTEL_SHORT(w(p+2));
265 p += n*sizeof(struct vms_vector) + 8;
268 n = INTEL_SHORT(w(p+2));
269 p += 30 + ((n&~1)+1)*2;
272 n = INTEL_SHORT(w(p+2));
273 p += 30 + ((n&~1)+1)*2 + n*12;
276 add_chunk(p, p - data + new_data, 28, list, no);
277 add_chunk(p, p - data + new_data, 30, list, no);
284 add_chunk(p, p - data + new_data, 16, list, no);
291 Error("invalid polygon model\n");
296 #endif //def WORDS_NEED_ALIGNMENT
298 void verify(ubyte *data)
303 while (w(p) != OP_EOF) {
307 p += n*sizeof(struct vms_vector) + 4;
311 p += n*sizeof(struct vms_vector) + 8;
315 p += 30 + ((n&~1)+1)*2;
319 p += 30 + ((n&~1)+1)*2 + n*12;
322 verify(p + w(p + 28));
323 verify(p + w(p + 30));
330 verify(p + w(p + 16));
337 Error("invalid polygon model\n");
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)
347 ubyte *p = model_ptr;
349 glow_num = -1; //glow off by default
351 while (w(p) != OP_EOF)
358 rotate_point_list(Interp_point_list,vp(p+4),n);
359 p += n*sizeof(struct vms_vector) + 4;
364 case OP_DEFP_START: {
368 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
369 p += n*sizeof(struct vms_vector) + 8;
377 Assert( nv < MAX_POINTS_PER_POLY );
378 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
384 // DPH: Now we treat this color as 15bpp
385 // gr_setcolor(w(p+28));
387 //l = (32 * model_light) >> 16;
388 l = f2i(fixmul(i2f(32), model_light));
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];
396 point_list[i] = Interp_point_list + wp(p+30)[i];
398 g3_draw_poly(nv,point_list);
401 p += 30 + ((nv&~1)+1)*2;
410 Assert( nv < MAX_POINTS_PER_POLY );
411 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
415 //calculate light from surface normal
417 if (glow_num < 0) { //no glow
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);
424 light = glow_values[glow_num];
428 //now poke light into l values
430 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
433 uvl_list[i].l = light;
436 point_list[i] = Interp_point_list + wp(p+30)[i];
438 g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
441 p += 30 + ((nv&~1)+1)*2 + nv*12;
448 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing
450 //draw back then front
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);
456 else { //not facing. draw front then back
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);
468 g3s_point rod_bot_p,rod_top_p;
470 g3_rotate_point(&rod_bot_p,vp(p+20));
471 g3_rotate_point(&rod_top_p,vp(p+4));
473 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
483 a = &anim_angles[w(p+2)];
487 g3_start_instance_angles(vp(p+4),a);
489 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
507 Error("invalid polygon model\n");
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)
519 ubyte *p = model_ptr;
520 fix *glow_values = NULL;
522 glow_num = -1; //glow off by default
524 while (w(p) != OP_EOF)
531 rotate_point_list(Interp_point_list,new_points,n);
532 p += n*sizeof(struct vms_vector) + 4;
537 case OP_DEFP_START: {
541 rotate_point_list(&Interp_point_list[s],new_points,n);
542 p += n*sizeof(struct vms_vector) + 8;
551 gr_setcolor(w(p+28));
554 point_list[i] = Interp_point_list + wp(p+30)[i];
556 for (ntris=nv-2;ntris;ntris--) {
558 point_list[2] = Interp_point_list + wp(p+30)[i++];
560 g3_check_and_draw_poly(3,point_list,NULL,NULL);
562 point_list[1] = point_list[2];
566 p += 30 + ((nv&~1)+1)*2;
574 g3s_uvl morph_uvls[3];
578 //calculate light from surface normal
580 if (glow_num < 0) { //no glow
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);
587 light = glow_values[glow_num];
591 //now poke light into l values
593 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
596 morph_uvls[i].l = light;
599 point_list[i] = Interp_point_list + wp(p+30)[i];
601 morph_uvls[i].u = uvl_list[i].u;
602 morph_uvls[i].v = uvl_list[i].v;
605 for (ntris=nv-2;ntris;ntris--) {
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;
612 g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
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;
620 p += 30 + ((nv&~1)+1)*2 + nv*12;
627 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing
629 //draw back then front
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);
635 else { //not facing. draw front then back
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);
647 g3s_point rod_bot_p,rod_top_p;
649 g3_rotate_point(&rod_bot_p,vp(p+20));
650 g3_rotate_point(&rod_top_p,vp(p+4));
652 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
662 a = &anim_angles[w(p+2)];
666 g3_start_instance_angles(vp(p+4),a);
668 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
689 void init_model_sub(ubyte *p)
691 Assert(++nest_count < 1000);
693 while (w(p) != OP_EOF) {
699 p += n*sizeof(struct vms_vector) + 4;
703 case OP_DEFP_START: {
705 p += n*sizeof(struct vms_vector) + 8;
712 Assert(nv > 2); //must have 3 or more points
714 // *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
716 p += 30 + ((nv&~1)+1)*2;
724 Assert(nv > 2); //must have 3 or more points
726 if (w(p+28) > highest_texture_num)
727 highest_texture_num = w(p+28);
729 p += 30 + ((nv&~1)+1)*2 + nv*12;
736 init_model_sub(p+w(p+28));
737 init_model_sub(p+w(p+30));
749 init_model_sub(p+w(p+16));
759 Error("invalid polygon model\n");
764 //init code for bitmap models
765 void g3_init_polygon_model(void *model_ptr)
771 highest_texture_num = -1;
773 init_model_sub((ubyte *) model_ptr);