Disabled shading of flat (non-textured) polygons. Fixes laser and plasma lighting...
[btb/d2x.git] / 3d / interp.c
index 7edd271..bd5c18e 100644 (file)
@@ -1,3 +1,4 @@
+/* $Id: interp.c,v 1.17 2005-03-16 01:56:24 btb Exp $ */
 /*
 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
@@ -7,46 +8,14 @@ IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
-AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
+AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
 */
+
 /*
- * $Source: /cvs/cvsroot/d2x/3d/interp.c,v $
- * $Revision: 1.4 $
- * $Author: bradleyb $
- * $Date: 2001-10-31 03:54:50 $
- * 
- * Polygon object interpreter
- * 
- * $Log: not supported by cvs2svn $
- * Revision 1.3  2001/10/19 08:06:20  bradleyb
- * Partial application of linux/alpha patch.  Courtesy of Falk Hueffner <falk.hueffner@student.uni-tuebingen.de>
- *
- * Revision 1.2  2001/01/31 15:17:48  bradleyb
- * Makefile and conf.h fixes
- *
- * Revision 1.1.1.1  2001/01/19 03:29:58  bradleyb
- * Import of d2x-0.0.8
- *
- * Revision 1.1.1.1  1999/06/14 21:57:47  donut
- * Import of d1x 1.37 source.
- *
- * Revision 1.4  1995/10/10  22:20:09  allender
- * new morphing code from Matt
  *
- * Revision 1.3  1995/08/31  15:40:24  allender
- * swap color data correctly
- *
- * Revision 1.2  1995/05/11  13:06:38  allender
- * fix int --> short problem
- *
- * Revision 1.1  1995/05/05  08:51:41  allender
- * Initial revision
+ * Polygon object interpreter
  *
- * Revision 1.1  1995/04/17  06:44:33  matt
- * Initial revision
- * 
- * 
  */
 
 #ifdef HAVE_CONFIG_H
@@ -54,34 +23,36 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
 #endif
 
 #ifdef RCS
-static char rcsid[] = "$Id: interp.c,v 1.4 2001-10-31 03:54:50 bradleyb Exp $";
+static char rcsid[] = "$Id: interp.c,v 1.17 2005-03-16 01:56:24 btb Exp $";
 #endif
 
 #include <stdlib.h>
 #include "error.h"
 
-#include "3d.h"
+#include "interp.h"
 #include "globvars.h"
 #include "gr.h"
+#include "byteswap.h"
+#include "u_mem.h"
 
-#define OP_EOF                         0       //eof
-#define OP_DEFPOINTS           1       //defpoints
-#define OP_FLATPOLY            2       //flat-shaded polygon
-#define OP_TMAPPOLY            3       //texture-mapped polygon
-#define OP_SORTNORM            4       //sort by normal
-#define OP_RODBM                       5       //rod bitmap
-#define OP_SUBCALL             6       //call a subobject
-#define OP_DEFP_START  7       //defpoints with start
-#define OP_GLOW                        8       //glow value for next poly
+#define OP_EOF          0   //eof
+#define OP_DEFPOINTS    1   //defpoints
+#define OP_FLATPOLY     2   //flat-shaded polygon
+#define OP_TMAPPOLY     3   //texture-mapped polygon
+#define OP_SORTNORM     4   //sort by normal
+#define OP_RODBM        5   //rod bitmap
+#define OP_SUBCALL      6   //call a subobject
+#define OP_DEFP_START   7   //defpoints with start
+#define OP_GLOW         8   //glow value for next poly
 
-#define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table))
+//#define N_OPCODES (sizeof(opcode_table) / sizeof(*opcode_table))
 
-#define MAX_POINTS_PER_POLY            25
+#define MAX_POINTS_PER_POLY 25
 
-short  highest_texture_num;
-int    g3d_interp_outline;
+short highest_texture_num;
+int g3d_interp_outline;
 
-g3s_point *Interp_point_list=NULL;
+g3s_point *Interp_point_list = NULL;
 
 #define MAX_INTERP_COLORS 100
 
@@ -98,6 +69,7 @@ void g3_set_interp_points(g3s_point *pointlist)
 
 #define w(p)  (*((short *) (p)))
 #define wp(p)  ((short *) (p))
+#define fp(p)  ((fix *) (p))
 #define vp(p)  ((vms_vector *) (p))
 
 void rotate_point_list(g3s_point *dest,vms_vector *src,int n)
@@ -112,6 +84,245 @@ g3s_point *point_list[MAX_POINTS_PER_POLY];
 
 int glow_num = -1;
 
