⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 csg.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
}


/*
===============
AddBspBrushListToTail
===============
*/
bspbrush_t *AddBrushListToTail (bspbrush_t *list, bspbrush_t *tail)
{
	bspbrush_t	*walk, *next;

	for (walk=list ; walk ; walk=next)
	{	// add to end of list
		next = walk->next;
		walk->next = NULL;
		tail->next = walk;
		tail = walk;
	}

	return tail;
}

/*
===========
CullList

Builds a new list that doesn't hold the given brush
===========
*/
bspbrush_t *CullList (bspbrush_t *list, bspbrush_t *skip1)
{
	bspbrush_t	*newlist;
	bspbrush_t	*next;

	newlist = NULL;

	for ( ; list ; list = next)
	{
		next = list->next;
		if (list == skip1)
		{
			FreeBrush (list);
			continue;
		}
		list->next = newlist;
		newlist = list;
	}
	return newlist;
}


/*
==================
WriteBrushMap
==================
*/
void WriteBrushMap (char *name, bspbrush_t *list)
{
	FILE	*f;
	side_t	*s;
	int		i;
	winding_t	*w;

	Msg("writing %s\n", name);
	f = fopen (name, "w");
	if (!f)
		Error ("Can't write %s\b", name);

	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");

	for ( ; list ; list=list->next )
	{
		fprintf (f, "{\n");
		for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
		{
			w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);

			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);

			fprintf (f, "%s 0 0 0 1 1\n", TexDataStringTable_GetString( GetTexData( texinfo[s->texinfo].texdata )->nameStringTableID ) );
			FreeWinding (w);
		}
		fprintf (f, "}\n");
	}
	fprintf (f, "}\n");

	fclose (f);

}

