Index: Myth2Code/hardware/OpenGL/render_opengl.c
===================================================================
--- Myth2Code/hardware/OpenGL/render_opengl.c	(revision 2135)
+++ Myth2Code/hardware/OpenGL/render_opengl.c	(working copy)
@@ -205,6 +205,8 @@
 static void rasterize_opengl_model_triangle( struct view_data *view, struct render_model_triangle *triangle );
 static void rasterize_opengl_mesh_triangle( struct view_data *view, struct render_triangle *triangle );
 
+static void batch_opengl_mesh_triangle(struct view_data *view, struct render_triangle *triangle);
+
 static void set_global_mode(int mode);
 static void my_opengl_shutdown(void);
 
@@ -227,7 +229,7 @@
 extern boolean fog_can_be_enabled_opengl;
 
 // must be larger than 4 b/c of fill_polygon_opengl
-static rendervert_t render_verts[MAXIMUM_VERTICES_PER_CLIPPED_TRIANGLE]; // MAXIMUM_EDGES_PER_POLYGON]; // NUMBER_OF_VERTICES_PER_QUADRALATERAL];
+static rendervert_t render_verts[32*1024]; // MAXIMUM_EDGES_PER_POLYGON]; // NUMBER_OF_VERTICES_PER_QUADRALATERAL];
 const float zero_one[2] = {0.0f, 1.0f};
 
 // Build 344 - ALS - to speed up dialog drawing
@@ -506,6 +508,15 @@
 	}
 }
 
+struct  
+{
+	int tex2Binds;
+	int drawArrays;
+	//int unique
+} stats;
+
+int batch_top = 0;
+
 static void opengl_bind_texture1(GLuint texture)
 {
 	static int current_texture = 0;
@@ -524,6 +535,8 @@
 			glBindTexture(GL_TEXTURE_2D, texture);
 		}
 
+		++stats.tex2Binds;
+
 		call_glActiveTexture(GL_TEXTURE0);
 		current_texture = texture;
 	}
@@ -552,6 +565,9 @@
 		glClear(bits);
 	}
 
+	batch_top = 0;
+	memset(&stats, 0, sizeof(stats));
+
 	// reset the depth state
 	depth_enabled = -1;
 	glDepthFunc(GL_LEQUAL);
@@ -586,7 +602,7 @@
 	assert(rasterizer_initialized);
 
 	prepare_to_render_new_frame(view, surfaces);
-
+/*
 	for (state= 0; state < NUMBER_OF_RASTERIZE_STATES; state++)
 	{
 		unsigned long required_flags= 0;
@@ -628,9 +644,7 @@
 			// If they aren't rendered they will leave line-like holes in the mesh.
 			// Try disabling this and setting the clear color to red to see the effect in action.
 			unsigned long prohibited_flags_mask = -1;
-			if(surface->subtype == _surface_subtype_mesh_triangle
-				/* actually, let's keep the original clipping for model triangles
-				|| surface->subtype == _surface_subtype_model_triangle*/)
+			if(surface->subtype == _surface_subtype_mesh_triangle)
 			{
 				prohibited_flags_mask = ~_surface_discarded_flag;
 			}
@@ -647,7 +661,7 @@
 				switch(surface->subtype)
 				{
 					case _surface_subtype_mesh_triangle:
-						rasterize_opengl_mesh_triangle(view, (struct render_triangle *)surface);
+						batch_opengl_mesh_triangle(view, (struct render_triangle *)surface);
 						break;
 					case _surface_subtype_model_triangle:
 					case _surface_subtype_object_triangle:
@@ -662,8 +676,35 @@
 				}
 			}
 		}
+	}*/
+
+//#define BATCH
+
+	{
+		struct render_surface *surface;
+				enable_depth_in_perspective_mode = TRUE;
+		for (surface = surfaces->last_surface; surface; surface = surface->previous_surface)
+		{
+			if(surface->subtype == _surface_subtype_mesh_triangle)
+			{
+#ifdef BATCH
+				batch_opengl_mesh_triangle(view, (struct render_triangle *)surface);
+#else
+				rasterize_opengl_mesh_triangle(view, (struct render_triangle *)surface);
+#endif
+			}
+		}
 	}
 
+#ifdef BATCH
+	set_projection_mode(view, _projection_mode_perspective);
+	enable_depth(TRUE);
+	set_global_mode(_mode_flat_alpha);
+	bind_volatile_cmap_texture_opengl();
+	toggle_filtering_effects_opengl(TRUE);
+	glDrawArrays(GL_TRIANGLES, 0, batch_top);
+#endif
+
 	opengl_bind_texture1(0);
 	set_projection_mode(view, _projection_mode_ortho);
 
@@ -678,6 +719,12 @@
 	}
 #endif
 
+/*	{
+		char str[256];
+		sprintf(str, "%d glDrawArrays calls | %d texture unit 2 state changes", stats.drawArrays, stats.tex2Binds);
+		SetWindowText(screen_window, str);
+	}*/
+
 	return;
 }
 
@@ -808,6 +855,45 @@
 	return;
 }
 
+static void batch_opengl_mesh_triangle(
+struct view_data *view,
+struct render_triangle *triangle)
+{
+	int vertex_index;
+	struct render_corner *render_corners = triangle->corners;
+
+	int pre = batch_top;
+
+	for (vertex_index = 0; vertex_index < VERTICES_PER_TRIANGLE; vertex_index++)
+	{
+		struct render_corner *render_corner = render_corners + vertex_index;
+		struct render_vertex *render_vertex = render_corner->vertex;
+
+		const float INV_WIDTH = 1.0f/MAXIMUM_MESH_REGION_WIDTH;
+
+		float u= render_corner->interpolants[_texture_u]*INV_WIDTH;
+		float v= render_corner->interpolants[_texture_v]*INV_WIDTH;
+
+		float x, y, z;
+
+		if(render_vertex->flags & _vertex_coordinate_overflow_hack_flag)
+		{
+			batch_top = pre;
+			return;
+		}
+		else
+		{
+			x = WORLD_TO_FLOAT(render_vertex->p.x);
+			y = WORLD_TO_FLOAT(render_vertex->p.y);
+			z = WORLD_TO_FLOAT(render_vertex->p.z);
+		}
+
+		SetTexture(batch_top+vertex_index, x, y, z, 1.0f, u, v);
+	}
+
+	batch_top+=3;
+}
+
 /*
  * Function:	rasterize_opengl_mesh_triangle
  */
@@ -1486,6 +1572,7 @@
 {
 	int code = ((num == 3 ) ? GL_TRIANGLES : GL_TRIANGLE_FAN);
 	glDrawArrays( code, 0, num );
+	stats.drawArrays++;
 	GL_ASSERT();
 }
 
