Index: Myth2Code/hardware/OpenGL/render_opengl.c
===================================================================
--- Myth2Code/hardware/OpenGL/render_opengl.c	(revision 4341)
+++ Myth2Code/hardware/OpenGL/render_opengl.c	(working copy)
@@ -2164,6 +2164,71 @@
 	}
 }
 
+void frustum_debug(struct view_data *view)
+{
+	int i, r;
+	struct mesh_region *region = view->region;
+
+	#define UNITS (1)
+	const int pixels_per_wu=4;
+	//int x = 50-(mesh_width-1-region->original_x0)*pixels_per_wu/UNITS, y = 50-region->original_y0*pixels_per_wu/UNITS;
+	int x = 50, y= 50;
+
+	world_point2d mesh_rect[] = {
+		{0, 0},
+		{mesh_width*UNITS, 0},
+		{mesh_width*UNITS, mesh_height*UNITS},
+		{0, mesh_height*UNITS}
+	};
+
+	world_point2d volatile_rect[] = {
+		{(region->original_x0)*UNITS, region->original_y0*UNITS},
+		{((region->original_x0+64))*UNITS, region->original_y0*UNITS},
+		{((region->original_x0+64))*UNITS, (region->original_y0+64)*UNITS},
+		{(region->original_x0)*UNITS, (region->original_y0+64)*UNITS}
+	};
+
+	set_render_mode_opengl(_shader_basic_color, _projection_mode_ortho, _depth_mode_none, _blend_mode_replace);
+
+	for(r = 0; r < 2; ++r)
+	{
+		world_point2d *verts = r ? mesh_rect : volatile_rect;
+		for(i = 0; i < 4; ++i)
+		{
+			int j = (i+1)%4;
+			int x0 = verts[i].x, y0 = verts[i].y;
+			int x1 = verts[j].x, y1 = verts[j].y;
+			SetGouraud(0, x+(mesh_width-1-x0)*pixels_per_wu/UNITS, y+y0*pixels_per_wu/UNITS, 0, 0, COLOR_ONE, COLOR_ONE, 0);
+			SetGouraud(1, x+(mesh_width-1-x1)*pixels_per_wu/UNITS, y+y1*pixels_per_wu/UNITS, 0, 0, COLOR_ONE, COLOR_ONE, 0);
+			submit_line_opengl();
+		}
+	}
+
+	for(i = region->y0; i <= region->y1; ++i)
+	{
+		struct mesh_span *span = region->spans + i - region->y0;
+		if(span->x0 < span->x1)
+		{
+			SetGouraud(0, x+(mesh_width-1-span->x0)*pixels_per_wu, y+i*pixels_per_wu, 0, 0, COLOR_ONE, 0, 0);
+			SetGouraud(1, x+(mesh_width-1-span->x1)*pixels_per_wu, y+i*pixels_per_wu, 0, 0, COLOR_ONE, 0, 0);
+			SetGouraud(2, x+(mesh_width-1-span->x1)*pixels_per_wu, y+(i+1)*pixels_per_wu, 0, 0, COLOR_ONE, 0, 0);
+			SetGouraud(3, x+(mesh_width-1-span->x0)*pixels_per_wu, y+(i+1)*pixels_per_wu, 0, 0, COLOR_ONE, 0, 0);
+			submit_fan_opengl(4);
+		}
+	}
+
+	for(i = 0; i < region->frustum_corner_count; ++i)
+	{
+		int j = (i+1)%region->frustum_corner_count;
+		int x0 = region->frustum_corners[i].x, y0 = region->frustum_corners[i].y;
+		int x1 = region->frustum_corners[j].x, y1 = region->frustum_corners[j].y;
+		SetGouraud(0, x+(mesh_width-1-x0)*pixels_per_wu/UNITS, y+y0*pixels_per_wu/UNITS, 0, 0, COLOR_ONE, COLOR_ONE, 0);
+		SetGouraud(1, x+(mesh_width-1-x1)*pixels_per_wu/UNITS, y+y1*pixels_per_wu/UNITS, 0, 0, COLOR_ONE, COLOR_ONE, 0);
+		submit_line_opengl();
+	}
+
+}
+
 void rasterize_scene_opengl(
 	struct view_data *view,
 	struct render_surface_list *surfaces)
@@ -2183,6 +2248,8 @@
 		rasterizing_scene = FALSE;
 	}
 
