示例#1
0
文件: fog.c 项目: otty/cake3
/*
====================
ChopPatchByBrush
====================
*/
qboolean ChopPatchByBrush(drawSurface_t * ds, bspBrush_t * b)
{
	int             i, j;
	side_t         *s;
	plane_t        *plane;
	mesh_t         *outside[MAX_BRUSH_SIDES];
	int             numOutside;
	mesh_t         *m, *front, *back;
	drawSurface_t  *newds;

	m = DrawSurfToMesh(ds);
	numOutside = 0;

	// only split by the top and bottom planes to avoid
	// some messy patch clipping issues

	for(i = 4; i <= 5; i++)
	{
		s = &b->sides[i];
		plane = &mapPlanes[s->planenum];

		SplitMeshByPlane(m, plane->normal, plane->dist, &front, &back);

		if(!back)
		{
			// nothing actually contained inside
			for(j = 0; j < numOutside; j++)
			{
				FreeMesh(outside[j]);
			}
			return qfalse;
		}
		m = back;

		if(front)
		{
			if(numOutside == MAX_BRUSH_SIDES)
			{
				Error("MAX_BRUSH_SIDES");
			}
			outside[numOutside] = front;
			numOutside++;
		}
	}

	// all of outside fragments become seperate drawsurfs
	c_fogPatchFragments += numOutside;
	for(i = 0; i < numOutside; i++)
	{
		newds = DrawSurfaceForMesh(outside[i]);
		newds->shaderInfo = ds->shaderInfo;
		FreeMesh(outside[i]);
	}

	// replace ds with m
	ds->patchWidth = m->width;
	ds->patchHeight = m->height;
	ds->numVerts = m->width * m->height;
	free(ds->verts);
	ds->verts = malloc(ds->numVerts * sizeof(*ds->verts));
	memcpy(ds->verts, m->verts, ds->numVerts * sizeof(*ds->verts));

	FreeMesh(m);

	return qtrue;
}
示例#2
0
void PatchMapDrawSurfs( entity_t *e )
{
	int						i, j, k, l, c1, c2;
	parseMesh_t				*pm;
	parseMesh_t				*check, *scan;
	mapDrawSurface_t		*ds;
	int						patchCount, groupCount;
	bspDrawVert_t			*v1, *v2;
	vec3_t					bounds[ 2 ];
	byte					*bordering;
	
	/* ydnar: mac os x fails with these if not static */
	MAC_STATIC parseMesh_t	*meshes[ MAX_MAP_DRAW_SURFS ];
	MAC_STATIC qboolean		grouped[ MAX_MAP_DRAW_SURFS ];
	MAC_STATIC byte			group[ MAX_MAP_DRAW_SURFS ];
	
	
	/* note it */
	Sys_FPrintf( SYS_VRB, "--- PatchMapDrawSurfs ---\n" );

	/* fetch patches from the entity */
	patchCount = 0;
	for ( pm = e->patches ; pm ; pm = pm->next  ) 
	{
		meshes[patchCount] = pm;
		patchCount++;
	}

	if ( !patchCount ) 
		return;

	bordering = (byte *)safe_malloc( patchCount * patchCount );
	memset( bordering, 0, patchCount * patchCount );

	// build the bordering matrix
	for ( k = 0 ; k < patchCount ; k++ ) 
	{
		bordering[k*patchCount+k] = 1;

		for ( l = k+1 ; l < patchCount ; l++ ) 
		{
			check = meshes[k];
			scan = meshes[l];
			c1 = scan->mesh.width * scan->mesh.height;
			v1 = scan->mesh.verts;

			for ( i = 0 ; i < c1 ; i++, v1++ ) 
			{
				c2 = check->mesh.width * check->mesh.height;
				v2 = check->mesh.verts;
				for ( j = 0 ; j < c2 ; j++, v2++ ) 
				{
					if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
						&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
						&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
						break;
					}
				}
				if ( j != c2 ) {
					break;
				}
			}
			if ( i != c1 ) 
			{
				// we have a connection
				bordering[k*patchCount+l] =
				bordering[l*patchCount+k] = 1;
			} else 
			{
				// no connection
				bordering[k*patchCount+l] =
				bordering[l*patchCount+k] = 0;
			}

		}
	}

	/* build groups */
	memset( grouped, 0, patchCount );
	groupCount = 0;
	for ( i = 0; i < patchCount; i++ )
	{
		/* get patch */
		scan = meshes[ i ];
		
		/* start a new group */
		if( !grouped[ i ] )
			groupCount++;
		
		/* recursively find all patches that belong in the same group */
		memset( group, 0, patchCount );
		GrowGroup_r( scan, i, patchCount, meshes, bordering, group );
		
		/* bound them */
		ClearBounds( bounds[ 0 ], bounds[ 1 ] );
		for( j = 0; j < patchCount; j++ )
		{
			if ( group[ j ] )
			{
				grouped[ j ] = qtrue;
				check = meshes[ j ];
				c1 = check->mesh.width * check->mesh.height;
				v1 = check->mesh.verts;
				for( k = 0; k < c1; k++, v1++ )
					AddPointToBounds( v1->xyz, bounds[ 0 ], bounds[ 1 ] );
			}
		}
		
		/* debug code */
		//%	Sys_Printf( "Longest curve: %f Iterations: %d\n", scan->longestCurve, scan->maxIterations );
		
		/* create drawsurf */
		scan->grouped = qtrue;
		ds = DrawSurfaceForMesh( e, scan, NULL );	/* ydnar */
		VectorCopy( bounds[ 0 ], ds->bounds[ 0 ] );
		VectorCopy( bounds[ 1 ], ds->bounds[ 1 ] );
	}
	
	/* emit some statistics */
	Sys_FPrintf( SYS_VRB, "%9d patches\n", patchCount );
	Sys_FPrintf( SYS_VRB, "%9d patch LOD groups\n", groupCount );
}
示例#3
0
/*
=====================
PatchMapDrawSurfs

Any patches that share an edge need to choose their
level of detail as a unit, otherwise the edges would
pull apart.
=====================
*/
void PatchMapDrawSurfs( entity_t *e ) {
	parseMesh_t			*pm;
	parseMesh_t			*check, *scan;
	mapDrawSurface_t	*ds;
	int					patchCount, groupCount;
	int					i, j, k, l, c1, c2;
	drawVert_t			*v1, *v2;
	vec3_t				bounds[2];
	byte				*bordering;
	parseMesh_t			*meshes[MAX_MAP_DRAW_SURFS];
	qboolean			grouped[MAX_MAP_DRAW_SURFS];
	byte				group[MAX_MAP_DRAW_SURFS];

	qprintf( "----- PatchMapDrawSurfs -----\n" );

	patchCount = 0;
	for ( pm = e->patches ; pm ; pm = pm->next  ) {
		meshes[patchCount] = pm;
		patchCount++;
	}

	if ( !patchCount ) {
		return;
	}
	bordering = malloc( patchCount * patchCount );
	memset( bordering, 0, patchCount * patchCount );

	// build the bordering matrix
	for ( k = 0 ; k < patchCount ; k++ ) {
		bordering[k*patchCount+k] = 1;

		for ( l = k+1 ; l < patchCount ; l++ ) {
			check = meshes[k];
			scan = meshes[l];
			c1 = scan->mesh.width * scan->mesh.height;
			v1 = scan->mesh.verts;

			for ( i = 0 ; i < c1 ; i++, v1++ ) {
				c2 = check->mesh.width * check->mesh.height;
				v2 = check->mesh.verts;
				for ( j = 0 ; j < c2 ; j++, v2++ ) {
					if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
						&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
						&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
						break;
					}
				}
				if ( j != c2 ) {
					break;
				}
			}
			if ( i != c1 ) {
				// we have a connection
				bordering[k*patchCount+l] =
				bordering[l*patchCount+k] = 1;
			} else {
				// no connection
				bordering[k*patchCount+l] =
				bordering[l*patchCount+k] = 0;
			}

		}
	}

	// build groups
	memset( grouped, 0, sizeof(grouped) );
	groupCount = 0;
	for ( i = 0 ; i < patchCount ; i++ ) {
		if ( !grouped[i] ) {
			groupCount++;
		}

		// recursively find all patches that belong in the same group
		memset( group, 0, patchCount );
		GrowGroup_r( i, patchCount, bordering, group );

		// bound them
		ClearBounds( bounds[0], bounds[1] );
		for ( j = 0 ; j < patchCount ; j++ ) {
			if ( group[j] ) {
				grouped[j] = qtrue;
				scan = meshes[j];
				c1 = scan->mesh.width * scan->mesh.height;
				v1 = scan->mesh.verts;
				for ( k = 0 ; k < c1 ; k++, v1++ ) {
					AddPointToBounds( v1->xyz, bounds[0], bounds[1] );
				}
			}
		}

		// create drawsurf
		scan = meshes[i];
		scan->grouped = qtrue;
		ds = DrawSurfaceForMesh( &scan->mesh );
		ds->shaderInfo = scan->shaderInfo;
		VectorCopy( bounds[0], ds->lightmapVecs[0] );
		VectorCopy( bounds[1], ds->lightmapVecs[1] );
	}

	qprintf( "%5i patches\n", patchCount );
	qprintf( "%5i patch LOD groups\n", groupCount );
}