1 /* $Id: interp.c,v 1.11 2003-01-03 00:57:00 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.11 2003-01-03 00:57:00 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 swap_polygon_model_data(ubyte *data)
131 while (w(p) != OP_EOF) {
134 short_swap(wp(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;
142 short_swap(wp(p + 2));
143 short_swap(wp(p + 4));
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;
153 vms_vector_swap(vp(p + 4));
154 vms_vector_swap(vp(p + 16));
155 short_swap(wp(p+28));
157 // swap the colors 0 and 255 here!!!!
160 else if (w(p+28) == 255)
163 for (i=0; i < n; i++)
164 short_swap(wp(p + 30 + (i * 2)));
165 p += 30 + ((n&~1)+1)*2;
171 vms_vector_swap(vp(p + 4));
172 vms_vector_swap(vp(p + 16));
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);
178 short_swap(wp(p+28));
180 short_swap(wp(p + 30 + (i * 2)));
181 p += 30 + ((n&~1)+1)*2 + n*12;
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));
195 vms_vector_swap(vp(p + 20));
196 vms_vector_swap(vp(p + 4));
198 fix_swap(fp(p + 16));
199 fix_swap(fp(p + 32));
205 vms_vector_swap(vp(p+4));
206 short_swap(wp(p+16));
207 swap_polygon_model_data(p + w(p+16));
212 short_swap(wp(p + 2));
217 Error("invalid polygon model\n"); //Int3();
224 #ifdef WORDS_NEED_ALIGNMENT
226 #include <string.h> // for memcpy
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
235 ubyte * old_dest(chunk o) // return where the chunk is (in unaligned structure)
237 return o.old_base + INTEL_SHORT(w(o.old_base + o.offset));
240 ubyte * new_dest(chunk o) // return where the chunk is (in aligned structure)
242 return o.new_base + INTEL_SHORT(w(o.old_base + o.offset)) + o.correction;
245 #define MAX_CHUNKS 100 // increase if insufficent
247 int no_chunks; // the number of chunks currently in array
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;
259 chunk get_first_chunk() // return chunk (from old structure) with smallest address, removing it from array
261 int i, first_index = 0;
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]))
270 first = chunk_list[first_index];
271 // remove it from array:
273 for (i = first_index; i < no_chunks; i++)
274 chunk_list[i] = chunk_list[i + 1];
279 * find out what chunks the chunk "data" points to, return length of current chunk
281 int get_chunks(ubyte *data, ubyte *new_data)
286 while (INTEL_SHORT(w(p)) != OP_EOF) {
287 switch (INTEL_SHORT(w(p))) {
289 n = INTEL_SHORT(w(p+2));
290 p += n*sizeof(struct vms_vector) + 4;
293 n = INTEL_SHORT(w(p+2));
294 p += n*sizeof(struct vms_vector) + 8;
297 n = INTEL_SHORT(w(p+2));
298 p += 30 + ((n&~1)+1)*2;
301 n = INTEL_SHORT(w(p+2));
302 p += 30 + ((n&~1)+1)*2 + n*12;
305 add_chunk(p, p - data + new_data, 28);
306 add_chunk(p, p - data + new_data, 30);
313 add_chunk(p, p - data + new_data, 16);
320 Error("invalid polygon model\n");
326 #define SHIFT_SPACE 500 // increase if insufficent
328 void align_polygon_model_data(polymodel *pm)
331 int total_correction = 0;
332 ubyte *cur_old, *cur_new;
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
339 chunk_list = cl; // so other functions can access it
341 //start with first chunk (is always aligned!)
342 cur_old = pm->model_data;
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
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
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);
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);
382 #endif //def WORDS_NEED_ALIGNMENT
384 void verify(ubyte *data)
389 while (w(p) != OP_EOF) {
393 p += n*sizeof(struct vms_vector) + 4;
397 p += n*sizeof(struct vms_vector) + 8;
401 p += 30 + ((n&~1)+1)*2;
405 p += 30 + ((n&~1)+1)*2 + n*12;
408 verify(p + w(p + 28));
409 verify(p + w(p + 30));
416 verify(p + w(p + 16));
423 Error("invalid polygon model\n");
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)
433 ubyte *p = model_ptr;
435 glow_num = -1; //glow off by default
437 while (w(p) != OP_EOF)
444 rotate_point_list(Interp_point_list,vp(p+4),n);
445 p += n*sizeof(struct vms_vector) + 4;
450 case OP_DEFP_START: {
454 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
455 p += n*sizeof(struct vms_vector) + 8;
463 Assert( nv < MAX_POINTS_PER_POLY );
464 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
470 // DPH: Now we treat this color as 15bpp
471 // gr_setcolor(w(p+28));
473 //l = (32 * model_light) >> 16;
474 l = f2i(fixmul(i2f(32), model_light));
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];
482 point_list[i] = Interp_point_list + wp(p+30)[i];
484 g3_draw_poly(nv,point_list);
487 p += 30 + ((nv&~1)+1)*2;
496 Assert( nv < MAX_POINTS_PER_POLY );
497 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
501 //calculate light from surface normal
503 if (glow_num < 0) { //no glow
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);
510 light = glow_values[glow_num];
514 //now poke light into l values
516 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
519 uvl_list[i].l = light;
522 point_list[i] = Interp_point_list + wp(p+30)[i];
524 g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
527 p += 30 + ((nv&~1)+1)*2 + nv*12;
534 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing
536 //draw back then front
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);
542 else { //not facing. draw front then back
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);
554 g3s_point rod_bot_p,rod_top_p;
556 g3_rotate_point(&rod_bot_p,vp(p+20));
557 g3_rotate_point(&rod_top_p,vp(p+4));
559 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
569 a = &anim_angles[w(p+2)];
573 g3_start_instance_angles(vp(p+4),a);
575 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
593 Error("invalid polygon model\n");
598 extern int gr_find_closest_color_15bpp( int rgb );
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)
607 ubyte *p = model_ptr;
608 fix *glow_values = NULL;
610 glow_num = -1; //glow off by default
612 while (w(p) != OP_EOF)
619 rotate_point_list(Interp_point_list,new_points,n);
620 p += n*sizeof(struct vms_vector) + 4;
625 case OP_DEFP_START: {
629 rotate_point_list(&Interp_point_list[s],new_points,n);
630 p += n*sizeof(struct vms_vector) + 8;
639 gr_setcolor(w(p+28));
642 point_list[i] = Interp_point_list + wp(p+30)[i];
644 for (ntris=nv-2;ntris;ntris--) {
646 point_list[2] = Interp_point_list + wp(p+30)[i++];
648 g3_check_and_draw_poly(3,point_list,NULL,NULL);
650 point_list[1] = point_list[2];
654 p += 30 + ((nv&~1)+1)*2;
662 g3s_uvl morph_uvls[3];
666 //calculate light from surface normal
668 if (glow_num < 0) { //no glow
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);
675 light = glow_values[glow_num];
679 //now poke light into l values
681 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
684 morph_uvls[i].l = light;
687 point_list[i] = Interp_point_list + wp(p+30)[i];
689 morph_uvls[i].u = uvl_list[i].u;
690 morph_uvls[i].v = uvl_list[i].v;
693 for (ntris=nv-2;ntris;ntris--) {
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;
700 g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
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;
708 p += 30 + ((nv&~1)+1)*2 + nv*12;
715 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing
717 //draw back then front
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);
723 else { //not facing. draw front then back
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);
735 g3s_point rod_bot_p,rod_top_p;
737 g3_rotate_point(&rod_bot_p,vp(p+20));
738 g3_rotate_point(&rod_top_p,vp(p+4));
740 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
750 a = &anim_angles[w(p+2)];
754 g3_start_instance_angles(vp(p+4),a);
756 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
777 void init_model_sub(ubyte *p)
779 Assert(++nest_count < 1000);
781 while (w(p) != OP_EOF) {
787 p += n*sizeof(struct vms_vector) + 4;
791 case OP_DEFP_START: {
793 p += n*sizeof(struct vms_vector) + 8;
800 Assert(nv > 2); //must have 3 or more points
802 // *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
804 p += 30 + ((nv&~1)+1)*2;
812 Assert(nv > 2); //must have 3 or more points
814 if (w(p+28) > highest_texture_num)
815 highest_texture_num = w(p+28);
817 p += 30 + ((nv&~1)+1)*2 + nv*12;
824 init_model_sub(p+w(p+28));
825 init_model_sub(p+w(p+30));
837 init_model_sub(p+w(p+16));
847 Error("invalid polygon model\n");
852 //init code for bitmap models
853 void g3_init_polygon_model(void *model_ptr)
859 highest_texture_num = -1;
861 init_model_sub((ubyte *) model_ptr);