//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pPatch - 
//			*pPoints - 
//			&vecNormal - 
//			flArea - 
//-----------------------------------------------------------------------------
bool CVRADDispColl::InitPatch( int iPatch, int iParentPatch, int iChild, Vector *pPoints, int *pIndices, float &flArea )
{
	// Get the current patch.
	CPatch *pPatch = &g_Patches[iPatch];
	if ( !pPatch )
		return false;

	// Clear the patch data.
	memset( pPatch, 0, sizeof( CPatch ) );

	// Setup the parent if we are not the parent.
	CPatch *pParentPatch = NULL;
	if ( iParentPatch != g_Patches.InvalidIndex() )
	{
		// Get the parent patch.
		pParentPatch = &g_Patches[iParentPatch];
		if ( !pParentPatch )
			return false;
	}

	// Attach the face to the correct lists.
	if ( !pParentPatch )
	{
		// This is a parent.
		pPatch->ndxNext = g_FacePatches.Element( GetParentIndex() );
		g_FacePatches[GetParentIndex()] = iPatch;
		pPatch->faceNumber = GetParentIndex();
	}
	else
	{
		pPatch->ndxNext = g_Patches.InvalidIndex();
		pPatch->faceNumber = pParentPatch->faceNumber;

		// Attach to the parent patch.
		if ( iChild == 0 )
		{
			pParentPatch->child1 = iPatch;
		}
		else
		{
			pParentPatch->child2 = iPatch;
		}
	}

	// Initialize parent and children indices.
	pPatch->child1 = g_Patches.InvalidIndex();
	pPatch->child2 = g_Patches.InvalidIndex();
	pPatch->ndxNextClusterChild = g_Patches.InvalidIndex();
	pPatch->ndxNextParent = g_Patches.InvalidIndex();
	pPatch->parent = iParentPatch;

	// Get triangle edges.
	Vector vecEdges[3];
	vecEdges[0] = pPoints[1] - pPoints[0];
	vecEdges[1] = pPoints[2] - pPoints[0];
	vecEdges[2] = pPoints[2] - pPoints[1];

	// Find the longest edge.
//	float flEdgeLength = 0.0f;
//	for ( int iEdge = 0; iEdge < 3; ++iEdge )
//	{
//		if ( flEdgeLength < vecEdges[iEdge].Length() )
//		{
//			flEdgeLength = vecEdges[iEdge].Length();
//		}
//	}

	// Calculate the triangle normal and area.
	Vector vecNormal = vecEdges[1].Cross( vecEdges[0] );
	flArea = VectorNormalize( vecNormal );
	flArea *= 0.5f;

	// Initialize the patch scale.
	pPatch->scale[0] = pPatch->scale[1] = 1.0f;

	// Set the patch chop - minchop (that is what the minimum area is based on).
	pPatch->chop = dispchop;

	// Displacements are not sky!
	pPatch->sky = false;

	// Copy the winding.
	Vector vecCenter( 0.0f, 0.0f, 0.0f );
	pPatch->winding = AllocWinding( 3 );
	pPatch->winding->numpoints = 3;
	for ( int iPoint = 0; iPoint < 3; ++iPoint )
	{
		VectorCopy( pPoints[iPoint], pPatch->winding->p[iPoint] );
		VectorAdd( pPoints[iPoint], vecCenter, vecCenter );

		pPatch->indices[iPoint] = static_cast<short>( pIndices[iPoint] );
	}

	// Set the origin and normal.
	VectorScale( vecCenter, ( 1.0f / 3.0f ), vecCenter );
	VectorCopy( vecCenter, pPatch->origin );
	VectorCopy( vecNormal, pPatch->normal );

	// Create the plane.
	pPatch->plane = new dplane_t;
	if ( !pPatch->plane )
		return false;

	VectorCopy( vecNormal, pPatch->plane->normal );
	pPatch->plane->dist = vecNormal.Dot( pPoints[0] );
	pPatch->plane->type = PlaneTypeForNormal( pPatch->plane->normal );
	pPatch->planeDist = pPatch->plane->dist;

	// Set the area.
	pPatch->area = flArea;

	// Calculate the mins/maxs.
	Vector vecMin( FLT_MAX, FLT_MAX, FLT_MAX );
	Vector vecMax( FLT_MIN, FLT_MIN, FLT_MIN );
	for ( int iPoint = 0; iPoint < 3; ++iPoint )
	{
		for ( int iAxis = 0; iAxis < 3; ++iAxis )
		{
			vecMin[iAxis] = MIN( vecMin[iAxis], pPoints[iPoint][iAxis] );
			vecMax[iAxis] = MAX( vecMax[iAxis], pPoints[iPoint][iAxis] );
		}
	}

	VectorCopy( vecMin, pPatch->mins );
	VectorCopy( vecMax, pPatch->maxs );

	if ( !pParentPatch )
	{
		VectorCopy( vecMin, pPatch->face_mins );
		VectorCopy( vecMax, pPatch->face_maxs );
	}
	else
	{
		VectorCopy( pParentPatch->face_mins, pPatch->face_mins );
		VectorCopy( pParentPatch->face_maxs, pPatch->face_maxs );
	}

	// Check for bumpmap.
	dface_t *pFace = dfaces + pPatch->faceNumber;
	texinfo_t *pTexInfo = &texinfo[pFace->texinfo];
	pPatch->needsBumpmap = pTexInfo->flags & SURF_BUMPLIGHT ? true : false;

	// Misc...
	pPatch->m_IterationKey = 0;

	// Get the base light for the face.
	if ( !pParentPatch )
	{
		BaseLightForFace( &g_pFaces[pPatch->faceNumber], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity );
	}
	else
	{
		VectorCopy( pParentPatch->baselight, pPatch->baselight );
		pPatch->basearea = pParentPatch->basearea;
		pPatch->reflectivity = pParentPatch->reflectivity;
	}

	return true;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : iPatch - 
//			iParentPatch - 
//			iChild - 
//			*pPoints - 
//			*pIndices - 
//			&flArea - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CVRADDispColl::InitParentPatch( int iPatch, Vector *pPoints, float &flArea )
{
	// Get the current patch.
	CPatch *pPatch = &g_Patches[iPatch];
	if ( !pPatch )
		return false;

	// Clear the patch data.
	memset( pPatch, 0, sizeof( CPatch ) );

	// This is a parent.
	pPatch->ndxNext = g_FacePatches.Element( GetParentIndex() );
	g_FacePatches[GetParentIndex()] = iPatch;
	pPatch->faceNumber = GetParentIndex();

	// Initialize parent and children indices.
	pPatch->child1 = g_Patches.InvalidIndex();
	pPatch->child2 = g_Patches.InvalidIndex();
	pPatch->parent = g_Patches.InvalidIndex();
	pPatch->ndxNextClusterChild = g_Patches.InvalidIndex();
	pPatch->ndxNextParent = g_Patches.InvalidIndex();

	Vector vecEdges[2];
	vecEdges[0] = pPoints[1] - pPoints[0];
	vecEdges[1] = pPoints[3] - pPoints[0];

	// Calculate the triangle normal and area.
	Vector vecNormal = vecEdges[1].Cross( vecEdges[0] );
	flArea = VectorNormalize( vecNormal );

	// Initialize the patch scale.
	pPatch->scale[0] = pPatch->scale[1] = 1.0f;

	// Set the patch chop - minchop (that is what the minimum area is based on).
	pPatch->chop = dispchop;

	// Displacements are not sky!
	pPatch->sky = false;

	// Copy the winding.
	Vector vecCenter( 0.0f, 0.0f, 0.0f );
	pPatch->winding = AllocWinding( 4 );
	pPatch->winding->numpoints = 4;
	for ( int iPoint = 0; iPoint < 4; ++iPoint )
	{
		VectorCopy( pPoints[iPoint], pPatch->winding->p[iPoint] );
		VectorAdd( pPoints[iPoint], vecCenter, vecCenter );
	}

	// Set the origin and normal.
	VectorScale( vecCenter, ( 1.0f / 4.0f ), vecCenter );
	VectorCopy( vecCenter, pPatch->origin );
	VectorCopy( vecNormal, pPatch->normal );

	// Create the plane.
	pPatch->plane = new dplane_t;
	if ( !pPatch->plane )
		return false;

	VectorCopy( vecNormal, pPatch->plane->normal );
	pPatch->plane->dist = vecNormal.Dot( pPoints[0] );
	pPatch->plane->type = PlaneTypeForNormal( pPatch->plane->normal );
	pPatch->planeDist = pPatch->plane->dist;

	// Set the area.
	pPatch->area = flArea;

	// Calculate the mins/maxs.
	Vector vecMin( FLT_MAX, FLT_MAX, FLT_MAX );
	Vector vecMax( FLT_MIN, FLT_MIN, FLT_MIN );
	for ( int iPoint = 0; iPoint < 4; ++iPoint )
	{
		for ( int iAxis = 0; iAxis < 3; ++iAxis )
		{
			vecMin[iAxis] = MIN( vecMin[iAxis], pPoints[iPoint][iAxis] );
			vecMax[iAxis] = MAX( vecMax[iAxis], pPoints[iPoint][iAxis] );
		}
	}

	VectorCopy( vecMin, pPatch->mins );
	VectorCopy( vecMax, pPatch->maxs );
	VectorCopy( vecMin, pPatch->face_mins );
	VectorCopy( vecMax, pPatch->face_maxs );

	// Check for bumpmap.
	dface_t *pFace = dfaces + pPatch->faceNumber;
	texinfo_t *pTexInfo = &texinfo[pFace->texinfo];
	pPatch->needsBumpmap = pTexInfo->flags & SURF_BUMPLIGHT ? true : false;

	// Misc...
	pPatch->m_IterationKey = 0;

	// Calculate the base light, area, and reflectivity.
	BaseLightForFace( &g_pFaces[pPatch->faceNumber], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity );

	return true;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CVRADDispColl::MakeParentPatch( int ndxPatch )
{
#if 0
	// debugging!
	if( !pDispFile )
	{
		pDispFile = g_pFileSystem->Open( "vraddisp.txt", "w" );
	}
#endif

	// get the current patch
	patch_t *pPatch = &patches[ndxPatch];
	if( pPatch )
	{
		int ndxStart = Nodes_CalcCount( m_Power - 1 );
		int ndxEnd = Nodes_CalcCount( m_Power );

		for( int ndxNode = ndxStart; ndxNode < ndxEnd; ndxNode++ )
		{
			VNode_t *pVNode = &m_pVNodes[ndxNode];
			if( pVNode )
			{
				VectorAdd( pPatch->normal, pVNode->patchNormal, pPatch->normal );
				pPatch->area += pVNode->patchArea;
				
				for( int ndxAxis = 0; ndxAxis < 3; ndxAxis++ )
				{
					if( pPatch->face_mins[ndxAxis] > pVNode->patchBounds[0][ndxAxis] )
					{
						pPatch->face_mins[ndxAxis] = pVNode->patchBounds[0][ndxAxis];
					}
					
					if( pPatch->face_maxs[ndxAxis] < pVNode->patchBounds[1][ndxAxis] )
					{
						pPatch->face_maxs[ndxAxis] = pVNode->patchBounds[1][ndxAxis];
					}
				}
			}
		}
	
#if 0
		// debugging!
		g_pFileSystem->FPrintf( pDispFile, "Parent Patch %d\n", ndxPatch );
		g_pFileSystem->FPrintf( pDispFile, "	Area: %lf\n", pPatch->area );
#endif

		// set the patch bounds to face bounds (as this is the face patch)
		pPatch->mins = pPatch->face_mins;
		pPatch->maxs = pPatch->face_maxs;

		VectorNormalize( pPatch->normal );
		DispUVToSurfPt( Vector2D( 0.5f, 0.5f ), pPatch->origin, 0.0f );		

		// fill in the patch plane into given the normal and origin (have to alloc one - lame!)
		pPatch->plane = new dplane_t;
		if( pPatch->plane )
		{
			pPatch->plane->normal = pPatch->normal;
			pPatch->plane->dist = pPatch->normal.Dot( pPatch->origin );
		}

		// copy the patch origin to face_centroids for main patch
		VectorCopy( pPatch->origin, face_centroids[m_ndxParent] );
		
		VectorAdd( pPatch->origin, pPatch->normal, pPatch->origin );

		// approximate patch winding - used for debugging!
		pPatch->winding = AllocWinding( 4 );
		if( pPatch->winding )
		{
			pPatch->winding->numpoints = 4;
			for( int ndxPt = 0; ndxPt < 4; ndxPt++ )
			{
				GetPoint( ndxPt, pPatch->winding->p[ndxPt] );
			}
		}

		// get base face normal (stab direction is base face normal)
		Vector vBaseFaceNormal;
		GetStabDirection( vBaseFaceNormal );
		int majorAxis = 0;
		float majorValue = vBaseFaceNormal[0];
		if( vBaseFaceNormal[1] > majorValue ) { majorAxis = 1; majorValue = vBaseFaceNormal[1]; }
		if( vBaseFaceNormal[2] > majorValue ) { majorAxis = 2; }
		pPatch->normalMajorAxis = majorAxis;

		// get the base light for the face
		BaseLightForFace( &dfaces[m_ndxParent], pPatch->baselight, &pPatch->basearea, pPatch->reflectivity );

		return true;
	}

	return false;
}
Exemplo n.º 4
0
void MakePatchForFace (int fn, winding_t *w)
{
	dface_t *f = dfaces + fn;

	// No patches at all for the sky!
	if ( !IsSky(f) )
	{
		float	area;
		patch_t		*patch;
		vec3_t light;
		vec3_t		centroid = {0,0,0};
		int			i, j;
		texinfo_t	*tx = &texinfo[f->texinfo];

		area = WindingArea (w);
		totalarea += area;

		patch = &patches[num_patches];
		if (num_patches == MAX_PATCHES)
			Error ("num_patches == MAX_PATCHES");
		patch->next = face_patches[fn];
		face_patches[fn] = patch;

		if ( texscale )
			{
			// Compute the texture "scale" in s,t
			for( i=0; i<2; i++ )
				{
				patch->scale[i] = 0.0;
				for( j=0; j<3; j++ )
					patch->scale[i] += tx->vecs[i][j] * tx->vecs[i][j];
				patch->scale[i] = sqrt( patch->scale[i] );
				}
			}
		else
			patch->scale[0] = patch->scale[1] = 1.0;

		patch->area = area;
		patch->chop = maxchop / (int)((patch->scale[0]+patch->scale[1])/2);
		patch->sky = FALSE;

		patch->winding = w;

		if (f->side)
			patch->plane = &backplanes[f->planenum];
		else
			patch->plane = &dplanes[f->planenum];

		for (j=0 ; j<f->numedges ; j++)
		{
			int edge = dsurfedges[ f->firstedge + j ];
			int edge2 = dsurfedges[ j==f->numedges-1 ? f->firstedge : f->firstedge + j + 1 ];

			if (edge > 0)
			{
				VectorAdd( dvertexes[dedges[edge].v[0]].point, centroid, centroid );
				VectorAdd( dvertexes[dedges[edge].v[1]].point, centroid, centroid );
			}
			else
			{
				VectorAdd( dvertexes[dedges[-edge].v[1]].point, centroid, centroid );
				VectorAdd( dvertexes[dedges[-edge].v[0]].point, centroid, centroid );
			}
		}
		VectorScale( centroid, 1.0 / (f->numedges * 2), centroid );
		VectorCopy( centroid, face_centroids[fn] );  // Save them for generating the patch normals later.

		patch->faceNumber = fn;
		WindingCenter (w, patch->origin);

#ifdef PHONG_NORMAL_PATCHES
// This seems to be a bad idea for some reason.  Leave it turned off for now.
		VectorAdd (patch->origin, patch->plane->normal, patch->origin);
		GetPhongNormal( fn, patch->origin, patch->normal );
		VectorSubtract (patch->origin, patch->plane->normal, patch->origin);
		if ( !VectorCompare( patch->plane->normal, patch->normal ) )
			patch->chop = 16; // Chop it fine!
#else
		VectorCopy( patch->plane->normal, patch->normal );
#endif
		VectorAdd (patch->origin, patch->normal, patch->origin);

		WindingBounds (w, patch->face_mins, patch->face_maxs);
		VectorCopy( patch->face_mins, patch->mins );
		VectorCopy( patch->face_maxs, patch->maxs );

		BaseLightForFace( f, light, patch->reflectivity );
		VectorCopy( light, patch->totallight );
		VectorCopy( light, patch->baselight );

		// Chop all texlights very fine.
		if ( !VectorCompare( light, vec3_origin ) )
			patch->chop = extra ? minchop / 2 : minchop;

		num_patches++;
	}
}
Exemplo n.º 5
0
void MakePatchForFace( int fn, winding_t *w ){
	dface_t *f;
	float area;
	patch_t     *patch;
	dplane_t    *pl;
	int i;
	vec3_t color;
	dleaf_t     *leaf;

	f = &dfaces[fn];

	area = WindingArea( w );
	totalarea += area;

	patch = &patches[num_patches];
	if ( num_patches == MAX_PATCHES ) {
		Error( "num_patches == MAX_PATCHES" );
	}
	patch->next = face_patches[fn];
	face_patches[fn] = patch;

	patch->winding = w;

	if ( f->side ) {
		patch->plane = &backplanes[f->planenum];
	}
	else{
		patch->plane = &dplanes[f->planenum];
	}
	if ( face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] ) { // origin offset faces must create new planes
		if ( numplanes + fakeplanes >= MAX_MAP_PLANES ) {
			Error( "numplanes + fakeplanes >= MAX_MAP_PLANES" );
		}
		pl = &dplanes[numplanes + fakeplanes];
		fakeplanes++;

		*pl = *( patch->plane );
		pl->dist += DotProduct( face_offset[fn], pl->normal );
		patch->plane = pl;
	}

	WindingCenter( w, patch->origin );
	VectorAdd( patch->origin, patch->plane->normal, patch->origin );
	leaf = Rad_PointInLeaf( patch->origin );
	patch->cluster = leaf->cluster;
	if ( patch->cluster == -1 ) {
		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
	}

	patch->area = area;
	if ( patch->area <= 1 ) {
		patch->area = 1;
	}
	patch->sky = IsSky( f );

	VectorCopy( texture_reflectivity[f->texinfo], patch->reflectivity );

	// non-bmodel patches can emit light
	if ( fn < dmodels[0].numfaces ) {
		BaseLightForFace( f, patch->baselight );

		ColorNormalize( patch->reflectivity, color );

		for ( i = 0 ; i < 3 ; i++ )
			patch->baselight[i] *= color[i];

		VectorCopy( patch->baselight, patch->totallight );
	}
	num_patches++;
}