Esempio n. 1
0
/*
===========
AddRegionBrushes

a regioned map will have temp walls put up at the region boundary
===========
*/
void AddRegionBrushes (void)
{
	vec3_t	mins, maxs;
	int		i;
	texdef_t	td;

	if (!region_active)
		return;

	memset (&td, 0, sizeof(td));
	//strcpy (td.name, "REGION");
	td.SetName("REGION");

	mins[0] = region_mins[0] - 16;
	maxs[0] = region_mins[0] + 1;
	mins[1] = region_mins[1] - 16;
	maxs[1] = region_maxs[1] + 16;
	mins[2] = MIN_WORLD_COORD;
	maxs[2] = MAX_WORLD_COORD;
	region_sides[0] = Brush_Create (mins, maxs, &td);

	mins[0] = region_maxs[0] - 1;
	maxs[0] = region_maxs[0] + 16;
	region_sides[1] = Brush_Create (mins, maxs, &td);

	mins[0] = region_mins[0] - 16;
	maxs[0] = region_maxs[0] + 16;
	mins[1] = region_mins[1] - 16;
	maxs[1] = region_mins[1] + 1;
	region_sides[2] = Brush_Create (mins, maxs, &td);

	mins[1] = region_maxs[1] - 1;
	maxs[1] = region_maxs[1] + 16;
	region_sides[3] = Brush_Create (mins, maxs, &td);

	for (i=0 ; i<4 ; i++)
	{
		Brush_AddToList (region_sides[i], &selected_brushes);
		Entity_LinkBrush (world_entity, region_sides[i]);
		Brush_Build( region_sides[i] );
	}
}
// creates a dummy brush in the active brushes list
// FIXME : is this one really USED ?
void WINAPI QERApp_CreateBrush(vec3_t vMin, vec3_t vMax)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
	
	brush_t* pBrush = Brush_Create(vMin, vMax, &g_qeglobals.d_texturewin.texdef);
	Entity_LinkBrush (world_entity, pBrush);
	Brush_Build(pBrush);
	Brush_AddToList (pBrush, &active_brushes);
	Select_Brush(pBrush);
	Sys_UpdateWindows(W_ALL);
}
Esempio n. 3
0
/*
 =======================================================================================================================
    AddRegionBrushes a regioned map will have temp walls put up at the region boundary
 =======================================================================================================================
 */
void AddRegionBrushes(void)
{
	idVec3		mins, maxs;
	int			i;
	texdef_t	td;

	if (!region_active) {
		return;
	}

	memset(&td, 0, sizeof(td));
	td = g_qeglobals.d_texturewin.texdef;

	// strcpy (td.name, "REGION");
	td.SetName("textures/REGION");

	const int REGION_WIDTH = 1024;


	mins[0] = region_mins[0] - REGION_WIDTH;
	maxs[0] = region_mins[0] + 1;
	mins[1] = region_mins[1] - REGION_WIDTH;
	maxs[1] = region_maxs[1] + REGION_WIDTH;
	mins[2] = MIN_WORLD_COORD;
	maxs[2] = MAX_WORLD_COORD;
	region_sides[0] = Brush_Create(mins, maxs, &td);


	mins[0] = region_maxs[0] - 1;
	maxs[0] = region_maxs[0] + REGION_WIDTH;
	region_sides[1] = Brush_Create(mins, maxs, &td);

	mins[0] = region_mins[0] - REGION_WIDTH;
	maxs[0] = region_maxs[0] + REGION_WIDTH;
	mins[1] = region_mins[1] - REGION_WIDTH;
	maxs[1] = region_mins[1] + 1;
	region_sides[2] = Brush_Create(mins, maxs, &td);

	mins[1] = region_maxs[1] - 1;
	maxs[1] = region_maxs[1] + REGION_WIDTH;
	region_sides[3] = Brush_Create(mins, maxs, &td);

	mins = region_mins;
	maxs = region_maxs;
	maxs[2] = mins[2] + REGION_WIDTH;
	region_sides[4] = Brush_Create(mins, maxs, &td);

	mins = region_mins;
	maxs = region_maxs;
	mins[2] = maxs[2] - REGION_WIDTH;
	region_sides[5] = Brush_Create(mins, maxs, &td);

	for (i = 0; i < 6; i++) {
		Brush_AddToList(region_sides[i], &selected_brushes);
		Entity_LinkBrush(world_entity, region_sides[i]);
		Brush_Build(region_sides[i]);
	}
}
Esempio n. 4
0
/*
==============
NewBrushDrag
==============
*/
void NewBrushDrag (int x, int y)
{
	vec3_t	mins, maxs, junk;
	int		i;
	float	temp;
	brush_t	*n;

	if (!DragDelta (x,y, junk))
		return;
	// delete the current selection
	if (selected_brushes.next != &selected_brushes)
		Brush_Free (selected_brushes.next);
	XY_ToGridPoint (pressx, pressy, mins);
	mins[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_bottom_z/g_qeglobals.d_gridsize));
	XY_ToGridPoint (x, y, maxs);
	maxs[2] = g_qeglobals.d_gridsize * ((int)(g_qeglobals.d_new_brush_top_z/g_qeglobals.d_gridsize));
	if (maxs[2] <= mins[2])
		maxs[2] = mins[2] + g_qeglobals.d_gridsize;

	for (i=0 ; i<3 ; i++)
	{
		if (mins[i] == maxs[i])
			return;	// don't create a degenerate brush
		if (mins[i] > maxs[i])
		{
			temp = mins[i];
			mins[i] = maxs[i];
			maxs[i] = temp;
		}
	}

	n = Brush_Create (mins, maxs, &g_qeglobals.d_texturewin.texdef);
	if (!n)
		return;

	Brush_AddToList (n, &selected_brushes);

	Entity_LinkBrush (world_entity, n);

	Brush_Build( n );

