brush.cpp

来自「quake3工具源码。包括生成bsp文件」· C++ 代码 · 共 2,619 行 · 第 1/5 页

CPP
2,619
字号
			{
				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, ") ");
			}
			
			if (g_qeglobals.bSurfacePropertiesPlugin)
			{
				g_pMemFile = pMemFile;
#ifdef _DEBUG
				if (!fa->pData)
					Sys_Printf("ERROR: unexpected IPluginTexdef* is NULL in Brush_Write\n");
				else
#endif
				GETPLUGINTEXDEF(fa)->WriteTexdef( QERApp_MapPrintf_MEMFILE );
			}
			else
			{
				pname = fa->texdef.name;
				if (pname[0] == 0)
					pname = "unnamed";
				
				MemFile_fprintf (pMemFile, "%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])
					MemFile_fprintf (pMemFile, "%i ", (int)fa->texdef.scale[0]);
				else
					MemFile_fprintf (pMemFile, "%f ", (float)fa->texdef.scale[0]);
				if (fa->texdef.scale[1] == (int)fa->texdef.scale[1])
					MemFile_fprintf (pMemFile, "%i", (int)fa->texdef.scale[1]);
				else
					MemFile_fprintf (pMemFile, "%f", (float)fa->texdef.scale[1]);
				
				MemFile_fprintf (pMemFile, " %i %i %i", fa->texdef.contents, fa->texdef.flags, fa->texdef.value);
			}
			MemFile_fprintf (pMemFile, "\n");
		}
		MemFile_fprintf (pMemFile, "}\n");
	}
	
	
}


/*
=============
Brush_Create

Create non-textured blocks for entities
The brush is NOT linked to any list
=============
*/
brush_t	*Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef)
{
	int		i, j;
	vec3_t	pts[4][2];
	face_t	*f;
	brush_t	*b;

	// brush primitive mode : convert texdef to brushprimit_texdef ?
	// most of the time texdef is empty
	if (g_qeglobals.m_bBrushPrimitMode)
	{
		// check texdef is empty .. if there are cases it's not we need to write some conversion code
		if (texdef->shift[0]!=0 || texdef->shift[1]!=0 || texdef->scale[0]!=0 || texdef->scale[1]!=0 || texdef->rotate!=0)
			Sys_Printf("Warning : non-zero texdef detected in Brush_Create .. need brush primitive conversion\n");
	}

	for (i=0 ; i<3 ; i++)
	{
		if (maxs[i] < mins[i])
			Error ("Brush_InitSolid: backwards");
	}

	b = Brush_Alloc();
	
	pts[0][0][0] = mins[0];
	pts[0][0][1] = mins[1];
	
	pts[1][0][0] = mins[0];
	pts[1][0][1] = maxs[1];
	
	pts[2][0][0] = maxs[0];
	pts[2][0][1] = maxs[1];
	
	pts[3][0][0] = maxs[0];
	pts[3][0][1] = mins[1];
	
	for (i=0 ; i<4 ; i++)
	{
		pts[i][0][2] = mins[2];
		pts[i][1][0] = pts[i][0][0];
		pts[i][1][1] = pts[i][0][1];
		pts[i][1][2] = maxs[2];
	}

	for (i=0 ; i<4 ; i++)
	{
		f = Face_Alloc();
		f->texdef = *texdef;
		f->texdef.flags &= ~SURF_KEEP;
		f->texdef.contents &= ~CONTENTS_KEEP;
		f->next = b->brush_faces;
		b->brush_faces = f;
		j = (i+1)%4;

		VectorCopy (pts[j][1], f->planepts[0]);
		VectorCopy (pts[i][1], f->planepts[1]);
		VectorCopy (pts[i][0], f->planepts[2]);
	}
	
	f = Face_Alloc();
	f->texdef = *texdef;
	f->texdef.flags &= ~SURF_KEEP;
	f->texdef.contents &= ~CONTENTS_KEEP;
	f->next = b->brush_faces;
	b->brush_faces = f;

	VectorCopy (pts[0][1], f->planepts[0]);
	VectorCopy (pts[1][1], f->planepts[1]);
	VectorCopy (pts[2][1], f->planepts[2]);

	f = Face_Alloc();
	f->texdef = *texdef;
	f->texdef.flags &= ~SURF_KEEP;
	f->texdef.contents &= ~CONTENTS_KEEP;
	f->next = b->brush_faces;
	b->brush_faces = f;

	VectorCopy (pts[2][0], f->planepts[0]);
	VectorCopy (pts[1][0], f->planepts[1]);
	VectorCopy (pts[0][0], f->planepts[2]);

	return b;
}

