brush.cpp

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

CPP
2,619
字号
	//get texture crap right
	for (i = 0; i < nummovefaces; i++)
	{
		Face_SetColor(b, movefaces[i], 1.0);
		for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
			EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
	}

	//now try to merge faces with their original faces
	lastface = NULL;
	for (face = b->brush_faces; face; face = nextface)
	{
		nextface = face->next;
		if (!face->original)
		{
			lastface = face;
			continue;
		}
		if (!Plane_Equal(&face->plane, &face->original->plane, false))
		{
			lastface = face;
			continue;
		}
		w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
		if (!w)
		{
			lastface = face;
			continue;
		}
		Winding_Free(face->original->face_winding);
		face->original->face_winding = w;
		//get texture crap right
		Face_SetColor(b, face->original, 1.0);
		for (j = 0; j < face->original->face_winding->numpoints; j++)
			EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
		//remove the face that was merged with the original
		if (lastface) lastface->next = face->next;
		else b->brush_faces = face->next;
		Face_Free(face);
	}
	return result;
}

/*
=================
Brush_MoveVertexes_old2

- The input brush must be convex
- The input brush must have face windings.
- The output brush will be convex.
- Returns true if the vertex movement is performed.
=================
*/

#define MAX_MOVE_FACES		64
#define INTERSECT_EPSILON	0.1
#define POINT_EPSILON		0.3