//	Sys_UpdateWindows (W_ALL);
	Sys_UpdateWindows (W_XY| W_CAMERA);
}
Esempio n. 5
0
brush_t *AddBrushForTerrain( terrainMesh_t *pm, bool bLinkToWorld ) {
	int		j;
	vec3_t	vMin;
	vec3_t	vMax;
	brush_t	*b;
	face_t	*f;

	// calculate the face normals
	Terrain_CalcNormals( pm );
   
	// find the farthest points in x,y,z
	Terrain_CalcBounds( pm, vMin, vMax );

	for( j = 0; j < 3; j++ ) {
		if ( vMin[ j ] == vMax[ j ] ) {
			vMin[ j ] -= 4;
			vMax[ j ] += 4;
		}
	}

	b = Brush_Create( vMin, vMax, &pm->heightmap->tri.texdef );

	for( f = b->brush_faces; f != NULL; f = f->next ) {
		// copy the texdef to the brush faces texdef
		f->texdef = pm->heightmap->tri.texdef;
	}

	// FIXME: this entire type of linkage needs to be fixed
	b->pTerrain		= pm;
	b->terrainBrush = true;
	pm->pSymbiot    = b;
	pm->bSelected   = false;
	pm->bDirty      = true;
	pm->nListID		= -1;

	if ( bLinkToWorld ) {
		Brush_AddToList( b, &active_brushes );
		Entity_LinkBrush( world_entity, b );
		Brush_Build( b, true );
	}
  
	return b;
}
Brush *BrushTemplate_CreateCylinder (const BrushTemplate_Cylinder *pTemplate)
{
	double		CurrentXDiameter, CurrentZDiameter;
	double		DeltaXDiameter, DeltaZDiameter;
	double		CurrentXOffset, CurrentZOffset;
	double		DeltaXOffset, DeltaZOffset, sqrcheck;
	double		EllipseZ;
	int			NumVerticalBands, HBand, VBand;
	int			VertexCount=0;
	geVec3d		*Verts, *TopPoints;
	geVec3d		Current, Final, Delta;
	geXForm3d	YRotation;
	FaceList	*fl;
	Face		*f;
	Brush		*b;

	NumVerticalBands	= (int)(pTemplate->VerticalStripes);

	if (NumVerticalBands < 3)
	{
		return	NULL;
	}


	Verts		=(geVec3d *)geRam_Allocate(sizeof(geVec3d)*NumVerticalBands * 2);
	TopPoints	=(geVec3d *)geRam_Allocate(sizeof(geVec3d)*NumVerticalBands);
	fl			=FaceList_Create(NumVerticalBands + 2);

	if(!Verts || !TopPoints ||!fl)
	{
		return	NULL;
	}

	geXForm3d_SetIdentity(&YRotation);
	geXForm3d_SetYRotation(&YRotation, (M_PI * 2.0f)/(geFloat)NumVerticalBands);

	// Start with the top of cylinder
	CurrentXDiameter	=pTemplate->TopXSize;
	CurrentZDiameter	=pTemplate->TopZSize;
	DeltaXDiameter		=(pTemplate->BotXSize - pTemplate->TopXSize);
	DeltaZDiameter		=(pTemplate->BotZSize - pTemplate->TopZSize);
	
	// Get the offset amounts
	CurrentXOffset	=pTemplate->TopXOffset;
	CurrentZOffset	=pTemplate->TopZOffset;
	DeltaXOffset	=(pTemplate->BotXOffset - pTemplate->TopXOffset);
	DeltaZOffset	=(pTemplate->BotZOffset - pTemplate->TopZOffset);

	// Get the band positions and deltas
	geVec3d_Set(&Current, (float)(pTemplate->TopXSize / 2), (float)(pTemplate->YSize / 2), 0.0);
	geVec3d_Set(&Delta, (float)((pTemplate->BotXSize / 2) - Current.X), (float)(-(pTemplate->YSize/2) - Current.Y), 0.0);

	for(HBand = 0;HBand <= 1;HBand++)
	{
		Final = Current;
		for(VBand = 0;VBand < NumVerticalBands;VBand++)
		{
			// Get the elliptical Z value
			// (x^2/a^2) + (z^2/b^2) = 1
			// z = sqrt(b^2(1 - x^2/a^2))
			sqrcheck=( ((CurrentZDiameter/2)*(CurrentZDiameter/2))
				* (1.0 - (Final.X*Final.X)
				/ ( (CurrentXDiameter/2)*(CurrentXDiameter/2) )) );
			if(sqrcheck <0.0)
				sqrcheck=0.0;
			EllipseZ = sqrt(sqrcheck);

			// Check if we need to negate this thing
			if(VBand > (NumVerticalBands/2))
				EllipseZ = -EllipseZ;

			geVec3d_Set
			(
				&Verts[VertexCount],
				(float)(Final.X + CurrentXOffset),
				Final.Y,
				(float)(EllipseZ + CurrentZOffset)
			);
			VertexCount++;

			// Rotate the point around the Y to get the next vertical band
			geXForm3d_Rotate(&YRotation, &Final, &Final);
		}
		CurrentXDiameter	+=DeltaXDiameter;
		CurrentZDiameter	+=DeltaZDiameter;
		CurrentXOffset		+=DeltaXOffset;
		CurrentZOffset		+=DeltaZOffset;

		geVec3d_Add(&Current, &Delta, &Current);
	}

	for(VBand=0;VBand < NumVerticalBands;VBand++)
	{
		TopPoints[VBand]	=Verts[VBand];
	}
	f	=Face_Create(NumVerticalBands, TopPoints, 0);

	if(f)
	{
		if(pTemplate->Solid > 1)
		{
			Face_SetFixedHull(f, GE_TRUE);
		}
		FaceList_AddFace(fl, f);
	}

	for(VBand=NumVerticalBands-1, HBand=0;VBand >=0;VBand--, HBand++)
	{
		TopPoints[HBand]	=Verts[VBand + NumVerticalBands];
	}
	f	=Face_Create(NumVerticalBands, TopPoints, 0);

	if(f)
	{
		if(pTemplate->Solid > 1)
		{
			Face_SetFixedHull(f, GE_TRUE);
		}
		FaceList_AddFace(fl, f);
	}

	// Generate the polygons
	for(HBand = 0;HBand < 1;HBand++)
	{
		for(VBand = 0;VBand < NumVerticalBands;VBand++)
		{
			TopPoints[3]	=Verts[(HBand * NumVerticalBands) + VBand];
			TopPoints[2]	=Verts[(HBand * NumVerticalBands) + ((VBand + 1) % NumVerticalBands)];
			TopPoints[1]	=Verts[((HBand + 1) * NumVerticalBands) + ((VBand + 1) % NumVerticalBands)];
			TopPoints[0]	=Verts[((HBand + 1) * NumVerticalBands) + VBand];
			f				=Face_Create(4, TopPoints, 0);
			if(f)
			{
				FaceList_AddFace(fl, f);
			}
		}
	}
	geRam_Free(Verts);
	geRam_Free(TopPoints);

	if(!pTemplate->Solid)
	{
		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetSubtract(b, pTemplate->TCut);
		}
		return	b;
	}
	else
	{
		BrushList	*bl	=BrushList_Create();
		Brush		*bh, *bm;

		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetHollow(b, GE_TRUE);
			Brush_SetHullSize(b, (float)pTemplate->Thickness);
			bh	=Brush_CreateHollowFromBrush(b);
			if(bh)
			{
				Brush_SetHollowCut(bh, GE_TRUE);
				BrushList_Append(bl, b);
				BrushList_Append(bl, bh);

				bm	=Brush_Create(BRUSH_MULTI, NULL, bl);
				if(bm)
				{
					Brush_SetHollow(bm, GE_TRUE);
					Brush_SetSubtract(bm, pTemplate->TCut);
					Brush_SetHullSize(bm, (float)pTemplate->Thickness);
					return	bm;
				}
			}
			else
			{
				Brush_Destroy(&b);
				BrushList_Destroy(&bl);
			}
		}
		else
		{
			BrushList_Destroy(&bl);
		}
	}

	return	NULL;
}
Brush *BrushTemplate_CreateCone (const BrushTemplate_Cone *pTemplate)
{
	int			index, BottomCount;
	geVec3d		StartPoint, CurPoint, OldPoint, OuterFocus;
	geVec3d		FaceVerts[3], *BottomVerts;
	FaceList	*fl;
	Face		*f;
	Brush		*b;

	double CurAngle;
	double AngleDeltaDegrees = 360.0f/(float)pTemplate->VerticalStrips;
	double AngleDelta = UNITS_DEGREES_TO_RADIANS (AngleDeltaDegrees);


	fl	=FaceList_Create(pTemplate->VerticalStrips + 1);
	
	geVec3d_Set (&OuterFocus, 0, (float)(pTemplate->Height/2), 0);
	geVec3d_Set (&StartPoint, (float)(pTemplate->Width/2), (float)-(pTemplate->Height/2), 0);

	CurPoint		=OldPoint	=StartPoint;
	BottomVerts		=(geVec3d *)geRam_Allocate (sizeof(geVec3d) * pTemplate->VerticalStrips);
	BottomVerts[0]	=CurPoint;

	CurAngle	=BottomCount	=0;
	for( index = 1; index < pTemplate->VerticalStrips; index++ )
	{
		//	Rotate around to create our successive points...
		CurAngle += AngleDelta;

		geVec3d_Set
		(
			&CurPoint,
			(float)(( StartPoint.X * cos( CurAngle ) ) +( StartPoint.Z * sin( CurAngle ) )),
			StartPoint.Y,
			(float)(( StartPoint.Z * cos( CurAngle ) ) -( StartPoint.X * sin( CurAngle ) ))
		);

		FaceVerts[2]	=OuterFocus;
		FaceVerts[1]	=OldPoint;
		FaceVerts[0]	=CurPoint;

		f	=Face_Create(3, FaceVerts, 0);
		FaceList_AddFace(fl, f);

		OldPoint		=CurPoint;

		//	Assign the current point to bottom plane...
		BottomVerts[++BottomCount]	=CurPoint;
	}

	//	Create the final polygon...
	CurAngle += AngleDelta;

	geVec3d_Set
	(
		&CurPoint,
		(float)(( StartPoint.X * cos( CurAngle ) ) + ( StartPoint.Z * sin( CurAngle ) )),
		StartPoint.Y,
		(float)(( StartPoint.Z * cos( CurAngle ) ) - ( StartPoint.X * sin( CurAngle ) ))
	);

	FaceVerts[2]	=OuterFocus;
	FaceVerts[1]	=OldPoint;
	FaceVerts[0]	=CurPoint;

	f	=Face_Create(3, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	f	=Face_Create(pTemplate->VerticalStrips, BottomVerts, 0);

	if(f)
	{
		if(pTemplate->Style > 1)	//default to hollow (if they make hollow later)
		{
			Face_SetFixedHull(f, GE_TRUE);
		}
		FaceList_AddFace(fl, f);
	}
	geRam_Free(BottomVerts);

	if(!pTemplate->Style)
	{
		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetSubtract(b, pTemplate->TCut);
		}
		return	b;
	}
	else
	{
		BrushList	*bl	=BrushList_Create();
		Brush		*bh, *bm;

		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetHollow(b, GE_TRUE);
			Brush_SetHullSize(b, (float)pTemplate->Thickness);
			bh	=Brush_CreateHollowFromBrush(b);
			if(bh)
			{
				Brush_SetHollowCut(bh, GE_TRUE);
				BrushList_Append(bl, b);
				BrushList_Append(bl, bh);

				bm	=Brush_Create(BRUSH_MULTI, NULL, bl);
				if(bm)
				{
					Brush_SetHollow(bm, GE_TRUE);
					Brush_SetSubtract(bm, pTemplate->TCut);
					Brush_SetHullSize(bm, (float)pTemplate->Thickness);
					return	bm;
				}
			}
			else
			{
				Brush_Destroy(&b);
				BrushList_Destroy(&bl);
			}
		}
		else
		{
			BrushList_Destroy(&bl);
		}
	}
	return	NULL;
}
Brush *BrushTemplate_CreateBox (const BrushTemplate_Box *pTemplate)
{
	//revisit for error handling when merged
	geVec3d		Verts[8];
	geVec3d		FaceVerts[4];
	FaceList	*fl;
	Face		*f;
	Brush		*b;

	fl	=FaceList_Create(6);

	// Vertices 0 to 3 are the 4 corners of the top face
	geVec3d_Set (&Verts[0], (float)-(pTemplate->XSizeTop/2), (float)(pTemplate->YSize/2), (float)-(pTemplate->ZSizeTop/2));
	geVec3d_Set (&Verts[1], (float)-(pTemplate->XSizeTop/2), (float)(pTemplate->YSize/2), (float)(pTemplate->ZSizeTop/2));
	geVec3d_Set (&Verts[2], (float)(pTemplate->XSizeTop/2), (float)(pTemplate->YSize/2), (float)(pTemplate->ZSizeTop/2));
	geVec3d_Set (&Verts[3], (float)(pTemplate->XSizeTop/2), (float)(pTemplate->YSize/2), (float)-(pTemplate->ZSizeTop/2));

	// Vertices 4 to 7 are the 4 corners of the bottom face
	geVec3d_Set (&Verts[4], (float)-(pTemplate->XSizeBot/2), (float)-(pTemplate->YSize/2), (float)-(pTemplate->ZSizeBot/2));
	geVec3d_Set (&Verts[5], (float)(pTemplate->XSizeBot/2), (float)-(pTemplate->YSize/2), (float)-(pTemplate->ZSizeBot/2));
	geVec3d_Set (&Verts[6], (float)(pTemplate->XSizeBot/2), (float)-(pTemplate->YSize/2), (float)(pTemplate->ZSizeBot/2));
	geVec3d_Set (&Verts[7], (float)-(pTemplate->XSizeBot/2), (float)-(pTemplate->YSize/2), (float)(pTemplate->ZSizeBot/2));

	FaceVerts[3]	=Verts[0];
	FaceVerts[2]	=Verts[1];
	FaceVerts[1]	=Verts[2];
	FaceVerts[0]	=Verts[3];

	f	=Face_Create(4, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	FaceVerts[3]	=Verts[4];
	FaceVerts[2]	=Verts[5];
	FaceVerts[1]	=Verts[6];
	FaceVerts[0]	=Verts[7];

	f	=Face_Create(4, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	FaceVerts[3]	=Verts[1];
	FaceVerts[2]	=Verts[7];
	FaceVerts[1]	=Verts[6];
	FaceVerts[0]	=Verts[2];

	f	=Face_Create(4, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	FaceVerts[3]	=Verts[0];
	FaceVerts[2]	=Verts[3];
	FaceVerts[1]	=Verts[5];
	FaceVerts[0]	=Verts[4];

	f	=Face_Create(4, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	FaceVerts[3]	=Verts[0];
	FaceVerts[2]	=Verts[4];
	FaceVerts[1]	=Verts[7];
	FaceVerts[0]	=Verts[1];

	f	=Face_Create(4, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	FaceVerts[3]	=Verts[3];
	FaceVerts[2]	=Verts[2];
	FaceVerts[1]	=Verts[6];
	FaceVerts[0]	=Verts[5];

	f	=Face_Create(4, FaceVerts, 0);
	if(f)
	{
		FaceList_AddFace(fl, f);
	}

	if(!pTemplate->Solid)
	{
		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetSubtract(b, pTemplate->TCut);
			Brush_SetSheet (b, pTemplate->TSheet);
		}
		return	b;
	}
	else
	{
		// hollow brush
		BrushList	*bl	=BrushList_Create();
		Brush		*bh, *bm;

		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetHollow(b, GE_TRUE);
			Brush_SetHullSize(b, (float)pTemplate->Thickness);
			bh	=Brush_CreateHollowFromBrush(b);
			if(bh)
			{
				Brush_SetHollowCut(bh, GE_TRUE);
				BrushList_Append(bl, b);
				BrushList_Append(bl, bh);

				bm	=Brush_Create(BRUSH_MULTI, NULL, bl);
				if(bm)
				{
					Brush_SetHollow(bm, GE_TRUE);
					Brush_SetSubtract(bm, pTemplate->TCut);
					Brush_SetHullSize(bm, (float)pTemplate->Thickness);
					return	bm;
				}
			}
			else
			{
				Brush_Destroy(&b);
				BrushList_Destroy(&bl);
			}
		}
		else
		{
			BrushList_Destroy(&bl);
		}
	}

	return	NULL;
}
Brush *BrushTemplate_CreateArch (const BrushTemplate_Arch *pTemplate)
{
	Brush		*b, *b2;
	BrushList	*MBList	=BrushList_Create();
	FaceList	*fl;
	Face		*f;
	geVec3d		FaceVerts[4];

	int		i, NumSlits			=pTemplate->NumSlits;
	int		NumCrossSections	=NumSlits + 2;
	geFloat	Thickness			=pTemplate->Thickness;
	geFloat	Width				=pTemplate->Width;
	geFloat	InnerRadius			=pTemplate->Radius;
//	geFloat	WallSize			=pTemplate->WallSize;
	double	StartAngleDegrees	=pTemplate->StartAngle;
	double	EndAngleDegrees		=pTemplate->EndAngle;
	double	AngleDelta			=0;
	double	CurAngle			=0;
	double	StartAngle			=Units_DegreesToRadians (StartAngleDegrees);
	double	EndAngle			=Units_DegreesToRadians (EndAngleDegrees);
	double	Temp;
	geVec3d	TopInnerPoint;
	geVec3d	TopOuterPoint;
	geVec3d	FinalTopInnerPoint;
	geVec3d	FinalTopOuterPoint;
	geVec3d	FinalBottomInnerPoint;
	geVec3d	FinalBottomOuterPoint;
	geVec3d	OldTopInner;
	geVec3d	OldTopOuter;
	geVec3d	OldBottomInner;
	geVec3d	OldBottomOuter;

	//If angles are equal, we have an empty shape...
	if(StartAngle==EndAngle)
	{
		return	NULL;
	}

	//	Put the angles in order...
	if(StartAngle > EndAngle)
	{
		Temp		=StartAngle;
		StartAngle	=EndAngle;
		EndAngle	=Temp;
	}

	geVec3d_Set(&TopInnerPoint, (float)InnerRadius, 0.0, (float)(Width / 2));
	geVec3d_Set(&TopOuterPoint, (float)(InnerRadius + Thickness), 0.0, (float)(Width / 2));

	AngleDelta	=(EndAngle - StartAngle)/(NumCrossSections - 1);
	CurAngle	=StartAngle + AngleDelta;

	//	Create first cross section of 4 vertices ( outer face @ start angle)...
	geVec3d_Set
	(
		&FinalTopInnerPoint,
		(float)(( TopInnerPoint.X * cos( StartAngle ) ) - ( TopInnerPoint.Y * sin( StartAngle ) )),
		(float)(( TopInnerPoint.X * sin( StartAngle ) ) + ( TopInnerPoint.Y * cos( StartAngle ) )),
		TopInnerPoint.Z
	);
	geVec3d_Set
	(
		&FinalTopOuterPoint,
		(float)(( TopOuterPoint.X * cos( StartAngle ) ) - ( TopInnerPoint.Y * sin( StartAngle ) )),
		(float)(( TopOuterPoint.X * sin( StartAngle ) ) + ( TopInnerPoint.Y * cos( StartAngle ) )),
		TopOuterPoint.Z
	);
	FinalBottomInnerPoint	=FinalTopInnerPoint;
	FinalBottomInnerPoint.Z	=-FinalTopInnerPoint.Z;
	FinalBottomOuterPoint	=FinalTopOuterPoint;
	FinalBottomOuterPoint.Z	=-FinalTopOuterPoint.Z;
	OldTopInner				=FinalTopInnerPoint;
	OldTopOuter				=FinalTopOuterPoint;
	OldBottomInner			=FinalBottomInnerPoint;
	OldBottomOuter			=FinalBottomOuterPoint;

	//Create the other cross sections and assign verts to polys after each...
	for(i=0;i < (NumCrossSections-1);i++)
	{
		geVec3d_Set
		(
			&FinalTopInnerPoint,
			(float)(( TopInnerPoint.X * cos( CurAngle ) ) - ( TopInnerPoint.Y * sin( CurAngle ) )),
			(float)(( TopInnerPoint.X * sin( CurAngle ) ) + ( TopInnerPoint.Y * cos( CurAngle ) )),
			TopInnerPoint.Z
		);
		geVec3d_Set
		(
			&FinalTopOuterPoint,
			(float)(( TopOuterPoint.X * cos( CurAngle ) ) - ( TopInnerPoint.Y * sin( CurAngle ) )),
			(float)(( TopOuterPoint.X * sin( CurAngle ) ) + ( TopInnerPoint.Y * cos( CurAngle ) )),
			TopOuterPoint.Z
		);
		FinalBottomInnerPoint = FinalTopInnerPoint;
		FinalBottomInnerPoint.Z = -FinalTopInnerPoint.Z;

		FinalBottomOuterPoint = FinalTopOuterPoint;
		FinalBottomOuterPoint.Z = -FinalTopOuterPoint.Z;

		CurAngle += AngleDelta;

		fl	=FaceList_Create(6);

		//Assign points to the 4 outer poly faces...

		//Top face...
		FaceVerts[0]	=FinalTopInnerPoint;
		FaceVerts[1]	=FinalTopOuterPoint;
		FaceVerts[2]	=OldTopOuter;
		FaceVerts[3]	=OldTopInner;
		f				=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		//	Bottom face...
		FaceVerts[3]	=FinalBottomInnerPoint;
		FaceVerts[2]	=FinalBottomOuterPoint;
		FaceVerts[1]	=OldBottomOuter;
		FaceVerts[0]	=OldBottomInner;
		f				=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		//	Inner side face...
		FaceVerts[0]	=FinalTopInnerPoint;
		FaceVerts[1]	=OldTopInner;
		FaceVerts[2]	=OldBottomInner;
		FaceVerts[3]	=FinalBottomInnerPoint;
		f				=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		//	Outer side face...
		FaceVerts[3]	=FinalTopOuterPoint;
		FaceVerts[2]	=OldTopOuter;
		FaceVerts[1]	=OldBottomOuter;
		FaceVerts[0]	=FinalBottomOuterPoint;
		f				=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		//make the end faces
		FaceVerts[0]	=OldTopOuter;
		FaceVerts[1]	=OldBottomOuter;
		FaceVerts[2]	=OldBottomInner;
		FaceVerts[3]	=OldTopInner;
		f				=Face_Create(4, FaceVerts, 0);

		if(f)
		{
			if(pTemplate->Style < 2)	//default to hollow (if they make hollow later)
			{
				if(i)
				{
					Face_SetFixedHull(f, GE_TRUE);
				}
			}
			else
			{
				Face_SetFixedHull(f, GE_TRUE);
			}
			FaceList_AddFace(fl, f);
		}

		FaceVerts[3]	=FinalTopOuterPoint;
		FaceVerts[2]	=FinalBottomOuterPoint;
		FaceVerts[1]	=FinalBottomInnerPoint;
		FaceVerts[0]	=FinalTopInnerPoint;
		f				=Face_Create(4, FaceVerts, 0);

		if(f)
		{
			if(pTemplate->Style < 2)	//default to hollow (if they make hollow later)
			{
				if(i < (NumCrossSections-2))
				{
					Face_SetFixedHull(f, GE_TRUE);
				}
			}
			else
			{
				Face_SetFixedHull(f, GE_TRUE);
			}
			FaceList_AddFace(fl, f);
		}

		if(!pTemplate->Style)
		{
			b2	=Brush_Create(BRUSH_LEAF, fl, NULL);
			if(b2)
			{
				Brush_SetSubtract(b2, pTemplate->TCut);
			}
			BrushList_Append(MBList, b2);
		}
		else
		{
			BrushList	*bl	=BrushList_Create();
			Brush		*bh, *bm;

			b2	=Brush_Create(BRUSH_LEAF, fl, NULL);
			if(b2)
			{
				Brush_SetHollow(b2, GE_TRUE);
				Brush_SetHullSize(b2, pTemplate->WallSize);
				bh	=Brush_CreateHollowFromBrush(b2);
				if(bh)
				{
					Brush_SetHollowCut(bh, GE_TRUE);
					BrushList_Append(bl, b2);
					BrushList_Append(bl, bh);

					bm	=Brush_Create(BRUSH_MULTI, NULL, bl);
					if(bm)
					{
						Brush_SetHollow(bm, GE_TRUE);
						Brush_SetSubtract(bm, pTemplate->TCut);
						Brush_SetHullSize(bm, pTemplate->WallSize);

						BrushList_Append(MBList, bm);
					}
				}
				else
				{
					Brush_Destroy(&b2);
					BrushList_Destroy(&bl);
				}
			}
			else
			{
				BrushList_Destroy(&bl);
			}
		}

		//	Set old points...
		OldTopInner		=FinalTopInnerPoint;
		OldTopOuter		=FinalTopOuterPoint;
		OldBottomInner	=FinalBottomInnerPoint;
		OldBottomOuter	=FinalBottomOuterPoint;

	}
	b	=Brush_Create(BRUSH_MULTI, NULL, MBList);

	if(b)
	{
		Brush_SetSubtract(b, pTemplate->TCut);
	}

	return	b;
}
Esempio n. 10
0
/*
   ===========
   AddRegionBrushes
   a regioned map will have temp walls put up at the region boundary
   \todo TODO TTimo old implementation of region brushes
   we still add them straight in the worldspawn and take them out after the map is saved
   with the new implementation we should be able to append them in a temporary manner to the data we pass to the map module
   ===========
 */
void AddRegionBrushes( void ){
	vec3_t mins, maxs;
	int i;
	texdef_t td;

	if ( !region_active ) {
#ifdef _DEBUG
		Sys_FPrintf( SYS_WRN, "Unexpected AddRegionBrushes call.\n" );
#endif
		return;
	}

	memset( &td, 0, sizeof( td ) );
	td.SetName( SHADER_NOT_FOUND );

	// set mins
	VectorSet( mins, region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 );

	// vary maxs
	for ( i = 0; i < 3; i++ )
	{
		VectorSet( maxs, region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 );
		maxs[i] = region_mins[i];
		region_sides[i] = Brush_Create( mins, maxs, &td );
	}

	// set maxs
	VectorSet( maxs, region_maxs[0] + 32, region_maxs[1] + 32, region_maxs[2] + 32 );

	// vary mins
	for ( i = 0; i < 3; i++ )
	{
		VectorSet( mins, region_mins[0] - 32, region_mins[1] - 32, region_mins[2] - 32 );
		mins[i] = region_maxs[i];
		region_sides[i + 3] = Brush_Create( mins, maxs, &td );
	}


	// this is a safe check, but it should not really happen anymore
	vec3_t vOrig;
	VectorSet( vOrig,
			   (int)g_pParentWnd->GetCamWnd()->Camera()->origin[0],
			   (int)g_pParentWnd->GetCamWnd()->Camera()->origin[1],
			   (int)g_pParentWnd->GetCamWnd()->Camera()->origin[2] );

	for ( i = 0 ; i < 3 ; i++ )
	{
		if ( vOrig[i] > region_maxs[i] || vOrig[i] < region_mins[i] ) {
			Sys_FPrintf( SYS_ERR, "Camera is NOT in the region, it's likely that the region won't compile correctly\n" );
		}
	}

	// write the info_playerstart
	region_startpoint = Entity_Alloc();
	SetKeyValue( region_startpoint, "classname", "info_player_start" );
	region_startpoint->eclass = Eclass_ForName( "info_player_start", false );
	char sTmp[1024];
	sprintf( sTmp, "%d %d %d", (int)vOrig[0], (int)vOrig[1], (int)vOrig[2] );
	SetKeyValue( region_startpoint, "origin", sTmp );
	sprintf( sTmp, "%d", (int)g_pParentWnd->GetCamWnd()->Camera()->angles[YAW] );
	SetKeyValue( region_startpoint, "angle", sTmp );
	// empty array of children
	region_startpoint->pData = new CPtrArray;
}
Esempio n. 11
0
void CPlugInManager::CommitEntityHandleToMap(LPVOID vpEntity)
{
	entity_t *pe;
	eclass_t *e;
	brush_t		*b;
	vec3_t mins,maxs;
	bool has_brushes;
	for (int i=0 ; i < m_EntityHandles.GetSize() ; i++ )
	{
		if (vpEntity == m_EntityHandles.GetAt(i))
		{
			m_EntityHandles.RemoveAt(i);
			pe = reinterpret_cast<entity_t*>(vpEntity);
			// fill additional fields
			// straight copy from Entity_Parse
			// entity_t::origin
			GetVectorForKey (pe, "origin", pe->origin);
			// entity_t::eclass
			if (pe->brushes.onext == &pe->brushes)
				has_brushes = false;
			else
				has_brushes = true;
			e = Eclass_ForName (ValueForKey (pe, "classname"), has_brushes);
			pe->eclass = e;
			// fixedsize
			if (e->fixedsize)
			{
				if (pe->brushes.onext != &pe->brushes)
				{
					Sys_Printf("Warning : Fixed size entity with brushes in CPlugInManager::CommitEntityHandleToMap\n");
				}
				// create a custom brush
				VectorAdd(e->mins, pe->origin, mins);
				VectorAdd(e->maxs, pe->origin, maxs);
				float a = 0;
				if (e->nShowFlags & ECLASS_MISCMODEL)
				{
					char* p = ValueForKey(pe, "model");
					if (p != NULL && strlen(p) > 0)
					{
						vec3_t vMin, vMax;
						a = FloatForKey (pe, "angle");
				        if (GetCachedModel(pe, p, vMin, vMax))
				        {
						      // create a custom brush
						      VectorAdd (pe->md3Class->mins, pe->origin, mins);
						      VectorAdd (pe->md3Class->maxs, pe->origin, maxs);
				        }
					}
			    }
		
			    b = Brush_Create (mins, maxs, &e->texdef);

			    if (a)
			    {
					vec3_t vAngle;
					vAngle[0] = vAngle[1] = 0;
					vAngle[2] = a;
					Brush_Rotate(b, vAngle, pe->origin, false);
				}

				b->owner = pe;

				b->onext = pe->brushes.onext;
				b->oprev = &pe->brushes;
				pe->brushes.onext->oprev = b;
				pe->brushes.onext = b;
			}
			else
			{	// brush entity
				if (pe->brushes.next == &pe->brushes)
					Sys_Printf ("Warning: Brush entity with no brushes in CPlugInManager::CommitEntityHandleToMap\n");
			}

			// add brushes to the active brushes list
			// and build them along the way
			for (b=pe->brushes.onext ; b != &pe->brushes ; b=b->onext)
			{
				// convert between old brushes and brush primitive
				if (g_qeglobals.m_bBrushPrimitMode)
				{
					// we only filled the shift scale rot fields, needs conversion
					Brush_Build( b, true, true, true );
				}
				else
				{
					// we are using old brushes
					Brush_Build( b );
				}
				b->next = active_brushes.next;
				active_brushes.next->prev = b;
				b->prev = &active_brushes;
				active_brushes.next = b;
			}

			// handle worldspawn entities
			// if worldspawn has no brushes, use the new one
			if (!strcmp(ValueForKey (pe, "classname"), "worldspawn"))
			{
				if ( world_entity && ( world_entity->brushes.onext != &world_entity->brushes ) )
				{
					// worldspawn already has brushes
					Sys_Printf ("Commiting worldspawn as func_group\n");
					SetKeyValue(pe, "classname", "func_group");
					// add the entity to the end of the entity list
					pe->next = &entities;
					pe->prev = entities.prev;
					entities.prev->next = pe;
					entities.prev = pe;
					g_qeglobals.d_num_entities++;
				}
				else
				{
					// there's a worldspawn with no brushes, we assume the map is empty
					if ( world_entity )
					{
						Entity_Free( world_entity );
						world_entity = pe;
					}
					else
						Sys_Printf("Warning : unexpected world_entity == NULL in CommitEntityHandleToMap\n");
				}
			}
			else
			{
				// add the entity to the end of the entity list
				pe->next = &entities;
				pe->prev = entities.prev;
				entities.prev->next = pe;
				entities.prev = pe;
				g_qeglobals.d_num_entities++;
			}
		}
	}
}
Esempio n. 12
0
entity_t *Entity_PostParse(entity_t *ent, brush_t *pList)
{
    bool		has_brushes;
    eclass_t	*e;
    brush_t		*b;
    idVec3		mins, maxs, zero;
    idBounds bo;

    zero.Zero();

    Entity_SetCurveData( ent );

    if (ent->brushes.onext == &ent->brushes)
    {
        has_brushes = false;
    }
    else
    {
        has_brushes = true;
    }

    bool needsOrigin = !GetVectorForKey(ent, "origin", ent->origin);
    const char	*pModel = ValueForKey(ent, "model");

    const char *cp = ValueForKey(ent, "classname");

    if (strlen(cp))
    {
        e = Eclass_ForName(cp, has_brushes);
    }
    else
    {
        const char *cp2 = ValueForKey(ent, "name");
        if (strlen(cp2))
        {
            char buff[1024];
            strcpy(buff, cp2);
            int len = strlen(buff);
            while ((isdigit(buff[len-1]) || buff[len-1] == '_') && len > 0)
            {
                buff[len-1] = '\0';
                len--;
            }
            e = Eclass_ForName(buff, has_brushes);
            SetKeyValue(ent, "classname", buff, false);
        }
        else
        {
            e = Eclass_ForName("", has_brushes);
        }
    }

    idStr str;

    if (e->defArgs.GetString("model", "", str) && e->entityModel == NULL)
    {
        e->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &e->defArgs );
    }

    ent->eclass = e;

    bool hasModel = EntityHasModel(ent);

    if (hasModel)
    {
        ent->eclass->defArgs.GetString("model", "", str);
        if (str.Length())
        {
            hasModel = false;
            ent->epairs.Delete("model");
        }
    }

    if (e->nShowFlags & ECLASS_WORLDSPAWN)
    {
        ent->origin.Zero();
        needsOrigin = false;
        ent->epairs.Delete( "model" );
    }
    else if (e->nShowFlags & ECLASS_LIGHT)
    {
        if (GetVectorForKey(ent, "light_origin", ent->lightOrigin))
        {
            GetMatrixForKey(ent, "light_rotation", ent->lightRotation);
            ent->trackLightOrigin = true;
        }
        else if (hasModel)
        {
            SetKeyValue(ent, "light_origin", ValueForKey(ent, "origin"));
            ent->lightOrigin = ent->origin;
            if (GetMatrixForKey(ent, "rotation", ent->lightRotation))
            {
                SetKeyValue(ent, "light_rotation", ValueForKey(ent, "rotation"));
            }
            ent->trackLightOrigin = true;
        }
    }
    else if ( e->nShowFlags & ECLASS_ENV )
    {
        // need to create an origin from the bones here
        idVec3 org;
        idAngles ang;
        bo.Clear();
        bool hasBody = false;
        const idKeyValue *arg = ent->epairs.MatchPrefix( "body ", NULL );
        while ( arg )
        {
            sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll );
            bo.AddPoint( org );
            arg = ent->epairs.MatchPrefix( "body ", arg );
            hasBody = true;
        }
        if (hasBody)
        {
            ent->origin = bo.GetCenter();
        }
    }

    if (e->fixedsize || hasModel)  			// fixed size entity
    {
        if (ent->brushes.onext != &ent->brushes)
        {
            for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext)
            {
                b->entityModel = true;
            }
        }

        if (hasModel)
        {
            // model entity
            idRenderModel *modelHandle = renderModelManager->FindModel( pModel );

            if ( dynamic_cast<idRenderModelPrt*>( modelHandle ) || dynamic_cast<idRenderModelLiquid*>( modelHandle ) )
            {
                bo.Zero();
                bo.ExpandSelf( 12.0f );
            }
            else
            {
                bo = modelHandle->Bounds( NULL );
            }

            VectorCopy(bo[0], mins);
            VectorCopy(bo[1], maxs);
            for (int i = 0; i < 3; i++)
            {
                if (mins[i] == maxs[i])
                {
                    mins[i]--;
                    maxs[i]++;
                }
            }
            VectorAdd(mins, ent->origin, mins);
            VectorAdd(maxs, ent->origin, maxs);
            b = Brush_Create(mins, maxs, &e->texdef);
            b->modelHandle = modelHandle;

            float		yaw = 0;
            bool		convertAngles = GetFloatForKey(ent, "angle", &yaw);
            extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild);
            extern void Brush_Rotate(brush_t *b, idVec3 rot, idVec3 origin, bool bBuild);

            if (convertAngles)
            {
                idVec3	rot(0, 0, yaw);
                Brush_Rotate(b, rot, ent->origin, false);
            }

            if (GetMatrixForKey(ent, "rotation", ent->rotation))
            {
                idBounds bo2;
                bo2.FromTransformedBounds(bo, ent->origin, ent->rotation);
                b->owner = ent;
                Brush_Resize(b, bo2[0], bo2[1]);
            }
            Entity_LinkBrush(ent, b);
        }

        if (!hasModel || (ent->eclass->nShowFlags & ECLASS_LIGHT && hasModel))
        {
            // create a custom brush
            if (ent->trackLightOrigin)
            {
                mins = e->mins + ent->lightOrigin;
                maxs = e->maxs + ent->lightOrigin;
            }
            else
            {
                mins = e->mins + ent->origin;
                maxs = e->maxs + ent->origin;
            }

            b = Brush_Create(mins, maxs, &e->texdef);
            GetMatrixForKey(ent, "rotation", ent->rotation);
            Entity_LinkBrush(ent, b);
            b->trackLightOrigin = ent->trackLightOrigin;
            if ( e->texdef.name == NULL )
            {
                brushprimit_texdef_t bp;
                texdef_t td;
                td.SetName( ent->eclass->defMaterial );
                Brush_SetTexture( b, &td, &bp, false );
            }
        }
    }
    else  	// brush entity
    {
        if (ent->brushes.next == &ent->brushes)
        {
            printf("Warning: Brush entity with no brushes\n");
        }

        if (!needsOrigin)
        {
            idStr cn = ValueForKey(ent, "classname");
            idStr name = ValueForKey(ent, "name");
            idStr model = ValueForKey(ent, "model");
            if (cn.Icmp("func_static") == 0)
            {
                if (name.Icmp(model) == 0)
                {
                    needsOrigin = true;
                }
            }
        }

        if (needsOrigin)
        {
            idVec3	mins, maxs, mid;
            int		i;
            char	text[32];
            mins[0] = mins[1] = mins[2] = 999999;
            maxs[0] = maxs[1] = maxs[2] = -999999;

            // add in the origin
            for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext)
            {
                Brush_Build(b, true, false, false);
                for (i = 0; i < 3; i++)
                {
                    if (b->mins[i] < mins[i])
                    {
                        mins[i] = b->mins[i];
                    }

                    if (b->maxs[i] > maxs[i])
                    {
                        maxs[i] = b->maxs[i];
                    }
                }
            }

            for (i = 0; i < 3; i++)
            {
                ent->origin[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
            }

            sprintf(text, "%i %i %i", (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
            SetKeyValue(ent, "origin", text);
        }

        if (!(e->nShowFlags & ECLASS_WORLDSPAWN))
        {
            if (e->defArgs.FindKey("model") == NULL && (pModel == NULL || (pModel && strlen(pModel) == 0)))
            {
                SetKeyValue(ent, "model", ValueForKey(ent, "name"));
            }
        }
        else
        {
            DeleteKey(ent, "origin");
        }
    }

    // add all the brushes to the main list
    if (pList)
    {
        for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext)
        {
            b->next = pList->next;
            pList->next->prev = b;
            b->prev = pList;
            pList->next = b;
        }
    }

    FixFloats(&ent->epairs);

    return ent;

}
Esempio n. 13
0
/*
 =======================================================================================================================
    Entity_Create Creates a new entity out of the selected_brushes list. If the entity class is fixed size, the brushes
    are only used to find a midpoint. Otherwise, the brushes have their ownership transfered to the new entity.
 =======================================================================================================================
 */