/*
=============
Brush_CreatePyramid

Create non-textured pyramid for light entities
The brush is NOT linked to any list
=============
*/
brush_t	*Brush_CreatePyramid (vec3_t mins, vec3_t maxs, texdef_t *texdef)
{
	//++timo handle new brush primitive ? return here ??
	return Brush_Create(mins, maxs, texdef);

	for (int i=0 ; i<3 ; i++)
		if (maxs[i] < mins[i])
			Error ("Brush_InitSolid: backwards");

	brush_t* b = Brush_Alloc();

	vec3_t corners[4];

	float fMid = Q_rint(mins[2] + (Q_rint((maxs[2] - mins[2]) / 2)));

	corners[0][0] = mins[0];
	corners[0][1] = mins[1];
	corners[0][2] = fMid;

	corners[1][0] = mins[0];
	corners[1][1] = maxs[1];
	corners[1][2] = fMid;

	corners[2][0] = maxs[0];
	corners[2][1] = maxs[1];
	corners[2][2] = fMid;

	corners[3][0] = maxs[0];
	corners[3][1] = mins[1];
	corners[3][2] = fMid;

	vec3_t top, bottom;

	top[0] = Q_rint(mins[0] + ((maxs[0] - mins[0]) / 2));
	top[1] = Q_rint(mins[1] + ((maxs[1] - mins[1]) / 2));
	top[2] = Q_rint(maxs[2]);

	VectorCopy(top, bottom);
	bottom[2] = mins[2];

	// sides
	for (i = 0; i < 4; i++)
	{
		face_t* f = Face_Alloc();
		f->texdef = *texdef;
		f->texdef.flags &= ~SURF_KEEP;
		f->texdef.contents &= ~CONTENTS_KEEP;
		f->next = b->brush_faces;
		b->brush_faces = f;
		int j = (i+1)%4;

		VectorCopy (top, f->planepts[0]);
		VectorCopy (corners[i], f->planepts[1]);
		VectorCopy(corners[j], f->planepts[2]);

		f = Face_Alloc();
		f->texdef = *texdef;
		f->texdef.flags &= ~SURF_KEEP;
		f->texdef.contents &= ~CONTENTS_KEEP;
		f->next = b->brush_faces;
		b->brush_faces = f;

		VectorCopy (bottom, f->planepts[2]);
		VectorCopy (corners[i], f->planepts[1]);
		VectorCopy(corners[j], f->planepts[0]);
	}

	return b;
}