+#ifdef WORDS_BIGENDIAN
+void short_swap(short *s)
+{
+       *s = SWAPSHORT(*s);
+}
+
+void fix_swap(fix *f)
+{
+       *f = (fix)SWAPINT((int)*f);
+}
+
+void vms_vector_swap(vms_vector *v)
+{
+       fix_swap(fp(&v->x));
+       fix_swap(fp(&v->y));
+       fix_swap(fp(&v->z));
+}
+
+void fixang_swap(fixang *f)
+{
+       *f = (fixang)SWAPSHORT((short)*f);
+}
+
+void vms_angvec_swap(vms_angvec *v)
+{
+       fixang_swap(&v->p);
+       fixang_swap(&v->b);
+       fixang_swap(&v->h);
+}
+
+void swap_polygon_model_data(ubyte *data)
+{
+       int i;
+       short n;
+       g3s_uvl *uvl_val;
+       ubyte *p = data;
+
+       short_swap(wp(p));
+
+       while (w(p) != OP_EOF) {
+               switch (w(p)) {
+                       case OP_DEFPOINTS:
+                               short_swap(wp(p + 2));
+                               n = w(p+2);
+                               for (i = 0; i < n; i++)
+                                       vms_vector_swap(vp((p + 4) + (i * sizeof(vms_vector))));
+                               p += n*sizeof(struct vms_vector) + 4;
+                               break;
+
+                       case OP_DEFP_START:
+                               short_swap(wp(p + 2));
+                               short_swap(wp(p + 4));
+                               n = w(p+2);
+                               for (i = 0; i < n; i++)
+                                       vms_vector_swap(vp((p + 8) + (i * sizeof(vms_vector))));
+                               p += n*sizeof(struct vms_vector) + 8;
+                               break;
+
+                       case OP_FLATPOLY:
+                               short_swap(wp(p+2));
+                               n = w(p+2);
+                               vms_vector_swap(vp(p + 4));
+                               vms_vector_swap(vp(p + 16));
+                               short_swap(wp(p+28));
+#ifdef MACINTOSH
+                               // swap the colors 0 and 255 here!!!!
+                               if (w(p+28) == 0)
+                                       w(p+28) = 255;
+                               else if (w(p+28) == 255)
+                                       w(p+28) = 0;
+#endif
+                               for (i=0; i < n; i++)
+                                       short_swap(wp(p + 30 + (i * 2)));
+                               p += 30 + ((n&~1)+1)*2;
+                               break;
+
+                       case OP_TMAPPOLY:
+                               short_swap(wp(p+2));
+                               n = w(p+2);
+                               vms_vector_swap(vp(p + 4));
+                               vms_vector_swap(vp(p + 16));
+                               for (i=0;i<n;i++) {
+                                       uvl_val = (g3s_uvl *)((p+30+((n&~1)+1)*2) + (i * sizeof(g3s_uvl)));
+                                       fix_swap(&uvl_val->u);
+                                       fix_swap(&uvl_val->v);
+                               }
+                               short_swap(wp(p+28));
+                               for (i=0;i<n;i++)
+                                       short_swap(wp(p + 30 + (i * 2)));
+                               p += 30 + ((n&~1)+1)*2 + n*12;
+                               break;
+
+                       case OP_SORTNORM:
+                               vms_vector_swap(vp(p + 4));
+                               vms_vector_swap(vp(p + 16));
+                               short_swap(wp(p + 28));
+                               short_swap(wp(p + 30));
+                               swap_polygon_model_data(p + w(p+28));
+                               swap_polygon_model_data(p + w(p+30));
+                               p += 32;
+                               break;
+
+                       case OP_RODBM:
+                               vms_vector_swap(vp(p + 20));
+                               vms_vector_swap(vp(p + 4));
+                               short_swap(wp(p+2));
+                               fix_swap(fp(p + 16));
+                               fix_swap(fp(p + 32));
+                               p+=36;
+                               break;
+
+                       case OP_SUBCALL:
+                               short_swap(wp(p+2));
+                               vms_vector_swap(vp(p+4));
+                               short_swap(wp(p+16));
+                               swap_polygon_model_data(p + w(p+16));
+                               p += 20;
+                               break;
+
+                       case OP_GLOW:
+                               short_swap(wp(p + 2));
+                               p += 4;
+                               break;
+
+                       default:
+                               Error("invalid polygon model\n"); //Int3();
+               }
+               short_swap(wp(p));
+       }
+}
+#endif
+
+#ifdef WORDS_NEED_ALIGNMENT
+void add_chunk(ubyte *old_base, ubyte *new_base, int offset,
+              chunk *chunk_list, int *no_chunks)
+{
+       Assert(*no_chunks + 1 < MAX_CHUNKS); //increase MAX_CHUNKS if you get this
+       chunk_list[*no_chunks].old_base = old_base;
+       chunk_list[*no_chunks].new_base = new_base;
+       chunk_list[*no_chunks].offset = offset;
+       chunk_list[*no_chunks].correction = 0;
+       (*no_chunks)++;
+}
+
+/*
+ * finds what chunks the data points to, adds them to the chunk_list, 
+ * and returns the length of the current chunk
+ */
+int get_chunks(ubyte *data, ubyte *new_data, chunk *list, int *no)
+{
+       short n;
+       ubyte *p = data;
+
+       while (INTEL_SHORT(w(p)) != OP_EOF) {
+               switch (INTEL_SHORT(w(p))) {
+               case OP_DEFPOINTS:
+                       n = INTEL_SHORT(w(p+2));
+                       p += n*sizeof(struct vms_vector) + 4;
+                       break;
+               case OP_DEFP_START:
+                       n = INTEL_SHORT(w(p+2));
+                       p += n*sizeof(struct vms_vector) + 8;
+                       break;
+               case OP_FLATPOLY:
+                       n = INTEL_SHORT(w(p+2));
+                       p += 30 + ((n&~1)+1)*2;
+                       break;
+               case OP_TMAPPOLY:
+                       n = INTEL_SHORT(w(p+2));
+                       p += 30 + ((n&~1)+1)*2 + n*12;
+                       break;
+               case OP_SORTNORM:
+                       add_chunk(p, p - data + new_data, 28, list, no);
+                       add_chunk(p, p - data + new_data, 30, list, no);
+                       p += 32;
+                       break;
+               case OP_RODBM:
+                       p+=36;
+                       break;
+               case OP_SUBCALL:
+                       add_chunk(p, p - data + new_data, 16, list, no);
+                       p+=20;
+                       break;
+               case OP_GLOW:
+                       p += 4;
+                       break;
+               default:
+                       Error("invalid polygon model\n");
+               }
+       }
+       return p + 2 - data;
+}
+#endif //def WORDS_NEED_ALIGNMENT
+
+void verify(ubyte *data)
+{
+       short n;
+       ubyte *p = data;
+
+       while (w(p) != OP_EOF) {
+               switch (w(p)) {
+               case OP_DEFPOINTS:
+                       n = (w(p+2));
+                       p += n*sizeof(struct vms_vector) + 4;
+                       break;
+               case OP_DEFP_START:
+                       n = (w(p+2));
+                       p += n*sizeof(struct vms_vector) + 8;
+                       break;
+               case OP_FLATPOLY:
+                       n = (w(p+2));
+                       p += 30 + ((n&~1)+1)*2;
+                       break;
+               case OP_TMAPPOLY:
+                       n = (w(p+2));
+                       p += 30 + ((n&~1)+1)*2 + n*12;
+                       break;
+               case OP_SORTNORM:
+                       verify(p + w(p + 28));
+                       verify(p + w(p + 30));
+                       p += 32;
+                       break;
+               case OP_RODBM:
+                       p+=36;
+                       break;
+               case OP_SUBCALL:
+                       verify(p + w(p + 16));
+                       p+=20;
+                       break;
+               case OP_GLOW:
+                       p += 4;
+                       break;
+               default:
+                       Error("invalid polygon model\n");
+               }
+       }
+}
+
+
 //calls the object interpreter to render an object.  The object renderer
 //is really a seperate pipeline. returns true if drew
 bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec *anim_angles,fix model_light,fix *glow_values)
