Пример #1
0
static void PutPointsOnCurve(srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int width, int height)
{
	int       i, j;
	srfVert_t prev, next;

	for (i = 0; i < width; i++)
	{
		for (j = 1; j < height; j += 2)
		{
			LerpSurfaceVert(&ctrl[j][i], &ctrl[j + 1][i], &prev);
			LerpSurfaceVert(&ctrl[j][i], &ctrl[j - 1][i], &next);
			LerpSurfaceVert(&prev, &next, &ctrl[j][i]);
		}
	}

	for (j = 0; j < height; j++)
	{
		for (i = 1; i < width; i += 2)
		{
			LerpSurfaceVert(&ctrl[j][i], &ctrl[j][i + 1], &prev);
			LerpSurfaceVert(&ctrl[j][i], &ctrl[j][i - 1], &next);
			LerpSurfaceVert(&prev, &next, &ctrl[j][i]);
		}
	}
}
Пример #2
0
srfGridMesh_t *R_GridInsertRow(srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror)
{
	int                  i, j;
	int                  width = grid->width, height = grid->height + 1, oldheight = 0;
	static srfVert_t     ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
	float                errorTable[2][MAX_GRID_SIZE];
	float                lodRadius;
	vec3_t               lodOrigin;
	int                  numTriangles;
	static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];

	if (height > MAX_GRID_SIZE)
	{
		return NULL;
	}
	for (i = 0; i < height; i++)
	{
		if (i == row)
		{
			//insert new row
			for (j = 0; j < grid->width; j++)
			{
				LerpSurfaceVert(&grid->verts[(i - 1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j]);
				if (j == column)
				{
					VectorCopy(point, ctrl[i][j].xyz);
				}
			}
			errorTable[1][i] = loderror;
			continue;
		}
		errorTable[1][i] = grid->heightLodError[oldheight];
		for (j = 0; j < grid->width; j++)
		{
			ctrl[i][j] = grid->verts[oldheight * grid->width + j];
		}
		oldheight++;
	}
	for (j = 0; j < grid->width; j++)
	{
		errorTable[0][j] = grid->widthLodError[j];
	}
	// put all the aproximating points on the curve
	//PutPointsOnCurve( ctrl, width, height );

	// calculate triangles
	numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);

	// calculate normals
	MakeMeshNormals(width, height, ctrl);
	MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);

	// calculate tangent spaces
	//MakeTangentSpaces(width, height, ctrl, numTriangles, triangles);

	VectorCopy(grid->lodOrigin, lodOrigin);
	lodRadius = grid->lodRadius;
	// free the old grid
	R_FreeSurfaceGridMesh(grid);
	// create a new grid
	grid            = R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
	grid->lodRadius = lodRadius;
	VectorCopy(lodOrigin, grid->lodOrigin);
	return grid;
}
Пример #3
0
srfGridMesh_t *R_SubdividePatchToGrid(int width, int height, srfVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE])
{
	int                  i, j, k, l;
	srfVert_t            prev, next, mid;
	float                len, maxLen;
	int                  dir;
	int                  t;
	static srfVert_t     ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
	float                errorTable[2][MAX_GRID_SIZE];
	int                  numTriangles;
	static srfTriangle_t triangles[SHADER_MAX_TRIANGLES];

	for (i = 0; i < width; i++)
	{
		for (j = 0; j < height; j++)
		{
			ctrl[j][i] = points[j * width + i];
		}
	}

	for (dir = 0; dir < 2; dir++)
	{

		for (j = 0; j < MAX_GRID_SIZE; j++)
		{
			errorTable[dir][j] = 0;
		}

		// horizontal subdivisions
		for (j = 0; j + 2 < width; j += 2)
		{
			// check subdivided midpoints against control points

			// FIXME: also check midpoints of adjacent patches against the control points
			// this would basically stitch all patches in the same LOD group together.

			maxLen = 0;
			for (i = 0; i < height; i++)
			{
				vec3_t midxyz;
				vec3_t midxyz2;
				vec3_t dir;
				vec3_t projected;
				float  d;

				// calculate the point on the curve
				for (l = 0; l < 3; l++)
				{
					midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j + 1].xyz[l] * 2 + ctrl[i][j + 2].xyz[l]) * 0.25f;
				}

				// see how far off the line it is
				// using dist-from-line will not account for internal
				// texture warping, but it gives a lot less polygons than
				// dist-from-midpoint
				VectorSubtract(midxyz, ctrl[i][j].xyz, midxyz);
				VectorSubtract(ctrl[i][j + 2].xyz, ctrl[i][j].xyz, dir);
				VectorNormalize(dir);

				d = DotProduct(midxyz, dir);
				VectorScale(dir, d, projected);
				VectorSubtract(midxyz, projected, midxyz2);
				len = VectorLengthSquared(midxyz2); // we will do the sqrt later
				if (len > maxLen)
				{
					maxLen = len;
				}
			}

			maxLen = sqrt(maxLen);

			// if all the points are on the lines, remove the entire columns
			if (maxLen < 0.1f)
			{
				errorTable[dir][j + 1] = 999;
				continue;
			}

			// see if we want to insert subdivided columns
			if (width + 2 > MAX_GRID_SIZE)
			{
				errorTable[dir][j + 1] = 1.0f / maxLen;
				continue;       // can't subdivide any more
			}

			if (maxLen <= r_subdivisions->value)
			{
				errorTable[dir][j + 1] = 1.0f / maxLen;
				continue;       // didn't need subdivision
			}

			errorTable[dir][j + 2] = 1.0f / maxLen;

			// insert two columns and replace the peak
			width += 2;
			for (i = 0; i < height; i++)
			{
				LerpSurfaceVert(&ctrl[i][j], &ctrl[i][j + 1], &prev);
				LerpSurfaceVert(&ctrl[i][j + 1], &ctrl[i][j + 2], &next);
				LerpSurfaceVert(&prev, &next, &mid);

				for (k = width - 1; k > j + 3; k--)
				{
					ctrl[i][k] = ctrl[i][k - 2];
				}
				ctrl[i][j + 1] = prev;
				ctrl[i][j + 2] = mid;
				ctrl[i][j + 3] = next;
			}

			// back up and recheck this set again, it may need more subdivision
			j -= 2;

		}

		Transpose(width, height, ctrl);
		t      = width;
		width  = height;
		height = t;
	}

	// put all the aproximating points on the curve
	PutPointsOnCurve(ctrl, width, height);

	// cull out any rows or columns that are colinear
	for (i = 1; i < width - 1; i++)
	{
		if (errorTable[0][i] != 999)
		{
			continue;
		}
		for (j = i + 1; j < width; j++)
		{
			for (k = 0; k < height; k++)
			{
				ctrl[k][j - 1] = ctrl[k][j];
			}
			errorTable[0][j - 1] = errorTable[0][j];
		}
		width--;
	}

	for (i = 1; i < height - 1; i++)
	{
		if (errorTable[1][i] != 999)
		{
			continue;
		}
		for (j = i + 1; j < height; j++)
		{
			for (k = 0; k < width; k++)
			{
				ctrl[j - 1][k] = ctrl[j][k];
			}
			errorTable[1][j - 1] = errorTable[1][j];
		}
		height--;
	}

#if 1
	// flip for longest tristrips as an optimization
	// the results should be visually identical with or
	// without this step
	if (height > width)
	{
		Transpose(width, height, ctrl);
		InvertErrorTable(errorTable, width, height);
		t      = width;
		width  = height;
		height = t;
		InvertCtrl(width, height, ctrl);
	}
#endif

	// calculate triangles
	numTriangles = MakeMeshTriangles(width, height, ctrl, triangles);

	// calculate normals
	MakeMeshNormals(width, height, ctrl);
	MakeMeshTangentVectors(width, height, ctrl, numTriangles, triangles);

	// calculate tangent spaces
	//MakeTangentSpaces(width, height, ctrl, numTriangles, triangles);

	return R_CreateSurfaceGridMesh(width, height, ctrl, errorTable, numTriangles, triangles);
}
Пример #4
0
/*
===============
R_GridInsertRow
===============
*/
srfGridMesh_t  *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror )
{
	int                  i, j;
	int                  width, height, oldheight;
	float                errorTable[ 2 ][ MAX_GRID_SIZE ];
	float                lodRadius;
	vec3_t               lodOrigin;
	int                  numTriangles;

	oldheight = 0;
	width = grid->width;
	height = grid->height + 1;

	if ( height > MAX_GRID_SIZE )
	{
		return nullptr;
	}

	for ( i = 0; i < height; i++ )
	{
		if ( i == row )
		{
			//insert new row
			for ( j = 0; j < grid->width; j++ )
			{
				LerpSurfaceVert( &grid->verts[( i - 1 ) * grid->width + j ], &grid->verts[ i * grid->width + j ], &gridctrl[ i ][ j ] );

				if ( j == column )
				{
					VectorCopy( point, gridctrl[ i ][ j ].xyz );
				}
			}

			errorTable[ 1 ][ i ] = loderror;
			continue;
		}

		errorTable[ 1 ][ i ] = grid->heightLodError[ oldheight ];

		for ( j = 0; j < grid->width; j++ )
		{
			gridctrl[ i ][ j ] = grid->verts[ oldheight * grid->width + j ];
		}

		oldheight++;
	}

	for ( j = 0; j < grid->width; j++ )
	{
		errorTable[ 0 ][ j ] = grid->widthLodError[ j ];
	}

	// calculate triangles
	numTriangles = MakeMeshTriangles( width, height, gridctrl, gridtriangles );

	// calculate normals
	MakeMeshNormals( width, height, gridctrl );

	VectorCopy( grid->lodOrigin, lodOrigin );
	lodRadius = grid->lodRadius;
	// free the old grid
	R_FreeSurfaceGridMesh( grid );
	// create a new grid
	grid = R_CreateSurfaceGridMesh( width, height, gridctrl, errorTable, numTriangles, gridtriangles );
	grid->lodRadius = lodRadius;
	VectorCopy( lodOrigin, grid->lodOrigin );
	return grid;
}