--- /dev/null
+Index: brush.c\r
+===================================================================\r
+--- brush.c (revision 158)\r
++++ brush.c (working copy)\r
+@@ -78,7 +78,7 @@\r
+
+
+ /* count brushes */
+- for( brushes; brushes != NULL; brushes = brushes->next )
++ for( ; brushes != NULL; brushes = brushes->next )
+ c++;
+ return c;
+ }
+@@ -122,7 +122,7 @@\r
+
+
+ /* error check */
+- if( *((int*) b) == 0xFEFEFEFE )
++ if( *((unsigned int*) b) == 0xFEFEFEFE )
+ {
+ Sys_FPrintf( SYS_VRB, "WARNING: Attempt to free an already freed brush!\n" );
+ return;
+@@ -135,7 +135,7 @@\r
+
+ /* ydnar: overwrite it */
+ memset( b, 0xFE, (int) &(((brush_t*) 0)->sides[ b->numsides ]) );
+- *((int*) b) = 0xFEFEFEFE;
++ *((unsigned int*) b) = 0xFEFEFEFE;
+
+ /* free it */
+ free( b );
+@@ -156,7 +156,7 @@\r
+
+
+ /* walk brush list */
+- for( brushes; brushes != NULL; brushes = next )
++ for( ; brushes != NULL; brushes = next )
+ {
+ next = brushes->next;
+ FreeBrush( brushes );
+Index: bsp.c\r
+===================================================================\r
+--- bsp.c (revision 158)\r
++++ bsp.c (working copy)\r
+@@ -194,7 +194,6 @@\r
+ char level[ 2 ], shader[ 1024 ];
+ const char *value;
+
+-
+ /* sets integer blockSize from worldspawn "_blocksize" key if it exists */
+ value = ValueForKey( &entities[ 0 ], "_blocksize" );
+ if( value[ 0 ] == '\0' )
+@@ -531,6 +530,9 @@\r
+
+ /* write fogs */
+ EmitFogs();
++
++ /* vortex: emit meta stats */
++ EmitMetaStats();
+ }
+
+
+Index: bspfile_abstract.c\r
+===================================================================\r
+--- bspfile_abstract.c (revision 158)\r
++++ bspfile_abstract.c (working copy)\r
+@@ -683,8 +683,26 @@\r
+ ep->value = copystring( value );
+ }
+
++/*
++KeyExists()
++returns true if entity has this key
++*/
+
++qboolean KeyExists( const entity_t *ent, const char *key )
++{
++ epair_t *ep;
++
++ /* walk epair list */
++ for( ep = ent->epairs; ep != NULL; ep = ep->next )
++ {
++ if( !EPAIR_STRCMP( ep->key, key ) )
++ return qtrue;
++ }
+
++ /* no match */
++ return qfalse;
++}
++
+ /*
+ ValueForKey()
+ gets the value for an entity key
+@@ -803,7 +821,6 @@\r
+ {
+ const char *value;
+
+-
+ /* get cast shadows */
+ if( castShadows != NULL )
+ {
+@@ -831,5 +848,19 @@\r
+ if( value[ 0 ] != '\0' )
+ *recvShadows = atoi( value );
+ }
++
++ /* vortex: game-specific default eneity keys */
++ value = ValueForKey( ent, "classname" );
++ if (!Q_stricmp( game->magic, "dq" ) || !Q_stricmp( game->magic, "prophecy" ) )
++ {
++ /* vortex: deluxe quake default shadow flags */
++ if (!Q_stricmp( value, "func_wall" ) )
++ {
++ if( recvShadows != NULL )
++ *recvShadows = 1;
++ if( castShadows != NULL )
++ *castShadows = 1;
++ }
++ }
+ }
+
+Index: facebsp.c\r
+===================================================================\r
+--- facebsp.c (revision 158)\r
++++ facebsp.c (working copy)\r
+@@ -180,7 +180,7 @@\r
+
+
+ c = 0;
+- for( list; list != NULL; list = list->next )
++ for( ; list != NULL; list = list->next )
+ c++;
+ return c;
+ }
+Index: game_ef.h\r
+===================================================================\r
+--- game_ef.h (revision 158)\r
++++ game_ef.h (working copy)\r
+@@ -113,7 +113,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "IBSP", /* bsp file prefix */
+ 46, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_etut.h\r
+===================================================================\r
+--- game_etut.h (revision 158)\r
++++ game_etut.h (working copy)\r
+@@ -148,7 +148,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 2.2f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "IBSP", /* bsp file prefix */
+ 47, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_ja.h\r
+===================================================================\r
+--- game_ja.h (revision 158)\r
++++ game_ja.h (working copy)\r
+@@ -67,7 +67,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "RBSP", /* bsp file prefix */
+ 1, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_jk2.h\r
+===================================================================\r
+--- game_jk2.h (revision 158)\r
++++ game_jk2.h (working copy)\r
+@@ -64,7 +64,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "RBSP", /* bsp file prefix */
+ 1, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_qfusion.h\r
+===================================================================\r
+--- game_qfusion.h (revision 158)\r
++++ game_qfusion.h (working copy)\r
+@@ -1,195 +1,204 @@\r
+-/* -------------------------------------------------------------------------------
+-
+-This code is based on source provided under the terms of the Id Software
+-LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with the
+-GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of
+-LICENSE_ID, please contact Id Software immediately at info@idsoftware.com.
+-
+-All changes and additions to the original source which have been developed by
+-other contributors (see CONTRIBUTORS) are provided under the terms of the
+-license the contributors choose (see LICENSE), to the extent permitted by the
+-LICENSE_ID. If you did not receive a copy of the contributor license,
+-please contact the GtkRadiant maintainers at info@gtkradiant.com immediately.
+-
+-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-
+-----------------------------------------------------------------------------------
+-
+-This code has been altered significantly from its original form, to support
+-several games based on the Quake III Arena engine, in the form of "Q3Map2."
+-
+-------------------------------------------------------------------------------- */
+-
+-
+-
+-/* marker */
+-#ifndef GAME_QFUSION_H
+-#define GAME_QFUSION_H
+-
+-
+-
+-/* -------------------------------------------------------------------------------
+-
+-content and surface flags
+-
+-------------------------------------------------------------------------------- */
+-
+-/* game flags */
+-#define F_CONT_SOLID 1 /* an eye is never valid in a solid */
+-#define F_CONT_LAVA 8
+-#define F_CONT_SLIME 16
+-#define F_CONT_WATER 32
+-#define F_CONT_FOG 64
+-
+-#define F_CONT_AREAPORTAL 0x8000
+-
+-#define F_CONT_PLAYERCLIP 0x10000
+-#define F_CONT_MONSTERCLIP 0x20000
+-#define F_CONT_TELEPORTER 0x40000
+-#define F_CONT_JUMPPAD 0x80000
+-#define F_CONT_CLUSTERPORTAL 0x100000
+-#define F_CONT_DONOTENTER 0x200000
+-#define F_CONT_BOTCLIP 0x400000
+-
+-#define F_CONT_ORIGIN 0x1000000 /* removed before bsping an entity */
+-
+-#define F_CONT_BODY 0x2000000 /* should never be on a brush, only in game */
+-#define F_CONT_CORPSE 0x4000000
+-#define F_CONT_DETAIL 0x8000000 /* brushes not used for the bsp */
+-#define F_CONT_STRUCTURAL 0x10000000 /* brushes used for the bsp */
+-#define F_CONT_TRANSLUCENT 0x20000000 /* don't consume surface fragments inside */
+-#define F_CONT_TRIGGER 0x40000000
+-#define F_CONT_NODROP 0x80000000 /* don't leave bodies or items (death fog, lava) */
+-
+-#define F_SURF_NODAMAGE 0x1 /* never give falling damage */
+-#define F_SURF_SLICK 0x2 /* effects game physics */
+-#define F_SURF_SKY 0x4 /* lighting from environment map */
+-#define F_SURF_LADDER 0x8
+-#define F_SURF_NOIMPACT 0x10 /* don't make missile explosions */
+-#define F_SURF_NOMARKS 0x20 /* don't leave missile marks */
+-#define F_SURF_FLESH 0x40 /* make flesh sounds and effects */
+-#define F_SURF_NODRAW 0x80 /* don't generate a drawsurface at all */
+-#define F_SURF_HINT 0x100 /* make a primary bsp splitter */
+-#define F_SURF_SKIP 0x200 /* completely ignore, allowing non-closed brushes */
+-#define F_SURF_NOLIGHTMAP 0x400 /* surface doesn't need a lightmap */
+-#define F_SURF_POINTLIGHT 0x800 /* generate lighting info at vertexes */
+-#define F_SURF_METALSTEPS 0x1000 /* clanking footsteps */
+-#define F_SURF_NOSTEPS 0x2000 /* no footstep sounds */
+-#define F_SURF_NONSOLID 0x4000 /* don't collide against curves with this set */
+-#define F_SURF_LIGHTFILTER 0x8000 /* act as a light filter during q3map -light */
+-#define F_SURF_ALPHASHADOW 0x10000 /* do per-pixel light shadow casting in q3map */
+-#define F_SURF_NODLIGHT 0x20000 /* don't dlight even if solid (solid lava, skies) */
+-#define F_SURF_DUST 0x40000 /* leave a dust trail when walking on this surface */
+-
+-/* ydnar flags */
+-#define F_SURF_VERTEXLIT (F_SURF_POINTLIGHT | F_SURF_NOLIGHTMAP)
+-
+-
+-
+-/* -------------------------------------------------------------------------------
+-
+-game_t struct
+-
+-------------------------------------------------------------------------------- */
+-
+-{
+- "qfusion", /* -game x */
+- "baseq3", /* default base game data dir */
+- ".q3a", /* unix home sub-dir */
+- "quake", /* magic path word */
+- "scripts", /* shader directory */
+- 2048, /* max lightmapped surface verts */
+- 2048, /* max surface verts */
+- 12288, /* max surface indexes */
+- qtrue, /* flares */
+- "flareshader", /* default flare shader */
+- qfalse, /* wolf lighting model? */
+- 512, /* lightmap width/height */
+- 1.0f, /* lightmap gamma */
+- 1.0f, /* lightmap compensate */
+- "FBSP", /* bsp file prefix */
+- 1, /* bsp file version */
+- qfalse, /* cod-style lump len/ofs order */
+- LoadRBSPFile, /* bsp load function */
+- WriteRBSPFile, /* bsp write function */
+-
+- {
+- /* name contentFlags contentFlagsClear surfaceFlags surfaceFlagsClear compileFlags compileFlagsClear */
+-
+- /* default */
+- { "default", F_CONT_SOLID, -1, 0, -1, C_SOLID, -1 },
+-
+-
+- /* ydnar */
+- { "lightgrid", 0, 0, 0, 0, C_LIGHTGRID, 0 },
+- { "antiportal", 0, 0, 0, 0, C_ANTIPORTAL, 0 },
+- { "skip", 0, 0, 0, 0, C_SKIP, 0 },
+-
+-
+- /* compiler */
+- { "origin", F_CONT_ORIGIN, F_CONT_SOLID, 0, 0, C_ORIGIN | C_TRANSLUCENT, C_SOLID },
+- { "areaportal", F_CONT_AREAPORTAL, F_CONT_SOLID, 0, 0, C_AREAPORTAL | C_TRANSLUCENT, C_SOLID },
+- { "trans", F_CONT_TRANSLUCENT, 0, 0, 0, C_TRANSLUCENT, 0 },
+- { "detail", F_CONT_DETAIL, 0, 0, 0, C_DETAIL, 0 },
+- { "structural", F_CONT_STRUCTURAL, 0, 0, 0, C_STRUCTURAL, 0 },
+- { "hint", 0, 0, F_SURF_HINT, 0, C_HINT, 0 },
+- { "nodraw", 0, 0, F_SURF_NODRAW, 0, C_NODRAW, 0 },
+-
+- { "alphashadow", 0, 0, F_SURF_ALPHASHADOW, 0, C_ALPHASHADOW | C_TRANSLUCENT, 0 },
+- { "lightfilter", 0, 0, F_SURF_LIGHTFILTER, 0, C_LIGHTFILTER | C_TRANSLUCENT, 0 },
+- { "nolightmap", 0, 0, F_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },
+- { "pointlight", 0, 0, F_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },
+-
+-
+- /* game */
+- { "nonsolid", 0, F_CONT_SOLID, F_SURF_NONSOLID, 0, 0, C_SOLID },
+-
+- { "trigger", F_CONT_TRIGGER, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+-
+- { "water", F_CONT_WATER, F_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },
+- { "slime", F_CONT_SLIME, F_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },
+- { "lava", F_CONT_LAVA, F_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },
+-
+- { "playerclip", F_CONT_PLAYERCLIP, F_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },
+- { "monsterclip", F_CONT_MONSTERCLIP, F_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },
+- { "nodrop", F_CONT_NODROP, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+-
+- { "clusterportal", F_CONT_CLUSTERPORTAL, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+- { "donotenter", F_CONT_DONOTENTER, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+- { "botclip", F_CONT_BOTCLIP, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+-
+- { "fog", F_CONT_FOG, F_CONT_SOLID, 0, 0, C_FOG, C_SOLID },
+- { "sky", 0, 0, F_SURF_SKY, 0, C_SKY, 0 },
+-
+- { "slick", 0, 0, F_SURF_SLICK, 0, 0, 0 },
+-
+- { "noimpact", 0, 0, F_SURF_NOIMPACT, 0, 0, 0 },
+- { "nomarks", 0, 0, F_SURF_NOMARKS, 0, C_NOMARKS, 0 },
+- { "ladder", 0, 0, F_SURF_LADDER, 0, 0, 0 },
+- { "nodamage", 0, 0, F_SURF_NODAMAGE, 0, 0, 0 },
+- { "metalsteps", 0, 0, F_SURF_METALSTEPS, 0, 0, 0 },
+- { "flesh", 0, 0, F_SURF_FLESH, 0, 0, 0 },
+- { "nosteps", 0, 0, F_SURF_NOSTEPS, 0, 0, 0 },
+- { "nodlight", 0, 0, F_SURF_NODLIGHT, 0, 0, 0 },
+- { "dust", 0, 0, F_SURF_DUST, 0, 0, 0 },
+-
+-
+- /* null */
+- { NULL, 0, 0, 0, 0, 0, 0 }
+- }
+-}
+-
+-
+-
+-/* end marker */
+-#endif
+-
++/* -------------------------------------------------------------------------------\r
++\r
++This code is based on source provided under the terms of the Id Software \r
++LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with the\r
++GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of \r
++LICENSE_ID, please contact Id Software immediately at info@idsoftware.com.\r
++\r
++All changes and additions to the original source which have been developed by\r
++other contributors (see CONTRIBUTORS) are provided under the terms of the\r
++license the contributors choose (see LICENSE), to the extent permitted by the\r
++LICENSE_ID. If you did not receive a copy of the contributor license,\r
++please contact the GtkRadiant maintainers at info@gtkradiant.com immediately.\r
++\r
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''\r
++AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
++IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
++DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY\r
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON\r
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
++\r
++----------------------------------------------------------------------------------\r
++\r
++This code has been altered significantly from its original form, to support\r
++several games based on the Quake III Arena engine, in the form of "Q3Map2."\r
++\r
++------------------------------------------------------------------------------- */\r
++\r
++\r
++\r
++/* marker */\r
++#ifndef GAME_QFUSION_H\r
++#define GAME_QFUSION_H\r
++\r
++\r
++\r
++/* -------------------------------------------------------------------------------\r
++\r
++content and surface flags\r
++\r
++------------------------------------------------------------------------------- */\r
++\r
++/* game flags */\r
++#define F_CONT_SOLID 1 /* an eye is never valid in a solid */\r
++#define F_CONT_LAVA 8\r
++#define F_CONT_SLIME 16\r
++#define F_CONT_WATER 32\r
++#define F_CONT_FOG 64\r
++\r
++#define F_CONT_AREAPORTAL 0x8000\r
++\r
++#define F_CONT_PLAYERCLIP 0x10000\r
++#define F_CONT_MONSTERCLIP 0x20000\r
++#define F_CONT_TELEPORTER 0x40000\r
++#define F_CONT_JUMPPAD 0x80000\r
++#define F_CONT_CLUSTERPORTAL 0x100000\r
++#define F_CONT_DONOTENTER 0x200000\r
++#define F_CONT_BOTCLIP 0x400000\r
++\r
++#define F_CONT_ORIGIN 0x1000000 /* removed before bsping an entity */\r
++\r
++#define F_CONT_BODY 0x2000000 /* should never be on a brush, only in game */\r
++#define F_CONT_CORPSE 0x4000000\r
++#define F_CONT_DETAIL 0x8000000 /* brushes not used for the bsp */\r
++#define F_CONT_STRUCTURAL 0x10000000 /* brushes used for the bsp */\r
++#define F_CONT_TRANSLUCENT 0x20000000 /* don't consume surface fragments inside */\r
++#define F_CONT_TRIGGER 0x40000000\r
++#define F_CONT_NODROP 0x80000000 /* don't leave bodies or items (death fog, lava) */\r
++\r
++#define F_SURF_NODAMAGE 0x1 /* never give falling damage */\r
++#define F_SURF_SLICK 0x2 /* effects game physics */\r
++#define F_SURF_SKY 0x4 /* lighting from environment map */\r
++#define F_SURF_LADDER 0x8\r
++#define F_SURF_NOIMPACT 0x10 /* don't make missile explosions */\r
++#define F_SURF_NOMARKS 0x20 /* don't leave missile marks */\r
++#define F_SURF_FLESH 0x40 /* make flesh sounds and effects */\r
++#define F_SURF_NODRAW 0x80 /* don't generate a drawsurface at all */\r
++#define F_SURF_HINT 0x100 /* make a primary bsp splitter */\r
++#define F_SURF_SKIP 0x200 /* completely ignore, allowing non-closed brushes */\r
++#define F_SURF_NOLIGHTMAP 0x400 /* surface doesn't need a lightmap */\r
++#define F_SURF_POINTLIGHT 0x800 /* generate lighting info at vertexes */\r
++#define F_SURF_METALSTEPS 0x1000 /* clanking footsteps */\r
++#define F_SURF_NOSTEPS 0x2000 /* no footstep sounds */\r
++#define F_SURF_NONSOLID 0x4000 /* don't collide against curves with this set */\r
++#define F_SURF_LIGHTFILTER 0x8000 /* act as a light filter during q3map -light */\r
++#define F_SURF_ALPHASHADOW 0x10000 /* do per-pixel light shadow casting in q3map */\r
++#define F_SURF_NODLIGHT 0x20000 /* don't dlight even if solid (solid lava, skies) */\r
++#define F_SURF_DUST 0x40000 /* leave a dust trail when walking on this surface */\r
++\r
++/* ydnar flags */\r
++#define F_SURF_VERTEXLIT (F_SURF_POINTLIGHT | F_SURF_NOLIGHTMAP)\r
++\r
++\r
++\r
++/* -------------------------------------------------------------------------------\r
++\r
++game_t struct\r
++\r
++------------------------------------------------------------------------------- */\r
++\r
++{\r
++ "qfusion", /* -game x */\r
++ "baseq3", /* default base game data dir */\r
++ ".q3a", /* unix home sub-dir */\r
++ "quake", /* magic path word */\r
++ "scripts", /* shader directory */\r
++ 2048, /* max lightmapped surface verts */\r
++ 2048, /* max surface verts */\r
++ 12288, /* max surface indexes */\r
++ qtrue, /* flares */\r
++ "flareshader", /* default flare shader */\r
++ qfalse, /* wolf lighting model? */\r
++ 512, /* lightmap width/height */\r
++ 1.0f, /* lightmap gamma */\r
++ 1.0f, /* lightmap exposure */\r
++ 1.0f, /* lightmap compensate */\r
++ 1.0f, /* lightgrid scale */\r
++ 1.0f, /* lightgrid ambient scale */\r
++ qfalse, /* disable shader lightstyles hack */\r
++ qfalse, /* keep light entities on bsp */\r
++ 8, /* default patchMeta subdivisions tolerance */\r
++ qfalse, /* patch casting enabled */\r
++ qfalse, /* compile deluxemaps */\r
++ 0, /* deluxemaps default mode */\r
++ "FBSP", /* bsp file prefix */\r
++ 1, /* bsp file version */\r
++ qfalse, /* cod-style lump len/ofs order */\r
++ LoadRBSPFile, /* bsp load function */\r
++ WriteRBSPFile, /* bsp write function */\r
++\r
++ {\r
++ /* name contentFlags contentFlagsClear surfaceFlags surfaceFlagsClear compileFlags compileFlagsClear */\r
++ \r
++ /* default */\r
++ { "default", F_CONT_SOLID, -1, 0, -1, C_SOLID, -1 },\r
++ \r
++ \r
++ /* ydnar */\r
++ { "lightgrid", 0, 0, 0, 0, C_LIGHTGRID, 0 },\r
++ { "antiportal", 0, 0, 0, 0, C_ANTIPORTAL, 0 },\r
++ { "skip", 0, 0, 0, 0, C_SKIP, 0 },\r
++ \r
++ \r
++ /* compiler */\r
++ { "origin", F_CONT_ORIGIN, F_CONT_SOLID, 0, 0, C_ORIGIN | C_TRANSLUCENT, C_SOLID },\r
++ { "areaportal", F_CONT_AREAPORTAL, F_CONT_SOLID, 0, 0, C_AREAPORTAL | C_TRANSLUCENT, C_SOLID },\r
++ { "trans", F_CONT_TRANSLUCENT, 0, 0, 0, C_TRANSLUCENT, 0 },\r
++ { "detail", F_CONT_DETAIL, 0, 0, 0, C_DETAIL, 0 },\r
++ { "structural", F_CONT_STRUCTURAL, 0, 0, 0, C_STRUCTURAL, 0 },\r
++ { "hint", 0, 0, F_SURF_HINT, 0, C_HINT, 0 },\r
++ { "nodraw", 0, 0, F_SURF_NODRAW, 0, C_NODRAW, 0 },\r
++ \r
++ { "alphashadow", 0, 0, F_SURF_ALPHASHADOW, 0, C_ALPHASHADOW | C_TRANSLUCENT, 0 },\r
++ { "lightfilter", 0, 0, F_SURF_LIGHTFILTER, 0, C_LIGHTFILTER | C_TRANSLUCENT, 0 },\r
++ { "nolightmap", 0, 0, F_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },\r
++ { "pointlight", 0, 0, F_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },\r
++ \r
++ \r
++ /* game */\r
++ { "nonsolid", 0, F_CONT_SOLID, F_SURF_NONSOLID, 0, 0, C_SOLID },\r
++ \r
++ { "trigger", F_CONT_TRIGGER, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "water", F_CONT_WATER, F_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },\r
++ { "slime", F_CONT_SLIME, F_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },\r
++ { "lava", F_CONT_LAVA, F_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "playerclip", F_CONT_PLAYERCLIP, F_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },\r
++ { "monsterclip", F_CONT_MONSTERCLIP, F_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },\r
++ { "nodrop", F_CONT_NODROP, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "clusterportal", F_CONT_CLUSTERPORTAL, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ { "donotenter", F_CONT_DONOTENTER, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ { "botclip", F_CONT_BOTCLIP, F_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "fog", F_CONT_FOG, F_CONT_SOLID, 0, 0, C_FOG, C_SOLID },\r
++ { "sky", 0, 0, F_SURF_SKY, 0, C_SKY, 0 },\r
++ \r
++ { "slick", 0, 0, F_SURF_SLICK, 0, 0, 0 },\r
++ \r
++ { "noimpact", 0, 0, F_SURF_NOIMPACT, 0, 0, 0 },\r
++ { "nomarks", 0, 0, F_SURF_NOMARKS, 0, C_NOMARKS, 0 },\r
++ { "ladder", 0, 0, F_SURF_LADDER, 0, 0, 0 },\r
++ { "nodamage", 0, 0, F_SURF_NODAMAGE, 0, 0, 0 },\r
++ { "metalsteps", 0, 0, F_SURF_METALSTEPS, 0, 0, 0 },\r
++ { "flesh", 0, 0, F_SURF_FLESH, 0, 0, 0 },\r
++ { "nosteps", 0, 0, F_SURF_NOSTEPS, 0, 0, 0 },\r
++ { "nodlight", 0, 0, F_SURF_NODLIGHT, 0, 0, 0 },\r
++ { "dust", 0, 0, F_SURF_DUST, 0, 0, 0 },\r
++ \r
++ \r
++ /* null */\r
++ { NULL, 0, 0, 0, 0, 0, 0 }\r
++ }\r
++}\r
++\r
++\r
++\r
++/* end marker */\r
++#endif\r
++\r
+Index: game_quake3.h\r
+===================================================================\r
+--- game_quake3.h (revision 158)\r
++++ game_quake3.h (working copy)\r
+@@ -112,7 +112,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "IBSP", /* bsp file prefix */
+ 46, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_sof2.h\r
+===================================================================\r
+--- game_sof2.h (revision 158)\r
++++ game_sof2.h (working copy)\r
+@@ -139,7 +139,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "RBSP", /* bsp file prefix */
+ 1, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_tenebrae.h\r
+===================================================================\r
+--- game_tenebrae.h (revision 158)\r
++++ game_tenebrae.h (working copy)\r
+@@ -112,7 +112,16 @@\r
+ qfalse, /* wolf lighting model? */
+ 512, /* lightmap width/height */
+ 2.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qtrue, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qtrue, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "IBSP", /* bsp file prefix */
+ 46, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_tremulous.h\r
+===================================================================\r
+--- game_tremulous.h (revision 158)\r
++++ game_tremulous.h (working copy)\r
+@@ -1,160 +1,169 @@\r
+-/* -------------------------------------------------------------------------------
+-
+-Copyright (C) 1999-2006 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
+-
+-----------------------------------------------------------------------------------
+-
+-This code has been altered significantly from its original form, to support
+-several games based on the Quake III Arena engine, in the form of "Q3Map2."
+-
+-------------------------------------------------------------------------------- */
+-
+-/* Tremulous support, by LinuxManMikeC */
+-
+-
+-/* marker */
+-#ifndef GAME_TREMULOUS_H
+-#define GAME_TREMULOUS_H
+-
+-
+-
+-/* -------------------------------------------------------------------------------
+-
+-content and surface flags - also uses defines from game_quake3.h
+-
+-------------------------------------------------------------------------------- */
+-#define TREM_CONT_NOALIENBUILD 0x1000
+-#define TREM_CONT_NOHUMANBUILD 0x2000
+-#define TREM_CONT_NOBUILD 0x4000
+-
+-#define TREM_SURF_NOALIENBUILDSURFACE 0x80000
+-#define TREM_SURF_NOHUMANBUILDSURFACE 0x100000
+-#define TREM_SURF_NOBUILDSURFACE 0x200000
+-
+-
+-
+-/* -------------------------------------------------------------------------------
+-
+-game_t struct
+-
+-------------------------------------------------------------------------------- */
+-
+-{
+- "tremulous", /* -game x */
+- "base", /* default base game data dir */
+- ".tremulous", /* unix home sub-dir */
+- "tremulous", /* magic path word - think this is right for trem*/
+- "scripts", /* shader directory */
+- 64, /* max lightmapped surface verts */
+- 999, /* max surface verts */
+- 6000, /* max surface indexes */
+- qfalse, /* flares */
+- "flareshader", /* default flare shader */
+- qfalse, /* wolf lighting model? */
+- 128, /* lightmap width/height */
+- 1.0f, /* lightmap gamma */
+- 1.0f, /* lightmap compensate */
+- "IBSP", /* bsp file prefix */
+- 46, /* bsp file version */
+- qfalse, /* cod-style lump len/ofs order */
+- LoadIBSPFile, /* bsp load function */
+- WriteIBSPFile, /* bsp write function */
+-
+- {
+- /* name contentFlags contentFlagsClear surfaceFlags surfaceFlagsClear compileFlags compileFlagsClear */
+-
+- /* default */
+- { "default", Q_CONT_SOLID, -1, 0, -1, C_SOLID, -1 },
+-
+-
+- /* ydnar */
+- { "lightgrid", 0, 0, 0, 0, C_LIGHTGRID, 0 },
+- { "antiportal", 0, 0, 0, 0, C_ANTIPORTAL, 0 },
+- { "skip", 0, 0, 0, 0, C_SKIP, 0 },
+-
+-
+- /* compiler */
+- { "origin", Q_CONT_ORIGIN, Q_CONT_SOLID, 0, 0, C_ORIGIN | C_TRANSLUCENT, C_SOLID },
+- { "areaportal", Q_CONT_AREAPORTAL, Q_CONT_SOLID, 0, 0, C_AREAPORTAL | C_TRANSLUCENT, C_SOLID },
+- { "trans", Q_CONT_TRANSLUCENT, 0, 0, 0, C_TRANSLUCENT, 0 },
+- { "detail", Q_CONT_DETAIL, 0, 0, 0, C_DETAIL, 0 },
+- { "structural", Q_CONT_STRUCTURAL, 0, 0, 0, C_STRUCTURAL, 0 },
+- { "hint", 0, 0, Q_SURF_HINT, 0, C_HINT, 0 },
+- { "nodraw", 0, 0, Q_SURF_NODRAW, 0, C_NODRAW, 0 },
+-
+- { "alphashadow", 0, 0, Q_SURF_ALPHASHADOW, 0, C_ALPHASHADOW | C_TRANSLUCENT, 0 },
+- { "lightfilter", 0, 0, Q_SURF_LIGHTFILTER, 0, C_LIGHTFILTER | C_TRANSLUCENT, 0 },
+- { "nolightmap", 0, 0, Q_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },
+- { "pointlight", 0, 0, Q_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },
+-
+-
+- /* game */
+- { "nonsolid", 0, Q_CONT_SOLID, Q_SURF_NONSOLID, 0, 0, C_SOLID },
+-
+- { "trigger", Q_CONT_TRIGGER, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+-
+- { "water", Q_CONT_WATER, Q_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },
+- { "slime", Q_CONT_SLIME, Q_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },
+- { "lava", Q_CONT_LAVA, Q_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },
+-
+- { "playerclip", Q_CONT_PLAYERCLIP, Q_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },
+- { "monsterclip", Q_CONT_MONSTERCLIP, Q_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },
+- { "nodrop", Q_CONT_NODROP, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+-
+- { "clusterportal", Q_CONT_CLUSTERPORTAL, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+- { "donotenter", Q_CONT_DONOTENTER, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+- { "botclip", Q_CONT_BOTCLIP, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },
+-
+- { "fog", Q_CONT_FOG, Q_CONT_SOLID, 0, 0, C_FOG, C_SOLID },
+- { "sky", 0, 0, Q_SURF_SKY, 0, C_SKY, 0 },
+-
+- { "slick", 0, 0, Q_SURF_SLICK, 0, 0, 0 },
+-
+- { "noimpact", 0, 0, Q_SURF_NOIMPACT, 0, 0, 0 },
+- { "nomarks", 0, 0, Q_SURF_NOMARKS, 0, C_NOMARKS, 0 },
+- { "ladder", 0, 0, Q_SURF_LADDER, 0, 0, 0 },
+- { "nodamage", 0, 0, Q_SURF_NODAMAGE, 0, 0, 0 },
+- { "metalsteps", 0, 0, Q_SURF_METALSTEPS, 0, 0, 0 },
+- { "flesh", 0, 0, Q_SURF_FLESH, 0, 0, 0 },
+- { "nosteps", 0, 0, Q_SURF_NOSTEPS, 0, 0, 0 },
+- { "nodlight", 0, 0, Q_SURF_NODLIGHT, 0, 0, 0 },
+- { "dust", 0, 0, Q_SURF_DUST, 0, 0, 0 },
+-
+-
+- /* tremulous */
+- {"noalienbuild", TREM_CONT_NOALIENBUILD,0,0,0,0,0},
+- {"nohumanbuild", TREM_CONT_NOHUMANBUILD,0,0,0,0,0},
+- {"nobuild", TREM_CONT_NOBUILD,0,0,0,0,0},
+-
+- {"noalienbuildsurface", 0,0,TREM_SURF_NOALIENBUILDSURFACE,0,0,0},
+- {"nohumanbuildsurface", 0,0,TREM_SURF_NOHUMANBUILDSURFACE,0,0,0},
+- {"nobuildsurface", 0,0,TREM_SURF_NOBUILDSURFACE,0,0,0},
+-
+-
+- /* null */
+- { NULL, 0, 0, 0, 0, 0, 0 }
+- }
+-}
+-
+-
+-
+-/* end marker */
+-#endif
+-
++/* -------------------------------------------------------------------------------\r
++\r
++Copyright (C) 1999-2006 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
++\r
++This code has been altered significantly from its original form, to support\r
++several games based on the Quake III Arena engine, in the form of "Q3Map2."\r
++\r
++------------------------------------------------------------------------------- */\r
++\r
++/* Tremulous support, by LinuxManMikeC */\r
++\r
++\r
++/* marker */\r
++#ifndef GAME_TREMULOUS_H\r
++#define GAME_TREMULOUS_H\r
++\r
++\r
++\r
++/* -------------------------------------------------------------------------------\r
++\r
++content and surface flags - also uses defines from game_quake3.h\r
++\r
++------------------------------------------------------------------------------- */\r
++#define TREM_CONT_NOALIENBUILD 0x1000\r
++#define TREM_CONT_NOHUMANBUILD 0x2000\r
++#define TREM_CONT_NOBUILD 0x4000\r
++ \r
++#define TREM_SURF_NOALIENBUILDSURFACE 0x80000 \r
++#define TREM_SURF_NOHUMANBUILDSURFACE 0x100000\r
++#define TREM_SURF_NOBUILDSURFACE 0x200000\r
++\r
++\r
++\r
++/* -------------------------------------------------------------------------------\r
++\r
++game_t struct\r
++\r
++------------------------------------------------------------------------------- */\r
++\r
++{\r
++ "tremulous", /* -game x */\r
++ "base", /* default base game data dir */\r
++ ".tremulous", /* unix home sub-dir */\r
++ "tremulous", /* magic path word - think this is right for trem*/\r
++ "scripts", /* shader directory */\r
++ 64, /* max lightmapped surface verts */\r
++ 999, /* max surface verts */\r
++ 6000, /* max surface indexes */\r
++ qfalse, /* flares */\r
++ "flareshader", /* default flare shader */\r
++ qfalse, /* wolf lighting model? */\r
++ 128, /* lightmap width/height */\r
++ 1.0f, /* lightmap gamma */\r
++ 1.0f, /* lightmap exposure */\r
++ 1.0f, /* lightmap compensate */\r
++ 1.0f, /* lightgrid scale */\r
++ 1.0f, /* lightgrid ambient scale */\r
++ qfalse, /* disable shader lightstyles hack */\r
++ qfalse, /* keep light entities on bsp */\r
++ 8, /* default patchMeta subdivisions tolerance */\r
++ qfalse, /* patch casting enabled */\r
++ qfalse, /* compile deluxemaps */\r
++ 0, /* deluxemaps default mode */\r
++ "IBSP", /* bsp file prefix */\r
++ 46, /* bsp file version */\r
++ qfalse, /* cod-style lump len/ofs order */\r
++ LoadIBSPFile, /* bsp load function */\r
++ WriteIBSPFile, /* bsp write function */\r
++\r
++ {\r
++ /* name contentFlags contentFlagsClear surfaceFlags surfaceFlagsClear compileFlags compileFlagsClear */\r
++ \r
++ /* default */\r
++ { "default", Q_CONT_SOLID, -1, 0, -1, C_SOLID, -1 },\r
++ \r
++ \r
++ /* ydnar */\r
++ { "lightgrid", 0, 0, 0, 0, C_LIGHTGRID, 0 },\r
++ { "antiportal", 0, 0, 0, 0, C_ANTIPORTAL, 0 },\r
++ { "skip", 0, 0, 0, 0, C_SKIP, 0 },\r
++ \r
++ \r
++ /* compiler */\r
++ { "origin", Q_CONT_ORIGIN, Q_CONT_SOLID, 0, 0, C_ORIGIN | C_TRANSLUCENT, C_SOLID },\r
++ { "areaportal", Q_CONT_AREAPORTAL, Q_CONT_SOLID, 0, 0, C_AREAPORTAL | C_TRANSLUCENT, C_SOLID },\r
++ { "trans", Q_CONT_TRANSLUCENT, 0, 0, 0, C_TRANSLUCENT, 0 },\r
++ { "detail", Q_CONT_DETAIL, 0, 0, 0, C_DETAIL, 0 },\r
++ { "structural", Q_CONT_STRUCTURAL, 0, 0, 0, C_STRUCTURAL, 0 },\r
++ { "hint", 0, 0, Q_SURF_HINT, 0, C_HINT, 0 },\r
++ { "nodraw", 0, 0, Q_SURF_NODRAW, 0, C_NODRAW, 0 },\r
++ \r
++ { "alphashadow", 0, 0, Q_SURF_ALPHASHADOW, 0, C_ALPHASHADOW | C_TRANSLUCENT, 0 },\r
++ { "lightfilter", 0, 0, Q_SURF_LIGHTFILTER, 0, C_LIGHTFILTER | C_TRANSLUCENT, 0 },\r
++ { "nolightmap", 0, 0, Q_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },\r
++ { "pointlight", 0, 0, Q_SURF_VERTEXLIT, 0, C_VERTEXLIT, 0 },\r
++ \r
++ \r
++ /* game */\r
++ { "nonsolid", 0, Q_CONT_SOLID, Q_SURF_NONSOLID, 0, 0, C_SOLID },\r
++ \r
++ { "trigger", Q_CONT_TRIGGER, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "water", Q_CONT_WATER, Q_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },\r
++ { "slime", Q_CONT_SLIME, Q_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },\r
++ { "lava", Q_CONT_LAVA, Q_CONT_SOLID, 0, 0, C_LIQUID | C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "playerclip", Q_CONT_PLAYERCLIP, Q_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },\r
++ { "monsterclip", Q_CONT_MONSTERCLIP, Q_CONT_SOLID, 0, 0, C_DETAIL | C_TRANSLUCENT, C_SOLID },\r
++ { "nodrop", Q_CONT_NODROP, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "clusterportal", Q_CONT_CLUSTERPORTAL, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ { "donotenter", Q_CONT_DONOTENTER, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ { "botclip", Q_CONT_BOTCLIP, Q_CONT_SOLID, 0, 0, C_TRANSLUCENT, C_SOLID },\r
++ \r
++ { "fog", Q_CONT_FOG, Q_CONT_SOLID, 0, 0, C_FOG, C_SOLID },\r
++ { "sky", 0, 0, Q_SURF_SKY, 0, C_SKY, 0 },\r
++ \r
++ { "slick", 0, 0, Q_SURF_SLICK, 0, 0, 0 },\r
++ \r
++ { "noimpact", 0, 0, Q_SURF_NOIMPACT, 0, 0, 0 },\r
++ { "nomarks", 0, 0, Q_SURF_NOMARKS, 0, C_NOMARKS, 0 },\r
++ { "ladder", 0, 0, Q_SURF_LADDER, 0, 0, 0 },\r
++ { "nodamage", 0, 0, Q_SURF_NODAMAGE, 0, 0, 0 },\r
++ { "metalsteps", 0, 0, Q_SURF_METALSTEPS, 0, 0, 0 },\r
++ { "flesh", 0, 0, Q_SURF_FLESH, 0, 0, 0 },\r
++ { "nosteps", 0, 0, Q_SURF_NOSTEPS, 0, 0, 0 },\r
++ { "nodlight", 0, 0, Q_SURF_NODLIGHT, 0, 0, 0 },\r
++ { "dust", 0, 0, Q_SURF_DUST, 0, 0, 0 },\r
++ \r
++ \r
++ /* tremulous */\r
++ {"noalienbuild", TREM_CONT_NOALIENBUILD,0,0,0,0,0},\r
++ {"nohumanbuild", TREM_CONT_NOHUMANBUILD,0,0,0,0,0},\r
++ {"nobuild", TREM_CONT_NOBUILD,0,0,0,0,0},\r
++ \r
++ {"noalienbuildsurface", 0,0,TREM_SURF_NOALIENBUILDSURFACE,0,0,0},\r
++ {"nohumanbuildsurface", 0,0,TREM_SURF_NOHUMANBUILDSURFACE,0,0,0},\r
++ {"nobuildsurface", 0,0,TREM_SURF_NOBUILDSURFACE,0,0,0},\r
++ \r
++ \r
++ /* null */\r
++ { NULL, 0, 0, 0, 0, 0, 0 }\r
++ }\r
++}\r
++\r
++\r
++\r
++/* end marker */\r
++#endif\r
++\r
+Index: game_wolf.h\r
+===================================================================\r
+--- game_wolf.h (revision 158)\r
++++ game_wolf.h (working copy)\r
+@@ -129,7 +129,16 @@\r
+ qtrue, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "IBSP", /* bsp file prefix */
+ 47, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: game_wolfet.h\r
+===================================================================\r
+--- game_wolfet.h (revision 158)\r
++++ game_wolfet.h (working copy)\r
+@@ -66,7 +66,16 @@\r
+ qtrue, /* wolf lighting model? */
+ 128, /* lightmap width/height */
+ 1.0f, /* lightmap gamma */
++ 1.0f, /* lightmap exposure */
+ 1.0f, /* lightmap compensate */
++ 1.0f, /* lightgrid scale */
++ 1.0f, /* lightgrid ambient scale */
++ qfalse, /* disable shader lightstyles hack */
++ qfalse, /* keep light entities on bsp */
++ 8, /* default patchMeta subdivisions tolerance */
++ qfalse, /* patch casting enabled */
++ qfalse, /* compile deluxemaps */
++ 0, /* deluxemaps default mode */
+ "IBSP", /* bsp file prefix */
+ 47, /* bsp file version */
+ qfalse, /* cod-style lump len/ofs order */
+Index: light.c\r
+===================================================================\r
+--- light.c (revision 158)\r
++++ light.c (working copy)\r
+@@ -313,7 +313,15 @@\r
+ flags |= LIGHT_GRID;
+ flags &= ~LIGHT_SURFACES;
+ }
+-
++
++ /* vortex: unnormalized? */
++ if (spawnflags & 32)
++ flags |= LIGHT_UNNORMALIZED;
++
++ /* vortex: distance atten? */
++ if (spawnflags & 64)
++ flags |= LIGHT_ATTEN_DISTANCE;
++
+ /* store the flags */
+ light->flags = flags;
+
+@@ -357,12 +365,13 @@\r
+ intensity *= scale;
+
+ /* ydnar: get deviance and samples */
++ /* VorteX: now set start value for _samples when _deviance is found */
+ deviance = FloatForKey( e, "_deviance" );
+ if( deviance == 0.0f )
+ deviance = FloatForKey( e, "_deviation" );
+ if( deviance == 0.0f )
+ deviance = FloatForKey( e, "_jitter" );
+- numSamples = IntForKey( e, "_samples" );
++ numSamples = max(IntForKey( e, "_samples" ), deviance);
+ if( deviance < 0.0f || numSamples < 1 )
+ {
+ deviance = 0.0f;
+@@ -385,14 +394,16 @@\r
+ if( _color && _color[ 0 ] )
+ {
+ sscanf( _color, "%f %f %f", &light->color[ 0 ], &light->color[ 1 ], &light->color[ 2 ] );
+- ColorNormalize( light->color, light->color );
++ if (!(light->flags & LIGHT_UNNORMALIZED))
++ {
++ ColorNormalize( light->color, light->color );
++ }
+ }
+ else
+ light->color[ 0 ] = light->color[ 1 ] = light->color[ 2 ] = 1.0f;
+-
++
+ intensity = intensity * pointScale;
+ light->photons = intensity;
+-
+ light->type = EMIT_POINT;
+
+ /* set falloff threshold */
+@@ -741,6 +752,7 @@\r
+
+ /* clear color */
+ VectorClear( trace->color );
++ VectorClear( trace->colorNoShadow );
+
+ /* ydnar: early out */
+ if( !(light->flags & LIGHT_SURFACES) || light->envelope <= 0.0f )
+@@ -766,7 +778,6 @@\r
+ float d;
+ vec3_t pushedOrigin;
+
+-
+ /* project sample point into light plane */
+ d = DotProduct( trace->origin, light->normal ) - light->dist;
+ if( d < 3.0f )
+@@ -881,8 +892,7 @@\r
+ {
+ float distByNormal, radiusAtDist, sampleRadius;
+ vec3_t pointAtDist, distToSample;
+-
+-
++
+ /* do cone calculation */
+ distByNormal = -DotProduct( trace->displacement, light->normal );
+ if( distByNormal < 0.0f )
+@@ -922,6 +932,9 @@\r
+ add = light->photons * angle;
+ if( add <= 0.0f )
+ return 0;
++
++ /* VorteX: set noShadow color */
++ VectorScale(light->color, add, trace->colorNoShadow);
+
+ /* setup trace */
+ trace->testAll = qtrue;
+@@ -942,6 +955,9 @@\r
+ /* return to sender */
+ return 1;
+ }
++
++ /* VorteX: set noShadow color */
++ VectorScale(light->color, add, trace->colorNoShadow);
+
+ /* ydnar: changed to a variable number */
+ if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) )
+@@ -1378,6 +1394,56 @@\r
+ break;
+ }
+
++ /////// Floodlighting for point //////////////////
++ //do our floodlight ambient occlusion loop, and add a single contribution based on the brightest dir
++ if (floodlighty)
++ {
++ int q;
++ float addSize,f;
++ vec3_t col,dir;
++ col[0]=col[1]=col[2]=floodlightIntensity;
++ dir[0]=dir[1]=0;
++ dir[2]=1;
++
++ trace.testOcclusion = qtrue;
++ trace.forceSunlight = qfalse;
++ trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
++ trace.testAll = qtrue;
++
++ for (q=0;q<2;q++)
++ {
++ if (q==0) //upper hemisphere
++ {
++ trace.normal[0]=0;
++ trace.normal[1]=0;
++ trace.normal[2]=1;
++ }
++ else //lower hemisphere
++ {
++ trace.normal[0]=0;
++ trace.normal[1]=0;
++ trace.normal[2]=-1;
++ }
++
++ f = FloodLightForSample(&trace, floodlightDistance, floodlight_lowquality);
++
++ contributions[ numCon ].color[0]=col[0]*f;
++ contributions[ numCon ].color[1]=col[1]*f;
++ contributions[ numCon ].color[2]=col[2]*f;
++
++ contributions[ numCon ].dir[0]=dir[0];
++ contributions[ numCon ].dir[1]=dir[1];
++ contributions[ numCon ].dir[2]=dir[2];
++
++ contributions[ numCon ].style = 0;
++ numCon++;
++ /* push average direction around */
++ addSize = VectorLength( col );
++ VectorMA( gp->dir, addSize, dir, gp->dir );
++ }
++ }
++ /////////////////////
++
+ /* normalize to get primary light direction */
+ VectorNormalize( gp->dir, gp->dir );
+
+@@ -1420,6 +1486,9 @@\r
+
+ /* ambient light will be at 1/4 the value of directed light */
+ /* (ydnar: nuke this in favor of more dramatic lighting?) */
++ /* (PM: how about actually making it work? d=1 when it got here for single lights/sun :P */
++// d = 0.25f;
++ /* (Hobbes: always setting it to .25 is hardly any better) */
+ d = 0.25f * (1.0f - d);
+ VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] );
+ }
+@@ -1437,8 +1506,10 @@\r
+ for( j = 0; j < 3; j++ )
+ if( color[ j ] < minGridLight[ j ] )
+ color[ j ] = minGridLight[ j ];
+- ColorToBytes( color, bgp->ambient[ i ], 1.0f );
+- ColorToBytes( gp->directed[ i ], bgp->directed[ i ], 1.0f );
++
++ /* vortex: apply gridscale and gridambientscale here */
++ ColorToBytes( color, bgp->ambient[ i ], gridScale*gridAmbientScale );
++ ColorToBytes( gp->directed[ i ], bgp->directed[ i ], gridScale );
+ }
+
+ /* debug code */
+@@ -1654,14 +1725,12 @@\r
+ if( dirty )
+ {
+ Sys_Printf( "--- DirtyRawLightmap ---\n" );
+-
+-
+-
+-
+ RunThreadsOnIndividual( numRawLightmaps, qtrue, DirtyRawLightmap );
+ }
+-
+
++ /* floodlight pass */
++ FloodlightRawLightmaps();
++
+ /* ydnar: set up light envelopes */
+ SetupEnvelopes( qfalse, fast );
+
+@@ -1774,12 +1843,64 @@\r
+
+ /* note it */
+ Sys_Printf( "--- Light ---\n" );
+-
++ Sys_Printf( "--- ProcessGameSpecific ---\n" );
++
+ /* set standard game flags */
+ wolfLight = game->wolfLight;
++ if (wolfLight == qtrue)
++ Sys_Printf( " lightning model: wolf\n" );
++ else
++ Sys_Printf( " lightning model: quake3\n" );
++
+ lmCustomSize = game->lightmapSize;
++ Sys_Printf( " lightmap size: %d x %d pixels\n", lmCustomSize, lmCustomSize );
++
+ lightmapGamma = game->lightmapGamma;
++ Sys_Printf( " lightning gamma: %f\n", lightmapGamma );
++
+ lightmapCompensate = game->lightmapCompensate;
++ Sys_Printf( " lightning compensation: %f\n", lightmapCompensate );
++
++ lightmapExposure = game->lightmapExposure;
++ Sys_Printf( " lightning exposure: %f\n", lightmapExposure );
++
++ gridScale = game->gridScale;
++ Sys_Printf( " lightgrid scale: %f\n", gridScale );
++
++ gridAmbientScale = game->gridAmbientScale;
++ Sys_Printf( " lightgrid ambient scale: %f\n", gridAmbientScale );
++
++ noStyles = game->noStyles;
++ if (noStyles == qtrue)
++ Sys_Printf( " shader lightstyles hack: disabled\n" );
++ else
++ Sys_Printf( " shader lightstyles hack: enabled\n" );
++
++ keepLights = game->keepLights;
++ if (keepLights == qtrue)
++ Sys_Printf( " keep lights: enabled\n" );
++ else
++ Sys_Printf( " keep lights: disabled\n" );
++
++ patchShadows = game->patchShadows;
++ if (patchShadows == qtrue)
++ Sys_Printf( " patch shadows: enabled\n" );
++ else
++ Sys_Printf( " patch shadows: disabled\n" );
++
++ deluxemap = game->deluxeMap;
++ deluxemode = game->deluxeMode;
++ if (deluxemap == qtrue)
++ {
++ if (deluxemode)
++ Sys_Printf( " deluxemapping: enabled with tangentspace deluxemaps\n" );
++ else
++ Sys_Printf( " deluxemapping: enabled with modelspace deluxemaps\n" );
++ }
++ else
++ Sys_Printf( " deluxemapping: disabled\n" );
++
++ Sys_Printf( "--- ProcessCommandLine ---\n" );
+
+ /* process commandline arguments */
+ for( i = 1; i < (argc - 1); i++ )
+@@ -1827,6 +1948,22 @@\r
+ Sys_Printf( "All light scaled by %f\n", f );
+ i++;
+ }
++
++ else if( !strcmp( argv[ i ], "-gridscale" ) )
++ {
++ f = atof( argv[ i + 1 ] );
++ Sys_Printf( "Grid lightning scaled by %f\n", f );
++ gridScale *= f;
++ i++;
++ }
++
++ else if( !strcmp( argv[ i ], "-gridambientscale" ) )
++ {
++ f = atof( argv[ i + 1 ] );
++ Sys_Printf( "Grid ambient lightning scaled by %f\n", f );
++ gridAmbientScale *= f;
++ i++;
++ }
+
+ else if( !strcmp( argv[ i ], "-gamma" ) )
+ {
+@@ -1836,6 +1973,14 @@\r
+ i++;
+ }
+
++ else if( !strcmp( argv[ i ], "-exposure" ) )
++ {
++ f = atof( argv[ i + 1 ] );
++ lightmapExposure = f;
++ Sys_Printf( "Lighting exposure set to %f\n", lightmapExposure );
++ i++;
++ }
++
+ else if( !strcmp( argv[ i ], "-compensate" ) )
+ {
+ f = atof( argv[ i + 1 ] );
+@@ -1889,12 +2034,6 @@\r
+ Sys_Printf( "Dark lightmap seams enabled\n" );
+ }
+
+-
+-
+-
+-
+-
+-
+ else if( !strcmp( argv[ i ], "-shadeangle" ) )
+ {
+ shadeAngleDegrees = atof( argv[ i + 1 ] );
+@@ -1927,13 +2066,28 @@\r
+ Sys_Printf( "Approximating lightmaps within a byte tolerance of %d\n", approximateTolerance );
+ i++;
+ }
+-
+ else if( !strcmp( argv[ i ], "-deluxe" ) || !strcmp( argv[ i ], "-deluxemap" ) )
+ {
+ deluxemap = qtrue;
+ Sys_Printf( "Generating deluxemaps for average light direction\n" );
+ }
+-
++ else if( !strcmp( argv[ i ], "-deluxemode" ))
++ {
++ deluxemode = atoi( argv[ i + 1 ] );
++ if (deluxemode == 0 || deluxemode > 1 || deluxemode < 0)
++ {
++ Sys_Printf( "Generating modelspace deluxemaps\n" );
++ deluxemode = 0;
++ }
++ else
++ Sys_Printf( "Generating tangentspace deluxemaps\n" );
++ i++;
++ }
++ else if( !strcmp( argv[ i ], "-nodeluxe" ) || !strcmp( argv[ i ], "-nodeluxemap" ) )
++ {
++ deluxemap = qfalse;
++ Sys_Printf( "Disabling generating of deluxemaps for average light direction\n" );
++ }
+ else if( !strcmp( argv[ i ], "-external" ) )
+ {
+ externalLightmaps = qtrue;
+@@ -2151,6 +2305,12 @@\r
+ i++;
+ Sys_Printf( "Default lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
+ }
++ else if( !strcmp( argv[ i ], "-samplescale" ) )
++ {
++ sampleScale = atoi( argv[ i + 1 ] );
++ i++;
++ Sys_Printf( "Lightmaps sample scale set to %d\n", sampleScale);
++ }
+ else if( !strcmp( argv[ i ], "-novertex" ) )
+ {
+ noVertexLighting = qtrue;
+@@ -2186,11 +2346,36 @@\r
+ noStyles = qtrue;
+ Sys_Printf( "Disabling lightstyles\n" );
+ }
++ else if( !strcmp( argv[ i ], "-style" ) || !strcmp( argv[ i ], "-styles" ) )
++ {
++ noStyles = qfalse;
++ Sys_Printf( "Enabling lightstyles\n" );
++ }
++ else if( !strcmp( argv[ i ], "-keeplights" ))
++ {
++ keepLights = qtrue;
++ Sys_Printf( "Leaving light entities on map after compile\n" );
++ }
+ else if( !strcmp( argv[ i ], "-cpma" ) )
+ {
+ cpmaHack = qtrue;
+ Sys_Printf( "Enabling Challenge Pro Mode Asstacular Vertex Lighting Mode (tm)\n" );
+ }
++ else if( !strcmp( argv[ i ], "-floodlight" ) )
++ {
++ floodlighty = qtrue;
++ Sys_Printf( "FloodLighting enabled\n" );
++ }
++ else if( !strcmp( argv[ i ], "-debugnormals" ) )
++ {
++ debugnormals = qtrue;
++ Sys_Printf( "DebugNormals enabled\n" );
++ }
++ else if( !strcmp( argv[ i ], "-lowquality" ) )
++ {
++ floodlight_lowquality = qtrue;
++ Sys_Printf( "Low Quality FloodLighting enabled\n" );
++ }
+
+ /* r7: dirtmapping */
+ else if( !strcmp( argv[ i ], "-dirty" ) )
+@@ -2212,6 +2397,7 @@\r
+ Sys_Printf( "Enabling randomized dirtmapping\n" );
+ else
+ Sys_Printf( "Enabling ordered dir mapping\n" );
++ i++;
+ }
+ else if( !strcmp( argv[ i ], "-dirtdepth" ) )
+ {
+@@ -2219,6 +2405,7 @@\r
+ if( dirtDepth <= 0.0f )
+ dirtDepth = 128.0f;
+ Sys_Printf( "Dirtmapping depth set to %.1f\n", dirtDepth );
++ i++;
+ }
+ else if( !strcmp( argv[ i ], "-dirtscale" ) )
+ {
+@@ -2226,6 +2413,7 @@\r
+ if( dirtScale <= 0.0f )
+ dirtScale = 1.0f;
+ Sys_Printf( "Dirtmapping scale set to %.1f\n", dirtScale );
++ i++;
+ }
+ else if( !strcmp( argv[ i ], "-dirtgain" ) )
+ {
+@@ -2233,6 +2421,7 @@\r
+ if( dirtGain <= 0.0f )
+ dirtGain = 1.0f;
+ Sys_Printf( "Dirtmapping gain set to %.1f\n", dirtGain );
++ i++;
+ }
+
+ /* unhandled args */
+@@ -2279,6 +2468,7 @@\r
+ /* ydnar: set up optimization */
+ SetupBrushes();
+ SetupDirt();
++ SetupFloodLight();
+ SetupSurfaceLightmaps();
+
+ /* initialize the surface facet tracing */
+Index: light_bounce.c\r
+===================================================================\r
+--- light_bounce.c (revision 158)\r
++++ light_bounce.c (working copy)\r
+@@ -510,7 +510,7 @@\r
+ break;
+
+ case MST_TRIANGLE_SOUP:
+- numTriangleDiffuseLights;
++ numTriangleDiffuseLights++;
+ break;
+
+ case MST_PATCH:
+Index: light_trace.c\r
+===================================================================\r
+--- light_trace.c (revision 158)\r
++++ light_trace.c (working copy)\r
+@@ -56,7 +56,7 @@\r
+ #define GROW_TRACE_NODES 16384 //% 16384
+ #define GROW_NODE_ITEMS 16 //% 256
+
+-#define MAX_TW_VERTS 12
++#define MAX_TW_VERTS 24 // vortex: increased from 12 to 24 for ability co compile some insane maps with large curve count
+
+ #define TRACE_ON_EPSILON 0.1f
+
+Index: light_ydnar.c\r
+===================================================================\r
+--- light_ydnar.c (revision 158)\r
++++ light_ydnar.c (working copy)\r
+@@ -49,6 +49,7 @@\r
+ int i;
+ float max, gamma;
+ vec3_t sample;
++ float inv, dif;
+
+
+ /* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
+@@ -72,16 +73,51 @@\r
+ /* gamma */
+ sample[ i ] = pow( sample[ i ] / 255.0f, gamma ) * 255.0f;
+ }
++
++ if (lightmapExposure == 1)
++ {
++ /* clamp with color normalization */
++ max = sample[ 0 ];
++ if( sample[ 1 ] > max )
++ max = sample[ 1 ];
++ if( sample[ 2 ] > max )
++ max = sample[ 2 ];
++ if( max > 255.0f )
++ VectorScale( sample, (255.0f / max), sample );
++ }
++ else
++ {
++ if (lightmapExposure==0)
++ {
++ lightmapExposure=1.0f;
++ }
++ inv=1.f/lightmapExposure;
++ //Exposure
++
++ max = sample[ 0 ];
++ if( sample[ 1 ] > max )
++ max = sample[ 1 ];
++ if( sample[ 2 ] > max )
++ max = sample[ 2 ];
++
++ dif = (1- exp(-max * inv) ) * 255;
++
++ if (max >0)
++ {
++ dif = dif / max;
++ }
++ else
++ {
++ dif = 0;
++ }
++
++ for (i=0;i<3;i++)
++ {
++ sample[i]*=dif;
++ }
++ }
++
+
+- /* clamp with color normalization */
+- max = sample[ 0 ];
+- if( sample[ 1 ] > max )
+- max = sample[ 1 ];
+- if( sample[ 2 ] > max )
+- max = sample[ 2 ];
+- if( max > 255.0f )
+- VectorScale( sample, (255.0f / max), sample );
+-
+ /* compensate for ingame overbrighting/bitshifting */
+ VectorScale( sample, (1.0f / lightmapCompensate), sample );
+
+@@ -384,7 +420,7 @@\r
+ #define NUDGE 0.5f
+ #define BOGUS_NUDGE -99999.0f
+
+-static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
++static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ], vec3_t worldverts[ 3 ] )
+ {
+ int i, x, y, numClusters, *clusters, pointCluster, *cluster;
+ float *luxel, *origin, *normal, d, lightmapSampleOffset;
+@@ -392,6 +428,12 @@\r
+ vec3_t pNormal;
+ vec3_t vecs[ 3 ];
+ vec3_t nudged;
++ vec3_t cverts[ 3 ];
++ vec3_t temp;
++ vec4_t sideplane, hostplane;
++ vec3_t origintwo;
++ int j, next;
++ float e;
+ float *nudge;
+ static float nudges[][ 2 ] =
+ {
+@@ -485,6 +527,51 @@\r
+ /* non axial lightmap projection (explicit xyz) */
+ else
+ VectorCopy( dv->xyz, origin );
++
++ //////////////////////
++ //27's test to make sure samples stay within the triangle boundaries
++ //1) Test the sample origin to see if it lays on the wrong side of any edge (x/y)
++ //2) if it does, nudge it onto the correct side.
++
++ if (worldverts!=NULL)
++ {
++ for (j=0;j<3;j++)
++ {
++ VectorCopy(worldverts[j],cverts[j]);
++ }
++ PlaneFromPoints(hostplane,cverts[0],cverts[1],cverts[2]);
++
++ for (j=0;j<3;j++)
++ {
++ for (i=0;i<3;i++)
++ {
++ //build plane using 2 edges and a normal
++ next=(i+1)%3;
++
++ VectorCopy(cverts[next],temp);
++ VectorAdd(temp,hostplane,temp);
++ PlaneFromPoints(sideplane,cverts[i],cverts[ next ], temp);
++
++ //planetest sample point
++ e=DotProduct(origin,sideplane);
++ e=e-sideplane[3];
++ if (e>0)
++ {
++ //we're bad.
++ //VectorClear(origin);
++ //Move the sample point back inside triangle bounds
++ origin[0]-=sideplane[0]*(e+1);
++ origin[1]-=sideplane[1]*(e+1);
++ origin[2]-=sideplane[2]*(e+1);
++#ifdef DEBUG_27_1
++ VectorClear(origin);
++#endif
++ }
++ }
++ }
++ }
++
++ ////////////////////////
+
+ /* planar surfaces have precalculated lightmap vectors for nudging */
+ if( lm->plane != NULL )
+@@ -516,8 +603,13 @@\r
+ else
+ origin[ lm->axisNum ] += lightmapSampleOffset;
+
++ VectorCopy(origin,origintwo);
++ origintwo[0]+=vecs[2][0];
++ origintwo[1]+=vecs[2][1];
++ origintwo[2]+=vecs[2][2];
++
+ /* get cluster */
+- pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
++ pointCluster = ClusterForPointExtFilter( origintwo, LUXEL_EPSILON, numClusters, clusters );
+
+ /* another retarded hack, storing nudge count in luxel[ 1 ] */
+ luxel[ 1 ] = 0.0f;
+@@ -533,14 +625,14 @@\r
+ for( i = 0; i < 3; i++ )
+ {
+ /* set nudged point*/
+- nudged[ i ] = origin[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
++ nudged[ i ] = origintwo[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
+ }
+ nudge += 2;
+
+ /* get pvs cluster */
+ pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
+- if( pointCluster >= 0 )
+- VectorCopy( nudged, origin );
++ //if( pointCluster >= 0 )
++ // VectorCopy( nudged, origin );
+ luxel[ 1 ] += 1.0f;
+ }
+ }
+@@ -550,8 +642,8 @@\r
+ {
+ VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
+ pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
+- if( pointCluster >= 0 )
+- VectorCopy( nudged, origin );
++ //if( pointCluster >= 0 )
++ // VectorCopy( nudged, origin );
+ luxel[ 1 ] += 1.0f;
+ }
+
+@@ -597,7 +689,7 @@\r
+ than the distance between two luxels (thanks jc :)
+ */
+
+-static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
++static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ], vec3_t worldverts[ 3 ] )
+ {
+ bspDrawVert_t mid, *dv2[ 3 ];
+ int max;
+@@ -645,7 +737,7 @@\r
+
+ /* split the longest edge and map it */
+ LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
+- MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
++ MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv, worldverts );
+
+ /* push the point up a little bit to account for fp creep (fixme: revisit this) */
+ //% VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
+@@ -653,12 +745,12 @@\r
+ /* recurse to first triangle */
+ VectorCopy( dv, dv2 );
+ dv2[ max ] = ∣
+- MapTriangle_r( lm, info, dv2, plane, stv, ttv );
++ MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
+
+ /* recurse to second triangle */
+ VectorCopy( dv, dv2 );
+ dv2[ (max + 1) % 3 ] = ∣
+- MapTriangle_r( lm, info, dv2, plane, stv, ttv );
++ MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
+ }
+
+
+@@ -674,8 +766,8 @@\r
+ int i;
+ vec4_t plane;
+ vec3_t *stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
++ vec3_t worldverts[ 3 ];
+
+-
+ /* get plane if possible */
+ if( lm->plane != NULL )
+ {
+@@ -699,16 +791,20 @@\r
+ ttv = NULL;
+ }
+
++ VectorCopy( dv[ 0 ]->xyz, worldverts[ 0 ] );
++ VectorCopy( dv[ 1 ]->xyz, worldverts[ 1 ] );
++ VectorCopy( dv[ 2 ]->xyz, worldverts[ 2 ] );
++
+ /* map the vertexes */
+- MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
+- MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
+- MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
++ MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, worldverts );
++ MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, worldverts );
++ MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, worldverts );
+
+ /* 2002-11-20: prefer axial triangle edges */
+ if( mapNonAxial )
+ {
+ /* subdivide the triangle */
+- MapTriangle_r( lm, info, dv, plane, stv, ttv );
++ MapTriangle_r( lm, info, dv, plane, stv, ttv, worldverts );
+ return qtrue;
+ }
+
+@@ -730,7 +826,7 @@\r
+ dv2[ 2 ] = dv[ (i + 1) % 3 ];
+
+ /* map the degenerate triangle */
+- MapTriangle_r( lm, info, dv2, plane, stv, ttv );
++ MapTriangle_r( lm, info, dv2, plane, stv, ttv, worldverts );
+ }
+ }
+
+@@ -792,8 +888,8 @@\r
+ LerpDrawVert( dv[ max + 2 ], dv[ (max + 3) % 4 ], &mid[ 1 ] );
+
+ /* map the vertexes */
+- MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
+- MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
++ MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv, NULL );
++ MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv, NULL );
+
+ /* 0 and 2 */
+ if( max == 0 )
+@@ -848,7 +944,6 @@\r
+ vec4_t plane;
+ vec3_t *stv, *ttv, stvStatic[ 4 ], ttvStatic[ 4 ];
+
+-
+ /* get plane if possible */
+ if( lm->plane != NULL )
+ {
+@@ -878,18 +973,16 @@\r
+ }
+
+ /* map the vertexes */
+- MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
+- MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
+- MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
+- MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
++ MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv, NULL );
++ MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv, NULL );
++ MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv, NULL );
++ MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv, NULL );
+
+ /* subdivide the quad */
+ MapQuad_r( lm, info, dv, plane, stv, ttv );
+ return qtrue;
+ }
+
+-
+-
+ /*
+ MapRawLightmap()
+ maps the locations, normals, and pvs clusters for a raw lightmap
+@@ -941,7 +1034,7 @@\r
+ num = lightSurfaces[ lm->firstLightSurface + n ];
+ ds = &bspDrawSurfaces[ num ];
+ info = &surfaceInfos[ num ];
+-
++
+ /* bail if no lightmap to calculate */
+ if( info->lm != lm )
+ {
+@@ -1173,7 +1266,7 @@\r
+ continue;
+
+ /* map the fake vert */
+- MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
++ MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL, NULL );
+ }
+ }
+ }
+@@ -1596,7 +1689,6 @@\r
+
+ VectorSubtract( origin2, origin, originVecs[ 0 ] );
+ //% VectorSubtract( normal2, normal, normalVecs[ 0 ] );
+-
+ /* calulate y vector */
+ if( (y < (lm->sh - 1) && bx >= 0.0f) || (y == 0 && bx <= 0.0f) )
+ {
+@@ -1660,7 +1752,6 @@\r
+ float biasDirs[ 4 ][ 2 ] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 1.0f }, { 1.0f, 1.0f } };
+ vec3_t color, total;
+
+-
+ /* limit check */
+ if( lightLuxel[ 3 ] >= lightSamples )
+ return;
+@@ -1693,7 +1784,6 @@\r
+ VectorCopy( normal[ b ], trace->normal );
+
+ /* sample light */
+-
+ LightContributionToSample( trace );
+
+ /* add to totals (fixme: make contrast function) */
+@@ -1768,7 +1858,6 @@\r
+ trace_t trace;
+ float stackLightLuxels[ STACK_LL_SIZE ];
+
+-
+ /* bail if this number exceeds the number of raw lightmaps */
+ if( rawLightmapNum >= numRawLightmaps )
+ return;
+@@ -1904,7 +1993,7 @@\r
+ else
+ {
+ VectorCopy( ambientColor, luxel );
+- if( deluxemap )
++ if( deluxemap)
+ VectorScale( normal, 0.00390625f, deluxel );
+ luxel[ 3 ] = 1.0f;
+ }
+@@ -1963,28 +2052,39 @@\r
+ deluxel = SUPER_DELUXEL( x, y );
+ origin = SUPER_ORIGIN( x, y );
+ normal = SUPER_NORMAL( x, y );
+-
+- /* set contribution count */
+- lightLuxel[ 3 ] = 1.0f;
+-
+- /* setup trace */
+- trace.cluster = *cluster;
+- VectorCopy( origin, trace.origin );
+- VectorCopy( normal, trace.normal );
+-
+- /* get light for this sample */
+- LightContributionToSample( &trace );
+- VectorCopy( trace.color, lightLuxel );
+-
+- /* add to count */
+- if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
++
++ ////////// 27's temp hack for testing edge clipping ////
++ if( origin[0]==0 && origin[1]==0 && origin[2]==0 )
++ {
++ lightLuxel[ 1 ] = 255;
++ lightLuxel[ 3 ] = 1.0f;
+ totalLighted++;
++ }
++ else
++ {
++ /* set contribution count */
++ lightLuxel[ 3 ] = 1.0f;
++
++ /* setup trace */
++ trace.cluster = *cluster;
++ VectorCopy( origin, trace.origin );
++ VectorCopy( normal, trace.normal );
++
++ /* get light for this sample */
++ LightContributionToSample( &trace );
++ VectorCopy( trace.color, lightLuxel );
++
++ /* add to count */
++ if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
++ totalLighted++;
++ }
+
+ /* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
+ if( deluxemap )
+ {
++ /* vortex: use noShadow color */
+ /* color to grayscale (photoshop rgb weighting) */
+- brightness = trace.color[ 0 ] * 0.3f + trace.color[ 1 ] * 0.59f + trace.color[ 2 ] * 0.11f;
++ brightness = trace.colorNoShadow[ 0 ] * 0.3f + trace.colorNoShadow[ 1 ] * 0.59f + trace.colorNoShadow[ 2 ] * 0.11f;
+ brightness *= (1.0 / 255.0);
+ VectorScale( trace.direction, brightness, trace.direction );
+ VectorAdd( deluxel, trace.direction, deluxel );
+@@ -2222,6 +2322,38 @@\r
+ /* free light list */
+ FreeTraceLights( &trace );
+
++ /* floodlight pass */
++ FloodlightIlluminateLightmap(lm);
++
++ if (debugnormals)
++ {
++ for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
++ {
++ /* early out */
++ if( lm->superLuxels[ lightmapNum ] == NULL )
++ continue;
++
++ for( y = 0; y < lm->sh; y++ )
++ {
++ for( x = 0; x < lm->sw; x++ )
++ {
++ /* get cluster */
++ cluster = SUPER_CLUSTER( x, y );
++ //% if( *cluster < 0 )
++ //% continue;
++
++ /* get particulars */
++ luxel = SUPER_LUXEL( lightmapNum, x, y );
++ normal = SUPER_NORMAL ( x, y );
++
++ luxel[0]=(normal[0]*127)+127;
++ luxel[1]=(normal[1]*127)+127;
++ luxel[2]=(normal[2]*127)+127;
++ }
++ }
++ }
++ }
++
+ /* -----------------------------------------------------------------
+ dirt pass
+ ----------------------------------------------------------------- */
+@@ -2263,7 +2395,7 @@\r
+ /* -----------------------------------------------------------------
+ filter pass
+ ----------------------------------------------------------------- */
+-
++
+ /* walk lightmaps */
+ for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+ {
+@@ -3112,7 +3244,7 @@\r
+ int i, x, y, z, x1, y1, z1;
+ light_t *light, *light2, **owner;
+ bspLeaf_t *leaf;
+- vec3_t origin, dir, mins, maxs, nullVector = { 0, 0, 0 };
++ vec3_t origin, dir, mins, maxs;
+ float radius, intensity;
+ light_t *buckets[ 256 ];
+
+@@ -3587,7 +3719,430 @@\r
+ CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
+ }
+
++/////////////////////////////////////////////////////////////
+
++#define FLOODLIGHT_CONE_ANGLE 88 /* degrees */
++#define FLOODLIGHT_NUM_ANGLE_STEPS 16
++#define FLOODLIGHT_NUM_ELEVATION_STEPS 4
++#define FLOODLIGHT_NUM_VECTORS (FLOODLIGHT_NUM_ANGLE_STEPS * FLOODLIGHT_NUM_ELEVATION_STEPS)
+
++static vec3_t floodVectors[ FLOODLIGHT_NUM_VECTORS ];
++static int numFloodVectors = 0;
+
++void SetupFloodLight( void )
++{
++ int i, j;
++ float angle, elevation, angleStep, elevationStep;
++ const char *value;
++ double v1,v2,v3,v4,v5;
++
++ /* note it */
++ Sys_FPrintf( SYS_VRB, "--- SetupFloodLight ---\n" );
++
++ /* calculate angular steps */
++ angleStep = DEG2RAD( 360.0f / FLOODLIGHT_NUM_ANGLE_STEPS );
++ elevationStep = DEG2RAD( FLOODLIGHT_CONE_ANGLE / FLOODLIGHT_NUM_ELEVATION_STEPS );
++
++ /* iterate angle */
++ angle = 0.0f;
++ for( i = 0, angle = 0.0f; i < FLOODLIGHT_NUM_ANGLE_STEPS; i++, angle += angleStep )
++ {
++ /* iterate elevation */
++ for( j = 0, elevation = elevationStep * 0.5f; j < FLOODLIGHT_NUM_ELEVATION_STEPS; j++, elevation += elevationStep )
++ {
++ floodVectors[ numFloodVectors ][ 0 ] = sin( elevation ) * cos( angle );
++ floodVectors[ numFloodVectors ][ 1 ] = sin( elevation ) * sin( angle );
++ floodVectors[ numFloodVectors ][ 2 ] = cos( elevation );
++ numFloodVectors++;
++ }
++ }
++
++ /* emit some statistics */
++ Sys_FPrintf( SYS_VRB, "%9d numFloodVectors\n", numFloodVectors );
+
++ /* floodlight */
++ value = ValueForKey( &entities[ 0 ], "_floodlight" );
++
++ if( value[ 0 ] != '\0' )
++ {
++ v1=v2=v3=0;
++ v4=floodlightDistance;
++ v5=floodlightIntensity;
++
++ sscanf( value, "%lf %lf %lf %lf %lf", &v1, &v2, &v3, &v4, &v5);
++
++ floodlightRGB[0]=v1;
++ floodlightRGB[1]=v2;
++ floodlightRGB[2]=v3;
++
++ if (VectorLength(floodlightRGB)==0)
++ {
++ VectorSet(floodlightRGB,240,240,255);
++ }
++
++ if (v4<1) v4=1024;
++ if (v5<1) v5=128;
++
++ floodlightDistance = v4;
++ floodlightIntensity = v5;
++
++ floodlighty = qtrue;
++ Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
++ }
++ else
++ {
++ VectorSet(floodlightRGB,240,240,255);
++ //floodlighty = qtrue;
++ //Sys_Printf( "FloodLighting enabled via worldspawn _floodlight key.\n" );
++ }
++ VectorNormalize(floodlightRGB,floodlightRGB);
++}
++
++/*
++FloodLightForSample()
++calculates floodlight value for a given sample
++once again, kudos to the dirtmapping coder
++*/
++
++float FloodLightForSample( trace_t *trace , float floodLightDistance, qboolean floodLightLowQuality)
++{
++ int i;
++ float d;
++ float contribution;
++ int sub = 0;
++ float gatherLight, outLight;
++ vec3_t normal, worldUp, myUp, myRt, direction, displacement;
++ float dd;
++ int vecs = 0;
++
++ gatherLight=0;
++ /* dummy check */
++ //if( !dirty )
++ // return 1.0f;
++ if( trace == NULL || trace->cluster < 0 )
++ return 0.0f;
++
++
++ /* setup */
++ dd = floodLightDistance;
++ VectorCopy( trace->normal, normal );
++
++ /* check if the normal is aligned to the world-up */
++ if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f )
++ {
++ if( normal[ 2 ] == 1.0f )
++ {
++ VectorSet( myRt, 1.0f, 0.0f, 0.0f );
++ VectorSet( myUp, 0.0f, 1.0f, 0.0f );
++ }
++ else if( normal[ 2 ] == -1.0f )
++ {
++ VectorSet( myRt, -1.0f, 0.0f, 0.0f );
++ VectorSet( myUp, 0.0f, 1.0f, 0.0f );
++ }
++ }
++ else
++ {
++ VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
++ CrossProduct( normal, worldUp, myRt );
++ VectorNormalize( myRt, myRt );
++ CrossProduct( myRt, normal, myUp );
++ VectorNormalize( myUp, myUp );
++ }
++
++ /* vortex: optimise floodLightLowQuality a bit */
++ if ( floodLightLowQuality == qtrue )
++ {
++ /* iterate through ordered vectors */
++ for( i = 0; i < numFloodVectors; i++ )
++ if (rand()%10 != 0 ) continue;
++ }
++ else
++ {
++ /* iterate through ordered vectors */
++ for( i = 0; i < numFloodVectors; i++ )
++ {
++ vecs++;
++
++ /* transform vector into tangent space */
++ direction[ 0 ] = myRt[ 0 ] * floodVectors[ i ][ 0 ] + myUp[ 0 ] * floodVectors[ i ][ 1 ] + normal[ 0 ] * floodVectors[ i ][ 2 ];
++ direction[ 1 ] = myRt[ 1 ] * floodVectors[ i ][ 0 ] + myUp[ 1 ] * floodVectors[ i ][ 1 ] + normal[ 1 ] * floodVectors[ i ][ 2 ];
++ direction[ 2 ] = myRt[ 2 ] * floodVectors[ i ][ 0 ] + myUp[ 2 ] * floodVectors[ i ][ 1 ] + normal[ 2 ] * floodVectors[ i ][ 2 ];
++
++ /* set endpoint */
++ VectorMA( trace->origin, dd, direction, trace->end );
++
++ //VectorMA( trace->origin, 1, direction, trace->origin );
++
++ SetupTrace( trace );
++ /* trace */
++ TraceLine( trace );
++ contribution=1;
++
++ if (trace->compileFlags & C_SKY )
++ {
++ contribution=1.0f;
++ }
++ else if ( trace->opaque )
++ {
++ VectorSubtract( trace->hit, trace->origin, displacement );
++ d=VectorLength( displacement );
++
++ // d=trace->distance;
++ //if (d>256) gatherDirt+=1;
++ contribution=d/dd;
++ if (contribution>1) contribution=1.0f;
++
++ //gatherDirt += 1.0f - ooDepth * VectorLength( displacement );
++ }
++
++ gatherLight+=contribution;
++ }
++ }
++
++ /* early out */
++ if( gatherLight <= 0.0f )
++ return 0.0f;
++
++ sub=vecs;
++
++ if (sub<1) sub=1;
++ gatherLight/=(sub);
++
++ outLight=gatherLight;
++ if( outLight > 1.0f )
++ outLight = 1.0f;
++
++ /* return to sender */
++ return outLight;
++}
++
++/*
++FloodLightRawLightmap
++lighttracer style ambient occlusion light hack.
++Kudos to the dirtmapping author for most of this source.
++VorteX: modified to floodlight up custom surfaces (q3map_floodLight)
++VorteX: fixed problems with deluxemapping
++*/
++
++// floodlight pass on a lightmap
++void FloodLightRawLightmapPass( rawLightmap_t *lm , vec3_t lmFloodLightRGB, float lmFloodLightIntensity, float lmFloodLightDistance, qboolean lmFloodLightLowQuality, float floodlightDirectionScale)
++{
++ int i, x, y, *cluster;
++ float *origin, *normal, *floodlight, floodLightAmount;
++ surfaceInfo_t *info;
++ trace_t trace;
++ // int sx, sy;
++ // float samples, average, *floodlight2;
++
++ memset(&trace,0,sizeof(trace_t));
++
++ /* setup trace */
++ trace.testOcclusion = qtrue;
++ trace.forceSunlight = qfalse;
++ trace.twoSided = qtrue;
++ trace.recvShadows = lm->recvShadows;
++ trace.numSurfaces = lm->numLightSurfaces;
++ trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
++ trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
++ trace.testAll = qfalse;
++ trace.distance = 1024;
++
++ /* twosided lighting (may or may not be a good idea for lightmapped stuff) */
++ //trace.twoSided = qfalse;
++ for( i = 0; i < trace.numSurfaces; i++ )
++ {
++ /* get surface */
++ info = &surfaceInfos[ trace.surfaces[ i ] ];
++
++ /* check twosidedness */
++ if( info->si->twoSided )
++ {
++ trace.twoSided = qtrue;
++ break;
++ }
++ }
++
++ /* gather floodlight */
++ for( y = 0; y < lm->sh; y++ )
++ {
++ for( x = 0; x < lm->sw; x++ )
++ {
++ /* get luxel */
++ cluster = SUPER_CLUSTER( x, y );
++ origin = SUPER_ORIGIN( x, y );
++ normal = SUPER_NORMAL( x, y );
++ floodlight = SUPER_FLOODLIGHT( x, y );
++
++ /* set default dirt */
++ *floodlight = 0.0f;
++
++ /* only look at mapped luxels */
++ if( *cluster < 0 )
++ continue;
++
++ /* copy to trace */
++ trace.cluster = *cluster;
++ VectorCopy( origin, trace.origin );
++ VectorCopy( normal, trace.normal );
++
++ /* get floodlight */
++ floodLightAmount = FloodLightForSample( &trace , lmFloodLightDistance, lmFloodLightLowQuality)*lmFloodLightIntensity;
++
++ /* add floodlight */
++ floodlight[0] += lmFloodLightRGB[0]*floodLightAmount;
++ floodlight[1] += lmFloodLightRGB[1]*floodLightAmount;
++ floodlight[2] += lmFloodLightRGB[2]*floodLightAmount;
++ floodlight[3] += floodlightDirectionScale;
++ }
++ }
++
++ /* testing no filtering */
++ return;
++
++#if 0
++
++ /* filter "dirt" */
++ for( y = 0; y < lm->sh; y++ )
++ {
++ for( x = 0; x < lm->sw; x++ )
++ {
++ /* get luxel */
++ cluster = SUPER_CLUSTER( x, y );
++ floodlight = SUPER_FLOODLIGHT(x, y );
++
++ /* filter dirt by adjacency to unmapped luxels */
++ average = *floodlight;
++ samples = 1.0f;
++ for( sy = (y - 1); sy <= (y + 1); sy++ )
++ {
++ if( sy < 0 || sy >= lm->sh )
++ continue;
++
++ for( sx = (x - 1); sx <= (x + 1); sx++ )
++ {
++ if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
++ continue;
++
++ /* get neighboring luxel */
++ cluster = SUPER_CLUSTER( sx, sy );
++ floodlight2 = SUPER_FLOODLIGHT( sx, sy );
++ if( *cluster < 0 || *floodlight2 <= 0.0f )
++ continue;
++
++ /* add it */
++ average += *floodlight2;
++ samples += 1.0f;
++ }
++
++ /* bail */
++ if( samples <= 0.0f )
++ break;
++ }
++
++ /* bail */
++ if( samples <= 0.0f )
++ continue;
++
++ /* scale dirt */
++ *floodlight = average / samples;
++ }
++ }
++#endif
++}
++
++void FloodLightRawLightmap( int rawLightmapNum )
++{
++ rawLightmap_t *lm;
++
++ /* bail if this number exceeds the number of raw lightmaps */
++ if( rawLightmapNum >= numRawLightmaps )
++ return;
++ /* get lightmap */
++ lm = &rawLightmaps[ rawLightmapNum ];
++
++ /* global pass */
++ if (floodlighty && floodlightIntensity)
++ FloodLightRawLightmapPass(lm, floodlightRGB, floodlightIntensity, floodlightDistance, floodlight_lowquality, 0);
++
++ /* custom pass */
++ if (lm->floodlightIntensity)
++ {
++ FloodLightRawLightmapPass(lm, lm->floodlightRGB, lm->floodlightIntensity, lm->floodlightDistance, qfalse, lm->floodlightDirectionScale);
++ numSurfacesFloodlighten += 1;
++ }
++}
++
++void FloodlightRawLightmaps()
++{
++ Sys_Printf( "--- FloodlightRawLightmap ---\n" );
++ numSurfacesFloodlighten = 0;
++ RunThreadsOnIndividual( numRawLightmaps, qtrue, FloodLightRawLightmap );
++ Sys_Printf( "%9d custom lightmaps floodlighted\n", numSurfacesFloodlighten );
++}
++
++/*
++FloodLightIlluminate()
++illuminate floodlight into lightmap luxels
++*/
++
++void FloodlightIlluminateLightmap( rawLightmap_t *lm )
++{
++ float *luxel, *floodlight, *deluxel, *normal;
++ int *cluster;
++ float brightness;
++ vec3_t lightvector;
++ int x, y, lightmapNum;
++
++ /* walk lightmaps */
++ for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
++ {
++ /* early out */
++ if( lm->superLuxels[ lightmapNum ] == NULL )
++ continue;
++
++ /* apply floodlight to each luxel */
++ for( y = 0; y < lm->sh; y++ )
++ {
++ for( x = 0; x < lm->sw; x++ )
++ {
++ /* get floodlight */
++ floodlight = SUPER_FLOODLIGHT( x, y );
++ if (!floodlight[0] && !floodlight[1] && !floodlight[2])
++ continue;
++
++ /* get cluster */
++ cluster = SUPER_CLUSTER( x, y );
++
++ /* only process mapped luxels */
++ if( *cluster < 0 )
++ continue;
++
++ /* get particulars */
++ luxel = SUPER_LUXEL( lightmapNum, x, y );
++ deluxel = SUPER_DELUXEL( x, y );
++
++ /* add to lightmap */
++ luxel[0]+=floodlight[0];
++ luxel[1]+=floodlight[1];
++ luxel[2]+=floodlight[2];
++
++ if (luxel[3]==0) luxel[3]=1;
++
++ /* add to deluxemap */
++ if (deluxemap && floodlight[3] > 0)
++ {
++ normal = SUPER_NORMAL( x, y );
++ brightness = floodlight[ 0 ] * 0.3f + floodlight[ 1 ] * 0.59f + floodlight[ 2 ] * 0.11f;
++ brightness *= ( 1.0f / 255.0f ) * floodlight[3];
++ VectorScale( normal, brightness, lightvector );
++ VectorAdd( deluxel, lightvector, deluxel );
++ }
++ }
++ }
++ }
++}
++
++
++
++
+Index: lightmaps_ydnar.c\r
+===================================================================\r
+--- lightmaps_ydnar.c (revision 158)\r
++++ lightmaps_ydnar.c (working copy)\r
+@@ -414,6 +414,12 @@\r
+ lm->superNormals = safe_malloc( size );
+ memset( lm->superNormals, 0, size );
+
++ /* allocate floodlight map storage */
++ size = lm->sw * lm->sh * SUPER_FLOODLIGHT_SIZE * sizeof( float );
++ if( lm->superFloodLight == NULL )
++ lm->superFloodLight = safe_malloc( size );
++ memset( lm->superFloodLight, 0, size );
++
+ /* allocate cluster map storage */
+ size = lm->sw * lm->sh * sizeof( int );
+ if( lm->superClusters == NULL )
+@@ -1087,17 +1093,25 @@\r
+ /* allocate a new raw lightmap */
+ lm = &rawLightmaps[ numRawLightmaps ];
+ numRawLightmaps++;
+-
++
+ /* set it up */
+ lm->splotchFix = info->si->splotchFix;
+ lm->firstLightSurface = numLightSurfaces;
+ lm->numLightSurfaces = 0;
+- lm->sampleSize = info->sampleSize;
+- lm->actualSampleSize = info->sampleSize;
++ /* vortex: multiply lightmap sample size by -samplescale */
++ if (sampleScale > 0)
++ lm->sampleSize = info->sampleSize*sampleScale;
++ else
++ lm->sampleSize = info->sampleSize;
++ lm->actualSampleSize = lm->sampleSize;
+ lm->entityNum = info->entityNum;
+ lm->recvShadows = info->recvShadows;
+ lm->brightness = info->si->lmBrightness;
+ lm->filterRadius = info->si->lmFilterRadius;
++ VectorCopy(info->si->floodlightRGB, lm->floodlightRGB);
++ lm->floodlightDistance = info->si->floodlightDistance;
++ lm->floodlightIntensity = info->si->floodlightIntensity;
++ lm->floodlightDirectionScale = info->si->floodlightDirectionScale;
+ VectorCopy( info->axis, lm->axis );
+ lm->plane = info->plane;
+ VectorCopy( info->mins, lm->mins );
+@@ -2254,7 +2268,6 @@\r
+ char *rgbGenValues[ 256 ];
+ char *alphaGenValues[ 256 ];
+
+-
+ /* note it */
+ Sys_Printf( "--- StoreSurfaceLightmaps ---\n");
+
+@@ -2269,7 +2282,7 @@\r
+ ----------------------------------------------------------------- */
+
+ /* note it */
+- Sys_FPrintf( SYS_VRB, "Subsampling..." );
++ Sys_Printf( "Subsampling..." );
+
+ /* walk the list of raw lightmaps */
+ numUsed = 0;
+@@ -2437,11 +2450,11 @@\r
+ /* get luxels */
+ luxel = SUPER_LUXEL( lightmapNum, x, y );
+ deluxel = SUPER_DELUXEL( x, y );
+-
++
+ /* copy light direction */
+ if( deluxemap && lightmapNum == 0 )
+ VectorCopy( deluxel, dirSample );
+-
++
+ /* is this a valid sample? */
+ if( luxel[ 3 ] > 0.0f )
+ {
+@@ -2521,7 +2534,7 @@\r
+ /* store the sample in the bsp luxels */
+ bspLuxel = BSP_LUXEL( lightmapNum, x, y );
+ bspDeluxel = BSP_DELUXEL( x, y );
+-
++
+ VectorAdd( bspLuxel, sample, bspLuxel );
+ if( deluxemap && lightmapNum == 0 )
+ VectorAdd( bspDeluxel, dirSample, bspDeluxel );
+@@ -2562,7 +2575,7 @@\r
+ }
+ }
+ }
+-
++
+ /* wrap bsp luxels if necessary */
+ if( lm->wrap[ 0 ] )
+ {
+@@ -2604,15 +2617,144 @@\r
+ }
+ }
+ }
+-
++
+ /* -----------------------------------------------------------------
++ convert modelspace deluxemaps to tangentspace
++ ----------------------------------------------------------------- */
++ /* note it */
++ if( !bouncing )
++ {
++ if( deluxemap && deluxemode == 1)
++ {
++ vec3_t worldUp, myNormal, myTangent, myBinormal;
++ float dist;
++
++ Sys_Printf( "converting..." );
++
++ for( i = 0; i < numRawLightmaps; i++ )
++ {
++ /* get lightmap */
++ lm = &rawLightmaps[ i ];
++
++ /* walk lightmap samples */
++ for( y = 0; y < lm->sh; y++ )
++ {
++ for( x = 0; x < lm->sw; x++ )
++ {
++ /* get normal and deluxel */
++ normal = SUPER_NORMAL(x, y);
++ cluster = SUPER_CLUSTER(x, y);
++ bspDeluxel = BSP_DELUXEL( x, y );
++ deluxel = SUPER_DELUXEL( x, y );
++
++ /* get normal */
++ VectorSet( myNormal, normal[0], normal[1], normal[2] );
++
++ /* get tangent vectors */
++ if( myNormal[ 0 ] == 0.0f && myNormal[ 1 ] == 0.0f )
++ {
++ if( myNormal[ 2 ] == 1.0f )
++ {
++ VectorSet( myTangent, 1.0f, 0.0f, 0.0f );
++ VectorSet( myBinormal, 0.0f, 1.0f, 0.0f );
++ }
++ else if( myNormal[ 2 ] == -1.0f )
++ {
++ VectorSet( myTangent, -1.0f, 0.0f, 0.0f );
++ VectorSet( myBinormal, 0.0f, 1.0f, 0.0f );
++ }
++ }
++ else
++ {
++ VectorSet( worldUp, 0.0f, 0.0f, 1.0f );
++ CrossProduct( myNormal, worldUp, myTangent );
++ VectorNormalize( myTangent, myTangent );
++ CrossProduct( myTangent, myNormal, myBinormal );
++ VectorNormalize( myBinormal, myBinormal );
++ }
++
++ /* project onto plane */
++ dist = -DotProduct(myTangent, myNormal);
++ VectorMA(myTangent, dist, myNormal, myTangent);
++ dist = -DotProduct(myBinormal, myNormal);
++ VectorMA(myBinormal, dist, myNormal, myBinormal);
++
++ /* renormalize */
++ VectorNormalize( myTangent, myTangent );
++ VectorNormalize( myBinormal, myBinormal );
++
++ /* convert modelspace deluxel to tangentspace */
++ dirSample[0] = bspDeluxel[0];
++ dirSample[1] = bspDeluxel[1];
++ dirSample[2] = bspDeluxel[2];
++ VectorNormalize(dirSample, dirSample);
++
++ /* fix tangents to world matrix */
++ if (myNormal[0] > 0 || myNormal[1] < 0 || myNormal[2] < 0)
++ VectorNegate(myTangent, myTangent);
++
++ /* build tangentspace vectors */
++ bspDeluxel[0] = DotProduct(dirSample, myTangent);
++ bspDeluxel[1] = DotProduct(dirSample, myBinormal);
++ bspDeluxel[2] = DotProduct(dirSample, myNormal);
++ }
++ }
++ }
++ }
++ }
++
++ /* -----------------------------------------------------------------
++ blend lightmaps
++ ----------------------------------------------------------------- */
++
++#ifdef sdfsdfwq312323
++ /* note it */
++ Sys_Printf( "blending..." );
++
++ for( i = 0; i < numRawLightmaps; i++ )
++ {
++ vec3_t myColor;
++ float myBrightness;
++
++ /* get lightmap */
++ lm = &rawLightmaps[ i ];
++
++ /* walk individual lightmaps */
++ for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
++ {
++ /* early outs */
++ if( lm->superLuxels[ lightmapNum ] == NULL )
++ continue;
++
++ /* walk lightmap samples */
++ for( y = 0; y < lm->sh; y++ )
++ {
++ for( x = 0; x < lm->sw; x++ )
++ {
++ /* get luxel */
++ bspLuxel = BSP_LUXEL( lightmapNum, x, y );
++
++ /* get color */
++ VectorNormalize(bspLuxel, myColor);
++ myBrightness = VectorLength(bspLuxel);
++ myBrightness *= (1 / 127.0f);
++ myBrightness = myBrightness*myBrightness;
++ myBrightness *= 127.0f;
++ VectorScale(myColor, myBrightness, bspLuxel);
++ }
++ }
++ }
++ }
++#endif
++
++ /* -----------------------------------------------------------------
+ collapse non-unique lightmaps
+ ----------------------------------------------------------------- */
+
+ if( noCollapse == qfalse && deluxemap == qfalse )
+ {
+ /* note it */
+- Sys_FPrintf( SYS_VRB, "collapsing..." );
++ Sys_Printf( "collapsing..." );
+
+ /* set all twin refs to null */
+ for( i = 0; i < numRawLightmaps; i++ )
+@@ -2674,13 +2816,13 @@\r
+ }
+ }
+ }
+-
++
+ /* -----------------------------------------------------------------
+ sort raw lightmaps by shader
+ ----------------------------------------------------------------- */
+
+ /* note it */
+- Sys_FPrintf( SYS_VRB, "sorting..." );
++ Sys_Printf( "sorting..." );
+
+ /* allocate a new sorted list */
+ if( sortLightmaps == NULL )
+@@ -2696,7 +2838,7 @@\r
+ ----------------------------------------------------------------- */
+
+ /* note it */
+- Sys_FPrintf( SYS_VRB, "allocating..." );
++ Sys_Printf( "allocating..." );
+
+ /* kill all existing output lightmaps */
+ if( outLightmaps != NULL )
+@@ -2749,7 +2891,7 @@\r
+ ----------------------------------------------------------------- */
+
+ /* note it */
+- Sys_FPrintf( SYS_VRB, "storing..." );
++ Sys_Printf( "storing..." );
+
+ /* count the bsp lightmaps and allocate space */
+ if( bspLightBytes != NULL )
+@@ -2817,7 +2959,7 @@\r
+ }
+
+ if( numExtLightmaps > 0 )
+- Sys_FPrintf( SYS_VRB, "\n" );
++ Sys_Printf( SYS_VRB, "\n" );
+
+ /* delete unused external lightmaps */
+ for( i = numExtLightmaps; i; i++ )
+@@ -2836,7 +2978,7 @@\r
+ ----------------------------------------------------------------- */
+
+ /* note it */
+- Sys_FPrintf( SYS_VRB, "projecting..." );
++ Sys_Printf( "projecting..." );
+
+ /* walk the list of surfaces */
+ for( i = 0; i < numBSPDrawSurfaces; i++ )
+@@ -3108,7 +3250,7 @@\r
+ }
+
+ /* finish */
+- Sys_FPrintf( SYS_VRB, "done.\n" );
++ Sys_Printf( "done.\n" );
+
+ /* calc num stored */
+ numStored = numBSPLightBytes / 3;
+Index: main.c\r
+===================================================================\r
+--- main.c (revision 158)\r
++++ main.c (working copy)\r
+@@ -604,7 +604,7 @@\r
+
+ /* set exit call */
+ atexit( ExitQ3Map );
+-
++
+ /* read general options first */
+ for( i = 1; i < argc; i++ )
+ {
+@@ -680,6 +680,10 @@\r
+
+ /* ydnar: new path initialization */
+ InitPaths( &argc, argv );
++
++ /* set game options */
++ if (!patchSubdivisions)
++ patchSubdivisions = game->patchSubdivisions;
+
+ /* check if we have enough options left to attempt something */
+ if( argc < 2 )
+Index: map.c\r
+===================================================================\r
+--- map.c (revision 158)\r
++++ map.c (working copy)\r
+@@ -1515,14 +1515,18 @@\r
+ /* get explicit shadow flags */
+ GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows );
+
++ /* vortex: added _ls key (short name of lightmapscale) */
+ /* ydnar: get lightmap scaling value for this entity */
+ if( strcmp( "", ValueForKey( mapEnt, "lightmapscale" ) ) ||
+- strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ) ) )
++ strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ) ) ||
++ strcmp( "", ValueForKey( mapEnt, "_ls" ) ) )
+ {
+ /* get lightmap scale from entity */
+ lightmapScale = FloatForKey( mapEnt, "lightmapscale" );
+ if( lightmapScale <= 0.0f )
+ lightmapScale = FloatForKey( mapEnt, "_lightmapscale" );
++ if( lightmapScale <= 0.0f )
++ lightmapScale = FloatForKey( mapEnt, "_ls" );
+ if( lightmapScale > 0.0f )
+ Sys_Printf( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale );
+ }
+Index: mesh.c\r
+===================================================================\r
+--- mesh.c (revision 158)\r
++++ mesh.c (working copy)\r
+@@ -563,7 +563,7 @@\r
+ }
+
+ /* keep chopping */
+- for( iterations; iterations > 0; iterations-- )
++ for( ; iterations > 0; iterations-- )
+ {
+ /* horizontal subdivisions */
+ for( j = 0; j + 2 < out.width; j += 4 )
+Index: model.c\r
+===================================================================\r
+--- model.c (revision 158)\r
++++ model.c (working copy)\r
+@@ -266,7 +266,7 @@\r
+ continue;
+
+ /* fix the surface's normals */
+- PicoFixSurfaceNormals( surface );
++ //PicoFixSurfaceNormals( surface );
+
+ /* allocate a surface (ydnar: gs mods) */
+ ds = AllocDrawSurface( SURFACE_TRIANGLES );
+@@ -521,7 +521,15 @@\r
+ else
+ free( buildBrush );
+ }
++ else
++ {
++ Sys_Printf( "WARNING: Model %s unable to generate brush - Case 1.\n", name );
++ }
+ }
++ else
++ {
++ Sys_Printf( "WARNING: Model %s unable to generate brush - Case 2.\n", name );
++ }
+ }
+ }
+ }
+@@ -566,8 +574,11 @@\r
+ }
+
+ /* get lightmap scale */
++ /* vortex: added _ls key (short name of lightmapscale) */
+ baseLightmapScale = FloatForKey( e, "_lightmapscale" );
+ if( baseLightmapScale <= 0.0f )
++ baseLightmapScale = FloatForKey( e, "_ls" );
++ if( baseLightmapScale <= 0.0f )
+ baseLightmapScale = 0.0f;
+
+ /* walk the entity list */
+@@ -688,8 +699,11 @@\r
+ celShader = NULL;
+
+ /* get lightmap scale */
++ /* vortex: added _ls key (short name of lightmapscale) */
+ lightmapScale = FloatForKey( e2, "_lightmapscale" );
+ if( lightmapScale <= 0.0f )
++ lightmapScale = FloatForKey( e2, "_ls" );
++ if( lightmapScale <= 0.0f )
+ lightmapScale = baseLightmapScale;
+
+ /* insert the model */
+Index: patch.c\r
+===================================================================\r
+--- patch.c (revision 158)\r
++++ patch.c (working copy)\r
+@@ -227,7 +227,6 @@\r
+ float longestCurve;
+ int maxIterations;
+
+-
+ MatchToken( "{" );
+
+ /* get texture */
+Index: path_init.c\r
+===================================================================\r
+--- path_init.c (revision 158)\r
++++ path_init.c (working copy)\r
+@@ -383,7 +383,7 @@\r
+ /* remove processed arguments */
+ for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
+ {
+- for( j; j < *argc && argv[ j ] == NULL; j++ );
++ for( ; j < *argc && argv[ j ] == NULL; j++ );
+ argv[ i ] = argv[ j ];
+ if( argv[ i ] != NULL )
+ k++;
+Index: q3map2.h\r
+===================================================================\r
+--- q3map2.h (revision 158)\r
++++ q3map2.h (working copy)\r
+@@ -35,8 +35,8 @@\r
+
+
+ /* version */
+-#define Q3MAP_VERSION "2.5.17"
+-#define Q3MAP_MOTD "Last one turns the lights off"
++#define Q3MAP_VERSION "2.5.17 base : FS_20g base : R5"
++#define Q3MAP_MOTD "Sorry, it doesn't match my furniture."
+
+
+
+@@ -235,6 +235,7 @@\r
+ #define LIGHT_FAST_TEMP 512
+ #define LIGHT_FAST_ACTUAL (LIGHT_FAST | LIGHT_FAST_TEMP)
+ #define LIGHT_NEGATIVE 1024
++#define LIGHT_UNNORMALIZED 2048 /* vortex: do not normalize _color */
+
+ #define LIGHT_SUN_DEFAULT (LIGHT_ATTEN_ANGLE | LIGHT_GRID | LIGHT_SURFACES)
+ #define LIGHT_AREA_DEFAULT (LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES) /* q3a and wolf are the same */
+@@ -267,6 +268,7 @@\r
+ #define SUPER_NORMAL_SIZE 4
+ #define SUPER_DELUXEL_SIZE 3
+ #define BSP_DELUXEL_SIZE 3
++#define SUPER_FLOODLIGHT_SIZE 4
+
+ #define VERTEX_LUXEL( s, v ) (vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
+ #define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
+@@ -279,9 +281,8 @@\r
+ #define SUPER_ORIGIN( x, y ) (lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
+ #define SUPER_NORMAL( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
+ #define SUPER_DIRT( x, y ) (lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE) + 3) /* stash dirtyness in normal[ 3 ] */
++#define SUPER_FLOODLIGHT(x, y ) (lm->superFloodLight + ((((y) * lm->sw) + (x)) * SUPER_FLOODLIGHT_SIZE))
+
+-
+-
+ /* -------------------------------------------------------------------------------
+
+ abstracted bsp file
+@@ -543,7 +544,16 @@\r
+ qboolean wolfLight; /* when true, lights work like wolf q3map */
+ int lightmapSize; /* bsp lightmap width/height */
+ float lightmapGamma; /* default lightmap gamma */
++ float lightmapExposure; /* default lightmap exposure */
+ float lightmapCompensate; /* default lightmap compensate value */
++ float gridScale; /* vortex: default lightgrid scale (affects both directional and ambient spectres) */
++ float gridAmbientScale; /* vortex: default lightgrid ambient spectre scale */
++ qboolean noStyles; /* use lightstyles hack or not */
++ qboolean keepLights; /* keep light entities on bsp */
++ int patchSubdivisions; /* default patch subdivisions tolerance */
++ qboolean patchShadows; /* patch casting enabled */
++ qboolean deluxeMap; /* compile deluxemaps */
++ int deluxeMode; /* deluxemap mode (0 - modelspace, 1 - tangentspace with renormalization, 2 - tangentspace without renormalization) */
+ char *bspIdent; /* 4-letter bsp file prefix */
+ int bspVersion; /* bsp version to use */
+ qboolean lumpSwap; /* cod-style len/ofs order */
+@@ -662,6 +672,7 @@\r
+ char *backShader; /* for surfaces that generate different front and back passes */
+ char *cloneShader; /* ydnar: for cloning of a surface */
+ char *remapShader; /* ydnar: remap a shader in final stage */
++ char *deprecateShader; /* vortex: shader is deprecated and replaced by this on use */
+
+ surfaceModel_t *surfaceModel; /* ydnar: for distribution of models */
+ foliage_t *foliage; /* ydnar/splash damage: wolf et foliage */
+@@ -737,7 +748,13 @@\r
+
+ vec3_t color; /* normalized color */
+ vec3_t averageColor;
+- byte lightStyle;
++ byte lightStyle;
++
++ /* vortex: per-surface floodlight */
++ float floodlightDirectionScale;
++ vec3_t floodlightRGB;
++ float floodlightIntensity;
++ float floodlightDistance;
+
+ qb_t lmMergable; /* ydnar */
+ int lmCustomWidth, lmCustomHeight; /* ydnar */
+@@ -1013,7 +1030,7 @@\r
+ int maxIterations;
+ int patchWidth, patchHeight;
+ vec3_t bounds[ 2 ];
+-
++
+ /* ydnar/sd: for foliage */
+ int numFoliageInstances;
+
+@@ -1061,6 +1078,7 @@\r
+ int mapEntityNum, firstDrawSurf;
+ int firstBrush, numBrushes; /* only valid during BSP compile */
+ epair_t *epairs;
++ qboolean forceNormalSmoothing; /* vortex: true if entity has _smoothnormals/_sn/_smooth key */
+ }
+ entity_t;
+
+@@ -1296,7 +1314,8 @@\r
+
+ /* input and output */
+ vec3_t color; /* starts out at full color, may be reduced if transparent surfaces are crossed */
+-
++ vec3_t colorNoShadow; /* result color with no shadow casting */
++
+ /* output */
+ vec3_t hit;
+ int compileFlags; /* for determining surface compile flags traced through */
+@@ -1367,6 +1386,13 @@\r
+ int numLightClusters, *lightClusters;
+
+ int sampleSize, actualSampleSize, axisNum;
++
++ /* vortex: per-surface floodlight */
++ float floodlightDirectionScale;
++ vec3_t floodlightRGB;
++ float floodlightIntensity;
++ float floodlightDistance;
++
+ int entityNum;
+ int recvShadows;
+ vec3_t mins, maxs, axis, origin, *vecs;
+@@ -1389,9 +1415,9 @@\r
+ float *superOrigins;
+ float *superNormals;
+ int *superClusters;
+-
+ float *superDeluxels; /* average light direction */
+ float *bspDeluxels;
++ float *superFloodLight; /* floodlight color */
+ }
+ rawLightmap_t;
+
+@@ -1421,8 +1447,6 @@\r
+ }
+ surfaceInfo_t;
+
+-
+-
+ /* -------------------------------------------------------------------------------
+
+ prototypes
+@@ -1556,6 +1580,7 @@\r
+ void ParsePatch( qboolean onlyLights );
+ mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength );
+ void PatchMapDrawSurfs( entity_t *e );
++void TriangulatePatchSurface( entity_t *e , mapDrawSurface_t *ds );
+
+
+ /* tjunction.c */
+@@ -1610,6 +1635,8 @@\r
+ void AddEntitySurfaceModels( entity_t *e );
+ int AddSurfaceModels( mapDrawSurface_t *ds );
+ void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
++void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds );
++static void EmitTriangleSurface( mapDrawSurface_t *ds );
+
+
+ /* surface_fur.c */
+@@ -1627,6 +1654,7 @@\r
+ void FixMetaTJunctions( void );
+ void SmoothMetaTriangles( void );
+ void MergeMetaTriangles( void );
++void EmitMetaStats(); // vortex: print meta statistics even in no-verbose mode
+
+
+ /* surface_extra.c */
+@@ -1704,6 +1732,12 @@\r
+ float DirtForSample( trace_t *trace );
+ void DirtyRawLightmap( int num );
+
++void SetupFloodLight();
++void FloodlightRawLightmaps();
++void FloodlightIlluminateLightmap( rawLightmap_t *lm );
++float FloodLightForSample( trace_t *trace , float floodLightDistance, qboolean floodLightLowQuality);
++void FloodLightRawLightmap( int num );
++
+ void IlluminateRawLightmap( int num );
+ void IlluminateVertexes( int num );
+
+@@ -1731,7 +1765,6 @@\r
+ void StitchSurfaceLightmaps( void );
+ void StoreSurfaceLightmaps( void );
+
+-
+ /* image.c */
+ void ImageFree( image_t *image );
+ image_t *ImageFind( const char *filename );
+@@ -1783,6 +1816,7 @@\r
+ void UnparseEntities( void );
+ void PrintEntity( const entity_t *ent );
+ void SetKeyValue( entity_t *ent, const char *key, const char *value );
++qboolean KeyExists( const entity_t *ent, const char *key ); /* VorteX: check if key exists */
+ const char *ValueForKey( const entity_t *ent, const char *key );
+ int IntForKey( const entity_t *ent, const char *key );
+ vec_t FloatForKey( const entity_t *ent, const char *key );
+@@ -1845,6 +1879,12 @@\r
+ ,
+ #include "game_qfusion.h" /* qfusion game */
+ ,
++ #include "game_darkplaces.h" /* vortex: darkplaces q1 engine */
++ ,
++ #include "game_dq.h" /* vortex: deluxe quake game ( darkplaces q1 engine) */
++ ,
++ #include "game_prophecy.h" /* vortex: prophecy game ( darkplaces q1 engine) */
++ ,
+ { NULL } /* null game */
+ };
+ #endif
+@@ -1929,6 +1969,7 @@\r
+ Q_EXTERN char outbase[ 32 ];
+
+ Q_EXTERN int sampleSize; /* lightmap sample size in units */
++Q_EXTERN int sampleScale; /* vortex: lightmap sample scale (ie quality)*/
+
+ Q_EXTERN int mapEntityNum Q_ASSIGN( 0 );
+
+@@ -2053,6 +2094,7 @@\r
+ Q_EXTERN qboolean wolfLight Q_ASSIGN( qfalse );
+ Q_EXTERN qboolean loMem Q_ASSIGN( qfalse );
+ Q_EXTERN qboolean noStyles Q_ASSIGN( qfalse );
++Q_EXTERN qboolean keepLights Q_ASSIGN( qfalse );
+
+ Q_EXTERN int sampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_SAMPLE_SIZE );
+ Q_EXTERN qboolean noVertexLighting Q_ASSIGN( qfalse );
+@@ -2065,6 +2107,7 @@\r
+
+ Q_EXTERN qboolean deluxemap Q_ASSIGN( qfalse );
+ Q_EXTERN qboolean debugDeluxemap Q_ASSIGN( qfalse );
++Q_EXTERN int deluxemode Q_ASSIGN( 0 ); /* deluxemap format (0 - modelspace, 1 - tangentspace with renormalization, 2 - tangentspace without renormalization) */
+
+ Q_EXTERN qboolean fast Q_ASSIGN( qfalse );
+ Q_EXTERN qboolean faster Q_ASSIGN( qfalse );
+@@ -2098,6 +2141,14 @@\r
+ Q_EXTERN float dirtScale Q_ASSIGN( 1.0f );
+ Q_EXTERN float dirtGain Q_ASSIGN( 1.0f );
+
++/* 27: floodlighting */
++Q_EXTERN qboolean debugnormals Q_ASSIGN( qfalse );
++Q_EXTERN qboolean floodlighty Q_ASSIGN( qfalse );
++Q_EXTERN qboolean floodlight_lowquality Q_ASSIGN( qfalse );
++Q_EXTERN vec3_t floodlightRGB;
++Q_EXTERN float floodlightIntensity Q_ASSIGN( 512.0f );
++Q_EXTERN float floodlightDistance Q_ASSIGN( 1024.0f );
++
+ Q_EXTERN qboolean dump Q_ASSIGN( qfalse );
+ Q_EXTERN qboolean debug Q_ASSIGN( qfalse );
+ Q_EXTERN qboolean debugUnused Q_ASSIGN( qfalse );
+@@ -2115,9 +2166,14 @@\r
+ Q_EXTERN float skyScale Q_ASSIGN( 1.0f );
+ Q_EXTERN float bounceScale Q_ASSIGN( 0.25f );
+
++/* vortex: gridscale and gridambientscale */
++Q_EXTERN float gridScale Q_ASSIGN( 1.0f );
++Q_EXTERN float gridAmbientScale Q_ASSIGN( 1.0f );
++
+ /* ydnar: lightmap gamma/compensation */
+ Q_EXTERN float lightmapGamma Q_ASSIGN( 1.0f );
+ Q_EXTERN float lightmapCompensate Q_ASSIGN( 1.0f );
++Q_EXTERN float lightmapExposure Q_ASSIGN( 1.0f );
+
+ /* ydnar: for runtime tweaking of falloff tolerance */
+ Q_EXTERN float falloffTolerance Q_ASSIGN( 1.0f );
+@@ -2221,6 +2277,9 @@\r
+ Q_EXTERN int numExtLightmaps Q_ASSIGN( 0 );
+ Q_EXTERN outLightmap_t *outLightmaps Q_ASSIGN( NULL );
+
++/* vortex: per surface floodlight statictics */
++Q_EXTERN int numSurfacesFloodlighten Q_ASSIGN( 0 );
++
+ /* grid points */
+ Q_EXTERN int numRawGridPoints Q_ASSIGN( 0 );
+ Q_EXTERN rawGridPoint_t *rawGridPoints Q_ASSIGN( NULL );
+Index: shaders.c\r
+===================================================================\r
+--- shaders.c (revision 158)\r
++++ shaders.c (working copy)\r
+@@ -793,8 +793,14 @@\r
+ }
+
+ if( VectorLength( si->color ) <= 0.0f )
++ {
+ ColorNormalize( color, si->color );
+- VectorScale( color, (1.0f / count), si->averageColor );
++ VectorScale( color, (1.0f / count), si->averageColor );
++ }
++ else
++ {
++ VectorCopy( si->color, si->averageColor );
++ }
+ }
+
+
+@@ -804,13 +810,15 @@\r
+ finds a shaderinfo for a named shader
+ */
+
++#define MAX_SHADER_DEPRECATION_DEPTH 16
++
+ shaderInfo_t *ShaderInfoForShader( const char *shaderName )
+ {
+ int i;
++ int deprecationDepth;
+ shaderInfo_t *si;
+ char shader[ MAX_QPATH ];
+-
+-
++
+ /* dummy check */
+ if( shaderName == NULL || shaderName[ 0 ] == '\0' )
+ {
+@@ -823,11 +831,27 @@\r
+ StripExtension( shader );
+
+ /* search for it */
++ deprecationDepth = 0;
+ for( i = 0; i < numShaderInfo; i++ )
+ {
+ si = &shaderInfo[ i ];
+ if( !Q_stricmp( shader, si->shader ) )
+ {
++ /* check if shader is deprecated */
++ if (deprecationDepth < MAX_SHADER_DEPRECATION_DEPTH && si->deprecateShader && si->deprecateShader[ 0 ] )
++ {
++ /* override name */
++ strcpy( shader, si->deprecateShader );
++ StripExtension( shader );
++ /* increase deprecation depth */
++ deprecationDepth++;
++ if (deprecationDepth == MAX_SHADER_DEPRECATION_DEPTH)
++ Sys_Printf("WARNING: Max deprecation depth of %i is reached on shader '%s'\n", MAX_SHADER_DEPRECATION_DEPTH, shader);
++ /* search again from beginning */
++ i = -1;
++ continue;
++ }
++
+ /* load image if necessary */
+ if( si->finished == qfalse )
+ {
+@@ -1340,7 +1364,6 @@\r
+ {
+ surfaceModel_t *model;
+
+-
+ /* allocate new model and attach it */
+ model = safe_malloc( sizeof( *model ) );
+ memset( model, 0, sizeof( *model ) );
+@@ -1465,6 +1488,24 @@\r
+ GetTokenAppend( shaderText, qfalse );
+ si->backsplashDistance = atof( token );
+ }
++
++ /* q3map_floodLight <r> <g> <b> <diste> <intensity> <light_direction_power> */
++ else if( !Q_stricmp( token, "q3map_floodLight" ) )
++ {
++ /* get color */
++ GetTokenAppend( shaderText, qfalse );
++ si->floodlightRGB[ 0 ] = atof( token );
++ GetTokenAppend( shaderText, qfalse );
++ si->floodlightRGB[ 1 ] = atof( token );
++ GetTokenAppend( shaderText, qfalse );
++ si->floodlightRGB[ 2 ] = atof( token );
++ GetTokenAppend( shaderText, qfalse );
++ si->floodlightDistance = atof( token );
++ GetTokenAppend( shaderText, qfalse );
++ si->floodlightIntensity = atof( token );
++ GetTokenAppend( shaderText, qfalse );
++ si->floodlightDirectionScale = atof( token );
++ }
+
+ /* q3map_lightmapSampleSize <value> */
+ else if( !Q_stricmp( token, "q3map_lightmapSampleSize" ) )
+@@ -1590,6 +1631,18 @@\r
+ strcpy( si->remapShader, token );
+ }
+ }
++
++ /* q3map_deprecateShader <shader> */
++ else if( !Q_stricmp( token, "q3map_deprecateShader" ) )
++ {
++ GetTokenAppend( shaderText, qfalse );
++ if( token[ 0 ] != '\0' )
++ {
++
++ si->deprecateShader = safe_malloc( strlen( token ) + 1 );
++ strcpy( si->deprecateShader, token );
++ }
++ }
+
+ /* ydnar: q3map_offset <value> */
+ else if( !Q_stricmp( token, "q3map_offset" ) )
+@@ -1896,12 +1949,14 @@\r
+ si->styleMarker = 2;
+
+ /* ydnar: default to searching for q3map_<surfaceparm> */
+- else
++#if 0
++ else
+ {
+- //% Sys_FPrintf( SYS_VRB, "Attempting to match %s with a known surfaceparm\n", token );
++ Sys_FPrintf( SYS_VRB, "Attempting to match %s with a known surfaceparm\n", token );
+ if( ApplySurfaceParm( &token[ 6 ], &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
+- ;//% Sys_Printf( "WARNING: Unknown q3map_* directive \"%s\"\n", token );
++ Sys_Printf( "WARNING: Unknown q3map_* directive \"%s\"\n", token );
+ }
++#endif
+ }
+
+
+Index: surface.c\r
+===================================================================\r
+--- surface.c (revision 158)\r
++++ surface.c (working copy)\r
+@@ -304,7 +304,7 @@\r
+ out = &mapDrawSurfs[ i ];
+
+ /* walk the surface list again until a proper surface is found */
+- for( j; j < numMapDrawSurfs; j++ )
++ for( ; j < numMapDrawSurfs; j++ )
+ {
+ /* get in surface */
+ in = &mapDrawSurfs[ j ];
+@@ -484,7 +484,7 @@\r
+
+
+ /* walk the list of surfaces */
+- for( numSurfs; numSurfs > 0; numSurfs--, ds++ )
++ for( ; numSurfs > 0; numSurfs--, ds++ )
+ {
+ /* ignore bogus (or flare) surfaces */
+ if( ds->type == SURFACE_BAD || ds->numVerts <= 0 )
+@@ -2445,25 +2445,27 @@\r
+ numSurfacesByType[ ds->type ]++;
+ }
+
+-
+-
+ /*
+ EmitPatchSurface()
+ emits a bsp patch drawsurface
+ */
+
+-void EmitPatchSurface( mapDrawSurface_t *ds )
++void EmitPatchSurface( entity_t *e, mapDrawSurface_t *ds )
+ {
+ int i, j;
+ bspDrawSurface_t *out;
+ int surfaceFlags, contentFlags;
++ int forcePatchMeta;
++
++ /* vortex: _patchMeta support */
++ forcePatchMeta = IntForKey(e, "_patchMeta" );
++ if (!forcePatchMeta)
++ forcePatchMeta = IntForKey(e, "patchMeta" );
+
+-
+ /* invert the surface if necessary */
+ if( ds->backSide || ds->shaderInfo->invert )
+ {
+ bspDrawVert_t *dv1, *dv2, temp;
+-
+
+ /* walk the verts, flip the normal */
+ for( i = 0; i < ds->numVerts; i++ )
+@@ -2485,7 +2487,7 @@\r
+ /* invert facing */
+ VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
+ }
+-
++
+ /* allocate a new surface */
+ if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
+ Error( "MAX_MAP_DRAW_SURFS" );
+@@ -2493,12 +2495,12 @@\r
+ ds->outputNum = numBSPDrawSurfaces;
+ numBSPDrawSurfaces++;
+ memset( out, 0, sizeof( *out ) );
+-
++
+ /* set it up */
+ out->surfaceType = MST_PATCH;
+ if( debugSurfaces )
+ out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL );
+- else if( patchMeta )
++ else if( patchMeta || forcePatchMeta )
+ {
+ /* patch meta requires that we have nodraw patches for collision */
+ surfaceFlags = ds->shaderInfo->surfaceFlags;
+@@ -2548,8 +2550,6 @@\r
+ numSurfacesByType[ ds->type ]++;
+ }
+
+-
+-
+ /*
+ OptimizeTriangleSurface() - ydnar
+ optimizes the vertex/index data in a triangle surface
+@@ -2677,8 +2677,7 @@\r
+ {
+ int i, temp;
+ bspDrawSurface_t *out;
+-
+-
++
+ /* invert the surface if necessary */
+ if( ds->backSide || ds->shaderInfo->invert )
+ {
+@@ -2689,15 +2688,15 @@\r
+ ds->indexes[ i ] = ds->indexes[ i + 1 ];
+ ds->indexes[ i + 1 ] = temp;
+ }
+-
++
+ /* walk the verts, flip the normal */
+ for( i = 0; i < ds->numVerts; i++ )
+ VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal );
+-
++
+ /* invert facing */
+ VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
+ }
+-
++
+ /* allocate a new surface */
+ if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
+ Error( "MAX_MAP_DRAW_SURFS" );
+@@ -2804,15 +2803,14 @@\r
+ emits a bsp planar winding (brush face) drawsurface
+ */
+
+-static void EmitFaceSurface( mapDrawSurface_t *ds )
++static void EmitFaceSurface(mapDrawSurface_t *ds )
+ {
+ /* strip/fan finding was moved elsewhere */
+ StripFaceSurface( ds );
+- EmitTriangleSurface( ds );
++ EmitTriangleSurface(ds);
+ }
+
+
+-
+ /*
+ MakeDebugPortalSurfs_r() - ydnar
+ generates drawsurfaces for passable portals in the bsp
+@@ -3502,7 +3500,7 @@\r
+ if( refs == 0 )
+ refs = FilterPatchIntoTree( ds, tree );
+ if( refs > 0 )
+- EmitPatchSurface( ds );
++ EmitPatchSurface( e, ds );
+ break;
+
+ /* handle triangle surfaces */
+Index: surface_meta.c\r
+===================================================================\r
+--- surface_meta.c (revision 158)\r
++++ surface_meta.c (working copy)\r
+@@ -312,23 +312,41 @@\r
+ creates triangles from a patch
+ */
+
+-void TriangulatePatchSurface( mapDrawSurface_t *ds )
++void TriangulatePatchSurface( entity_t *e , mapDrawSurface_t *ds )
+ {
+ int iterations, x, y, pw[ 5 ], r;
+ mapDrawSurface_t *dsNew;
+ mesh_t src, *subdivided, *mesh;
+-
+-
++ int forcePatchMeta;
++ int patchQuality;
++ int patchSubdivision;
++
++ /* vortex: _patchMeta, _patchQuality, _patchSubdivide support */
++ forcePatchMeta = IntForKey(e, "_patchMeta" );
++ if (!forcePatchMeta)
++ forcePatchMeta = IntForKey(e, "patchMeta" );
++ patchQuality = IntForKey(e, "_patchQuality" );
++ if (!patchQuality)
++ patchQuality = IntForKey(e, "patchQuality" );
++ if (!patchQuality)
++ patchQuality = 1.0;
++ patchSubdivision = IntForKey(e, "_patchSubdivide" );
++ if (!patchSubdivision)
++ patchSubdivision = IntForKey(e, "patchSubdivide" );
++
+ /* try to early out */
+- if( ds->numVerts == 0 || ds->type != SURFACE_PATCH || patchMeta == qfalse )
++ if(ds->numVerts == 0 || ds->type != SURFACE_PATCH || ( patchMeta == qfalse && !forcePatchMeta) )
+ return;
+-
+ /* make a mesh from the drawsurf */
+ src.width = ds->patchWidth;
+ src.height = ds->patchHeight;
+ src.verts = ds->verts;
+ //% subdivided = SubdivideMesh( src, 8, 999 );
+- iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
++ if (patchSubdivision)
++ iterations = IterationsForCurve( ds->longestCurve, patchSubdivision );
++ else
++ iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions / patchQuality );
++
+ subdivided = SubdivideMesh2( src, iterations ); //% ds->maxIterations
+
+ /* fit it to the curve and remove colinear verts on rows/columns */
+@@ -599,7 +617,22 @@\r
+ }
+
+
++/*
++EmitMetaStatictics
++vortex: prints meta statistics in general output
++*/
+
++void EmitMetaStats()
++{
++ Sys_Printf( "--- EmitMetaStats ---\n" );
++ Sys_Printf( "%9d total meta surfaces\n", numMetaSurfaces );
++ Sys_Printf( "%9d stripped surfaces\n", numStripSurfaces );
++ Sys_Printf( "%9d fanned surfaces\n", numFanSurfaces );
++ Sys_Printf( "%9d patch meta surfaces\n", numPatchMetaSurfaces );
++ Sys_Printf( "%9d meta verts\n", numMetaVerts );
++ Sys_Printf( "%9d meta triangles\n", numMetaTriangles );
++}
++
+ /*
+ MakeEntityMetaTriangles()
+ builds meta triangles from brush faces (tristrips and fans)
+@@ -652,12 +685,12 @@\r
+ break;
+
+ case SURFACE_PATCH:
+- TriangulatePatchSurface( ds );
++ TriangulatePatchSurface(e, ds );
+ break;
+
+ case SURFACE_TRIANGLES:
+ break;
+-
++
+ case SURFACE_FORCED_META:
+ case SURFACE_META:
+ SurfaceToMetaTriangles( ds );
+@@ -972,8 +1005,8 @@\r
+ vec3_t average, diff;
+ int indexes[ MAX_SAMPLES ];
+ vec3_t votes[ MAX_SAMPLES ];
++ const char *classname;
+
+-
+ /* note it */
+ Sys_FPrintf( SYS_VRB, "--- SmoothMetaTriangles ---\n" );
+
+@@ -994,11 +1027,31 @@\r
+ and set per-vertex smoothing angle */
+ for( i = 0, tri = &metaTriangles[ i ]; i < numMetaTriangles; i++, tri++ )
+ {
++ /* vortex: try get smoothing from entity key */
++ shadeAngle = FloatForKey(&entities[tri->entityNum], "_smoothnormals");
++ if (shadeAngle <= 0.0f)
++ shadeAngle = FloatForKey(&entities[tri->entityNum], "_sn");
++ if (shadeAngle <= 0.0f)
++ shadeAngle = FloatForKey(&entities[tri->entityNum], "_smooth");
++ if (shadeAngle > 0.0f)
++ {
++ if (entities[tri->entityNum].forceNormalSmoothing == qfalse)
++ {
++ entities[tri->entityNum].forceNormalSmoothing = qtrue;
++ classname = ValueForKey( &entities[tri->entityNum], "classname" );
++ Sys_Printf( "Entity %d (%s) has vertex normal smoothing with breaking angle of %3.0f\n", tri->entityNum, classname, shadeAngle );
++ }
++ shadeAngle = DEG2RAD( shadeAngle );
++ }
++
+ /* get shader for shade angle */
+- if( tri->si->shadeAngleDegrees > 0.0f )
+- shadeAngle = DEG2RAD( tri->si->shadeAngleDegrees );
+- else
+- shadeAngle = defaultShadeAngle;
++ if (shadeAngle <= 0.0f)
++ {
++ if( tri->si->shadeAngleDegrees > 0.0f )
++ shadeAngle = DEG2RAD( tri->si->shadeAngleDegrees );
++ else
++ shadeAngle = defaultShadeAngle;
++ }
+ if( shadeAngle > maxShadeAngle )
+ maxShadeAngle = shadeAngle;
+
+Index: writebsp.c\r
+===================================================================\r
+--- writebsp.c (revision 158)\r
++++ writebsp.c (working copy)\r
+@@ -136,7 +136,6 @@\r
+ bspLeaf_t *leaf_p;
+ brush_t *b;
+ drawSurfRef_t *dsr;
+- int i = 0;
+
+
+ /* check limits */
+@@ -278,18 +277,19 @@\r
+ void SetLightStyles( void )
+ {
+ int i, j, style, numStyles;
+- qboolean keepLights;
+ const char *t;
+ entity_t *e;
+ epair_t *ep, *next;
+ char value[ 10 ];
+ char lightTargets[ MAX_SWITCHED_LIGHTS ][ 64 ];
+ int lightStyles[ MAX_SWITCHED_LIGHTS ];
+-
+-
++
+ /* ydnar: determine if we keep lights in the bsp */
+- t = ValueForKey( &entities[ 0 ], "_keepLights" );
+- keepLights = (t[ 0 ] == '1') ? qtrue : qfalse;
++ if (KeyExists(&entities[ 0 ], "_keepLights") == qtrue)
++ {
++ t = ValueForKey( &entities[ 0 ], "_keepLights" );
++ keepLights = (t[ 0 ] == '1') ? qtrue : qfalse;
++ }
+
+ /* any light that is controlled (has a targetname) must have a unique style number generated for it */
+ numStyles = 0;