@@ -149,13 +360,18 @@ bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec
                                Assert( nv < MAX_POINTS_PER_POLY );
                                if (g3_check_normal_facing(vp(p+4),vp(p+16)) > 0) {
                                        int i;
+#ifdef FADE_FLATPOLY
                                        short c;
                                        unsigned char cc;
                                        int l;
+#endif
 
 //                                     DPH: Now we treat this color as 15bpp
 //                                     gr_setcolor(w(p+28));
                                        
+#ifndef FADE_FLATPOLY
+                                       gr_setcolor(gr_find_closest_color_15bpp(w(p + 28)));
+#else
                                        //l = (32 * model_light) >> 16;
                                        l = f2i(fixmul(i2f(32), model_light));
                                        if (l<0) l = 0;
@@ -163,6 +379,7 @@ bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec
                                        cc = gr_find_closest_color_15bpp(w(p+28));
                                        c = gr_fade_table[(l<<8)|cc];
                                        gr_setcolor(c);
+#endif
 
                                        for (i=0;i<nv;i++)
                                                point_list[i] = Interp_point_list + wp(p+30)[i];
@@ -276,13 +493,11 @@ bool g3_draw_polygon_model(void *model_ptr,grs_bitmap **model_bitmaps,vms_angvec
                                break;
 
                        default:
-                       ;
+                               Error("invalid polygon model\n");
                }
        return 1;
 }
 
-extern int gr_find_closest_color_15bpp( int rgb );
-
 #ifndef NDEBUG
 int nest_count;
 #endif
@@ -529,8 +744,8 @@ void init_model_sub(ubyte *p)
                        case OP_GLOW:
                                p += 4;
                                break;
-                       default:
-                               Assert(0);
+                       default:
+                               Error("invalid polygon model\n");
                }
        }
 }
@@ -547,3 +762,9 @@ void g3_init_polygon_model(void *model_ptr)
        init_model_sub((ubyte *) model_ptr);
 }
 
+//uninit code for bitmap models
+void g3_uninit_polygon_model(void *model_ptr)
+{
+       // not required, the above g3_init_polygon_model doesn't change the data
+       model_ptr = model_ptr;
+}