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 + -
显示快捷键?