/*
=============
Brush_MakeSided

Makes the current brush have the given number of 2d sides
=============
*/
void Brush_MakeSided (int sides)
{
	int		i, axis;
	vec3_t	mins, maxs;
	brush_t	*b;
	texdef_t	*texdef;
	face_t	*f;
	vec3_t	mid;
	float	width;
	float	sv, cv;

	if (sides < 3)
	{
		Sys_Status ("Bad sides number", 0);
		return;
	}

	if (sides >= MAX_POINTS_ON_WINDING-4)
	{
		Sys_Printf("too many sides.\n");
		return;
	}

	if (!QE_SingleBrush ())
	{
		Sys_Status ("Must have a single brush selected", 0 );
		return;
	}

	b = selected_brushes.next;
	VectorCopy (b->mins, mins);
	VectorCopy (b->maxs, maxs);
	texdef = &g_qeglobals.d_texturewin.texdef;

	Brush_Free (b);

	if (g_pParentWnd->ActiveXY())
	{
		switch(g_pParentWnd->ActiveXY()->GetViewType())
		{
			case XY: axis = 2; break;
			case XZ: axis = 1; break;
			case YZ: axis = 0; break;
		}
	}
	else
	{
		axis = 2;
	}

	// find center of brush
	width = 8;
	for (i = 0; i < 3; i++)
	{
		mid[i] = (maxs[i] + mins[i]) * 0.5;
		if (i == axis) continue;
		if ((maxs[i] - mins[i]) * 0.5 > width)
			width = (maxs[i] - mins[i]) * 0.5;
	}

	b = Brush_Alloc();
		
	// create top face
	f = Face_Alloc();
	f->texdef = *texdef;
	f->next = b->brush_faces;
	b->brush_faces = f;

	f->planepts[2][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[2][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[2][axis] = maxs[axis];
	f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = maxs[axis];
	f->planepts[0][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[0][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[0][axis] = maxs[axis];

	// create bottom face
	f = Face_Alloc();
	f->texdef = *texdef;
	f->next = b->brush_faces;
	b->brush_faces = f;

	f->planepts[0][(axis+1)%3] = mins[(axis+1)%3]; f->planepts[0][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[0][axis] = mins[axis];
	f->planepts[1][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[1][(axis+2)%3] = mins[(axis+2)%3]; f->planepts[1][axis] = mins[axis];
	f->planepts[2][(axis+1)%3] = maxs[(axis+1)%3]; f->planepts[2][(axis+2)%3] = maxs[(axis+2)%3]; f->planepts[2][axis] = mins[axis];

	for (i=0 ; i<sides ; i++)
	{
		f = Face_Alloc();
		f->texdef = *texdef;
		f->next = b->brush_faces;
		b->brush_faces = f;

		sv = sin (i*3.14159265*2/sides);
		cv = cos (i*3.14159265*2/sides);

		f->planepts[0][(axis+1)%3] = floor(mid[(axis+1)%3]+width*cv+0.5);
		f->planepts[0][(axis+2)%3] = floor(mid[(axis+2)%3]+width*sv+0.5);
		f->planepts[0][axis] = mins[axis];

		f->planepts[1][(axis+1)%3] = f->planepts[0][(axis+1)%3];
		f->planepts[1][(axis+2)%3] = f->planepts[0][(axis+2)%3];
		f->planepts[1][axis] = maxs[axis];

		f->planepts[2][(axis+1)%3] = floor(f->planepts[0][(axis+1)%3] - width*sv + 0.5);
		f->planepts[2][(axis+2)%3] = floor(f->planepts[0][(axis+2)%3] + width*cv + 0.5);
		f->planepts[2][axis] = maxs[axis];
	}

	Brush_AddToList (b, &selected_brushes);

	Entity_LinkBrush (world_entity, b);

	Brush_Build( b );

	Sys_UpdateWindows (W_ALL);
}



/*
=============
Brush_Free

Frees the brush with all of its faces and display list.
Unlinks the brush from whichever chain it is in.
Decrements the owner entity's brushcount.
Removes owner entity if this was the last brush
unless owner is the world.
Removes from groups
=============
*/
void Brush_Free (brush_t *b, bool bRemoveNode)
{
	face_t	*f, *next;
	epair_t	*ep, *enext;

	// remove from group
	if (bRemoveNode)
		Group_RemoveBrush(b);

	// free the patch if it's there
	if (b->patchBrush)
	{
		Patch_Delete(b->pPatch);
	}

	// free faces
	for (f=b->brush_faces ; f ; f=next)
	{
		next = f->next;
		Face_Free( f );
	}

	//Timo : free brush epairs
	for (ep = b->epairs ; ep ; ep=enext )
	{
		enext = ep->next;
		free (ep->key);
		free (ep->value);
		free (ep);
	}

	// unlink from active/selected list
	if (b->next)
		Brush_RemoveFromList (b);

	// unlink from entity list
	if (b->onext)
		Entity_UnlinkBrush (b);

	free (b);
}

/*
=============
Face_MemorySize
=============
*/
int Face_MemorySize(face_t *f )
{
	int size = 0;

	if (f->face_winding)
	{
		size += _msize(f->face_winding);
	}
	//f->texdef.~texdef_t();;
	size += _msize(f);
	return size;
}

/*
=============
Brush_MemorySize
=============
*/
int Brush_MemorySize(brush_t *b)
{
	face_t	*f;
	epair_t	*ep;
	int size = 0;

	//
	if (b->patchBrush)
	{
		size += Patch_MemorySize(b->pPatch);
	}
	//
	for (f = b->brush_faces; f; f = f->next)
	{
		size += Face_MemorySize(f);
	}
	//
	for (ep = b->epairs; ep; ep = ep->next )
	{
		size += _msize(ep->key);
		size += _msize(ep->value);
		size += _msize(ep);
	}
	size += _msize(b);
	return size;
}


/*
============
Brush_Clone

Does NOT add the new brush to any lists
============
*/
brush_t *Brush_Clone (brush_t *b)
{
	brush_t	*n = NULL;
	face_t	*f, *nf;

	if (b->patchBrush)
	{
		patchMesh_t *p = Patch_Duplicate(b->pPatch);
		Brush_RemoveFromList(p->pSymbiot);
		Entity_UnlinkBrush(p->pSymbiot);
		n = p->pSymbiot;
	}
	else
	{
  	n = Brush_Alloc();
	  n->numberId = g_nBrushId++;
		n->owner = b->owner;
		for (f=b->brush_faces ; f ; f=f->next)
		{
			nf = Face_Clone( f );
			nf->next = n->brush_faces;
			n->brush_faces = nf;
		}
	}

	return n;
}



/*
============
Brush_Clone

Does NOT add the new brush to any lists
============
*/
brush_t *Brush_FullClone(brush_t *b)
{
	brush_t	*n = NULL;
	face_t *f, *nf, *f2, *nf2;
	int j;

	if (b->patchBrush)
	{
		patchMesh_t *p = Patch_Duplicate(b->pPatch);
		Brush_RemoveFromList(p->pSymbiot);
		Entity_UnlinkBrush(p->pSymbiot);
		n = p->pSymbiot;
		n->owner = b->owner;
		Brush_Build(n);
	}
	else
	{
  	n = Brush_Alloc();
   	n->numberId = g_nBrushId++;
		n->owner = b->owner;
		VectorCopy(b->mins, n->mins);
		VectorCopy(b->maxs, n->maxs);
		//
		for (f = b->brush_faces; f; f = f->next)
		{
			if (f->original) con

⌨️ 快捷键说明

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