1 /* $Id: interp.c,v 1.9 2003-01-02 23:13:21 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.9 2003-01-02 23:13:21 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)
109 void fix_swap(fix *f)
111 *f = (fix)SWAPINT((int)*f);
114 void vms_vector_swap(vms_vector *v)
121 void swap_polygon_model_data(ubyte *data)
130 while (w(p) != OP_EOF) {
133 short_swap(wp(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;
141 short_swap(wp(p + 2));
142 short_swap(wp(p + 4));
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;
152 vms_vector_swap(vp(p + 4));
153 vms_vector_swap(vp(p + 16));
154 short_swap(wp(p+28));
156 // swap the colors 0 and 255 here!!!!
159 else if (w(p+28) == 255)
162 for (i=0; i < n; i++)
163 short_swap(wp(p + 30 + (i * 2)));
164 p += 30 + ((n&~1)+1)*2;
170 vms_vector_swap(vp(p + 4));
171 vms_vector_swap(vp(p + 16));
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);
177 short_swap(wp(p+28));
179 short_swap(wp(p + 30 + (i * 2)));
180 p += 30 + ((n&~1)+1)*2 + n*12;
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));
194 vms_vector_swap(vp(p + 20));
195 vms_vector_swap(vp(p + 4));
197 fix_swap(fp(p + 16));
198 fix_swap(fp(p + 32));
204 vms_vector_swap(vp(p+4));
205 short_swap(wp(p+16));
206 swap_polygon_model_data(p + w(p+16));
211 short_swap(wp(p + 2));
216 Error("invalid polygon model\n"); //Int3();
223 #ifdef WORDS_NEED_ALIGNMENT
225 #include <string.h> // for memcpy
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
234 ubyte * old_dest(chunk o) // return where the chunk is (in unaligned structure)
236 return o.old_base + INTEL_SHORT(w(o.old_base + o.offset));
239 ubyte * new_dest(chunk o) // return where the chunk is (in aligned structure)
241 return o.new_base + INTEL_SHORT(w(o.old_base + o.offset)) + o.correction;
244 #define MAX_CHUNKS 100 // increase if insufficent
246 int no_chunks; // the number of chunks currently in array
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;
258 chunk get_first_chunk() // return chunk (from old structure) with smallest address, removing it from array
260 int i, first_index = 0;
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]))
269 first = chunk_list[first_index];
270 // remove it from array:
272 for (i = first_index; i < no_chunks; i++)
273 chunk_list[i] = chunk_list[i + 1];
278 * find out what chunks the chunk "data" points to, return length of current chunk
280 int get_chunks(ubyte *data, ubyte *new_data)
285 while (INTEL_SHORT(w(p)) != OP_EOF) {
286 switch (INTEL_SHORT(w(p))) {
288 n = INTEL_SHORT(w(p+2));
289 p += n*sizeof(struct vms_vector) + 4;
292 n = INTEL_SHORT(w(p+2));
293 p += n*sizeof(struct vms_vector) + 8;
296 n = INTEL_SHORT(w(p+2));
297 p += 30 + ((n&~1)+1)*2;
300 n = INTEL_SHORT(w(p+2));
301 p += 30 + ((n&~1)+1)*2 + n*12;
304 add_chunk(p, p - data + new_data, 28);
305 add_chunk(p, p - data + new_data, 30);
312 add_chunk(p, p - data + new_data, 16);
319 Error("invalid polygon model\n");
325 #define SHIFT_SPACE 500 // increase if insufficent
327 void align_polygon_model_data(polymodel *pm)
330 int total_correction = 0;
331 ubyte *cur_old, *cur_new;
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
338 chunk_list = cl; // so other functions can access it
340 //start with first chunk (is always aligned!)
341 cur_old = pm->model_data;
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
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
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);
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);
381 #endif //def WORDS_NEED_ALIGNMENT
383 void verify(ubyte *data)
388 while (w(p) != OP_EOF) {
392 p += n*sizeof(struct vms_vector) + 4;
396 p += n*sizeof(struct vms_vector) + 8;
400 p += 30 + ((n&~1)+1)*2;
404 p += 30 + ((n&~1)+1)*2 + n*12;
407 verify(p + w(p + 28));
408 verify(p + w(p + 30));
415 verify(p + w(p + 16));
422 Error("invalid polygon model\n");
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)
432 ubyte *p = model_ptr;
434 glow_num = -1; //glow off by default
436 while (w(p) != OP_EOF)
443 rotate_point_list(Interp_point_list,vp(p+4),n);
444 p += n*sizeof(struct vms_vector) + 4;
449 case OP_DEFP_START: {
453 rotate_point_list(&Interp_point_list[s],vp(p+8),n);
454 p += n*sizeof(struct vms_vector) + 8;
462 Assert( nv < MAX_POINTS_PER_POLY );
463 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
469 // DPH: Now we treat this color as 15bpp
470 // gr_setcolor(w(p+28));
472 //l = (32 * model_light) >> 16;
473 l = f2i(fixmul(i2f(32), model_light));
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];
481 point_list[i] = Interp_point_list + wp(p+30)[i];
483 g3_draw_poly(nv,point_list);
486 p += 30 + ((nv&~1)+1)*2;
495 Assert( nv < MAX_POINTS_PER_POLY );
496 if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
500 //calculate light from surface normal
502 if (glow_num < 0) { //no glow
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);
509 light = glow_values[glow_num];
513 //now poke light into l values
515 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
518 uvl_list[i].l = light;
521 point_list[i] = Interp_point_list + wp(p+30)[i];
523 g3_draw_tmap(nv,point_list,uvl_list,model_bitmaps[w(p+28)]);
526 p += 30 + ((nv&~1)+1)*2 + nv*12;
533 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing
535 //draw back then front
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);
541 else { //not facing. draw front then back
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);
553 g3s_point rod_bot_p,rod_top_p;
555 g3_rotate_point(&rod_bot_p,vp(p+20));
556 g3_rotate_point(&rod_top_p,vp(p+4));
558 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
568 a = &anim_angles[w(p+2)];
572 g3_start_instance_angles(vp(p+4),a);
574 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
592 Error("invalid polygon model\n");
597 extern int gr_find_closest_color_15bpp( int rgb );
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)
606 ubyte *p = model_ptr;
607 fix *glow_values = NULL;
609 glow_num = -1; //glow off by default
611 while (w(p) != OP_EOF)
618 rotate_point_list(Interp_point_list,new_points,n);
619 p += n*sizeof(struct vms_vector) + 4;
624 case OP_DEFP_START: {
628 rotate_point_list(&Interp_point_list[s],new_points,n);
629 p += n*sizeof(struct vms_vector) + 8;
638 gr_setcolor(w(p+28));
641 point_list[i] = Interp_point_list + wp(p+30)[i];
643 for (ntris=nv-2;ntris;ntris--) {
645 point_list[2] = Interp_point_list + wp(p+30)[i++];
647 g3_check_and_draw_poly(3,point_list,NULL,NULL);
649 point_list[1] = point_list[2];
653 p += 30 + ((nv&~1)+1)*2;
661 g3s_uvl morph_uvls[3];
665 //calculate light from surface normal
667 if (glow_num < 0) { //no glow
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);
674 light = glow_values[glow_num];
678 //now poke light into l values
680 uvl_list = (g3s_uvl *) (p+30+((nv&~1)+1)*2);
683 morph_uvls[i].l = light;
686 point_list[i] = Interp_point_list + wp(p+30)[i];
688 morph_uvls[i].u = uvl_list[i].u;
689 morph_uvls[i].v = uvl_list[i].v;
692 for (ntris=nv-2;ntris;ntris--) {
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;
699 g3_check_and_draw_tmap(3,point_list,uvl_list,model_bitmaps[w(p+28)],NULL,NULL);
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;
707 p += 30 + ((nv&~1)+1)*2 + nv*12;
714 if (g3_check_normal_facing(vp(p+16),vp(p+4)) > 0) { //facing
716 //draw back then front
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);
722 else { //not facing. draw front then back
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);
734 g3s_point rod_bot_p,rod_top_p;
736 g3_rotate_point(&rod_bot_p,vp(p+20));
737 g3_rotate_point(&rod_top_p,vp(p+4));
739 g3_draw_rod_tmap(model_bitmaps[w(p+2)],&rod_bot_p,w(p+16),&rod_top_p,w(p+32),f1_0);
749 a = &anim_angles[w(p+2)];
753 g3_start_instance_angles(vp(p+4),a);
755 g3_draw_polygon_model(p+w(p+16),model_bitmaps,anim_angles,model_light,glow_values);
776 void init_model_sub(ubyte *p)
778 Assert(++nest_count < 1000);
780 while (w(p) != OP_EOF) {
786 p += n*sizeof(struct vms_vector) + 4;
790 case OP_DEFP_START: {
792 p += n*sizeof(struct vms_vector) + 8;
799 Assert(nv > 2); //must have 3 or more points
801 // *wp(p+28) = (short)gr_find_closest_color_15bpp(w(p+28));
803 p += 30 + ((nv&~1)+1)*2;
811 Assert(nv > 2); //must have 3 or more points
813 if (w(p+28) > highest_texture_num)
814 highest_texture_num = w(p+28);
816 p += 30 + ((nv&~1)+1)*2 + nv*12;
823 init_model_sub(p+w(p+28));
824 init_model_sub(p+w(p+30));
836 init_model_sub(p+w(p+16));
846 Error("invalid polygon model\n");
851 //init code for bitmap models
852 void g3_init_polygon_model(void *model_ptr)
858 highest_texture_num = -1;
860 init_model_sub((ubyte *) model_ptr);
863 // routine which allocates, reads, and inits a polymodel's model_data
864 void polygon_model_data_read(polymodel *pm, CFILE *fp)
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);
872 #ifdef WORDS_BIGENDIAN
873 swap_polygon_model_data(pm->model_data);
875 //verify(pm->model_data);
876 g3_init_polygon_model(pm->model_data);