Index: model_alias.c
===================================================================
--- model_alias.c	(revision 9146)
+++ model_alias.c	(working copy)
@@ -98,7 +98,7 @@
 		const float *v = model->surfmesh.data_vertex3f;
 		const int *wi = model->surfmesh.data_vertexweightindex4i;
 		const float *wf = model->surfmesh.data_vertexweightinfluence4f;
-		memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+		//memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
 		for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3)
 		{
 			if (wf[0] == 1)
@@ -131,7 +131,7 @@
 		const float *n = model->surfmesh.data_normal3f;
 		const int *wi = model->surfmesh.data_vertexweightindex4i;
 		const float *wf = model->surfmesh.data_vertexweightinfluence4f;
-		memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+		//memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
 		for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3)
 		{
 			if (wf[0] == 1)
@@ -164,7 +164,7 @@
 		const float *sv = model->surfmesh.data_svector3f;
 		const int *wi = model->surfmesh.data_vertexweightindex4i;
 		const float *wf = model->surfmesh.data_vertexweightinfluence4f;
-		memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+		//memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
 		for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3)
 		{
 			if (wf[0] == 1)
@@ -197,7 +197,7 @@
 		const float *tv = model->surfmesh.data_tvector3f;
 		const int *wi = model->surfmesh.data_vertexweightindex4i;
 		const float *wf = model->surfmesh.data_vertexweightinfluence4f;
-		memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
+		//memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices);
 		for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3)
 		{
 			if (wf[0] == 1)
Index: r_shadow.c
===================================================================
--- r_shadow.c	(revision 9146)
+++ r_shadow.c	(working copy)
@@ -169,6 +169,8 @@
 
 int maxshadowvertices;
 float *shadowvertex3f;
+//Tom : tex coord needed for improved on-GPU vertex extrusion
+float *shadowvertexprojdist1f;
 
 int maxshadowmark;
 int numshadowmark;
@@ -301,6 +303,15 @@
 cachepic_t *r_editlights_sprcubemapnoshadowlight;
 cachepic_t *r_editlights_sprselection;
 
+// Tom: GLSL shader handles and uniform addresses for on-GPU vertex extrusion in shadow volumes
+GLhandleARB glslDirectionalExtrusionProgram;
+GLhandleARB glslPointExtrusionProgram;
+
+GLint projectionDirectionAddr;
+GLint projectionOriginAddr;
+
+int UseGPUExtrusion = 0;
+
 void r_shadow_start(void)
 {
 	// allocate vertex processing arrays
@@ -316,6 +327,7 @@
 	shadowelements = NULL;
 	maxshadowvertices = 0;
 	shadowvertex3f = NULL;
+	shadowvertexprojdist1f = NULL;
 	maxvertexupdate = 0;
 	vertexupdate = NULL;
 	vertexremap = NULL;
@@ -335,7 +347,107 @@
 	r_shadow_buffer_numshadowtrispvsbytes = 0;
 	r_shadow_buffer_shadowtrispvs = NULL;
 	r_shadow_buffer_numlighttrispvsbytes = 0;
-	r_shadow_buffer_lighttrispvs = NULL;
+	r_shadow_buffer_lighttrispvs = NULL; 
+	
+	//TOM: test system for GLSL compliant GPU
+	
+	Con_Printf("gl_support_shader_objects %i\n",gl_support_shader_objects);
+	
+	if(gl_support_shader_objects){
+		GLenum vertex_shader,fragment_shader;
+		GLint status;
+		const char * vertex_source = 	"uniform vec3 projDir;\
+						void main(void){\
+							vec3 mov = float(gl_MultiTexCoord0) * normalize(projDir);\
+							gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(mov[0],mov[1],mov[2],0.0));\
+						}";
+		const char * fragment_source = "void main(void){ }";
+		
+		const char * point_vertex_source = "uniform vec3 projOrigin;\
+						void main(void){\
+							vec3 direction = vec3(gl_Vertex) - projOrigin;\
+							vec3 mov = (float(gl_MultiTexCoord0) - length(direction) ) * normalize(direction);\
+							gl_Position = gl_ModelViewProjectionMatrix * (gl_Vertex + vec4(mov[0],mov[1],mov[2],0.0));\
+						}";
+		
+		Con_Printf("loading vertex extrusion program objects\n");
+		
+		//directional light extrusion
+		
+		glslDirectionalExtrusionProgram = qglCreateProgramObjectARB();
+		vertex_shader = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
+     		fragment_shader = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+     		qglShaderSourceARB(vertex_shader, 1, &vertex_source, NULL);
+      		qglShaderSourceARB(fragment_shader, 1, &fragment_source, NULL);
+     		qglCompileShaderARB(vertex_shader);
+      		status = 0;
+      		qglGetObjectParameterivARB(vertex_shader,GL_OBJECT_COMPILE_STATUS_ARB,&status);
+      		if(!status){
+      			Con_Printf("<!> glslDirectionalExtrusionProgram vertex shader not compiled\n");
+      		}
+      		qglCompileShaderARB(fragment_shader);
+      		status = 0;
+      		qglGetObjectParameterivARB(fragment_shader,GL_OBJECT_COMPILE_STATUS_ARB,&status);
+      		if(!status){
+      			Con_Printf("<!> glslDirectionalExtrusionProgram fragment shader not compiled\n");
+      		}
+      		
+      		qglAttachObjectARB(glslDirectionalExtrusionProgram, vertex_shader);
+      		qglAttachObjectARB(glslDirectionalExtrusionProgram, fragment_shader);
+
+      		qglLinkProgramARB(glslDirectionalExtrusionProgram);
+      		status = 0;
+      		qglGetObjectParameterivARB(glslDirectionalExtrusionProgram,GL_OBJECT_LINK_STATUS_ARB,&status);
+      		if(!status){
+      			Con_Printf("<!> glslDirectionalExtrusionProgram program object not linked\n");
+      		}
+      		
+      		qglUseProgramObjectARB(glslDirectionalExtrusionProgram);
+      		
+      		projectionDirectionAddr = qglGetUniformLocationARB(glslDirectionalExtrusionProgram,"projDir");
+      		
+      		qglUseProgramObjectARB(0);
+      		
+      		//point light extrusion
+		
+		glslPointExtrusionProgram = qglCreateProgramObjectARB();
+		vertex_shader = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
+     		fragment_shader = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+     		qglShaderSourceARB(vertex_shader, 1, &point_vertex_source, NULL);
+      		qglShaderSourceARB(fragment_shader, 1, &fragment_source, NULL);
+     		qglCompileShaderARB(vertex_shader);
+      		status = 0;
+      		qglGetObjectParameterivARB(vertex_shader,GL_OBJECT_COMPILE_STATUS_ARB,&status);
+      		if(!status){
+      			Con_Printf("<!> glslPointExtrusionProgram vertex shader not compiled\n");
+      		}
+      		qglCompileShaderARB(fragment_shader);
+      		status = 0;
+      		qglGetObjectParameterivARB(fragment_shader,GL_OBJECT_COMPILE_STATUS_ARB,&status);
+      		if(!status){
+      			Con_Printf("<!> glslPointExtrusionProgram fragment shader not compiled\n");
+      		}
+      		
+      		qglAttachObjectARB(glslPointExtrusionProgram, vertex_shader);
+      		qglAttachObjectARB(glslPointExtrusionProgram, fragment_shader);
+
+      		qglLinkProgramARB(glslPointExtrusionProgram);
+      		status = 0;
+      		qglGetObjectParameterivARB(glslPointExtrusionProgram,GL_OBJECT_LINK_STATUS_ARB,&status);
+      		if(!status){
+      			Con_Printf("<!> glslPointExtrusionProgram program object not linked\n");
+      		}
+      		
+      		qglUseProgramObjectARB(glslPointExtrusionProgram);
+      		
+      		projectionOriginAddr = qglGetUniformLocationARB(glslPointExtrusionProgram,"projOrigin");
+      		
+      		qglUseProgramObjectARB(0);
+      		
+      		//enable GPU extrusion
+      		UseGPUExtrusion = 1;
+		
+	}
 }
 
 void r_shadow_shutdown(void)
@@ -354,6 +466,9 @@
 	if (shadowvertex3f)
 		Mem_Free(shadowvertex3f);
 	shadowvertex3f = NULL;
+	if (shadowvertexprojdist1f)
+		Mem_Free(shadowvertexprojdist1f);
+	shadowvertexprojdist1f = NULL;
 	maxvertexupdate = 0;
 	if (vertexupdate)
 		Mem_Free(vertexupdate);
@@ -394,6 +509,12 @@
 	r_shadow_buffer_numlighttrispvsbytes = 0;
 	if (r_shadow_buffer_lighttrispvs)
 		Mem_Free(r_shadow_buffer_lighttrispvs);
+		
+	if(gl_support_shader_objects){
+		qglDeleteObjectARB(glslDirectionalExtrusionProgram);
+		qglDeleteObjectARB(glslPointExtrusionProgram);
+	
+	}
 }
 
 void r_shadow_newmap(void)