// UNDONE: This isn't quite working yet
#if 0
void WriteBrushVMF(char *name, bspbrush_t *list)
{
	FILE	*f;
	side_t	*s;
	int		i;
	winding_t	*w;
	Vector	u, v;

	Msg("writing %s\n", name);
	f = fopen (name, "w");
	if (!f)
		Error ("Can't write %s\b", name);

	fprintf (f, "world\n{\n\"classname\" \"worldspawn\"\n");

	for ( ; list ; list=list->next )
	{
		fprintf (f, "\tsolid\n\t{\n");
		for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
		{
			fprintf( f, "\t\tside\n\t\t{\n" );
			fprintf( f, "\t\t\t\"plane\" \"" );
			w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);

			fprintf (f,"(%i %i %i) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
			fprintf (f,"(%i %i %i) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
			fprintf (f,"(%i %i %i)", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
			fprintf( f, "\"\n" );
			fprintf( f, "\t\t\t\"material\" \"%s\"\n", GetTexData( texinfo[s->texinfo].texdata )->name );
			// UNDONE: recreate correct texture axes
			BasisForPlane( mapplanes[s->planenum].normal, u, v );
			fprintf( f, "\t\t\t\"uaxis\" \"[%.3f %.3f %.3f 0] 1.0\"\n", u[0], u[1], u[2] );
			fprintf( f, "\t\t\t\"vaxis\" \"[%.3f %.3f %.3f 0] 1.0\"\n", v[0], v[1], v[2] );
			
			fprintf( f, "\t\t\t\"rotation\" \"0.0\"\n" );
			fprintf( f, "\t\t\t\"lightmapscale\" \"16.0\"\n" );

			FreeWinding (w);
			fprintf (f, "\t\t}\n");
		}
		fprintf (f, "\t}\n");
	}
	fprintf (f, "}\n");

	fclose (f);

}
#endif

void PrintBrushContents( int contents )
{
	if( contents & CONTENTS_SOLID )
	{
		printf( "CONTENTS_SOLID " );
	}
	if( contents & CONTENTS_WINDOW )
	{
		printf( "CONTENTS_WINDOW " );
	}
	if( contents & CONTENTS_AUX )
	{
		printf( "CONTENTS_AUX " );
	}
	if( contents & CONTENTS_GRATE )
	{
		printf( "CONTENTS_GRATE " );
	}
	if( contents & CONTENTS_SLIME )
	{
		printf( "CONTENTS_SLIME " );
	}
	if( contents & CONTENTS_WATER )
	{
		printf( "CONTENTS_WATER " );
	}
	if( contents & CONTENTS_MIST )
	{
		printf( "CONTENTS_MIST " );
	}
	if( contents & CONTENTS_OPAQUE )
	{
		printf( "CONTENTS_OPAQUE " );
	}
	if( contents & CONTENTS_AREAPORTAL )
	{
		printf( "CONTENTS_AREAPORTAL " );
	}
}

/*
==================
BrushGE

Returns true if b1 is allowed to bite b2
==================
*/
qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2)
{
	// Areaportals are allowed to bite water
	// NOTE: This brush combo should have been fixed up
	// in a first pass (FixupAreaportalWaterBrushes)
	if( (b2->original->contents & CONTENTS_WATER) && 
		(b1->original->contents & CONTENTS_AREAPORTAL) )
	{
		return true;
	}
	
	// detail brushes never bite structural brushes
	if ( (b1->original->contents & CONTENTS_DETAIL) 
		&& !(b2->original->contents & CONTENTS_DETAIL) )
		return false;
	if (b1->original->contents & CONTENTS_SOLID)
		return true;
	// Transparent brushes are not marked as detail anymore, so let them cut each other.
	if ( (b1->original->contents & TRANSPARENT_CONTENTS) && (b2->original->contents & TRANSPARENT_CONTENTS) )
		return true;

	return false;
}

/*
=================
ChopBrushes

Carves any intersecting solid brushes into the minimum number
of non-intersecting brushes. 
=================
*/
bspbrush_t *ChopBrushes (bspbrush_t *head)
{
	bspbrush_t	*b1, *b2, *next;
	bspbrush_t	*tail;
	bspbrush_t	*keep;
	bspbrush_t	*sub, *sub2;
	int			c1, c2;

	qprintf ("---- ChopBrushes ----\n");
	qprintf ("original brushes: %i\n", CountBrushList (head));

#if 0
	if (startbrush == 0)
		WriteBrushList ("before.gl", head, false);
#endif
	keep = NULL;

newlist:
	// find tail
	if (!head)
		return NULL;
	for (tail=head ; tail->next ; tail=tail->next)
	;

	for (b1=head ; b1 ; b1=next)
	{
		next = b1->next;
		for (b2=b1->next ; b2 ; b2 = b2->next)
		{
			if (BrushesDisjoint (b1, b2))
				continue;

			sub = NULL;
			sub2 = NULL;
			c1 = 999999;
			c2 = 999999;

			if ( BrushGE (b2, b1) )
			{
//				printf( "b2 bites b1\n" );
				sub = SubtractBrush (b1, b2);
				if (sub == b1)
					continue;		// didn't really intersect
				if (!sub)
				{	// b1 is swallowed by b2
					head = CullList (b1, b1);
					goto newlist;
				}
				c1 = CountBrushList (sub);
			}

			if ( BrushGE (b1, b2) )
			{
//				printf( "b1 bites b2\n" );
				sub2 = SubtractBrush (b2, b1);
				if (sub2 == b2)
					continue;		// didn't really intersect
				if (!sub2)
				{	// b2 is swallowed by b1
					FreeBrushList (sub);
					head = CullList (b1, b2);
					goto newlist;
				}
				c2 = CountBrushList (sub2);
			}

			if (!sub && !sub2)
				continue;		// neither one can bite

			// only accept if it didn't fragment
			// (commening this out allows full fragmentation)
			if (c1 > 1 && c2 > 1)
			{
				const int contents1 = b1->original->contents;
				const int contents2 = b2->original->contents;
				// if both detail, allow fragmentation
				if ( !((contents1&contents2) & CONTENTS_DETAIL) && !((contents1|contents2) & CONTENTS_AREAPORTAL) )
				{
					if (sub2)
						FreeBrushList (sub2);
					if (sub)
						FreeBrushList (sub);
					continue;
				}
			}

			if (c1 < c2)
			{
				if (sub2)
					FreeBrushList (sub2);
				tail = AddBrushListToTail (sub, tail);
				head = CullList (b1, b1);
				goto newlist;
			}
			else
			{
				if (sub)
					FreeBrushList (sub);
				tail = AddBrushListToTail (sub2, tail);
				head = CullList (b1, b2);
				goto newlist;
			}
		}

		if (!b2)
		{	// b1 is no longer intersecting anything, so keep it
			b1->next = keep;
			keep = b1;
		}
	}

	qprintf ("output brushes: %i\n", CountBrushList (keep));
#if 0
	if ( head->original->entitynum == 0 )
	{
		WriteBrushList ("after.gl", keep, false);
		WriteBrushMap ("after.map", keep);
	}
#endif
	return keep;
}


/*
=================
InitialBrushList
=================
*/
bspbrush_t *InitialBrushList (bspbrush_t *list)
{
	bspbrush_t *b;
	bspbrush_t	*out, *newb;
	int			i;

	// only return brushes that have visible faces
	out = NULL;
	for (b=list ; b ; b=b->next)
	{
#if 0
		for (i=0 ; i<b->numsides ; i++)
			if (b->sides[i].visible)
				break;
		if (i == b->numsides)
			continue;
#endif
		newb = CopyBrush (b);
		newb->next = out;
		out = newb;

		// clear visible, so it must be set by MarkVisibleFaces_r
		// to be used in the optimized list
		for (i=0 ; i<b->numsides ; i++)
		{
			newb->sides[i].original = &b->sides[i];
//			newb->sides[i].visible = true;
			b->sides[i].visible = false;
		}
	}

	return out;
}

/*
=================
OptimizedBrushList
=================
*/
bspbrush_t *OptimizedBrushList (bspbrush_t *list)
{
	bspbrush_t *b;
	bspbrush_t	*out, *newb;
	int			i;

	// only return brushes that have visible faces
	out = NULL;
	for (b=list ; b ; b=b->next)
	{
		for (i=0 ; i<b->numsides ; i++)
			if (b->sides[i].visible)
				break;
		if (i == b->numsides)
			continue;
		newb = CopyBrush (b);
		newb->next = out;
		out = newb;
	}

//	WriteBrushList ("vis.gl", out, true);

	return out;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -