📄 csg.cpp
字号:
}
/*
===============
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 + -