@@ -489,6 +610,7 @@
 	shadowelements = NULL;
 	maxshadowvertices = 0;
 	shadowvertex3f = NULL;
+	shadowvertexprojdist1f = NULL;
 	maxvertexupdate = 0;
 	vertexupdate = NULL;
 	vertexremap = NULL;
@@ -541,12 +663,21 @@
 		shadowelements = (int *)Mem_Alloc(r_main_mempool, maxshadowtriangles * sizeof(int[24]));
 	}
 	// make sure shadowvertex3f is big enough for this volume
+	// Tom : ...and shadowvertexprojdist1f for telling shaders how to prepare vertices in VS
+	
 	if (maxshadowvertices < numvertices)
 	{
 		maxshadowvertices = numvertices;
 		if (shadowvertex3f)
 			Mem_Free(shadowvertex3f);
+			
+		if(shadowvertexprojdist1f)
+			Mem_Free(shadowvertexprojdist1f);
+			
 		shadowvertex3f = (float *)Mem_Alloc(r_main_mempool, maxshadowvertices * sizeof(float[6]));
+		
+		if(UseGPUExtrusion)
+			shadowvertexprojdist1f = (float*) Mem_Alloc(r_main_mempool,maxshadowvertices * sizeof(float[2]));
 	}
 }
 
@@ -632,51 +763,118 @@
 	else
 		VectorClear(projectvector);
 
+
 	// create the vertices
-	if (projectdirection)
-	{
-		for (i = 0;i < numshadowmarktris;i++)
+	// Tom : if we can, we use on-GPU vertex extrusion
+
+	if(UseGPUExtrusion && !r_shadow_compilingrtlight){
+	
+		float * currentshadowvertexprojdist1f = shadowvertexprojdist1f;
+	
+		if (projectdirection)
 		{
-			element = inelement3i + shadowmarktris[i] * 3;
-			for (j = 0;j < 3;j++)
+		
+			float projectionLength = VectorLength(projectdirection);
+			
+			for (i = 0;i < numshadowmarktris;i++)
 			{
-				if (vertexupdate[element[j]] != vertexupdatenum)
+				element = inelement3i + shadowmarktris[i] * 3;
+				for (j = 0;j < 3;j++)
 				{
-					vertexupdate[element[j]] = vertexupdatenum;
-					vertexremap[element[j]] = outvertices;
-					vertex = invertex3f + element[j] * 3;
-					// project one copy of the vertex according to projectvector
-					VectorCopy(vertex, outvertex3f);
-					VectorAdd(vertex, projectvector, (outvertex3f + 3));
-					outvertex3f += 6;
-					outvertices += 2;
+					if (vertexupdate[element[j]] != vertexupdatenum)
+					{
+						vertexupdate[element[j]] = vertexupdatenum;
+						vertexremap[element[j]] = outvertices;
+						vertex = invertex3f + element[j] * 3;
+						// project one copy of the vertex according to projectvector
+						VectorCopy(vertex, outvertex3f);
+						VectorCopy(vertex, (outvertex3f+3));
+						
+						*currentshadowvertexprojdist1f = 0;				//no extrusion
+						*(currentshadowvertexprojdist1f+1) = projectionLength;		//extrusion for projectionLength distance
+						currentshadowvertexprojdist1f += 2;
+						
+						outvertex3f += 6;
+						outvertices += 2;
+					}
 				}
 			}
 		}
-	}
-	else
-	{
-		for (i = 0;i < numshadowmarktris;i++)
+		else
 		{
-			element = inelement3i + shadowmarktris[i] * 3;
-			for (j = 0;j < 3;j++)
+			for (i = 0;i < numshadowmarktris;i++)
 			{
-				if (vertexupdate[element[j]] != vertexupdatenum)
+				element = inelement3i + shadowmarktris[i] * 3;
+				for (j = 0;j < 3;j++)
 				{
-					vertexupdate[element[j]] = vertexupdatenum;
-					vertexremap[element[j]] = outvertices;
-					vertex = invertex3f + element[j] * 3;
-					// project one copy of the vertex to the sphere radius of the light
-					// (FIXME: would projecting it to the light box be better?)
-					VectorSubtract(vertex, projectorigin, direction);
-					ratio = projectdistance / VectorLength(direction);
-					VectorCopy(vertex, outvertex3f);
-					VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
-					outvertex3f += 6;
-					outvertices += 2;
+					if (vertexupdate[element[j]] != vertexupdatenum)
+					{
+						vertexupdate[element[j]] = vertexupdatenum;
+						vertexremap[element[j]] = outvertices;
+						vertex = invertex3f + element[j] * 3;
+						// project one copy of the vertex to the sphere radius of the light
+						// (FIXME: would projecting it to the light box be better?)
+						
+						VectorCopy(vertex, outvertex3f);
+						VectorCopy(vertex, (outvertex3f+3));
+						
+						*currentshadowvertexprojdist1f = 0;
+						*(currentshadowvertexprojdist1f+1) = projectdistance;
+						currentshadowvertexprojdist1f += 2;
+						
+						outvertex3f += 6;
+						outvertices += 2;
+					}
 				}
 			}
 		}
+	
+	} else {
+		if (projectdirection)
+		{
+			for (i = 0;i < numshadowmarktris;i++)
+			{
+				element = inelement3i + shadowmarktris[i] * 3;
+				for (j = 0;j < 3;j++)
+				{
+					if (vertexupdate[element[j]] != vertexupdatenum)
+					{
+						vertexupdate[element[j]] = vertexupdatenum;
+						vertexremap[element[j]] = outvertices;
+						vertex = invertex3f + element[j] * 3;
+						// project one copy of the vertex according to projectvector
+						VectorCopy(vertex, outvertex3f);
+						VectorAdd(vertex, projectvector, (outvertex3f + 3));
+						outvertex3f += 6;
+						outvertices += 2;
+					}
+				}
+			}
+		}
+		else
+		{
+			for (i = 0;i < numshadowmarktris;i++)
+			{
+				element = inelement3i + shadowmarktris[i] * 3;
+				for (j = 0;j < 3;j++)
+				{
+					if (vertexupdate[element[j]] != vertexupdatenum)
+					{
+						vertexupdate[element[j]] = vertexupdatenum;
+						vertexremap[element[j]] = outvertices;
+						vertex = invertex3f + element[j] * 3;
+						// project one copy of the vertex to the sphere radius of the light
+						// (FIXME: would projecting it to the light box be better?)
+						VectorSubtract(vertex, projectorigin, direction);
+						ratio = projectdistance / VectorLength(direction);
+						VectorCopy(vertex, outvertex3f);
+						VectorMA(projectorigin, ratio, direction, (outvertex3f + 3));
+						outvertex3f += 6;
+						outvertices += 2;
+					}
+				}
+			}
+		}
 	}
 
 	if (r_shadow_frontsidecasting.integer)
@@ -830,6 +1028,107 @@
 	else
 		VectorClear(projectvector);
 
+	if(UseGPUExtrusion && !r_shadow_compilingrtlight){
+	
+		float * currentshadowvertexprojdist1f = shadowvertexprojdist1f;
+		float projectionLength = VectorLength(projectdirection);
+		
+		for (i = 0;i < numshadowmarktris;i++)
+		{
+			int remappedelement[3];
+			int markindex;
+			const int *neighbortriangle;
+
+			markindex = shadowmarktris[i] * 3;
+			neighbortriangle = inneighbor3i + markindex;
+			side[0] = shadowmark[neighbortriangle[0]] == shadowmarkcount;
+			side[1] = shadowmark[neighbortriangle[1]] == shadowmarkcount;
+			side[2] = shadowmark[neighbortriangle[2]] == shadowmarkcount;
+			if (side[0] + side[1] + side[2] == 0)
+				continue;
+
+			side[3] = side[0];
+			element = inelement3i + markindex;
+
+			// create the vertices
+			for (j = 0;j < 3;j++)
+			{
+				if (side[j] + side[j+1] == 0)
+					continue;
+				k = element[j];
+				if (vertexupdate[k] != vertexupdatenum)
+				{
+					vertexupdate[k] = vertexupdatenum;
+					vertexremap[k] = outvertices;
+					vertex = invertex3f + k * 3;
+					VectorCopy(vertex, outvertex3f);
+					VectorCopy(vertex, (outvertex3f+3));
+					if (projectdirection)
+					{
+					
+						*currentshadowvertexprojdist1f = 0;				//no extrusion
+						*(currentshadowvertexprojdist1f+1) = projectionLength;		//extrusion for projectionLength distance
+						currentshadowvertexprojdist1f += 2;
+					
+					}
+					else
+					{
+						*currentshadowvertexprojdist1f = 0;				//no extrusion
+						*(currentshadowvertexprojdist1f+1) = projectdistance;		//extrusion for projectionLength distance
+						currentshadowvertexprojdist1f += 2;
+					}
+					outvertex3f += 6;
+					outvertices += 2;
+				}
+			}
+
+			// output the sides (facing outward from this triangle)
+			if (!side[0])
+			{
+				remappedelement[0] = vertexremap[element[0]];
+				remappedelement[1] = vertexremap[element[1]];
+				outelement3i[0] = remappedelement[1];
+				outelement3i[1] = remappedelement[0];
+				outelement3i[2] = remappedelement[0] + 1;
+				outelement3i[3] = remappedelement[1];
+				outelement3i[4] = remappedelement[0] + 1;
+				outelement3i[5] = remappedelement[1] + 1;
+
+				outelement3i += 6;
+				outtriangles += 2;
+			}
+			if (!side[1])
+			{
+				remappedelement[1] = vertexremap[element[1]];
+				remappedelement[2] = vertexremap[element[2]];
+				outelement3i[0] = remappedelement[2];
+				outelement3i[1] = remappedelement[1];
+				outelement3i[2] = remappedelement[1] + 1;
+				outelement3i[3] = remappedelement[2];
+				outelement3i[4] = remappedelement[1] + 1;
+				outelement3i[5] = remappedelement[2] + 1;
+
+				outelement3i += 6;
+				outtriangles += 2;
+			}
+			if (!side[2])
+			{
+				remappedelement[0] = vertexremap[element[0]];
+				remappedelement[2] = vertexremap[element[2]];
+				outelement3i[0] = remappedelement[0];
+				outelement3i[1] = remappedelement[2];
+				outelement3i[2] = remappedelement[2] + 1;
+				outelement3i[3] = remappedelement[0];
+				outelement3i[4] = remappedelement[2] + 1;
+				outelement3i[5] = remappedelement[0] + 1;
+
+				outelement3i += 6;
+				outtriangles += 2;
+			}
+		}
+
+	} else
+
 	for (i = 0;i < numshadowmarktris;i++)
 	{
 		int remappedelement[3];
@@ -1051,6 +1350,7 @@
 	{
 		// decide which type of shadow to generate and set stencil mode
 		R_Shadow_RenderMode_StencilShadowVolumes(R_Shadow_UseZPass(trismins, trismaxs));
+		
 		// generate the sides or a solid volume, depending on type
 		if (r_shadow_rendermode >= R_SHADOW_RENDERMODE_ZPASS_STENCIL && r_shadow_rendermode <= R_SHADOW_RENDERMODE_ZPASS_STENCILTWOSIDE)
 			tris = R_Shadow_ConstructShadowVolume_ZPass(numverts, numtris, elements, neighbors, invertex3f, &outverts, shadowelements, shadowvertex3f, projectorigin, projectdirection, projectdistance, nummarktris, marktris);
@@ -1060,6 +1360,28 @@
 		r_refdef.stats.lights_shadowtriangles += tris;
 		CHECKGLERROR
 		R_Mesh_VertexPointer(shadowvertex3f, 0, 0);
+		
+		// Tom : turn this on if we have GLSL compliant GPU
+		if(UseGPUExtrusion){
+		
+			R_Mesh_TexCoordPointer(0,	//0 texture unit
+			1,				//one float per vertex - distance of extrusion
+			shadowvertexprojdist1f,		//source of data
+			0,0);				//other parameters
+			
+			if(projectdirection){
+				qglUseProgramObjectARB(glslDirectionalExtrusionProgram);
+				qglUniform3fARB(projectionDirectionAddr,projectdirection[0],projectdirection[1],projectdirection[2]);
+			
+			}
+			else
+			{
+				qglUseProgramObjectARB(glslPointExtrusionProgram);
+				qglUniform3fARB(projectionOriginAddr,projectorigin[0],projectorigin[1],projectorigin[2]);
+				
+			}
+		}
+		
 		GL_LockArrays(0, outverts);
 		if (r_shadow_rendermode == R_SHADOW_RENDERMODE_ZPASS_STENCIL)
 		{
@@ -1084,6 +1406,10 @@
 		R_Mesh_Draw(0, outverts, 0, tris, shadowelements, NULL, 0, 0);
 		GL_LockArrays(0, 0);
 		CHECKGLERROR
+		
+		// Tom : turn this off only if we have GLSL compliant GPU
+		if(UseGPUExtrusion)
+			qglUseProgramObjectARB(0);
 	}
 }
 
Index: zone.c
===================================================================
--- zone.c	(revision 9146)
+++ zone.c	(working copy)
@@ -21,7 +21,7 @@
 
 #include "quakedef.h"
 
-#if MEMPARANOIA
+//#if MEMPARANOIA
 #ifdef _MSC_VER
 #include <vadefs.h>
 #else
@@ -29,10 +29,10 @@
 #endif
 #define MEMHEADER_SENTINEL_FOR_ADDRESS(p) ((sentinel_seed ^ (unsigned int) (uintptr_t) (p)) + sentinel_seed)
 unsigned int sentinel_seed;
-#else
+//#else
 #define MEMHEADER_SENTINEL1 0xDEADF00D
 #define MEMHEADER_SENTINEL2 0xDF
-#endif
+//#endif
 
 #if MEMCLUMPING
 #define MEMCLUMP_SENTINEL 0xABADCAFE