entity_t *Entity_Create(eclass_t *c, bool forceFixed)
{
    entity_t	*e;
    brush_t		*b;
    idVec3		mins, maxs, origin;
    char		text[32];
    texdef_t td;
    brushprimit_texdef_t bp;

    // check to make sure the brushes are ok
    for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
    {
        if (b->owner != world_entity)
        {
            Sys_Status("Entity NOT created, brushes not all from world\n");
            Sys_Beep();
            return NULL;
        }
    }

    idStr str;
    if (c->defArgs.GetString("model", "", str) && c->entityModel == NULL)
    {
        c->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &c->defArgs );
    }

    // create it
    e = Entity_New();
    e->brushes.onext = e->brushes.oprev = &e->brushes;
    e->eclass = c;
    e->epairs.Copy(c->args);
    SetKeyValue(e, "classname", c->name);
    Entity_Name(e, false);

    // add the entity to the entity list
    Entity_AddToList(e, &entities);

    if (c->fixedsize)
    {
        //
        // just use the selection for positioning b = selected_brushes.next; for (i=0 ;
        // i<3 ; i++) { e->origin[i] = b->mins[i] - c->mins[i]; }
        //
        Select_GetMid(e->origin);
        VectorCopy(e->origin, origin);

        // create a custom brush
        VectorAdd(c->mins, e->origin, mins);
        VectorAdd(c->maxs, e->origin, maxs);

        b = Brush_Create(mins, maxs, &c->texdef);

        Entity_LinkBrush(e, b);

        if (c->defMaterial.Length())
        {
            td.SetName(c->defMaterial);
            Brush_SetTexture(b, &td, &bp, false);
        }


        // delete the current selection
        Select_Delete();

        // select the new brush
        b->next = b->prev = &selected_brushes;
        selected_brushes.next = selected_brushes.prev = b;

        Brush_Build(b);
    }
    else
    {

        Select_GetMid(origin);

        // change the selected brushes over to the new entity
        for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
        {
            Entity_UnlinkBrush(b);
            Entity_LinkBrush(e, b);
            Brush_Build(b); // so the key brush gets a name
            if (c->defMaterial.Length())
            {
                td.SetName(c->defMaterial);
                Brush_SetTexture(b, &td, &bp, false);
            }

        }

        //for (int i = 0; i < 3; i++) {
        //	origin[i] = vMin[i] + vMax[i] * 0.5;
        //}

        if (!forceFixed)
        {
            SetKeyValue(e, "model", ValueForKey(e, "name"));
        }
    }

    sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
    SetKeyValue(e, "origin", text);
    VectorCopy(origin, e->origin);

    Sys_UpdateWindows(W_ALL);
    return e;
}
Esempio n. 14
0
/*
============
Entity_Create

Creates a new entity out of the selected_brushes list.
If the entity class is fixed size, the brushes are only
used to find a midpoint.  Otherwise, the brushes have
their ownershi[ transfered to the new entity.
============
*/
entity_t	*Entity_Create (eclass_t *c)
{
	entity_t	*e;
	brush_t		*b;
	vec3_t		mins, maxs;
	int			i;

	// check to make sure the brushes are ok

	for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
		if (b->owner != world_entity)
		{
			Sys_Printf ("Entity NOT created, brushes not all from world\n");
			Sys_Beep ();
			return NULL;
		}

	// create it

	e = (entity_t*)qmalloc(sizeof(*e));
	e->brushes.onext = e->brushes.oprev = &e->brushes;
	e->eclass = c;
	SetKeyValue (e, "classname", c->name);
							  
	// add the entity to the entity list
	e->next = entities.next;
	entities.next = e;
	e->next->prev = e;
	e->prev = &entities;

	if (c->fixedsize)
	{
		//
		// just use the selection for positioning
		//
		b = selected_brushes.next;
		for (i=0 ; i<3 ; i++)
			e->origin[i] = b->mins[i] - c->mins[i];

		// create a custom brush
		VectorAdd (c->mins, e->origin, mins);
		VectorAdd (c->maxs, e->origin, maxs);

	  b = Brush_Create (mins, maxs, &c->texdef);

		Entity_LinkBrush (e, b);

		// delete the current selection
		Select_Delete ();

		// select the new brush
		b->next = b->prev = &selected_brushes;
		selected_brushes.next = selected_brushes.prev = b;

		Brush_Build( b );
	}
	else
	{
		//
		// change the selected brushes over to the new entity
		//
		for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
		{
			Entity_UnlinkBrush (b);
			Entity_LinkBrush (e, b);
			Brush_Build( b );	// so the key brush gets a name
		}
	}

	Sys_UpdateWindows (W_ALL);
	return e;
}
Esempio n. 15
0
/*
================
Entity_Parse

If onlypairs is set, the classname info will not
be looked up, and the entity will not be added
to the global list.  Used for parsing the project.
================
*/
entity_t	*Entity_Parse (qboolean onlypairs, brush_t* pList)
{
	entity_t	*ent;
	eclass_t	*e;
	brush_t		*b;
	vec3_t		mins, maxs;
	epair_t		*ep;
	qboolean	has_brushes;
#ifdef SOF
	float		scale;
#endif

	if (!GetToken (true))
		return NULL;

	if (strcmp (token, "{") )
		Error ("ParseEntity: { not found");
	
	ent = (entity_t*)qmalloc (sizeof(*ent));
	ent->brushes.onext = ent->brushes.oprev = &ent->brushes;

	do
	{
		if (!GetToken (true))
    {
			Warning ("ParseEntity: EOF without closing brace");
      return NULL;
    }
		if (!strcmp (token, "}") )
			break;
		if (!strcmp (token, "{") )
		{
			b = Brush_Parse ();
      if (b != NULL)
      {
			  b->owner = ent;

			  // add to the end of the entity chain
			  b->onext = &ent->brushes;
			  b->oprev = ent->brushes.oprev;
			  ent->brushes.oprev->onext = b;
			  ent->brushes.oprev = b;
      }
      else
      {
        break;
      }
    
		}
		else
		{
			ep = ParseEpair ();
			{
				// update: the original code here may have been simple, but it meant that every map load/save
				//	the key/value pair fields were reversed in the save file, which messes up SourceSafe when it
				//	tries to delta the two versions during check-in... -slc
#if 0
				ep->next = ent->epairs;
				ent->epairs = ep;
#else
				// join this onto the END of the chain instead...
				//
				if (ent->epairs == NULL)	// special case for if there isn't a chain yet... :-)
				{
					ep->next = ent->epairs;
					ent->epairs = ep;
				}
				else
				{						
					for (epair_t* ep2 = ent->epairs ; ep2 ; ep2=ep2->next)
					{
						if (ep2->next == NULL)
						{
							// found the end, so...
							//
							ep2->next = ep;							
							ep->next = NULL;
							break;
						}
					}
				}
#endif
			}
		}
	} while (1);

	if (onlypairs)
		return ent;

	if (ent->brushes.onext == &ent->brushes)
		has_brushes = false;
	else
		has_brushes = true;

	GetVectorForKey (ent, "origin", ent->origin);

	e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
	ent->eclass = e;
	if (e->fixedsize)
	{	// fixed size entity
		if (ent->brushes.onext != &ent->brushes)
		{
			printf ("Warning: Fixed size entity with brushes\n");
#if 0
			while (ent->brushes.onext != &ent->brushes)
			{	// FIXME: this will free the entity and crash!
				Brush_Free (b);
			}
#endif
      ent->brushes.next = ent->brushes.prev = &ent->brushes;
		}

    // create a custom brush
		VectorAdd (e->mins, ent->origin, mins);
		VectorAdd (e->maxs, ent->origin, maxs);

    float a = 0;
    if (strnicmp(e->name, "misc_model",10) == 0)
    {
      char* p = ValueForKey(ent, "model");
      if (p != NULL && strlen(p) > 0)
      {
        vec3_t vMin, vMax;
        a = FloatForKey (ent, "angle");
		gEntityToSetBoundsOf = ent;
        if (GetCachedModel(ent, p, vMin, vMax))
        {
	      // create a custom brush
	      VectorAdd (ent->md3Class->mins, ent->origin, mins);
	      VectorAdd (ent->md3Class->maxs, ent->origin, maxs);
        }
      }
    }
#ifdef SOF
	if (strnicmp(e->name, "misc_",			5) == 0 ||
		strnicmp(e->name, "light_",			6) == 0 ||
		strnicmp(e->name, "m_",				2) == 0 ||
		strnicmp(e->name, "item_weapon_",	12)== 0 ||
		strnicmp(e->name, "item_ammo_",		10)== 0
		)
		a = FloatForKey (ent, "angle");
#endif		
		b = Brush_Create (mins, maxs, &e->texdef);
///////
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
///////
		Brush_Build(b);

#ifdef SOF
		scale = FloatForKey (ent, "scale");
		if (scale)
		{
		  Brush_Scale2(e, b, scale, ent->origin,false);
		}
#endif

//		if (a)
//		{
//			vec3_t vAngle;
//			vAngle[0] = vAngle[1] = 0;
//			vAngle[2] = a;
//			Brush_Rotate(b, vAngle, ent->origin, false);
//		}

/*
		b->owner = ent;

		b->onext = ent->brushes.onext;
		b->oprev = &ent->brushes;
		ent->brushes.onext->oprev = b;
		ent->brushes.onext = b;
*/
		// do this AFTER doing the brush stuff just above, so don't join to the other "if (a)"...
		//
		if (a)
		{
			// pick any old value to rotate away to, then back from, to avoid 0/360 weirdness on key-compares
			//
			SetKeyValue(ent, "angle", "0",			false);	// false = no tracking, ie just set the angle and nothing else			
			SetKeyValue(ent, "angle", va("%g",a),	true);	// true = do tracking, ie actually do the brush rotate
		}
	}
	else
	{	// brush entity
		if (ent->brushes.next == &ent->brushes)
			printf ("Warning: Brush entity with no brushes\n");
	}

	// add all the brushes to the main list
  if (pList)
  {
	  for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
    {
		  b->next = pList->next;
		  pList->next->prev = b;
		  b->prev = pList;
		  pList->next = b;
    }
  }

	return ent;
}
Brush	*BrushTemplate_CreateSpheroid (const BrushTemplate_Spheroid *pTemplate)
{
	double		z, ring_radius, r, dz, t, dt;
	int			vcnt, HBand, VBand;
	geVec3d		*sv, FaceVerts[4];
	FaceList	*fl;
	Face		*f;
	Brush		*b;

	if((pTemplate->HorizontalBands < 2) || (pTemplate->VerticalBands < 3))
	{
		return GE_FALSE ;
	}
	
	fl			=FaceList_Create((pTemplate->HorizontalBands)* pTemplate->VerticalBands);
	sv			=(geVec3d *)geRam_Allocate(sizeof(geVec3d) * (((pTemplate->HorizontalBands-1) * pTemplate->VerticalBands)+2));
	r			=pTemplate->YSize;
	vcnt		=0;
	geVec3d_Set (&sv[vcnt], 0.0f, pTemplate->YSize, 0.0f);
	vcnt++;
	dz			=2.0*r/(double)(pTemplate->HorizontalBands-1);
	for(z=(-r)+dz/2.0; z<(r-dz/2.0+dz/4.0); z+=dz)
	{
		ring_radius	=sqrt(r*r - z*z);
		dt			=PI2 /(double)(pTemplate->VerticalBands);
		for(t=0.0;t < PI2-(dt*0.5);t+=dt)
		{
			sv[vcnt].X	=(float)(sin(t) * ring_radius);
			sv[vcnt].Z	=(float)(cos(t) * ring_radius);
			sv[vcnt++].Y=(float)(-z);
		}
	}
	sv[vcnt].X	=0.0f;
	sv[vcnt].Y	=(float)(-pTemplate->YSize);
	sv[vcnt++].Z=0.0f;

	for(VBand=0;VBand < pTemplate->VerticalBands;VBand++)
	{
		FaceVerts[0]	=sv[0];
		FaceVerts[1]	=sv[(((1 + VBand) % pTemplate->VerticalBands) + 1)];
		FaceVerts[2]	=sv[(VBand % pTemplate->VerticalBands)+1];

		f	=Face_Create(3, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}
	}

	for(HBand=1;HBand < (pTemplate->HorizontalBands-1);HBand++)
	{
		for(VBand=0;VBand < pTemplate->VerticalBands;VBand++)
		{
			FaceVerts[0]	=sv[(((HBand-1)*pTemplate->VerticalBands)+1)+VBand];
			FaceVerts[1]	=sv[(((HBand-1)*pTemplate->VerticalBands)+1)+((VBand+1)%pTemplate->VerticalBands)];
			FaceVerts[2]	=sv[((HBand*pTemplate->VerticalBands)+1)+((VBand+1)%pTemplate->VerticalBands)];
			FaceVerts[3]	=sv[((HBand*pTemplate->VerticalBands)+1)+VBand];

			f	=Face_Create(4, FaceVerts, 0);
			if(f)
			{
				FaceList_AddFace(fl, f);
			}
		}
	}

	for(VBand=0;VBand < pTemplate->VerticalBands;VBand++)
	{
		FaceVerts[0]	=sv[1+((pTemplate->HorizontalBands-2)*pTemplate->VerticalBands)+VBand];
		FaceVerts[1]	=sv[1+((pTemplate->HorizontalBands-2)*pTemplate->VerticalBands)+((VBand+1)%pTemplate->VerticalBands)];
		FaceVerts[2]	=sv[((pTemplate->HorizontalBands-1)*pTemplate->VerticalBands)+1];

		f	=Face_Create(3, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}
	}
	geRam_Free(sv);

	if(!pTemplate->Solid)
	{
		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetSubtract(b, pTemplate->TCut);
		}
		return	b;
	}
	else
	{
		BrushList	*bl	=BrushList_Create();
		Brush		*bh, *bm;

		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
		if(b)
		{
			Brush_SetHollow(b, GE_TRUE);
			Brush_SetHullSize(b, (float)pTemplate->Thickness);
			bh	=Brush_CreateHollowFromBrush(b);
			if(bh)
			{
				Brush_SetHollowCut(bh, GE_TRUE);
				BrushList_Append(bl, b);
				BrushList_Append(bl, bh);

				bm	=Brush_Create(BRUSH_MULTI, NULL, bl);
				if(bm)
				{
					Brush_SetHollow(bm, GE_TRUE);
					Brush_SetSubtract(bm, pTemplate->TCut);
					Brush_SetHullSize(bm, (float)pTemplate->Thickness);
					return	bm;
				}
			}
			else
			{
				Brush_Destroy(&b);
				BrushList_Destroy(&bl);
			}
		}
		else
		{
			BrushList_Destroy(&bl);
		}
	}
	return	NULL;
}
Brush	*BrushTemplate_CreateStaircase (const BrushTemplate_Staircase *pTemplate)
{
	int			i;
	geFloat		HalfWidth = (geFloat)(pTemplate->Width/2);
	geFloat		HalfHeight = (geFloat)(pTemplate->Height/2);
	geFloat		HalfLength = (geFloat)(pTemplate->Length/2);
	Brush		*b, *b2;
	BrushList	*MBList	=BrushList_Create();
	FaceList	*fl;
	Face		*f;
	geVec3d		v, FaceVerts[4];


	if( pTemplate->MakeRamp )
	{
		fl	=FaceList_Create(5);

		geVec3d_Set (&(FaceVerts[3]), -HalfWidth, -HalfHeight, HalfLength);
		geVec3d_Set (&(FaceVerts[2]), HalfWidth,  -HalfHeight, HalfLength);
		geVec3d_Set (&(FaceVerts[1]), HalfWidth,	 HalfHeight,  HalfLength);
		geVec3d_Set (&(FaceVerts[0]), -HalfWidth, HalfHeight,  HalfLength);
		f	=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		geVec3d_Set (&(FaceVerts[3]), HalfWidth,  -HalfHeight,  HalfLength);
		geVec3d_Set (&(FaceVerts[2]), -HalfWidth, -HalfHeight,  HalfLength);
		geVec3d_Set (&(FaceVerts[1]), -HalfWidth, -HalfHeight,  -HalfLength);
		geVec3d_Set (&(FaceVerts[0]), HalfWidth,  -HalfHeight,  -HalfLength);
		f	=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		geVec3d_Set (&(FaceVerts[3]), -HalfWidth, HalfHeight,   HalfLength);
		geVec3d_Set (&(FaceVerts[2]), HalfWidth,  HalfHeight,   HalfLength);
		geVec3d_Set (&(FaceVerts[1]), HalfWidth,  -HalfHeight,  -HalfLength);
		geVec3d_Set (&(FaceVerts[0]), -HalfWidth, -HalfHeight,  -HalfLength);
		f	=Face_Create(4, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		geVec3d_Set (&(FaceVerts[2]), HalfWidth,  HalfHeight,   HalfLength);
		geVec3d_Set (&(FaceVerts[1]), HalfWidth,  -HalfHeight,  HalfLength);
		geVec3d_Set (&(FaceVerts[0]), HalfWidth,  -HalfHeight,  -HalfLength);
		f	=Face_Create(3, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		geVec3d_Set (&(FaceVerts[0]), -HalfWidth, HalfHeight,   HalfLength);
		geVec3d_Set (&(FaceVerts[1]), -HalfWidth, -HalfHeight,  HalfLength);
		geVec3d_Set (&(FaceVerts[2]), -HalfWidth, -HalfHeight,  -HalfLength);
		f	=Face_Create(3, FaceVerts, 0);
		if(f)
		{
			FaceList_AddFace(fl, f);
		}

		b	=Brush_Create(BRUSH_LEAF, fl, NULL);
	}
	else
	{
		float	StairYSize	=(geFloat)pTemplate->Height/(geFloat)pTemplate->NumberOfStairs;
		float	DZ			=(geFloat)pTemplate->Length/(geFloat)pTemplate->NumberOfStairs;
		float	ZSize		=(geFloat)pTemplate->Length;
		BrushTemplate_Box BoxTemplate;

		BoxTemplate.Solid = 0;
		BoxTemplate.TCut = pTemplate->TCut;
		BoxTemplate.Thickness = 0.0f;
		BoxTemplate.XSizeTop = pTemplate->Width;
		BoxTemplate.XSizeBot = pTemplate->Width;
		BoxTemplate.YSize = StairYSize;

		for(i=0;i < pTemplate->NumberOfStairs;i++)
		{
			BoxTemplate.ZSizeTop = ZSize;
			BoxTemplate.ZSizeBot = ZSize;
			BoxTemplate.TSheet	 = GE_FALSE;	// nasty, nasty, nasty
			b2 = BrushTemplate_CreateBox (&BoxTemplate);
			ZSize	-=DZ;
			geVec3d_Set(&v, 0.0f, i*StairYSize, (i*DZ)/2);
			Brush_Move(b2, &v);
			BrushList_Append(MBList, b2);
		}
		b	=Brush_Create(BRUSH_MULTI, NULL, MBList);
	}

	if(b)
	{
		Brush_SetSubtract(b, pTemplate->TCut);
	}

	return	b;
}
Esempio n. 18
0
/*!\todo Possibly make the import Undo-friendly by calling Undo_End for new brushes and ents */
void Map_ImportEntities( CPtrArray *ents, bool bAddSelected = false ){
	int num_ents, num_brushes;
	CPtrArray *brushes;
	vec3_t mins, maxs;
	entity_t *e;
	brush_t *b;
	face_t *f;
	int i,j;

	GPtrArray *new_ents = g_ptr_array_new();

	g_qeglobals.bPrimitBrushes = false;

	brush_t *pBrushList = ( bAddSelected ) ? &selected_brushes : &active_brushes;

	bool bDoneBPCheck = false;
	g_qeglobals.bNeedConvert = false;
	// HACK: find out if this map file was a BP one
	// check the first brush in the file that is NOT a patch
	// this will not be necessary when we allow both formats in the same file
	num_ents = ents->GetSize();
	for ( i = 0; !bDoneBPCheck && i < num_ents; i++ )
	{
		e = (entity_t*)ents->GetAt( i );
		brushes = (CPtrArray*)e->pData;
		num_brushes = brushes->GetSize();
		for ( j = 0; !bDoneBPCheck && j < num_brushes; j++ )
		{
			/*!todo Allow mixing texdef formats per-face. */
			b = (brush_t *)brushes->GetAt( j );
			if ( b->patchBrush ) {
				continue;
			}
			bDoneBPCheck = true;
			int BP_param = -1;
			if ( b->bBrushDef && !g_qeglobals.m_bBrushPrimitMode ) {
				BP_param = 0;
			}
			else if ( !b->bBrushDef && g_qeglobals.m_bBrushPrimitMode ) {
				BP_param = 1;
			}

			if ( BP_param != -1 ) {
				switch ( BP_MessageBox( BP_param ) )
				{
				case 0:
					Map_FreeEntities( ents );
					return;
				case 1:
					g_qeglobals.bNeedConvert = true;
					break;
				case 2:
					g_qeglobals.bNeedConvert = false;
					break;
				}
			}
		}
	}

	// process the entities into the world geometry
	num_ents = ents->GetSize();
	for ( i = 0; i < num_ents; i++ )
	{
		num_brushes = 0;
		e = (entity_t*)ents->GetAt( i );
		brushes = (CPtrArray*)e->pData;

		num_brushes = brushes->GetSize();
		// link brushes into entity
		for ( j = 0; j < num_brushes; j++ )
		{
			Entity_LinkBrush( e, (brush_t *)brushes->GetAt( j ) );
			g_qeglobals.d_parsed_brushes++;
		}
		brushes->RemoveAll();
		delete brushes;
		e->pData = NULL;

		// set entity origin
		GetVectorForKey( e, "origin", e->origin );
		// set entity eclass
		/*!\todo Make SetKeyValue check for "classname" change and assign appropriate eclass */
		e->eclass = Eclass_ForName( ValueForKey( e, "classname" ),
									( e->brushes.onext != &e->brushes ) );

		// go through all parsed brushes and build stuff
		for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
		{
			for ( f = b->brush_faces; f != NULL; f = f->next )
			{
				f->pShader = QERApp_Shader_ForName( f->texdef.GetName() );
				f->d_texture = f->pShader->getTexture();
			}

			// when brushes are in final state, build the planes and windings
			// NOTE: also converts BP brushes if g_qeglobals.bNeedConvert is true
			Brush_Build( b );
		}

//#define TERRAIN_HACK
#undef TERRAIN_HACK

#ifdef TERRAIN_HACK
		if ( ( strcmp( ValueForKey( e, "terrain" ),"1" ) == 0 && strcmp( e->eclass->name,"func_group" ) == 0 ) ) {

			// two aux pointers to the shaders used in the terrain entity
			// we don't keep refcount on them since they are only temporary
			// this avoids doing expensive lookups by name for all faces
			IShader *pTerrainShader, *pCaulk;

			pTerrainShader = NULL;
			pCaulk = QERApp_Shader_ForName( SHADER_CAULK );

			for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
			{
				if ( pTerrainShader == NULL ) {
					for ( f = b->brush_faces; f != NULL; f = f->next )
						if ( strcmp( f->texdef.GetName(), SHADER_CAULK ) != 0 ) {
							pTerrainShader = f->pShader;
						}
				}

				if ( pTerrainShader ) {
					for ( f = b->brush_faces; f != NULL; f = f->next )
					{
						if ( strcmp( f->texdef.GetName(), SHADER_CAULK ) != 0 ) { // not caulk
							Face_SetShader( f, pTerrainShader->getName() );
						}
						else{
							Face_SetShader( f, pCaulk->getName() );
						}
					}
				}
				else{
					Sys_FPrintf( SYS_WRN, "WARNING: no terrain shader found for brush\n" );
				}
			}
		}
#endif

#define PATCH_HACK
#ifdef PATCH_HACK
		for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
		{
			// patch hack, to be removed when dependency on brush_faces is removed
			if ( b->patchBrush ) {
				Patch_CalcBounds( b->pPatch, mins, maxs );
				for ( int i = 0; i < 3; i++ )
				{
					if ( (int)mins[i] == (int)maxs[i] ) {
						mins[i] -= 4;
						maxs[i] += 4;
					}
				}
				Brush_Resize( b, mins, maxs );
				Brush_Build( b );
			}
		}
#endif
		// add brush for fixedsize entity
		if ( e->eclass->fixedsize ) {
			vec3_t mins, maxs;
			VectorAdd( e->eclass->mins, e->origin, mins );
			VectorAdd( e->eclass->maxs, e->origin, maxs );
			b = Brush_Create( mins, maxs, &e->eclass->texdef );
			Entity_LinkBrush( e, b );
			Brush_Build( b );
		}

		for ( b = e->brushes.onext; b != &e->brushes; b = b->onext )
			Brush_AddToList( b, pBrushList );

		if ( strcmp( e->eclass->name, "worldspawn" ) == 0 ) {
			if ( world_entity ) {
				while ( e->brushes.onext != &e->brushes )
				{
					b = e->brushes.onext;
					Entity_UnlinkBrush( b );
					Entity_LinkBrush( world_entity, b );
				}
				Entity_Free( e );
			}
			else
			{
				world_entity = e;
			}
		}
		else if ( strcmp( e->eclass->name, "group_info" ) == 0 ) {
			// it's a group thing!
			Group_Add( e );
			Entity_Free( e );
		}
		else
		{
			// fix target/targetname collisions
			if ( ( g_PrefsDlg.m_bDoTargetFix ) && ( strcmp( ValueForKey( e, "target" ), "" ) != 0 ) ) {
				GPtrArray *t_ents = g_ptr_array_new();
				entity_t *e_target;
				const char *target = ValueForKey( e, "target" );
				qboolean bCollision = FALSE;

				// check the current map entities for an actual collision
				for ( e_target = entities.next; e_target != &entities; e_target = e_target->next )
				{
					if ( !strcmp( target, ValueForKey( e_target, "target" ) ) ) {
						bCollision = TRUE;
						// make sure the collision is not between two imported entities
						for ( j = 0; j < (int)new_ents->len; j++ )
						{
							if ( e_target == g_ptr_array_index( new_ents, j ) ) {
								bCollision = FALSE;
							}
						}
					}
				}

				// find the matching targeted entity(s)
				if ( bCollision ) {
					for ( j = num_ents - 1; j > 0; j-- )
					{
						e_target = (entity_t*)ents->GetAt( j );
						if ( e_target != NULL && e_target != e ) {
							const char *targetname = ValueForKey( e_target, "targetname" );
							if ( ( targetname != NULL ) && ( strcmp( target, targetname ) == 0 ) ) {
								g_ptr_array_add( t_ents, (gpointer)e_target );
							}
						}
					}
					if ( t_ents->len > 0 ) {
						// link the first to get a unique target/targetname
						Entity_Connect( e, (entity_t*)g_ptr_array_index( t_ents,0 ) );
						// set the targetname of the rest of them manually
						for ( j = 1; j < (int)t_ents->len; j++ )
							SetKeyValue( (entity_t*)g_ptr_array_index( t_ents, j ), "targetname", ValueForKey( e, "target" ) );
					}
					g_ptr_array_free( t_ents, FALSE );
				}
			}

			// add the entity to the end of the entity list
			Entity_AddToList( e, &entities );
			g_qeglobals.d_num_entities++;

			// keep a list of ents added to avoid testing collisions against them
			g_ptr_array_add( new_ents, (gpointer)e );
		}
	}
	g_ptr_array_free( new_ents, FALSE );

	ents->RemoveAll();

	g_qeglobals.bNeedConvert = false;
}