]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/q2map/patches.c
eol style
[xonotic/netradiant.git] / tools / quake2 / q2map / patches.c
index eb76bc390d7e68cc37833328a6647606f3be5bac..8b9b75fbb95e7e02f5636f9782ad9f46ddfb288c 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-\r
-#include "qrad.h"\r
-\r
-vec3_t texture_reflectivity[MAX_MAP_TEXINFO];\r
-\r
-/*\r
-===================================================================\r
-\r
-  TEXTURE LIGHT VALUES\r
-\r
-===================================================================\r
-*/\r
-\r
-/*\r
-======================\r
-CalcTextureReflectivity_Quake2\r
-======================\r
-*/\r
-void CalcTextureReflectivity_Quake2 (void)\r
-{\r
-       int                             i;\r
-       int                             j, k, texels;\r
-       int                             color[3];\r
-       int                             texel;\r
-       byte                    *palette;\r
-       char                    path[1024];\r
-       float                   r, scale;\r
-       miptex_t                *mt;\r
-\r
-       sprintf (path, "%spics/colormap.pcx", gamedir);\r
-\r
-       // get the game palette\r
-       Load256Image (path, NULL, &palette, NULL, NULL);\r
-\r
-       // allways set index 0 even if no textures\r
-       texture_reflectivity[0][0] = 0.5;\r
-       texture_reflectivity[0][1] = 0.5;\r
-       texture_reflectivity[0][2] = 0.5;\r
-\r
-       for (i=0 ; i<numtexinfo ; i++)\r
-       {\r
-               // see if an earlier texinfo allready got the value\r
-               for (j=0 ; j<i ; j++)\r
-               {\r
-                       if (!strcmp (texinfo[i].texture, texinfo[j].texture))\r
-                       {\r
-                               VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);\r
-                               break;\r
-                       }\r
-               }\r
-               if (j != i)\r
-                       continue;\r
-\r
-               // load the wal file\r
-               sprintf (path, "%stextures/%s.wal", gamedir, texinfo[i].texture);\r
-               if (TryLoadFile (path, (void **)&mt) == -1)\r
-               {\r
-                       Sys_Printf ("Couldn't load %s\n", path);\r
-                       texture_reflectivity[i][0] = 0.5;\r
-                       texture_reflectivity[i][1] = 0.5;\r
-                       texture_reflectivity[i][2] = 0.5;\r
-                       continue;\r
-               }\r
-               texels = LittleLong(mt->width)*LittleLong(mt->height);\r
-               color[0] = color[1] = color[2] = 0;\r
-\r
-               for (j=0 ; j<texels ; j++)\r
-               {\r
-                       texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];\r
-                       for (k=0 ; k<3 ; k++)\r
-                               color[k] += palette[texel*3+k];\r
-               }\r
-\r
-               for (j=0 ; j<3 ; j++)\r
-               {\r
-                       r = color[j]/texels/255.0;\r
-                       texture_reflectivity[i][j] = r;\r
-               }\r
-               // scale the reflectivity up, because the textures are\r
-               // so dim\r
-               scale = ColorNormalize (texture_reflectivity[i],\r
-                       texture_reflectivity[i]);\r
-               if (scale < 0.5)\r
-               {\r
-                       scale *= 2;\r
-                       VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]);\r
-               }\r
-#if 0\r
-texture_reflectivity[i][0] = 0.5;\r
-texture_reflectivity[i][1] = 0.5;\r
-texture_reflectivity[i][2] = 0.5;\r
-#endif\r
-       }\r
-}\r
-\r
-/*\r
-======================\r
-CalcTextureReflectivity_Heretic2\r
-======================\r
-*/\r
-void CalcTextureReflectivity_Heretic2 (void)\r
-{\r
-       int                             i;\r
-       int                             j, texels;\r
-       int                             color[3];\r
-       int                             texel;\r
-       char                    path[1024];\r
-       float                   r;\r
-       miptex_m8_t             *mt;\r
-       miptex_m32_t            *mt32;\r
-       byte                    *pos;\r
-\r
-\r
-       // allways set index 0 even if no textures\r
-       texture_reflectivity[0][0] = 0.5;\r
-       texture_reflectivity[0][1] = 0.5;\r
-       texture_reflectivity[0][2] = 0.5;\r
-\r
-       for (i=0 ; i<numtexinfo ; i++)\r
-       {\r
-               // see if an earlier texinfo allready got the value\r
-               for (j=0 ; j<i ; j++)\r
-               {\r
-                       if (!strcmp (texinfo[i].texture, texinfo[j].texture))\r
-                       {\r
-                               VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);\r
-                               break;\r
-                       }\r
-               }\r
-               if (j != i)\r
-                       continue;\r
-\r
-               // load the wal file\r
-\r
-               sprintf (path, "%stextures/%s.m32", gamedir, texinfo[i].texture);\r
-               if (TryLoadFile (path, (void **)&mt32) == -1)\r
-               {\r
-                       sprintf (path, "%stextures/%s.m8", gamedir, texinfo[i].texture);\r
-                       if (TryLoadFile (path, (void **)&mt) == -1)\r
-                       {\r
-                               Sys_Printf ("Couldn't load %s\n", path);\r
-                               texture_reflectivity[i][0] = 0.5;\r
-                               texture_reflectivity[i][1] = 0.5;\r
-                               texture_reflectivity[i][2] = 0.5;\r
-                               continue;\r
-                       }\r
-                       texels = LittleLong(mt->width[0])*LittleLong(mt->height[0]);\r
-                       color[0] = color[1] = color[2] = 0;\r
-\r
-                       for (j=0 ; j<texels ; j++)\r
-                       {\r
-                               texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];\r
-                               color[0] += mt->palette[texel].r;\r
-                               color[1] += mt->palette[texel].g;\r
-                               color[2] += mt->palette[texel].b;\r
-                       }\r
-\r
-                       free(mt);\r
-               }\r
-               else\r
-               {\r
-                       texels = LittleLong(mt32->width[0])*LittleLong(mt32->height[0]);\r
-                       color[0] = color[1] = color[2] = 0;\r
-\r
-                       for (j=0 ; j<texels ; j++)\r
-                       {\r
-                               pos = (byte *)mt32 + mt32->offsets[0] + (j<<2);\r
-                               color[0] += *pos++;     // r\r
-                               color[1] += *pos++;     // g\r
-                               color[2] += *pos++;     // b\r
-                       }\r
-\r
-                       free(mt32);\r
-               }\r
-\r
-\r
-               for (j=0 ; j<3 ; j++)\r
-               {\r
-                       r = color[j]/((float) texels*255.0);\r
-                       texture_reflectivity[i][j] = r;\r
-               }\r
-       }\r
-}\r
-\r
-/*\r
-=======================================================================\r
-\r
-MAKE FACES\r
-\r
-=======================================================================\r
-*/\r
-\r
-/*\r
-=============\r
-WindingFromFace\r
-=============\r
-*/\r
-winding_t      *WindingFromFace (dface_t *f)\r
-{\r
-       int                     i;\r
-       int                     se;\r
-       dvertex_t       *dv;\r
-       int                     v;\r
-       winding_t       *w;\r
-\r
-       w = AllocWinding (f->numedges);\r
-       w->numpoints = f->numedges;\r
-\r
-       for (i=0 ; i<f->numedges ; i++)\r
-       {\r
-               se = dsurfedges[f->firstedge + i];\r
-               if (se < 0)\r
-                       v = dedges[-se].v[1];\r
-               else\r
-                       v = dedges[se].v[0];\r
-\r
-               dv = &dvertexes[v];\r
-               VectorCopy (dv->point, w->p[i]);\r
-       }\r
-\r
-       RemoveColinearPoints (w);\r
-\r
-       return w;\r
-}\r
-\r
-/*\r
-=============\r
-BaseLightForFace\r
-=============\r
-*/\r
-void BaseLightForFace (dface_t *f, vec3_t color)\r
-{\r
-       texinfo_t       *tx;\r
-\r
-       //\r
-       // check for light emited by texture\r
-       //\r
-       tx = &texinfo[f->texinfo];\r
-       if (!(tx->flags & SURF_LIGHT) || tx->value == 0)\r
-       {\r
-               VectorClear (color);\r
-               return;\r
-       }\r
-\r
-       VectorScale (texture_reflectivity[f->texinfo], tx->value, color);\r
-}\r
-\r
-qboolean IsSky (dface_t *f)\r
-{\r
-       texinfo_t       *tx;\r
-\r
-       tx = &texinfo[f->texinfo];\r
-       if (tx->flags & SURF_SKY)\r
-               return true;\r
-       return false;\r
-}\r
-\r
-/*\r
-=============\r
-MakePatchForFace\r
-=============\r
-*/\r
-float  totalarea;\r
-void MakePatchForFace (int fn, winding_t *w)\r
-{\r
-       dface_t *f;\r
-       float   area;\r
-       patch_t         *patch;\r
-       dplane_t        *pl;\r
-       int                     i;\r
-       vec3_t          color;\r
-       dleaf_t         *leaf;\r
-\r
-       f = &dfaces[fn];\r
-\r
-       area = WindingArea (w);\r
-       totalarea += area;\r
-\r
-       patch = &patches[num_patches];\r
-       if (num_patches == MAX_PATCHES)\r
-               Error ("num_patches == MAX_PATCHES");\r
-       patch->next = face_patches[fn];\r
-       face_patches[fn] = patch;\r
-\r
-       patch->winding = w;\r
-\r
-       if (f->side)\r
-               patch->plane = &backplanes[f->planenum];\r
-       else\r
-               patch->plane = &dplanes[f->planenum];\r
-       if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] )\r
-       {       // origin offset faces must create new planes\r
-               if (numplanes + fakeplanes >= MAX_MAP_PLANES)\r
-                       Error ("numplanes + fakeplanes >= MAX_MAP_PLANES");\r
-               pl = &dplanes[numplanes + fakeplanes];\r
-               fakeplanes++;\r
-\r
-               *pl = *(patch->plane);\r
-               pl->dist += DotProduct (face_offset[fn], pl->normal);\r
-               patch->plane = pl;\r
-       }\r
-\r
-       WindingCenter (w, patch->origin);\r
-       VectorAdd (patch->origin, patch->plane->normal, patch->origin);\r
-       leaf = Rad_PointInLeaf(patch->origin);\r
-       patch->cluster = leaf->cluster;\r
-       if (patch->cluster == -1)\r
-               Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");\r
-\r
-       patch->area = area;\r
-       if (patch->area <= 1)\r
-               patch->area = 1;\r
-       patch->sky = IsSky (f);\r
-\r
-       VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity);\r
-\r
-       // non-bmodel patches can emit light\r
-       if (fn < dmodels[0].numfaces)\r
-       {\r
-               BaseLightForFace (f, patch->baselight);\r
-\r
-               ColorNormalize (patch->reflectivity, color);\r
-\r
-               for (i=0 ; i<3 ; i++)\r
-                       patch->baselight[i] *= color[i];\r
-\r
-               VectorCopy (patch->baselight, patch->totallight);\r
-       }\r
-       num_patches++;\r
-}\r
-\r
-\r
-entity_t *EntityForModel (int modnum)\r
-{\r
-       int             i;\r
-       char    *s;\r
-       char    name[16];\r
-\r
-       sprintf (name, "*%i", modnum);\r
-       // search the entities for one using modnum\r
-       for (i=0 ; i<num_entities ; i++)\r
-       {\r
-               s = ValueForKey (&entities[i], "model");\r
-               if (!strcmp (s, name))\r
-                       return &entities[i];\r
-       }\r
-\r
-       return &entities[0];\r
-}\r
-\r
-/*\r
-=============\r
-MakePatches\r
-=============\r
-*/\r
-void MakePatches (void)\r
-{\r
-       int             i, j, k;\r
-       dface_t *f;\r
-       int             fn;\r
-       winding_t       *w;\r
-       dmodel_t        *mod;\r
-       vec3_t          origin;\r
-       entity_t        *ent;\r
-\r
-       Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces);\r
-\r
-       for (i=0 ; i<nummodels ; i++)\r
-       {\r
-               mod = &dmodels[i];\r
-               ent = EntityForModel (i);\r
-               // bmodels with origin brushes need to be offset into their\r
-               // in-use position\r
-               GetVectorForKey (ent, "origin", origin);\r
-//VectorCopy (vec3_origin, origin);\r
-\r
-               for (j=0 ; j<mod->numfaces ; j++)\r
-               {\r
-                       fn = mod->firstface + j;\r
-                       face_entity[fn] = ent;\r
-                       VectorCopy (origin, face_offset[fn]);\r
-                       f = &dfaces[fn];\r
-                       w = WindingFromFace (f);\r
-                       for (k=0 ; k<w->numpoints ; k++)\r
-                       {\r
-                               VectorAdd (w->p[k], origin, w->p[k]);\r
-                       }\r
-                       MakePatchForFace (fn, w);\r
-               }\r
-       }\r
-\r
-       Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)(totalarea/64));\r
-}\r
-\r
-/*\r
-=======================================================================\r
-\r
-SUBDIVIDE\r
-\r
-=======================================================================\r
-*/\r
-\r
-void FinishSplit (patch_t *patch, patch_t *newp)\r
-{\r
-       dleaf_t         *leaf;\r
-\r
-       VectorCopy (patch->baselight, newp->baselight);\r
-       VectorCopy (patch->totallight, newp->totallight);\r
-       VectorCopy (patch->reflectivity, newp->reflectivity);\r
-       newp->plane = patch->plane;\r
-       newp->sky = patch->sky;\r
-\r
-       patch->area = WindingArea (patch->winding);\r
-       newp->area = WindingArea (newp->winding);\r
-\r
-       if (patch->area <= 1)\r
-               patch->area = 1;\r
-       if (newp->area <= 1)\r
-               newp->area = 1;\r
-\r
-       WindingCenter (patch->winding, patch->origin);\r
-       VectorAdd (patch->origin, patch->plane->normal, patch->origin);\r
-       leaf = Rad_PointInLeaf(patch->origin);\r
-       patch->cluster = leaf->cluster;\r
-       if (patch->cluster == -1)\r
-               Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");\r
-\r
-       WindingCenter (newp->winding, newp->origin);\r
-       VectorAdd (newp->origin, newp->plane->normal, newp->origin);\r
-       leaf = Rad_PointInLeaf(newp->origin);\r
-       newp->cluster = leaf->cluster;\r
-       if (newp->cluster == -1)\r
-               Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");\r
-}\r
-\r
-/*\r
-=============\r
-SubdividePatch\r
-\r
-Chops the patch only if its local bounds exceed the max size\r
-=============\r
-*/\r
-void   SubdividePatch (patch_t *patch)\r
-{\r
-       winding_t *w, *o1, *o2;\r
-       vec3_t  mins, maxs, total;\r
-       vec3_t  split;\r
-       vec_t   dist;\r
-       int             i, j;\r
-       vec_t   v;\r
-       patch_t *newp;\r
-\r
-       w = patch->winding;\r
-       mins[0] = mins[1] = mins[2] = 99999;\r
-       maxs[0] = maxs[1] = maxs[2] = -99999;\r
-       for (i=0 ; i<w->numpoints ; i++)\r
-       {\r
-               for (j=0 ; j<3 ; j++)\r
-               {\r
-                       v = w->p[i][j];\r
-                       if (v < mins[j])\r
-                               mins[j] = v;\r
-                       if (v > maxs[j])\r
-                               maxs[j] = v;\r
-               }\r
-       }\r
-       VectorSubtract (maxs, mins, total);\r
-       for (i=0 ; i<3 ; i++)\r
-               if (total[i] > (subdiv+1) )\r
-                       break;\r
-       if (i == 3)\r
-       {\r
-               // no splitting needed\r
-               return;         \r
-       }\r
-\r
-       //\r
-       // split the winding\r
-       //\r
-       VectorCopy (vec3_origin, split);\r
-       split[i] = 1;\r
-       dist = (mins[i] + maxs[i])*0.5;\r
-       ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);\r
-\r
-       //\r
-       // create a new patch\r
-       //\r
-       if (num_patches == MAX_PATCHES)\r
-               Error ("MAX_PATCHES");\r
-       newp = &patches[num_patches];\r
-       num_patches++;\r
-\r
-       newp->next = patch->next;\r
-       patch->next = newp;\r
-\r
-       patch->winding = o1;\r
-       newp->winding = o2;\r
-\r
-       FinishSplit (patch, newp);\r
-\r
-       SubdividePatch (patch);\r
-       SubdividePatch (newp);\r
-}\r
-\r
-\r
-/*\r
-=============\r
-DicePatch\r
-\r
-Chops the patch by a global grid\r
-=============\r
-*/\r
-void   DicePatch (patch_t *patch)\r
-{\r
-       winding_t *w, *o1, *o2;\r
-       vec3_t  mins, maxs;\r
-       vec3_t  split;\r
-       vec_t   dist;\r
-       int             i;\r
-       patch_t *newp;\r
-\r
-       w = patch->winding;\r
-       WindingBounds (w, mins, maxs);\r
-       for (i=0 ; i<3 ; i++)\r
-               if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv))\r
-                       break;\r
-       if (i == 3)\r
-       {\r
-               // no splitting needed\r
-               return;         \r
-       }\r
-\r
-       //\r
-       // split the winding\r
-       //\r
-       VectorCopy (vec3_origin, split);\r
-       split[i] = 1;\r
-       dist = subdiv*(1+floor((mins[i]+1)/subdiv));\r
-       ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);\r
-\r
-       //\r
-       // create a new patch\r
-       //\r
-       if (num_patches == MAX_PATCHES)\r
-               Error ("MAX_PATCHES");\r
-       newp = &patches[num_patches];\r
-       num_patches++;\r
-\r
-       newp->next = patch->next;\r
-       patch->next = newp;\r
-\r
-       patch->winding = o1;\r
-       newp->winding = o2;\r
-\r
-       FinishSplit (patch, newp);\r
-\r
-       DicePatch (patch);\r
-       DicePatch (newp);\r
-}\r
-\r
-\r
-/*\r
-=============\r
-SubdividePatches\r
-=============\r
-*/\r
-void SubdividePatches (void)\r
-{\r
-       int             i, num;\r
-\r
-       if (subdiv < 1)\r
-               return;\r
-\r
-       num = num_patches;      // because the list will grow\r
-       for (i=0 ; i<num ; i++)\r
-       {\r
-//             SubdividePatch (&patches[i]);\r
-               DicePatch (&patches[i]);\r
-       }\r
-       Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches);\r
-}\r
-\r
-//=====================================================================\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qrad.h"
+
+vec3_t texture_reflectivity[MAX_MAP_TEXINFO];
+
+/*
+===================================================================
+
+  TEXTURE LIGHT VALUES
+
+===================================================================
+*/
+
+/*
+======================
+CalcTextureReflectivity_Quake2
+======================
+*/
+void CalcTextureReflectivity_Quake2 (void)
+{
+       int                             i;
+       int                             j, k, texels;
+       int                             color[3];
+       int                             texel;
+       byte                    *palette;
+       char                    path[1024];
+       float                   r, scale;
+       miptex_t                *mt;
+
+       sprintf (path, "%spics/colormap.pcx", gamedir);
+
+       // get the game palette
+       Load256Image (path, NULL, &palette, NULL, NULL);
+
+       // allways set index 0 even if no textures
+       texture_reflectivity[0][0] = 0.5;
+       texture_reflectivity[0][1] = 0.5;
+       texture_reflectivity[0][2] = 0.5;
+
+       for (i=0 ; i<numtexinfo ; i++)
+       {
+               // see if an earlier texinfo allready got the value
+               for (j=0 ; j<i ; j++)
+               {
+                       if (!strcmp (texinfo[i].texture, texinfo[j].texture))
+                       {
+                               VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
+                               break;
+                       }
+               }
+               if (j != i)
+                       continue;
+
+               // load the wal file
+               sprintf (path, "%stextures/%s.wal", gamedir, texinfo[i].texture);
+               if (TryLoadFile (path, (void **)&mt) == -1)
+               {
+                       Sys_Printf ("Couldn't load %s\n", path);
+                       texture_reflectivity[i][0] = 0.5;
+                       texture_reflectivity[i][1] = 0.5;
+                       texture_reflectivity[i][2] = 0.5;
+                       continue;
+               }
+               texels = LittleLong(mt->width)*LittleLong(mt->height);
+               color[0] = color[1] = color[2] = 0;
+
+               for (j=0 ; j<texels ; j++)
+               {
+                       texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
+                       for (k=0 ; k<3 ; k++)
+                               color[k] += palette[texel*3+k];
+               }
+
+               for (j=0 ; j<3 ; j++)
+               {
+                       r = color[j]/texels/255.0;
+                       texture_reflectivity[i][j] = r;
+               }
+               // scale the reflectivity up, because the textures are
+               // so dim
+               scale = ColorNormalize (texture_reflectivity[i],
+                       texture_reflectivity[i]);
+               if (scale < 0.5)
+               {
+                       scale *= 2;
+                       VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]);
+               }
+#if 0
+texture_reflectivity[i][0] = 0.5;
+texture_reflectivity[i][1] = 0.5;
+texture_reflectivity[i][2] = 0.5;
+#endif
+       }
+}
+
+/*
+======================
+CalcTextureReflectivity_Heretic2
+======================
+*/
+void CalcTextureReflectivity_Heretic2 (void)
+{
+       int                             i;
+       int                             j, texels;
+       int                             color[3];
+       int                             texel;
+       char                    path[1024];
+       float                   r;
+       miptex_m8_t             *mt;
+       miptex_m32_t            *mt32;
+       byte                    *pos;
+
+
+       // allways set index 0 even if no textures
+       texture_reflectivity[0][0] = 0.5;
+       texture_reflectivity[0][1] = 0.5;
+       texture_reflectivity[0][2] = 0.5;
+
+       for (i=0 ; i<numtexinfo ; i++)
+       {
+               // see if an earlier texinfo allready got the value
+               for (j=0 ; j<i ; j++)
+               {
+                       if (!strcmp (texinfo[i].texture, texinfo[j].texture))
+                       {
+                               VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
+                               break;
+                       }
+               }
+               if (j != i)
+                       continue;
+
+               // load the wal file
+
+               sprintf (path, "%stextures/%s.m32", gamedir, texinfo[i].texture);
+               if (TryLoadFile (path, (void **)&mt32) == -1)
+               {
+                       sprintf (path, "%stextures/%s.m8", gamedir, texinfo[i].texture);
+                       if (TryLoadFile (path, (void **)&mt) == -1)
+                       {
+                               Sys_Printf ("Couldn't load %s\n", path);
+                               texture_reflectivity[i][0] = 0.5;
+                               texture_reflectivity[i][1] = 0.5;
+                               texture_reflectivity[i][2] = 0.5;
+                               continue;
+                       }
+                       texels = LittleLong(mt->width[0])*LittleLong(mt->height[0]);
+                       color[0] = color[1] = color[2] = 0;
+
+                       for (j=0 ; j<texels ; j++)
+                       {
+                               texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
+                               color[0] += mt->palette[texel].r;
+                               color[1] += mt->palette[texel].g;
+                               color[2] += mt->palette[texel].b;
+                       }
+
+                       free(mt);
+               }
+               else
+               {
+                       texels = LittleLong(mt32->width[0])*LittleLong(mt32->height[0]);
+                       color[0] = color[1] = color[2] = 0;
+
+                       for (j=0 ; j<texels ; j++)
+                       {
+                               pos = (byte *)mt32 + mt32->offsets[0] + (j<<2);
+                               color[0] += *pos++;     // r
+                               color[1] += *pos++;     // g
+                               color[2] += *pos++;     // b
+                       }
+
+                       free(mt32);
+               }
+
+
+               for (j=0 ; j<3 ; j++)
+               {
+                       r = color[j]/((float) texels*255.0);
+                       texture_reflectivity[i][j] = r;
+               }
+       }
+}
+
+/*
+=======================================================================
+
+MAKE FACES
+
+=======================================================================
+*/
+
+/*
+=============
+WindingFromFace
+=============
+*/
+winding_t      *WindingFromFace (dface_t *f)
+{
+       int                     i;
+       int                     se;
+       dvertex_t       *dv;
+       int                     v;
+       winding_t       *w;
+
+       w = AllocWinding (f->numedges);
+       w->numpoints = f->numedges;
+
+       for (i=0 ; i<f->numedges ; i++)
+       {
+               se = dsurfedges[f->firstedge + i];
+               if (se < 0)
+                       v = dedges[-se].v[1];
+               else
+                       v = dedges[se].v[0];
+
+               dv = &dvertexes[v];
+               VectorCopy (dv->point, w->p[i]);
+       }
+
+       RemoveColinearPoints (w);
+
+       return w;
+}
+
+/*
+=============
+BaseLightForFace
+=============
+*/
+void BaseLightForFace (dface_t *f, vec3_t color)
+{
+       texinfo_t       *tx;
+
+       //
+       // check for light emited by texture
+       //
+       tx = &texinfo[f->texinfo];
+       if (!(tx->flags & SURF_LIGHT) || tx->value == 0)
+       {
+               VectorClear (color);
+               return;
+       }
+
+       VectorScale (texture_reflectivity[f->texinfo], tx->value, color);
+}
+
+qboolean IsSky (dface_t *f)
+{
+       texinfo_t       *tx;
+
+       tx = &texinfo[f->texinfo];
+       if (tx->flags & SURF_SKY)
+               return true;
+       return false;
+}
+
+/*
+=============
+MakePatchForFace
+=============
+*/
+float  totalarea;
+void MakePatchForFace (int fn, winding_t *w)
+{
+       dface_t *f;
+       float   area;
+       patch_t         *patch;
+       dplane_t        *pl;
+       int                     i;
+       vec3_t          color;
+       dleaf_t         *leaf;
+
+       f = &dfaces[fn];
+
+       area = WindingArea (w);
+       totalarea += area;
+
+       patch = &patches[num_patches];
+       if (num_patches == MAX_PATCHES)
+               Error ("num_patches == MAX_PATCHES");
+       patch->next = face_patches[fn];
+       face_patches[fn] = patch;
+
+       patch->winding = w;
+
+       if (f->side)
+               patch->plane = &backplanes[f->planenum];
+       else
+               patch->plane = &dplanes[f->planenum];
+       if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] )
+       {       // origin offset faces must create new planes
+               if (numplanes + fakeplanes >= MAX_MAP_PLANES)
+                       Error ("numplanes + fakeplanes >= MAX_MAP_PLANES");
+               pl = &dplanes[numplanes + fakeplanes];
+               fakeplanes++;
+
+               *pl = *(patch->plane);
+               pl->dist += DotProduct (face_offset[fn], pl->normal);
+               patch->plane = pl;
+       }
+
+       WindingCenter (w, patch->origin);
+       VectorAdd (patch->origin, patch->plane->normal, patch->origin);
+       leaf = Rad_PointInLeaf(patch->origin);
+       patch->cluster = leaf->cluster;
+       if (patch->cluster == -1)
+               Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
+
+       patch->area = area;
+       if (patch->area <= 1)
+               patch->area = 1;
+       patch->sky = IsSky (f);
+
+       VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity);
+
+       // non-bmodel patches can emit light
+       if (fn < dmodels[0].numfaces)
+       {
+               BaseLightForFace (f, patch->baselight);
+
+               ColorNormalize (patch->reflectivity, color);
+
+               for (i=0 ; i<3 ; i++)
+                       patch->baselight[i] *= color[i];
+
+               VectorCopy (patch->baselight, patch->totallight);
+       }
+       num_patches++;
+}
+
+
+entity_t *EntityForModel (int modnum)
+{
+       int             i;
+       char    *s;
+       char    name[16];
+
+       sprintf (name, "*%i", modnum);
+       // search the entities for one using modnum
+       for (i=0 ; i<num_entities ; i++)
+       {
+               s = ValueForKey (&entities[i], "model");
+               if (!strcmp (s, name))
+                       return &entities[i];
+       }
+
+       return &entities[0];
+}
+
+/*
+=============
+MakePatches
+=============
+*/
+void MakePatches (void)
+{
+       int             i, j, k;
+       dface_t *f;
+       int             fn;
+       winding_t       *w;
+       dmodel_t        *mod;
+       vec3_t          origin;
+       entity_t        *ent;
+
+       Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces);
+
+       for (i=0 ; i<nummodels ; i++)
+       {
+               mod = &dmodels[i];
+               ent = EntityForModel (i);
+               // bmodels with origin brushes need to be offset into their
+               // in-use position
+               GetVectorForKey (ent, "origin", origin);
+//VectorCopy (vec3_origin, origin);
+
+               for (j=0 ; j<mod->numfaces ; j++)
+               {
+                       fn = mod->firstface + j;
+                       face_entity[fn] = ent;
+                       VectorCopy (origin, face_offset[fn]);
+                       f = &dfaces[fn];
+                       w = WindingFromFace (f);
+                       for (k=0 ; k<w->numpoints ; k++)
+                       {
+                               VectorAdd (w->p[k], origin, w->p[k]);
+                       }
+                       MakePatchForFace (fn, w);
+               }
+       }
+
+       Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)(totalarea/64));
+}
+
+/*
+=======================================================================
+
+SUBDIVIDE
+
+=======================================================================
+*/
+
+void FinishSplit (patch_t *patch, patch_t *newp)
+{
+       dleaf_t         *leaf;
+
+       VectorCopy (patch->baselight, newp->baselight);
+       VectorCopy (patch->totallight, newp->totallight);
+       VectorCopy (patch->reflectivity, newp->reflectivity);
+       newp->plane = patch->plane;
+       newp->sky = patch->sky;
+
+       patch->area = WindingArea (patch->winding);
+       newp->area = WindingArea (newp->winding);
+
+       if (patch->area <= 1)
+               patch->area = 1;
+       if (newp->area <= 1)
+               newp->area = 1;
+
+       WindingCenter (patch->winding, patch->origin);
+       VectorAdd (patch->origin, patch->plane->normal, patch->origin);
+       leaf = Rad_PointInLeaf(patch->origin);
+       patch->cluster = leaf->cluster;
+       if (patch->cluster == -1)
+               Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
+
+       WindingCenter (newp->winding, newp->origin);
+       VectorAdd (newp->origin, newp->plane->normal, newp->origin);
+       leaf = Rad_PointInLeaf(newp->origin);
+       newp->cluster = leaf->cluster;
+       if (newp->cluster == -1)
+               Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
+}
+
+/*
+=============
+SubdividePatch
+
+Chops the patch only if its local bounds exceed the max size
+=============
+*/
+void   SubdividePatch (patch_t *patch)
+{
+       winding_t *w, *o1, *o2;
+       vec3_t  mins, maxs, total;
+       vec3_t  split;
+       vec_t   dist;
+       int             i, j;
+       vec_t   v;
+       patch_t *newp;
+
+       w = patch->winding;
+       mins[0] = mins[1] = mins[2] = 99999;
+       maxs[0] = maxs[1] = maxs[2] = -99999;
+       for (i=0 ; i<w->numpoints ; i++)
+       {
+               for (j=0 ; j<3 ; j++)
+               {
+                       v = w->p[i][j];
+                       if (v < mins[j])
+                               mins[j] = v;
+                       if (v > maxs[j])
+                               maxs[j] = v;
+               }
+       }
+       VectorSubtract (maxs, mins, total);
+       for (i=0 ; i<3 ; i++)
+               if (total[i] > (subdiv+1) )
+                       break;
+       if (i == 3)
+       {
+               // no splitting needed
+               return;         
+       }
+
+       //
+       // split the winding
+       //
+       VectorCopy (vec3_origin, split);
+       split[i] = 1;
+       dist = (mins[i] + maxs[i])*0.5;
+       ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
+
+       //
+       // create a new patch
+       //
+       if (num_patches == MAX_PATCHES)
+               Error ("MAX_PATCHES");
+       newp = &patches[num_patches];
+       num_patches++;
+
+       newp->next = patch->next;
+       patch->next = newp;
+
+       patch->winding = o1;
+       newp->winding = o2;
+
+       FinishSplit (patch, newp);
+
+       SubdividePatch (patch);
+       SubdividePatch (newp);
+}
+
+
+/*
+=============
+DicePatch
+
+Chops the patch by a global grid
+=============
+*/
+void   DicePatch (patch_t *patch)
+{
+       winding_t *w, *o1, *o2;
+       vec3_t  mins, maxs;
+       vec3_t  split;
+       vec_t   dist;
+       int             i;
+       patch_t *newp;
+
+       w = patch->winding;
+       WindingBounds (w, mins, maxs);
+       for (i=0 ; i<3 ; i++)
+               if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv))
+                       break;
+       if (i == 3)
+       {
+               // no splitting needed
+               return;         
+       }
+
+       //
+       // split the winding
+       //
+       VectorCopy (vec3_origin, split);
+       split[i] = 1;
+       dist = subdiv*(1+floor((mins[i]+1)/subdiv));
+       ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
+
+       //
+       // create a new patch
+       //
+       if (num_patches == MAX_PATCHES)
+               Error ("MAX_PATCHES");
+       newp = &patches[num_patches];
+       num_patches++;
+
+       newp->next = patch->next;
+       patch->next = newp;
+
+       patch->winding = o1;
+       newp->winding = o2;
+
+       FinishSplit (patch, newp);
+
+       DicePatch (patch);
+       DicePatch (newp);
+}
+
+
+/*
+=============
+SubdividePatches
+=============
+*/
+void SubdividePatches (void)
+{
+       int             i, num;
+
+       if (subdiv < 1)
+               return;
+
+       num = num_patches;      // because the list will grow
+       for (i=0 ; i<num ; i++)
+       {
+//             SubdividePatch (&patches[i]);
+               DicePatch (&patches[i]);
+       }
+       Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches);
+}
+
+//=====================================================================