brush.cpp
来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 2,619 行 · 第 1/5 页
CPP
2,619 行
=================
Brush_InsertVertexBetween
=================
*/
int Brush_InsertVertexBetween(brush_t *b, vec3_t p1, vec3_t p2)
{
face_t *face;
winding_t *w, *neww;
vec3_t point;
int i, insert;
if (Point_Equal(p1, p2, 0.4))
return false;
VectorAdd(p1, p2, point);
VectorScale(point, 0.5, point);
insert = false;
//the end point may not be the same as another vertex
for (face = b->brush_faces; face; face = face->next)
{
w = face->face_winding;
if (!w) continue;
neww = NULL;
for (i = 0; i < w->numpoints; i++)
{
if (!Point_Equal(w->points[i], p1, 0.1))
continue;
if (Point_Equal(w->points[(i+1) % w->numpoints], p2, 0.1))
{
neww = Winding_InsertPoint(w, point, (i+1) % w->numpoints);
break;
}
else if (Point_Equal(w->points[(i-1+w->numpoints) % w->numpoints], p2, 0.3))
{
neww = Winding_InsertPoint(w, point, i);
break;
}
}
if (neww)
{
Winding_Free(face->face_winding);
face->face_winding = neww;
insert = true;
}
}
return insert;
}
/*
=================
Brush_ResetFaceOriginals
=================
*/
void Brush_ResetFaceOriginals(brush_t *b)
{
face_t *face;
for (face = b->brush_faces; face; face = face->next)
{
face->original = NULL;
}
}
/*
=================
Brush_Parse
The brush is NOT linked to any list
=================
*/
//++timo FIXME: when using old brush primitives, the test loop for "Brush" and "patchDef2" "patchDef3" is ran
// before each face parsing. It works, but it's a performance hit
brush_t *Brush_Parse (void)
{
brush_t *b;
face_t *f;
int i,j;
g_qeglobals.d_parsed_brushes++;
b = Brush_Alloc();
do
{
if (!GetToken (true))
break;
if (!strcmp (token, "}") )
break;
// handle "Brush" primitive
if (strcmpi(token, "brushDef") == 0)
{
// Timo parsing new brush format
g_qeglobals.bPrimitBrushes=true;
// check the map is not mixing the two kinds of brushes
if (g_qeglobals.m_bBrushPrimitMode)
{
if (g_qeglobals.bOldBrushes)
Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
}
//++Timo write new brush primitive -> old conversion code for Q3->Q2 conversions ?
else
Sys_Printf("Warning : conversion code from brush primitive not done ( Brush_Parse )\n");
BrushPrimit_Parse(b);
if (b == NULL)
{
Warning ("parsing brush primitive");
return NULL;
}
else
{
continue;
}
}
if (strcmpi(token, "patchDef2") == 0 || strcmpi(token, "patchDef3") == 0)
{
free (b);
// double string compare but will go away soon
b = Patch_Parse(strcmpi(token, "patchDef2") == 0);
if (b == NULL)
{
Warning ("parsing patch/brush");
return NULL;
}
else
{
continue;
}
// handle inline patch
}
else
{
// Timo parsing old brush format
g_qeglobals.bOldBrushes=true;
if (g_qeglobals.m_bBrushPrimitMode)
{
// check the map is not mixing the two kinds of brushes
if (g_qeglobals.bPrimitBrushes)
Sys_Printf("Warning : old brushes and brush primitive in the same file are not allowed ( Brush_Parse )\n");
// set the "need" conversion flag
g_qeglobals.bNeedConvert=true;
}
f = Face_Alloc();
// add the brush to the end of the chain, so
// loading and saving a map doesn't reverse the order
f->next = NULL;
if (!b->brush_faces)
{
b->brush_faces = f;
}
else
{
face_t *scan;
for (scan=b->brush_faces ; scan->next ; scan=scan->next)
;
scan->next = f;
}
// read the three point plane definition
for (i=0 ; i<3 ; i++)
{
if (i != 0)
GetToken (true);
if (strcmp (token, "(") )
{
Warning ("parsing brush");
return NULL;
}
for (j=0 ; j<3 ; j++)
{
GetToken (false);
f->planepts[i][j] = atof(token);
}
GetToken (false);
if (strcmp (token, ")") )
{
Warning ("parsing brush");
return NULL;
}
}
}
// Timo
// if we have a surface plugin, we'll call the plugin parsing
if (g_qeglobals.bSurfacePropertiesPlugin)
{
GETPLUGINTEXDEF(f)->ParseTexdef();
}
else
{
// read the texturedef
GetToken (false);
f->texdef.SetName(token);
if (token[0] == '(')
{
int i = 32;
}
GetToken (false);
f->texdef.shift[0] = atoi(token);
GetToken (false);
f->texdef.shift[1] = atoi(token);
GetToken (false);
f->texdef.rotate = atoi(token);
GetToken (false);
f->texdef.scale[0] = atof(token);
GetToken (false);
f->texdef.scale[1] = atof(token);
// the flags and value field aren't necessarily present
f->d_texture = Texture_ForName( f->texdef.name );
f->texdef.flags = f->d_texture->flags;
f->texdef.value = f->d_texture->value;
f->texdef.contents = f->d_texture->contents;
if (TokenAvailable ())
{
GetToken (false);
f->texdef.contents = atoi(token);
GetToken (false);
f->texdef.flags = atoi(token);
GetToken (false);
f->texdef.value = atoi(token);
}
}
} while (1);
return b;
}
/*
=================
QERApp_MapPrintf_FILE
callback for surface properties plugin
must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
=================
*/
// carefully initialize !
FILE * g_File;
void WINAPI QERApp_MapPrintf_FILE( char *text, ... )
{
va_list argptr;
char buf[32768];
va_start (argptr,text);
vsprintf (buf, text,argptr);
va_end (argptr);
fprintf( g_File, buf );
}
/*
==============
Brush_SetEpair
sets an epair for the given brush
==============
*/
void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue)
{
if (g_qeglobals.m_bBrushPrimitMode)
{
if (b->patchBrush)
{
Patch_SetEpair(b->pPatch, pKey, pValue);
}
else
{
SetKeyValue(b->epairs, pKey, pValue);
}
}
else
{
Sys_Printf("Can only set key/values in Brush primitive mode\n");
}
}
/*
=================
Brush_GetKeyValue
=================
*/
const char* Brush_GetKeyValue(brush_t *b, const char *pKey)
{
if (g_qeglobals.m_bBrushPrimitMode)
{
if (b->patchBrush)
{
return Patch_GetKeyValue(b->pPatch, pKey);
}
else
{
return ValueForKey(b->epairs, pKey);
}
}
else
{
Sys_Printf("Can only set brush/patch key/values in Brush primitive mode\n");
}
return "";
}
/*
=================
Brush_Write
save all brushes as Brush primitive format
=================
*/
void Brush_Write (brush_t *b, FILE *f)
{
epair_t *ep;
face_t *fa;
char *pname;
int i;
if (b->patchBrush)
{
Patch_Write(b->pPatch, f);
return;
}
if (g_qeglobals.m_bBrushPrimitMode)
{
// save brush primitive format
fprintf (f, "{\nbrushDef\n{\n");
// brush epairs
if (b->epairs)
for (ep = b->epairs ; ep ; ep=ep->next)
fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
for (fa=b->brush_faces ; fa ; fa=fa->next)
{
// save planepts
for (i=0 ; i<3 ; i++)
{
fprintf(f, "( ");
for (int j = 0; j < 3; j++)
if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
else
fprintf(f, "%f ", fa->planepts[i][j]);
fprintf(f, ") ");
}
// save texture coordinates
fprintf(f,"( ( ");
for (i=0 ; i<3 ; i++)
if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
else
fprintf(f,"%f ",fa->brushprimit_texdef.coords[0][i]);
fprintf(f,") ( ");
for (i=0 ; i<3 ; i++)
if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
fprintf(f,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
else
fprintf(f,"%f ",fa->brushprimit_texdef.coords[1][i]);
fprintf(f,") ) ");
// save texture attribs
//++timo surface properties plugin not implemented for brush primitives
if (g_qeglobals.bSurfacePropertiesPlugin)
Sys_Printf("WARNING: surface properties plugin not supported with brush primitives (yet)\n");
char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
fprintf(f, "%s ", pName );
fprintf(f, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
}
fprintf (f, "}\n}\n");
}
else
{
fprintf (f, "{\n");
for (fa=b->brush_faces ; fa ; fa=fa->next)
{
for (i=0 ; i<3 ; i++)
{
fprintf(f, "( ");
for (int j = 0; j < 3; j++)
{
if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
fprintf(f, "%i ", static_cast<int>(fa->planepts[i][j]));
else
fprintf(f, "%f ", fa->planepts[i][j]);
}
fprintf(f, ") ");
}
if (g_qeglobals.bSurfacePropertiesPlugin)
{
g_File = f;
#ifdef _DEBUG
if (!fa->pData)
Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
else
#endif
GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_FILE );
}
else
{
pname = fa->texdef.name;
if (pname[0] == 0)
pname = "unnamed";
fprintf (f, "%s %i %i %i ", pname,
(int)fa->texdef.shift[0], (int)fa->texdef.shift[1],
(int)fa->texdef.rotate);
if (fa->texdef.scale[0] == (int)fa->texdef.scale[0])
fprintf (f, "%i ", (int)fa->texdef.scale[0]);
else
fprintf (f, "%f ", (float)fa->texdef.scale[0]);
if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
fprintf (f, "%i", (int)fa->texdef.scale[1]);
else
fprintf (f, "%f", (float)fa->texdef.scale[1]);
fprintf (f, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
}
fprintf (f, "\n");
}
fprintf (f, "}\n");
}
}
/*
=================
QERApp_MapPrintf_MEMFILE
callback for surface properties plugin
must fit a PFN_QERAPP_MAPPRINTF ( see isurfaceplugin.h )
=================
*/
// carefully initialize !
CMemFile * g_pMemFile;
void WINAPI QERApp_MapPrintf_MEMFILE( char *text, ... )
{
va_list argptr;
char buf[32768];
va_start (argptr,text);
vsprintf (buf, text,argptr);
va_end (argptr);
MemFile_fprintf( g_pMemFile, buf );
}
/*
=================
Brush_Write to a CMemFile*
save all brushes as Brush primitive format
=================
*/
void Brush_Write (brush_t *b, CMemFile *pMemFile)
{
epair_t *ep;
face_t *fa;
char *pname;
int i;
if (b->patchBrush)
{
Patch_Write(b->pPatch, pMemFile);
return;
}
//++timo NOTE: it's not very difficult to add since the surface properties plugin
// writes throught a printf-style function prototype
if (g_qeglobals.bSurfacePropertiesPlugin)
{
Sys_Printf("WARNING: Brush_Write to a CMemFile and Surface Properties plugin not done\n");
}
if (g_qeglobals.m_bBrushPrimitMode)
{
// brush primitive format
MemFile_fprintf (pMemFile, "{\nBrushDef\n{\n");
// brush epairs
if (b->epairs)
for( ep = b->epairs ; ep ; ep=ep->next )
MemFile_fprintf (pMemFile, "\"%s\" \"%s\"\n", ep->key, ep->value );
for (fa=b->brush_faces ; fa ; fa=fa->next)
{
// save planepts
for (i=0 ; i<3 ; i++)
{
MemFile_fprintf(pMemFile, "( ");
for (int j = 0; j < 3; j++)
if (fa->planepts[i][j] == static_cast<int>(fa->planepts[i][j]))
MemFile_fprintf(pMemFile, "%i ", static_cast<int>(fa->planepts[i][j]));
else
MemFile_fprintf(pMemFile, "%f ", fa->planepts[i][j]);
MemFile_fprintf(pMemFile, ") ");
}
// save texture coordinates
MemFile_fprintf(pMemFile,"( ( ");
for (i=0 ; i<3 ; i++)
if (fa->brushprimit_texdef.coords[0][i] == static_cast<int>(fa->brushprimit_texdef.coords[0][i]))
MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[0][i]));
else
MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[0][i]);
MemFile_fprintf(pMemFile,") ( ");
for (i=0 ; i<3 ; i++)
if (fa->brushprimit_texdef.coords[1][i] == static_cast<int>(fa->brushprimit_texdef.coords[1][i]))
MemFile_fprintf(pMemFile,"%i ",static_cast<int>(fa->brushprimit_texdef.coords[1][i]));
else
MemFile_fprintf(pMemFile,"%f ",fa->brushprimit_texdef.coords[1][i]);
MemFile_fprintf(pMemFile,") ) ");
// save texture attribs
char *pName = strlen(fa->texdef.name) > 0 ? fa->texdef.name : "unnamed";
MemFile_fprintf(pMemFile, "%s ", pName);
MemFile_fprintf(pMemFile, "%i %i %i\n", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
}
MemFile_fprintf (pMemFile, "}\n}\n");
}
else
{
// old brushes format
// also handle surface properties plugin
MemFile_fprintf (pMemFile, "{\n");
for (fa=b->brush_faces ; fa ; fa=fa->next)
{
for (i=0 ; i<3 ; i++)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?