示例#1
0
/*
=================
idSurface_Patch::PutOnCurve

Expects an expanded patch.
=================
*/
void idSurface_Patch::PutOnCurve()
{
	int i, j;
	idDrawVert prev, next;
	
	assert( expanded == true );
	// put all the approximating points on the curve
	for( i = 0; i < width; i++ )
	{
		for( j = 1; j < height; j += 2 )
		{
			LerpVert( verts[j * maxWidth + i], verts[( j + 1 )*maxWidth + i], prev );
			LerpVert( verts[j * maxWidth + i], verts[( j - 1 )*maxWidth + i], next );
			LerpVert( prev, next, verts[j * maxWidth + i] );
		}
	}
	
	for( j = 0; j < height; j++ )
	{
		for( i = 1; i < width; i += 2 )
		{
			LerpVert( verts[j * maxWidth + i], verts[j * maxWidth + i + 1], prev );
			LerpVert( verts[j * maxWidth + i], verts[j * maxWidth + i - 1], next );
			LerpVert( prev, next, verts[j * maxWidth + i] );
		}
	}
}
示例#2
0
/*
=================
idSurface_Patch::Subdivide
=================
*/
void idSurface_Patch::Subdivide( float maxHorizontalError, float maxVerticalError, float maxLength, bool genNormals ) {
	int			i, j, k, l;
	idDrawVert	prev, next, mid;
	idVec3		prevxyz, nextxyz, midxyz;
	idVec3		delta;
	float		maxHorizontalErrorSqr, maxVerticalErrorSqr, maxLengthSqr;

	// generate normals for the control mesh
	if ( genNormals ) {
		GenerateNormals();
	}

	maxHorizontalErrorSqr = Square( maxHorizontalError );
	maxVerticalErrorSqr = Square( maxVerticalError );
	maxLengthSqr = Square( maxLength );

	Expand();

	// horizontal subdivisions
	for ( j = 0; j + 2 < width; j += 2 ) {
		// check subdivided midpoints against control points
		for ( i = 0; i < height; i++ ) {
			for ( l = 0; l < 3; l++ ) {
				prevxyz[l] = verts[i*maxWidth + j+1].xyz[l] - verts[i*maxWidth + j  ].xyz[l];
				nextxyz[l] = verts[i*maxWidth + j+2].xyz[l] - verts[i*maxWidth + j+1].xyz[l];
				midxyz[l] = (verts[i*maxWidth + j  ].xyz[l] + verts[i*maxWidth + j+1].xyz[l] * 2.0f +
														   verts[i*maxWidth + j+2].xyz[l] ) * 0.25f;
			}

			if ( maxLength > 0.0f ) {
				// if the span length is too long, force a subdivision
				if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
					break;
				}
			}
			// see if this midpoint is off far enough to subdivide
			delta = verts[i*maxWidth + j+1].xyz - midxyz;
			if ( delta.LengthSqr() > maxHorizontalErrorSqr ) {
				break;
			}
		}

		if ( i == height ) {
			continue;	// didn't need subdivision
		}

		if ( width + 2 >= maxWidth ) {
			ResizeExpanded( maxHeight, maxWidth + 4 );
		}

		// insert two columns and replace the peak
		width += 2;

		for ( i = 0; i < height; i++ ) {
			idSurface_Patch::LerpVert( verts[i*maxWidth + j  ], verts[i*maxWidth + j+1], prev );
			idSurface_Patch::LerpVert( verts[i*maxWidth + j+1], verts[i*maxWidth + j+2], next );
			idSurface_Patch::LerpVert( prev, next, mid );

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

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

	// vertical subdivisions
	for ( j = 0; j + 2 < height; j += 2 ) {
		// check subdivided midpoints against control points
		for ( i = 0; i < width; i++ ) {
			for ( l = 0; l < 3; l++ ) {
				prevxyz[l] = verts[(j+1)*maxWidth + i].xyz[l] - verts[j*maxWidth + i].xyz[l];
				nextxyz[l] = verts[(j+2)*maxWidth + i].xyz[l] - verts[(j+1)*maxWidth + i].xyz[l];
				midxyz[l] = (verts[j*maxWidth + i].xyz[l] + verts[(j+1)*maxWidth + i].xyz[l] * 2.0f +
														verts[(j+2)*maxWidth + i].xyz[l] ) * 0.25f;
			}

			if ( maxLength > 0.0f ) {
				// if the span length is too long, force a subdivision
				if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
					break;
				}
			}
			// see if this midpoint is off far enough to subdivide
			delta = verts[(j+1)*maxWidth + i].xyz - midxyz;
			if ( delta.LengthSqr() > maxVerticalErrorSqr ) {
				break;
			}
		}

		if ( i == width ) {
			continue;	// didn't need subdivision
		}

		if ( height + 2 >= maxHeight ) {
			ResizeExpanded( maxHeight + 4, maxWidth );
		}

		// insert two columns and replace the peak
		height += 2;

		for ( i = 0; i < width; i++ ) {
			LerpVert( verts[j*maxWidth + i], verts[(j+1)*maxWidth + i], prev );
			LerpVert( verts[(j+1)*maxWidth + i], verts[(j+2)*maxWidth + i], next );
			LerpVert( prev, next, mid );

			for ( k = height - 1; k > j + 3; k-- ) {
				verts[k*maxWidth + i] = verts[(k-2)*maxWidth + i];
			}
			verts[(j+1)*maxWidth + i] = prev;
			verts[(j+2)*maxWidth + i] = mid;
			verts[(j+3)*maxWidth + i] = next;
		}

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

	PutOnCurve();

	RemoveLinearColumnsRows();

	Collapse();

	// normalize all the lerped normals
	if ( genNormals ) {
		for ( i = 0; i < width * height; i++ ) {
			verts[i].normal.Normalize();
		}
	}

	GenerateIndexes();
}