+	frustum_debug(view);
+
 	nvtx_end();
 
 #ifdef CAPTURE_VIDEO
Index: Myth2Code/observer.c
===================================================================
--- Myth2Code/observer.c	(revision 4340)
+++ Myth2Code/observer.c	(working copy)
@@ -38,7 +38,7 @@
 
 #include <string.h>
 
-//#define FREE_CAMERA_HACK
+#define FREE_CAMERA_HACK
 
 /* ---------- constants */
 
Index: Myth2Code/render/render.h
===================================================================
--- Myth2Code/render/render.h	(revision 4340)
+++ Myth2Code/render/render.h	(working copy)
@@ -409,6 +409,7 @@
 
 	// ƒ(input)
 
+	struct mesh_region *region;
 	short x0, y0; // mesh origin computed from location.position.x, location.position.y
 	short region_x0, region_y0; // origin of projected region (for volatile textures)
 
Index: Myth2Code/render/render_private.h
===================================================================
--- Myth2Code/render/render_private.h	(revision 4340)
+++ Myth2Code/render/render_private.h	(working copy)
@@ -67,6 +67,9 @@
 	
 	struct mesh_span *spans;
 	struct render_vertex **vertices;
+
+	int frustum_corner_count;
+	world_point2d *frustum_corners;
 };
 
 /* ---------- buckets */
Index: Myth2Code/render/render_scene.c
===================================================================
--- Myth2Code/render/render_scene.c	(revision 4340)
+++ Myth2Code/render/render_scene.c	(working copy)
@@ -120,6 +120,7 @@
 
 	region= build_mesh_region(view);
 	last_region = region;
+	view->region = region;
 	view->region_x0= region->x0;
 	view->region_y0= region->y0;
 
@@ -165,7 +166,7 @@
 	}
 	build_mesh_surface_list(view, region);
 
-	if((view->flags & _render_view_moved_flag) || (view->tick_count != last_ticks))
+	//if((view->flags & _render_view_moved_flag) || (view->tick_count != last_ticks))
 	{
 		build_volatile_maps(view, region);
 		rasterize_shadow_map_overlays(view->shadow_map_overlays, _rasterize_shadow_maps);
@@ -237,6 +238,497 @@
 
 /* ---------- view volume projection */
 
+// Build 400 - DRB - new method:
+// (1) project frustum corners onto xy plane
+// (2) take the convex hull of the projected points
+// (3) do a polygon rasterization of the hull to get x0,x1 spans
+// (4) construct the mesh region from these spans
+
+typedef struct { int x, y; } point;
+
+static point makePoint(int x, int y)
+{
+	point p;
+	p.x = x;
+	p.y = y;
+	return p;
+}
+
+static point pointAdd(point p, point q)
+{
+	p.x += q.x;
+	p.y += q.y;
+	return p;
+}
+
+static point pointSub(point p, point q)
+{
+	p.x -= q.x;
+	p.y -= q.y;
+	return p;
+}
+
+static int point2DMag(point p)
+{
+	return p.x*p.x + p.y*p.y;
+}
+
+static int cross2DMag(point p, point q)
+{
+	// ((p:0)x(q:0)).z
+	return p.x*q.y - q.x*p.y;
+}
+
+// true iff the angle of (0,q) is less than the angle of (0,p)
+static boolean rightQ(point p, point q)
+{
+	return cross2DMag(p,q) < 0;
+}
+
+// true iff the point p is to the right of the infinite line (q0->q1)
+static boolean right2Q(point p, point q0, point q1)
+{
+	return rightQ(pointSub(p,q0),pointSub(q1,q0));
+}
+
+// true iff lines (0,p) and (0,q) are colinear
+static boolean colinearQ(point p, point q)
+{
+	return cross2DMag(p,q) == 0;
+}
+
+static void pointSwap(point points[], int i, int j)
+{
+	point temp = points[i];
+	points[i] = points[j];
+	points[j] = temp;
+}
+
+// selection sort the points by ascending counterclockwise angle 
+// between the horizontal and the line 0->p. break ties by distance
+// from the origin (further points first).
+void angularSort(point points[], int count)
+{
+	int i;
+	for(i = 0; i < count-1; i++)
+	{
+		int j, best_i = i;
+		for(j = i+1; j < count; j++)
+		{
+			point p = points[j];
+			point q = points[best_i];
+			int mag = cross2DMag(p,q);
+			if(mag < 0 || mag == 0 && point2DMag(p) > point2DMag(q))
+			{
+				best_i = j;
+			}
+		}
+
+		pointSwap(points, i, best_i);
+	}
+}
+
+// as above, but keep only one point for each unique angle,
+// the one furthest from the origin.
+int angularSortUnique(point points[], int count)
+{
+	int i, rangeFirst = 0, saved = 1;
+	angularSort(points, count);
+	for(i = 1; i < count; ++i)
+	{
+		if(cross2DMag(points[rangeFirst], points[i]))
+		{
+			rangeFirst = i;
+			points[saved++] = points[i];
+		}
+	}
+	return saved;
+}
+
+int grahamScan(point points[], int count)
+{
+	int hull_vertices;
+	int i, best_i;
+	int unique_count;
+	point origin;
+
+	// need at least 3 points to define a convex region.
+	if(count < 3)
+	{
+		return 0;
+	}
+
+	// find the "origin" point - the point with the least y, ties broken by least x.
+	best_i = 0;
+	for(i = 1; i < count; ++i)
+	{
+		if(points[i].y < points[best_i].y || points[i].y == points[best_i].y && points[i].x < points[best_i].x)
+		{
+			best_i = i;
+		}
+	}
+
+	pointSwap(points, 0, best_i);
+	origin = points[0];
+
+	// make all points relative to the origin
+	for(i = 0; i < count; ++i)
+	{
+		points[i] = pointSub(points[i], origin);
+	}
+
+	// together with the origin point, we need at least 2 unique angular points
+	// to get the 3 needed to define a convex region.
+	unique_count = 1 + angularSortUnique(points+1, count-1);
+	if(unique_count < 3)
+	{
+		return 0;
+	}
+
+	// perform the graham scan
+	hull_vertices = 2; // initialize the hull to points[0], points[1]
+	for(i = 2; i < unique_count; ++i)
+	{
+		while(!right2Q(points[i], points[hull_vertices-1], points[hull_vertices-2]))
+			--hull_vertices;
+		points[hull_vertices++] = points[i];
+	}
+
+	// translate back to absolute coordinates
+	for(i = 0; i < hull_vertices; ++i)
+	{
+		points[i] = pointAdd(points[i], origin);
+	}
+
+	return hull_vertices;
+}
+
+int polygonArea(point points[], int count)
+{
+	int A = 0, i;
+	for(i = 0; i < count; ++i)
+		A += cross2DMag(points[i], points[(i+1)%count]);
+	return A/2;
+}
+
+point polygonCenter(point points[], int count)
+{
+	int i;
+	int Cx = 0, Cy = 0, A = 0;
+	for(i = 0; i < count; ++i)
+	{
+		int j = (i+1)%count;
+		int cm = cross2DMag(points[i], points[j]);
+		A += cm;
+		Cx += (points[i].x+points[j].x)*cm;
+		Cy += (points[i].y+points[j].y)*cm;
+	}
+	return makePoint(Cx/(3*A), Cy/(3*A));
+}
+
+int get_minimum_mesh_height()
+{
+	static boolean initialized = FALSE;
+	static int min_height = INT_MAX;
+	if(!initialized)
+	{
+		int i, count = mesh_width*mesh_height;
+		for(i = 0; i < count; ++i)
+		{
+			int h = GET_TRUE_CELL_HEIGHT(&mesh_cells[i]);
+			min_height = MIN(min_height, h);
+		}
+		initialized = TRUE;
+	}
+
+	return min_height;
+}
+
+#define MAXIMUM_FRUSTUM_POLYGON_VERTICES (20)
+
+#include "keyboard.h"
+
+void compute_frustum_polygon(struct view_data *view, struct mesh_region *region)
+{
+	world_point3d eye = view->location.position;
+	matrix3x3 *m = &view->world_to_viewer_rotation;
+	real x_range[2] = {view->left, view->right};
+	real y_range[2] = {view->top, view->bottom};
+	int i, point_count = 0;
+
+	point * points = (point*)render_malloc(sizeof(world_point2d)*MAXIMUM_FRUSTUM_POLYGON_VERTICES);
+	region->frustum_corners = (world_point2d*)points;
+
+	points[point_count++] = makePoint(eye.x, eye.y);
+	for(i = 0; i < 4; ++i)
+	{
+		real x = x_range[(i>>0)&1];
+		real y = y_range[(i>>1)&1];
+
+		// get the far frustum corner in world space:
+		// <rx,ry,rz> = transpose(world_to_viewer_rotation)*<x,y,-1>*far
+		const real fardist = MAXIMUM_VIEW_CELLS;
+		const real scale = fardist*WORLD_ONE/TRIG_MAGNITUDE;
+		real rx = (x*m->n[0][0] + y*m->n[0][1] - m->n[0][2])*scale;
+		real ry = (x*m->n[1][0] + y*m->n[1][1] - m->n[1][2])*scale;
+		real rz = (x*m->n[2][0] + y*m->n[2][1] - m->n[2][2])*scale;
+
+		if(key_down(_key_shift)){
+		// ray from eye to eye + <rx, ry, rz>
+		// intersect with z = min height
+		if(abs(rz) > 0) {
+			real t = (real)(get_minimum_mesh_height()-eye.z)/rz;
+			if(t > 0 && t < 1) {
+				rx = rx*t;
+				ry = ry*t;
+				//rz = rz*t;
+			}
+		}
+		}
+
+		{
+			const int D = 2*WORLD_ONE;
+			point corner = makePoint(eye.x + rx, eye.y + ry);
+			points[point_count++] = pointAdd(corner, makePoint(-D,-D));
+			points[point_count++] = pointAdd(corner, makePoint(D,-D));
+			points[point_count++] = pointAdd(corner, makePoint(D,D));
+			points[point_count++] = pointAdd(corner, makePoint(-D,D));
+		}
+	}
+
+	region->frustum_corner_count = grahamScan((point*)region->frustum_corners, point_count);
+
+	for(i = 0; i < region->frustum_corner_count; ++i)
+	{
+		region->frustum_corners[i].x = WORLD_TO_INTEGER(region->frustum_corners[i].x);
+		region->frustum_corners[i].y = WORLD_TO_INTEGER(region->frustum_corners[i].y);
+	}
+}
+
+void compute_mesh_region_origin(struct view_data *view, struct mesh_region *region)
+{
+	int x0, y0;
+	point C = polygonCenter((point*)region->frustum_corners, region->frustum_corner_count);
+	point eye = makePoint(WORLD_TO_INTEGER(view->location.position.x), WORLD_TO_INTEGER(view->location.position.y));
+	point v = pointSub(C,eye);
+	real len = sqrtf(point2DMag(v));
+	const real maximum_dist_from_origin = (MAXIMUM_MESH_REGION_WIDTH/2)-2;
+	if(len > maximum_dist_from_origin)
+	{
+		real norm = maximum_dist_from_origin/len;
+		C.x = eye.x + v.x*norm;
+		C.y = eye.y + v.y*norm;
+	}
+
+	x0 = C.x - (MAXIMUM_MESH_REGION_WIDTH/2);
+	y0 = C.y - (MAXIMUM_MESH_REGION_WIDTH/2);
+
+	x0= MAX(x0, 0);
+	x0= x0&~1;
+	x0= MIN(x0, mesh_width-MAXIMUM_MESH_REGION_WIDTH);
+	y0= MAX(y0, 0);
+	y0= y0&~1;
+	y0= MIN(y0, mesh_height-MAXIMUM_MESH_REGION_WIDTH);
+
+	region->original_x0= x0;
+	region->original_y0= y0;
+}
+
+// Author : Michael Y. Polyakov
+// email  : myp@andrew.cmu.edu or mikepolyakov@hotmail.com
+void DDA(void *context, int x0, int y0, int x1, int y1, void (*point)(void *context, int x, int y))
+{
+	int dx, dy, incXH, incXL, incYH, incYL, longD, shortD, d, incDL, incDH, i;
+
+	/* Step 1: Find dx and dy */
+	dx = x1 - x0;
+	dy = y1 - y0;
+
+	/* Step 2: Defining increments on x axis */
+	incXH, incXL;
+	if(dx >= 0) incXH = incXL = 1;
+	else { dx = -dx; incXH = incXL = -1; }
+
+	/* Step 3: Defining increments on y axis */
+	incYH, incYL;
+	if(dy >= 0) incYH = incYL = 1;
+	else { dy = -dy; incYH = incYL = -1; }
+
+	/* Step 4: Defining the long and short sides (based on dx and dy) and change increments appropriatly */
+	longD, shortD;
+	if(dx >= dy) { longD = dx;  shortD = dy;  incYL = 0; }
+	else		 { longD = dy;  shortD = dx;  incXL = 0; }
+
+	/* Step 5: Initialize d */
+	d = 2*shortD - longD;
+
+	/* Step 6: Defining d increments depending on the last point drawn */
+	incDL = 2*shortD;				//for L-type increments
+	incDH = 2*shortD - 2*longD;		//for H-type increments
+
+	/* Step 7: Draw points in the loop. Increment x, y, and d according to the last point type */
+	/* Starting from first point (x1, y1)... */
+	for(i = 0; i <= longD; i++)
+	{
+		point(context, x0, y0);
+		if(d >= 0)	{ x0 += incXH; y0 += incYH; d += incDH; }	//H-type
+		else		{ x0 += incXL; y0 += incYL; d += incDL; }	//L-type
+	}
+}
+
+void extend_spans(struct mesh_region *region, int x, int y)
+{
+	int yy = y - region->original_y0;
+	if(yy >= 0 && yy < MAXIMUM_MESH_REGION_WIDTH)
+	{
+		struct mesh_span *span = region->spans + yy;
+		x = MAX(x, region->original_x0);
+		x = MIN(x, region->original_x0+MAXIMUM_MESH_REGION_WIDTH-2);
+		span->x0 = MIN(span->x0, x);
+		span->x1 = MAX(span->x1, x);
+		region->x0 = MIN(region->x0, x);
+		region->x1 = MAX(region->x1, x);
+		region->y0 = MIN(region->y0, y);
+		region->y1 = MAX(region->y1, y);
+	}
+}
+
+void compute_mesh_region_spans(struct view_data *view, struct mesh_region *region)
+{
+	int i;
+
+	region->x0 = region->y0 = SHORT_MAX;
+	region->x1 = region->y1 = SHORT_MIN;
+
+	for(i = 0; i < MAXIMUM_MESH_REGION_WIDTH; ++i)
+	{
+		struct mesh_span *span = region->spans + i;
+		span->x0 = SHORT_MAX;
+		span->x1 = SHORT_MIN;
+	}
+
+	for(i = 0; i < region->frustum_corner_count; ++i)
+	{
+		int j = (i+1)%region->frustum_corner_count;
+		world_point2d p = region->frustum_corners[i];
+		world_point2d q = region->frustum_corners[j];
+		DDA(region, p.x, p.y, q.x, q.y, (void (*)(void*, int, int))extend_spans);
+	}
+
+	region->spans += region->y0 - region->original_y0;
+}
+
+static struct mesh_region *build_mesh_region_new(
+	struct view_data *view)
+{
+	struct media_definition *media_definition= get_media_definition(0);
+
+	struct mesh_region *region= (struct mesh_region*)render_malloc(sizeof(struct mesh_region));
+	struct mesh_span *spans= (struct mesh_span*)render_malloc(MAXIMUM_PROJECTED_MESH_WIDTH*sizeof(struct mesh_span));
+	struct render_vertex **region_vertices= (struct render_vertex**)render_malloc(MAXIMUM_MESH_REGION_WIDTH*MAXIMUM_MESH_REGION_WIDTH*sizeof(struct render_vertex *));
+
+	int mesh_x, mesh_y;
+	int x0, y0;
+	boolean models_cells_can_limit_rendering= !(get_mesh_file_header()->flags&_mesh_models_dont_limit_rendering_flag); // Build 252 - PAB - Import from 1.3.1
+
+	region->spans = spans;
+	region->vertices= region_vertices;
+	memset(region_vertices, 0, MAXIMUM_MESH_REGION_WIDTH*MAXIMUM_MESH_REGION_WIDTH*sizeof(struct render_vertex *));
+
+	compute_frustum_polygon(view, region);
+	compute_mesh_region_origin(view, region);
+	compute_mesh_region_spans(view, region);
+
+	x0 = region->original_x0;
+	y0 = region->original_y0;
+
+	for(mesh_y = region->y0; mesh_y <= region->y1; ++mesh_y)
+	{
+		struct mesh_span *span = region->spans + mesh_y - region->y0;
+		for(mesh_x = span->x0; mesh_x < span->x1; ++mesh_x)
+		{
+			struct mesh_cell *cell= get_mesh_cell(mesh_x, mesh_y);
+			world_point3d p;
+
+			p.x= INTEGER_TO_WORLD(mesh_x);
+			p.y= INTEGER_TO_WORLD(mesh_y);
+			p.z= cell->height;
+
+			if (!(view->flags&_render_view_omit_media_flag))
+			{
+				// cells containing models do not use media height or wobble unless models can limit rendering
+				if ((cell->model_index == NONE || models_cells_can_limit_rendering) &&
+					cell->flags&_mesh_vertex_is_media_flag)
+				{
+					p.z= cell->media_height; // MAX(cell->media_height, p.z);
+
+					if (cell->flags&_mesh_vertex_is_animated_media_flag)
+					{
+						long t= 377*mesh_x + 211*mesh_y + view->tick_count;
+
+						if (media_definition->wobble_magnitude.i) p.x+= (media_definition->wobble_magnitude.i*sine(t*media_definition->wobble_phase_multiplier.i))>>TRIG_SHIFT;
+						if (media_definition->wobble_magnitude.j) p.y+= (media_definition->wobble_magnitude.j*sine(t*media_definition->wobble_phase_multiplier.j))>>TRIG_SHIFT;
+						if (media_definition->wobble_magnitude.k) p.z+= (media_definition->wobble_magnitude.k*sine(t*media_definition->wobble_phase_multiplier.k))>>TRIG_SHIFT;
+					}
+				}
+			}
+
+			// create a render_vertex in world space
+			{
+				struct world_point3d transformed;
+				struct short_world_point3d short_transformed;
+				boolean overflow = FALSE;
+
+				transform_point3d(&transformed, &view->world_to_viewer_rotation, &view->location.position, &p);
+
+				if(((short_transformed.x= transformed.x) - transformed.x) |
+					((short_transformed.y= transformed.y) - transformed.y) |
+					((short_transformed.z= transformed.z) - transformed.z))
+				{
+					overflow = TRUE;
+				}
+
+				if(!overflow)
+				{
+					struct render_vertex *vertex= (struct render_vertex*)new_render_vertex();
+					vertex->p = short_transformed;
+					vertex->flags= 0;
+					vertex->mesh_vertex.x= mesh_x;
+					vertex->mesh_vertex.y= mesh_y;
+
+					clip_affine_vertex_to_all_planes(view, vertex);
+
+					{
+						int y = mesh_y - y0;
+						int x = mesh_x-x0;
+						assert(y >= 0 && y < MAXIMUM_MESH_REGION_WIDTH);
+						assert(x >= 0 && y < MAXIMUM_MESH_REGION_WIDTH);
+						region_vertices[y*MAXIMUM_MESH_REGION_WIDTH+x]= vertex;
+					}
+
+					// cells containing models can't mark frustum edges unless models can limit rendering
+					if ((cell->model_index == NONE || models_cells_can_limit_rendering) &&
+						vertex->flags&(_vertex_out_left_flag|_vertex_out_top_flag|_vertex_out_right_flag|_vertex_discarded_flag))
+					{
+
+					}
+					else
+					{
+						//span->x0 = MIN(span->x0, mesh_x);
+						//span->x1 = MAX(span->x1, mesh_x);
+					}
+				}
+			}
+		}
+	}
+
+	return region;
+}
+
+
+
+
+
 enum
 {
 	STARTING_POSITION_OFFSET= 6*WORLD_ONE,
@@ -261,7 +753,7 @@
 #define VISITED(a, x, y) ((a)[(y)*(MAXIMUM_MESH_REGION_WIDTH/LONG_BITS) + ((x)>>5)] & FLAG((x)&31))
 #define MARK_AS_VISITED(a, x, y) (a)[(y)*(MAXIMUM_MESH_REGION_WIDTH/LONG_BITS) + ((x)>>5)]|= FLAG((x)&31)
 
-static struct mesh_region *build_mesh_region(
+static struct mesh_region *build_mesh_region_old(
 	struct view_data *view)
 {
 	struct media_definition *media_definition= get_media_definition(0);
@@ -507,3 +999,17 @@
 	
 	return region;
 }
+
+struct mesh_region* build_mesh_region(struct view_data *view)
+{
+	if(key_down(_key_space))
+	{
+		struct mesh_region *region = build_mesh_region_old(view);
+		compute_frustum_polygon(view, region);
+		return region;
+	}
+	else
+	{
+		return build_mesh_region_new(view);
+	}
+}
\ No newline at end of file