int Brush_MoveVertex_old2(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
{
	face_t *f, *face, *newface, *lastface, *nextface;
	face_t *movefaces[MAX_MOVE_FACES];
	int movefacepoints[MAX_MOVE_FACES];
	winding_t *w, tmpw;
	int i, j, k, nummovefaces, result;
	float dot;

	result = true;
	//
	tmpw.numpoints = 3;
	tmpw.maxpoints = 3;
	VectorAdd(vertex, delta, end);
	//snap or not?
	if (bSnap)
		for (i = 0; i < 3; i++)
			end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
	//chop off triangles from all brush faces that use the to be moved vertex
	//store pointers to these chopped off triangles in movefaces[]
	nummovefaces = 0;
	for (face = b->brush_faces; face; face = face->next)
	{
		w = face->face_winding;
		if (!w) continue;
		for (i = 0; i < w->numpoints; i++)
		{
			if (Point_Equal(w->points[i], vertex, POINT_EPSILON))
			{
				if (face->face_winding->numpoints <= 3)
				{
					movefacepoints[nummovefaces] = i;
					movefaces[nummovefaces++] = face;
					break;
				}
				dot = DotProduct(end, face->plane.normal) - face->plane.dist;
				//if the end point is in front of the face plane
				if (dot > 0.1)
				{
					//fanout triangle subdivision
					for (k = i; k < i + w->numpoints-3; k++)
					{
						VectorCopy(w->points[i], tmpw.points[0]);
						VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
						VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
						//
						newface = Face_Clone(face);
						//get the original
						for (f = face; f->original; f = f->original) ;
						newface->original = f;
						//store the new winding
						if (newface->face_winding) Winding_Free(newface->face_winding);
						newface->face_winding = Winding_Clone(&tmpw);
						//get the texture
						newface->d_texture = Texture_ForName( newface->texdef.name );
						//add the face to the brush
						newface->next = b->brush_faces;
						b->brush_faces = newface;
						//add this new triangle to the move faces
						movefacepoints[nummovefaces] = 0;
						movefaces[nummovefaces++] = newface;
					}
					//give the original face a new winding
					VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
					VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
					VectorCopy(w->points[i], tmpw.points[2]);
					Winding_Free(face->face_winding);
					face->face_winding = Winding_Clone(&tmpw);
					//add the original face to the move faces
					movefacepoints[nummovefaces] = 2;
					movefaces[nummovefaces++] = face;
				}
				else
				{
					//chop a triangle off the face
					VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
					VectorCopy(w->points[i], tmpw.points[1]);
					VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
					//remove the point from the face winding
					Winding_RemovePoint(w, i);
					//get texture crap right
					Face_SetColor(b, face, 1.0);
					for (j = 0; j < w->numpoints; j++)
						EmitTextureCoordinates(w->points[j], face->d_texture, face);
					//make a triangle face
					newface = Face_Clone(face);
					//get the original
					for (f = face; f->original; f = f->original) ;
					newface->original = f;
					//store the new winding
					if (newface->face_winding) Winding_Free(newface->face_winding);
					newface->face_winding = Winding_Clone(&tmpw);
					//get the texture
					newface->d_texture = Texture_ForName( newface->texdef.name );
					//add the face to the brush
					newface->next = b->brush_faces;
					b->brush_faces = newface;
					//
					movefacepoints[nummovefaces] = 1;
					movefaces[nummovefaces++] = newface;
				}
				break;
			}
		}
	}
	//now movefaces contains pointers to triangle faces that
	//contain the to be moved vertex

	//move the vertex
	for (i = 0; i < nummovefaces; i++)
	{
		//move vertex to end position
		VectorCopy(end, movefaces[i]->face_winding->points[movefacepoints[i]]);
		//create new face plane
		for (j = 0; j < 3; j++)
		{
			VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
		}
		Face_MakePlane(movefaces[i]);
	}
	//if the brush is no longer convex
	if (!Brush_Convex(b))
	{
		for (i = 0; i < nummovefaces; i++)
		{
			//move the vertex back to the initial position
			VectorCopy(vertex, movefaces[i]->face_winding->points[movefacepoints[i]]);
			//create new face plane
			for (j = 0; j < 3; j++)
			{
				VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
			}
			Face_MakePlane(movefaces[i]);
		}
		result = false;
	}
	//get texture crap right
	for (i = 0; i < nummovefaces; i++)
	{
		Face_SetColor(b, movefaces[i], 1.0);
		for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
			EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
	}

	//now try to merge faces with their original faces
	lastface = NULL;
	for (face = b->brush_faces; face; face = nextface)
	{
		nextface = face->next;
		if (!face->original)
		{
			lastface = face;
			continue;
		}
		if (!Plane_Equal(&face->plane, &face->original->plane, false))
		{
			lastface = face;
			continue;
		}
		w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
		if (!w)
		{
			lastface = face;
			continue;
		}
		Winding_Free(face->original->face_winding);
		face->original->face_winding = w;
		//get texture crap right
		Face_SetColor(b, face->original, 1.0);
		for (j = 0; j < face->original->face_winding->numpoints; j++)
			EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
		//remove the face that was merged with the original
		if (lastface) lastface->next = face->next;
		else b->brush_faces = face->next;
		Face_Free(face);
	}
	return result;
}

/*
=================
Brush_MoveVertexes

- The input brush must be convex
- The input brush must have face windings.
- The output brush will be convex.
- Returns true if the WHOLE vertex movement is performed.
=================
*/

#define MAX_MOVE_FACES		64

int Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap)
{
	face_t *f, *face, *newface, *lastface, *nextface;
	face_t *movefaces[MAX_MOVE_FACES];
	int movefacepoints[MAX_MOVE_FACES];
	winding_t *w, tmpw;
	vec3_t start, mid;
	plane_t plane;
	int i, j, k, nummovefaces, result, done;
	float dot, front, back, frac, smallestfrac;

	result = true;
	//
	tmpw.numpoints = 3;
	tmpw.maxpoints = 3;
	VectorCopy(vertex, start);
	VectorAdd(vertex, delta, end);
	//snap or not?
	if (bSnap)
		for (i = 0; i < 3; i++)
			end[i] = floor(end[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
	//
	VectorCopy(end, mid);
	//if the start and end are the same
	if (Point_Equal(start, end, 0.3)) return 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;
		for (i = 0; i < w->numpoints; i++)
		{
			if (Point_Equal(w->points[i], end, 0.3))
			{
				VectorCopy(vertex, end);
				return false;
			}
		}
	}
	//
	done = false;
	while(!done)
	{
		//chop off triangles from all brush faces that use the to be moved vertex
		//store pointers to these chopped off triangles in movefaces[]
		nummovefaces = 0;
		for (face = b->brush_faces; face; face = face->next)
		{
			w = face->face_winding;
			if (!w) continue;
			for (i = 0; i < w->numpoints; i++)
			{
				if (Point_Equal(w->points[i], start, 0.2))
				{
					if (face->face_winding->numpoints <= 3)
					{
						movefacepoints[nummovefaces] = i;
						movefaces[nummovefaces++] = face;
						break;
					}
					dot = DotProduct(end, face->plane.normal) - face->plane.dist;
					//if the end point is in front of the face plane
					if (dot > 0.1)
					{
						//fanout triangle subdivision
						for (k = i; k < i + w->numpoints-3; k++)
						{
							VectorCopy(w->points[i], tmpw.points[0]);
							VectorCopy(w->points[(k+1) % w->numpoints], tmpw.points[1]);
							VectorCopy(w->points[(k+2) % w->numpoints], tmpw.points[2]);
							//
							newface = Face_Clone(face);
							//get the original
							for (f = face; f->original; f = f->original) ;
							newface->original = f;
							//store the new winding
							if (newface->face_winding) Winding_Free(newface->face_winding);
							newface->face_winding = Winding_Clone(&tmpw);
							//get the texture
							newface->d_texture = Texture_ForName( newface->texdef.name );
							//add the face to the brush
							newface->next = b->brush_faces;
							b->brush_faces = newface;
							//add this new triangle to the move faces
							movefacepoints[nummovefaces] = 0;
							movefaces[nummovefaces++] = newface;
						}
						//give the original face a new winding
						VectorCopy(w->points[(i-2+w->numpoints) % w->numpoints], tmpw.points[0]);
						VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[1]);
						VectorCopy(w->points[i], tmpw.points[2]);
						Winding_Free(face->face_winding);
						face->face_winding = Winding_Clone(&tmpw);
						//add the original face to the move faces
						movefacepoints[nummovefaces] = 2;
						movefaces[nummovefaces++] = face;
					}
					else
					{
						//chop a triangle off the face
						VectorCopy(w->points[(i-1+w->numpoints) % w->numpoints], tmpw.points[0]);
						VectorCopy(w->points[i], tmpw.points[1]);
						VectorCopy(w->points[(i+1) % w->numpoints], tmpw.points[2]);
						//remove the point from the face winding
						Winding_RemovePoint(w, i);
						//get texture crap right
						Face_SetColor(b, face, 1.0);
						for (j = 0; j < w->numpoints; j++)
							EmitTextureCoordinates(w->points[j], face->d_texture, face);
						//make a triangle face
						newface = Face_Clone(face);
						//get the original
						for (f = face; f->original; f = f->original) ;
						newface->original = f;
						//store the new winding
						if (newface->face_winding) Winding_Free(newface->face_winding);
						newface->face_winding = Winding_Clone(&tmpw);
						//get the texture
						newface->d_texture = Texture_ForName( newface->texdef.name );
						//add the face to the brush
						newface->next = b->brush_faces;
						b->brush_faces = newface;
						//
						movefacepoints[nummovefaces] = 1;
						movefaces[nummovefaces++] = newface;
					}
					break;
				}
			}
		}
		//now movefaces contains pointers to triangle faces that
		//contain the to be moved vertex
		//
		done = true;
		VectorCopy(end, mid);
		smallestfrac = 1;
		for (face = b->brush_faces; face; face = face->next)
		{
			//check if there is a move face that has this face as the original
			for (i = 0; i < nummovefaces; i++)
			{
				if (movefaces[i]->original == face) break;
			}
			if (i >= nummovefaces) continue;
			//check if the original is not a move face itself
			for (j = 0; j < nummovefaces; j++)
			{
				if (face == movefaces[j]) break;
			}
			//if the original is not a move face itself
			if (j >= nummovefaces)
			{
				memcpy(&plane, &movefaces[i]->original->plane, sizeof(plane_t));
			}
			else
			{
				k = movefacepoints[j];
				w = movefaces[j]->face_winding;
				VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[0]);
				VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[1]);
				//
				k = movefacepoints[i];
				w = movefaces[i]->face_winding;
				VectorCopy(w->points[(k+1)%w->numpoints], tmpw.points[2]);
				if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
				{
					VectorCopy(w->points[(k+2)%w->numpoints], tmpw.points[2]);
					if (!Plane_FromPoints(tmpw.points[0], tmpw.points[1], tmpw.points[2], &plane))
						//this should never happen otherwise the face merge did a crappy job a previous pass
						continue;
				}
			}
			//now we've got the plane to check agains
			front = DotProduct(start, plane.normal) - plane.dist;
			back = DotProduct(end, plane.normal) - plane.dist;
			//if the whole move is at one side of the plane
			if (front < 0.01 && back < 0.01) continue;
			if (front > -0.01 && back > -0.01) continue;
			//if there's no movement orthogonal to this plane at all
			if (fabs(front-back) < 0.001) continue;
			//ok first only move till the plane is hit
			frac = front/(front-back);
			if (frac < smallestfrac)
			{
				mid[0] = start[0] + (end[0] - start[0]) * frac;
				mid[1] = start[1] + (end[1] - start[1]) * frac;
				mid[2] = start[2] + (end[2] - start[2]) * frac;
				smallestfrac = frac;
			}
			//
			done = false;
		}

		//move the vertex
		for (i = 0; i < nummovefaces; i++)
		{
			//move vertex to end position
			VectorCopy(mid, movefaces[i]->face_winding->points[movefacepoints[i]]);
			//create new face plane
			for (j = 0; j < 3; j++)
			{
				VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
			}
			Face_MakePlane(movefaces[i]);
			if (VectorLength(movefaces[i]->plane.normal) < 0.1)
				result = false;
		}
		//if the brush is no longer convex
		if (!result || !Brush_Convex(b))
		{
			for (i = 0; i < nummovefaces; i++)
			{
				//move the vertex back to the initial position
				VectorCopy(start, movefaces[i]->face_winding->points[movefacepoints[i]]);
				//create new face plane
				for (j = 0; j < 3; j++)
				{
					VectorCopy(movefaces[i]->face_winding->points[j], movefaces[i]->planepts[j]);
				}
				Face_MakePlane(movefaces[i]);
			}
			result = false;
			VectorCopy(start, end);
			done = true;
		}
		else
		{
			VectorCopy(mid, start);
		}
		//get texture crap right
		for (i = 0; i < nummovefaces; i++)
		{
			Face_SetColor(b, movefaces[i], 1.0);
			for (j = 0; j < movefaces[i]->face_winding->numpoints; j++)
				EmitTextureCoordinates(movefaces[i]->face_winding->points[j], movefaces[i]->d_texture, movefaces[i]);
		}

		//now try to merge faces with their original faces
		lastface = NULL;
		for (face = b->brush_faces; face; face = nextface)
		{
			nextface = face->next;
			if (!face->original)
			{
				lastface = face;
				continue;
			}
			if (!Plane_Equal(&face->plane, &face->original->plane, false))
			{
				lastface = face;
				continue;
			}
			w = Winding_TryMerge(face->face_winding, face->original->face_winding, face->plane.normal, true);
			if (!w)
			{
				lastface = face;
				continue;
			}
			Winding_Free(face->original->face_winding);
			face->original->face_winding = w;
			//get texture crap right
			Face_SetColor(b, face->original, 1.0);
			for (j = 0; j < face->original->face_winding->numpoints; j++)
				EmitTextureCoordinates(face->original->face_winding->points[j], face->original->d_texture, face->original);
			//remove the face that was merged with the original
			if (lastface) lastface->next = face->next;
			else b->brush_faces = face->next;
			Face_Free(face);
		}
	}
	return result;
}

/*

⌨️ 快捷键说明

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