示例#1
0
//===========================================================================
// this function sets the func_rotating_door in it's final position
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_PositionFuncRotatingBrush(entity_t *mapent, mapbrush_t *brush)
{
	int    spawnflags, i;
	float  distance;
	vec3_t movedir, angles, pos1, pos2;
	side_t *s;

	spawnflags = FloatForKey(mapent, "spawnflags");
	VectorClear(movedir);
	if (spawnflags & DOOR_X_AXIS)
	{
		movedir[2] = 1.0;       //roll
	}
	else if (spawnflags & DOOR_Y_AXIS)
	{
		movedir[0] = 1.0;       //pitch
	}
	else     // Z_AXIS
	{
		movedir[1] = 1.0;       //yaw

	}
	// check for reverse rotation
	if (spawnflags & DOOR_REVERSE)
	{
		VectorInverse(movedir);
	}

	distance = FloatForKey(mapent, "distance");
	if (!distance)
	{
		distance = 90;
	}

	GetVectorForKey(mapent, "angles", angles);
	VectorCopy(angles, pos1);
	VectorMA(angles, -distance, movedir, pos2);
	// if it starts open, switch the positions
	if (spawnflags & DOOR_START_OPEN)
	{
		VectorCopy(pos2, angles);
		VectorCopy(pos1, pos2);
		VectorCopy(angles, pos1);
		VectorInverse(movedir);
	} //end if
	  //
	for (i = 0; i < brush->numsides; i++)
	{
		s           = &brush->original_sides[i];
		s->planenum = AAS_TransformPlane(s->planenum, mapent->origin, pos2);
	} //end for
	  //
	FreeBrushWindings(brush);
	AAS_MakeBrushWindings(brush);
	AddBrushBevels(brush);
	FreeBrushWindings(brush);
} //end of the function AAS_PositionFuncRotatingBrush
示例#2
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void Q1_BSPBrushToMapBrush(bspbrush_t *bspbrush, entity_t *mapent)
{
    mapbrush_t *mapbrush;
    side_t *side;
    int i, besttexinfo;

    CheckBSPBrush(bspbrush);

    if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
        Error ("nummapbrushes == MAX_MAPFILE_BRUSHES");

    mapbrush = &mapbrushes[nummapbrushes];
    mapbrush->original_sides = &brushsides[nummapbrushsides];
    mapbrush->entitynum = mapent - entities;
    mapbrush->brushnum = nummapbrushes - mapent->firstbrush;
    mapbrush->leafnum = -1;
    mapbrush->numsides = 0;

    besttexinfo = TEXINFO_NODE;
    for (i = 0; i < bspbrush->numsides; i++)
    {
        if (!bspbrush->sides[i].winding) continue;
        //
        if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
            Error ("MAX_MAPFILE_BRUSHSIDES");
        side = &brushsides[nummapbrushsides];
        //the contents of the bsp brush is stored in the side variable
        side->contents = bspbrush->side;
        side->surf = 0;
        side->planenum = bspbrush->sides[i].planenum;
        side->texinfo = bspbrush->sides[i].texinfo;
        if (side->texinfo != TEXINFO_NODE)
        {
            //this brush side is textured
            side->flags |= SFL_TEXTURED;
            besttexinfo = side->texinfo;
        } //end if
        //
        nummapbrushsides++;
        mapbrush->numsides++;
    } //end for
    //
    if (besttexinfo == TEXINFO_NODE)
    {
        mapbrush->numsides = 0;
        q1_numclipbrushes++;
        return;
    } //end if
    //set the texinfo for all the brush sides without texture
    for (i = 0; i < mapbrush->numsides; i++)
    {
        if (mapbrush->original_sides[i].texinfo == TEXINFO_NODE)
        {
            mapbrush->original_sides[i].texinfo = besttexinfo;
        } //end if
    } //end for
    //contents of the brush
    mapbrush->contents = bspbrush->side;
    //
    if (create_aas)
    {
        //create the AAS brushes from this brush, add brush bevels
        AAS_CreateMapBrushes(mapbrush, mapent, true);
        return;
    } //end if
    //create windings for sides and bounds for brush
    MakeBrushWindings(mapbrush);
    //add brush bevels
    AddBrushBevels(mapbrush);
    //a new brush has been created
    nummapbrushes++;
    mapent->numbrushes++;
} //end of the function Q1_BSPBrushToMapBrush
示例#3
0
/*
=================
FinishBrush

produces a final brush based on the buildBrush->sides array
and links it to the current entity
=================
*/
brush_t *FinishBrush( void )
{
	brush_t		*b;
	
	// create windings for sides and bounds for brush
	if( !CreateBrushWindings( buildBrush ))
		return NULL;

	// origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
	// after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush
	if( buildBrush->compileFlags & C_ORIGIN )
	{
		char	string[32];
		vec3_t	size, movedir, origin;

		if( numEntities == 1 )
		{
			Msg( "Entity %i, Brush %i: origin brushes not allowed in world\n", mapEnt->mapEntityNum, entitySourceBrushes );
			return NULL;
		}
		
		// calcualte movedir (Xash 0.4 style)
		VectorAverage( buildBrush->mins, buildBrush->maxs, origin );
		VectorSubtract( buildBrush->maxs, buildBrush->mins, size );

		if( size[2] > size[0] && size[2] > size[1] )
            		VectorSet( movedir, 0.0f, 1.0f, 0.0f );	// x-rotate
		else if( size[1] > size[2] && size[1] > size[0] )
            		VectorSet( movedir, 1.0f, 0.0f, 0.0f );	// y-rotate
		else if( size[0] > size[2] && size[0] > size[1] )
			VectorSet( movedir, 0.0f, 0.0f, 1.0f );	// z-rotate
		else VectorClear( movedir ); // custom movedir

#if 0
		if( !VectorIsNull( movedir ))
		{
			com.snprintf( string, sizeof( string ), "%i %i %i", (int)movedir[0], (int)movedir[1], (int)movedir[2] );
			SetKeyValue( &entities[numEntities - 1], "movedir", string );
		}
#endif
		if(!VectorIsNull( origin ))
		{
			com.snprintf( string, sizeof( string ), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2] );
			SetKeyValue( &entities[numEntities - 1], "origin", string );
			VectorCopy( origin, entities[numEntities - 1].origin );
                    }

		// don't keep this brush
		return NULL;
	}
	
	// determine if the brush is an area portal
	if( buildBrush->compileFlags & C_AREAPORTAL )
	{
		if( numEntities != 1 )
		{
			Msg( "Entity %i, Brush %i: areaportals only allowed in world\n", mapEnt->mapEntityNum, entitySourceBrushes );
			return NULL;
		}
	}
	
	AddBrushBevels();
	
	b = CopyBrush( buildBrush );
	
	b->entityNum = mapEnt->mapEntityNum;
	b->brushNum = entitySourceBrushes;
	
	b->original = b;
	
	// link opaque brushes to head of list, translucent brushes to end
	if( b->opaque || mapEnt->lastBrush == NULL )
	{
		b->next = mapEnt->brushes;
		mapEnt->brushes = b;
		if( mapEnt->lastBrush == NULL )
			mapEnt->lastBrush = b;
	}
	else
	{
		b->next = NULL;
		mapEnt->lastBrush->next = b;
		mapEnt->lastBrush = b;
	}
	
	// link colorMod volume brushes to the entity directly
	if( b->contentShader != NULL && b->contentShader->colorMod != NULL && b->contentShader->colorMod->type == CM_VOLUME )
	{
		b->nextColorModBrush = mapEnt->colorModBrushes;
		mapEnt->colorModBrushes = b;
	}
	return b;
}
示例#4
0
文件: map.c 项目: TTimo/GtkRadiant
/*
=================
ParseBrush
=================
*/
void ParseBrush (entity_t *mapent)
{
	mapbrush_t		*b;
	int			i,j, k;
	int			mt;
	side_t		*side, *s2;
	int			planenum;
	brush_texture_t	td;
	int			planepts[3][3];

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Error ("nummapbrushes == MAX_MAP_BRUSHES");

	b = &mapbrushes[nummapbrushes];
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities-1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	do
	{
		if (!GetToken (true))
			break;
		if (!strcmp (token, "}") )
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Error ("MAX_MAP_BRUSHSIDES");
		side = &brushsides[nummapbrushsides];

		// read the three point plane definition
		for (i=0 ; i<3 ; i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Error ("parsing brush");
			
			for (j=0 ; j<3 ; j++)
			{
				GetToken (false);
				planepts[i][j] = atoi(token);
			}
			
			GetToken (false);
			if (strcmp (token, ")") )
				Error ("parsing brush");
				
		}


		//
		// read the texturedef
		//
		GetToken (false);
		strcpy (td.name, token);

		GetToken (false);
		td.shift[0] = atoi(token);
		GetToken (false);
		td.shift[1] = atoi(token);
		GetToken (false);
		td.rotate = atoi(token);	
		GetToken (false);
		td.scale[0] = atof(token);
		GetToken (false);
		td.scale[1] = atof(token);

		// find default flags and values
		mt = FindMiptex (td.name);
		td.flags = textureref[mt].flags;
		td.value = textureref[mt].value;
		side->contents = textureref[mt].contents;
		side->surf = td.flags = textureref[mt].flags;

		if (TokenAvailable())
		{
			GetToken (false);
			side->contents = atoi(token);
			GetToken (false);
			side->surf = td.flags = atoi(token);
			GetToken (false);
			td.value = atoi(token);
		}

		// translucent objects are automatically classified as detail
		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
			side->contents |= CONTENTS_DETAIL;
		if (fulldetail)
			side->contents &= ~CONTENTS_DETAIL;
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
			side->contents |= CONTENTS_SOLID;

		// hints and skips are never detail, and have no content
		if (side->surf & (SURF_HINT|SURF_SKIP) )
		{
			side->contents = 0;
			side->surf &= ~CONTENTS_DETAIL;
		}


		//
		// find the plane number
		//
		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
		if (planenum == -1)
		{
			printf ("Entity %i, Brush %i: plane with no normal\n"
				, b->entitynum, b->brushnum);
			continue;
		}

		//
		// see if the plane has been used already
		//
		for (k=0 ; k<b->numsides ; k++)
		{
			s2 = b->original_sides + k;
			if (s2->planenum == planenum)
			{
				printf ("Entity %i, Brush %i: duplicate plane\n"
					, b->entitynum, b->brushnum);
				break;
			}
			if ( s2->planenum == (planenum^1) )
			{
				printf ("Entity %i, Brush %i: mirrored plane\n"
					, b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
			continue;		// duplicated

		//
		// keep this side
		//

		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
			&td, vec3_origin);

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		side_brushtextures[nummapbrushsides] = td;

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	// get the content for the entire brush
	b->contents = BrushContents (b);

	// allow detail brushes to be removed 
	if (nodetail && (b->contents & CONTENTS_DETAIL) )
	{
		b->numsides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
	{
		b->numsides = 0;
		return;
	}

	// create windings for sides and bounds for brush
	MakeBrushWindings (b);

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
	{
		c_clipbrushes++;
		for (i=0 ; i<b->numsides ; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	//
	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity.  After the entire entity is parsed,
	// the planenums and texinfos will be adjusted for
	// the origin brush
	//
	if (b->contents & CONTENTS_ORIGIN)
	{
		char	string[32];
		vec3_t	origin;

		if (num_entities == 1)
		{
			Error ("Entity %i, Brush %i: origin brushes not allowed in world"
				, b->entitynum, b->brushnum);
			return;
		}

		VectorAdd (b->mins, b->maxs, origin);
		VectorScale (origin, 0.5, origin);

		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue (&entities[b->entitynum], "origin", string);

		VectorCopy (origin, entities[b->entitynum].origin);

		// don't keep this brush
		b->numsides = 0;

		return;
	}

	AddBrushBevels (b);

	nummapbrushes++;
	mapent->numbrushes++;		
}
示例#5
0
void AAS_CreateCurveBrushes(void)
{
	int i, j, n, planenum, numcurvebrushes = 0;
	q3_dsurface_t *surface;
	q3_drawVert_t *dv_p;
	vec3_t points[MAX_PATCH_VERTS];
	int width, height, c;
	patchCollide_t *pc;
	facet_t *facet;
	mapbrush_t *brush;
	side_t *side;
	entity_t *mapent;
	winding_t *winding;

	qprintf("nummapbrushsides = %d\n", nummapbrushsides);
	mapent = &entities[0];

	for(i = 0; i < q3_numDrawSurfaces; i++)
	{
		surface = &q3_drawSurfaces[i];

		if(!surface->patchWidth)
		{
			continue;
		}

		//if the curve is not solid
		if(!(q3_dshaders[surface->shaderNum].contentFlags & (CONTENTS_SOLID | CONTENTS_PLAYERCLIP)))
		{
			//Log_Print("skipped non-solid curve\n");
			continue;
		} //end if

		//
		width = surface->patchWidth;
		height = surface->patchHeight;
		c = width * height;

		if(c > MAX_PATCH_VERTS)
		{
			Error("ParseMesh: MAX_PATCH_VERTS");
		} //end if

		dv_p = q3_drawVerts + surface->firstVert;

		for(j = 0 ; j < c ; j++, dv_p++)
		{
			points[j][0] = dv_p->xyz[0];
			points[j][1] = dv_p->xyz[1];
			points[j][2] = dv_p->xyz[2];
		} //end for

		// create the internal facet structure
		pc = CM_GeneratePatchCollide(width, height, points);

		//
		for(j = 0; j < pc->numFacets; j++)
		{
			facet = &pc->facets[j];
			//
			brush = &mapbrushes[nummapbrushes];
			brush->original_sides = &brushsides[nummapbrushsides];
			brush->entitynum = 0;
			brush->brushnum = nummapbrushes - mapent->firstbrush;
			//
			brush->numsides = facet->numBorders + 2;
			nummapbrushsides += brush->numsides;
			brush->contents = CONTENTS_SOLID;
			//
			//qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
			qprintf("\r%6d curve brushes", ++numcurvebrushes);
			//
			planenum = FindFloatPlane(pc->planes[facet->surfacePlane].plane, pc->planes[facet->surfacePlane].plane[3]);
			//
			side = &brush->original_sides[0];
			side->planenum = planenum;
			side->contents = CONTENTS_SOLID;
			side->flags |= SFL_TEXTURED | SFL_VISIBLE | SFL_CURVE;
			side->surf = 0;
			//
			side = &brush->original_sides[1];

			if(create_aas)
			{
				//the plane is expanded later so it's not a problem that
				//these first two opposite sides are coplanar
				side->planenum = planenum ^ 1;
			} //end if
			else
			{
				side->planenum = FindFloatPlane(mapplanes[planenum ^ 1].normal, mapplanes[planenum ^ 1].dist + 1);
				side->flags |= SFL_TEXTURED | SFL_VISIBLE;
			} //end else

			side->contents = CONTENTS_SOLID;
			side->flags |= SFL_CURVE;
			side->surf = 0;
			//
			winding = BaseWindingForPlane(mapplanes[side->planenum].normal, mapplanes[side->planenum].dist);

			for(n = 0; n < facet->numBorders; n++)
			{
				//never use the surface plane as a border
				if(facet->borderPlanes[n] == facet->surfacePlane)
				{
					continue;
				}

				//
				side = &brush->original_sides[2 + n];
				side->planenum = FindFloatPlane(pc->planes[facet->borderPlanes[n]].plane, pc->planes[facet->borderPlanes[n]].plane[3]);

				if(facet->borderInward[n])
				{
					side->planenum ^= 1;
				}

				side->contents = CONTENTS_SOLID;
				side->flags |= SFL_TEXTURED | SFL_CURVE;
				side->surf = 0;

				//chop the winding in place
				if(winding)
				{
					ChopWindingInPlace(&winding, mapplanes[side->planenum ^ 1].normal, mapplanes[side->planenum ^ 1].dist, 0.1);      //CLIP_EPSILON);
				}
			} //end for

			//VectorCopy(pc->bounds[0], brush->mins);
			//VectorCopy(pc->bounds[1], brush->maxs);
			if(!winding)
			{
				Log_Print("WARNING: AAS_CreateCurveBrushes: no winding\n");
				brush->numsides = 0;
				continue;
			} //end if

			brush->original_sides[0].winding = winding;
			WindingBounds(winding, brush->mins, brush->maxs);

			for(n = 0; n < 3; n++)
			{
				//IDBUG: all the indexes into the mins and maxs were zero (not using i)
				if(brush->mins[n] < -MAX_MAP_BOUNDS || brush->maxs[n] > MAX_MAP_BOUNDS)
				{
					Log_Print("entity %i, brush %i: bounds out of range\n", brush->entitynum, brush->brushnum);
					Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
					brush->numsides = 0; //remove the brush
					break;
				} //end if

				if(brush->mins[n] > MAX_MAP_BOUNDS || brush->maxs[n] < -MAX_MAP_BOUNDS)
				{
					Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
					Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
					brush->numsides = 0; //remove the brush
					break;
				} //end if
			} //end for

			if(create_aas)
			{
				//NOTE: brush bevels now already added
				//AddBrushBevels(brush);
				AAS_CreateMapBrushes(brush, mapent, false);
			} //end if
			else
			{
				// create windings for sides and bounds for brush
				MakeBrushWindings(brush);
				AddBrushBevels(brush);
				nummapbrushes++;
				mapent->numbrushes++;
			} //end else
		} //end for
	} //end for

	//qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
	qprintf("\r%6d curve brushes\n", numcurvebrushes);
} //end of the function AAS_CreateCurveBrushes
示例#6
0
文件: map.c 项目: EEmmanuel7/quetoo
/*
 * @brief
 */
static void ParseBrush(entity_t *mapent) {
	map_brush_t *b;
	int32_t i, j, k;
	side_t *side, *s2;
	int32_t plane_num;
	map_brush_texture_t td;
	vec3_t planepts[3];

	if (num_map_brushes == MAX_BSP_BRUSHES)
		Com_Error(ERR_FATAL, "MAX_BSP_BRUSHES\n");

	b = &map_brushes[num_map_brushes];
	b->original_sides = &map_brush_sides[num_map_brush_sides];
	b->entity_num = num_entities - 1;
	b->brush_num = num_map_brushes - mapent->first_brush;

	do {
		if (!GetToken(true))
			break;
		if (!g_strcmp0(token, "}"))
			break;

		if (num_map_brush_sides == MAX_BSP_BRUSH_SIDES)
			Com_Error(ERR_FATAL, "MAX_BSP_BRUSH_SIDES\n");
		side = &map_brush_sides[num_map_brush_sides];

		// read the three point plane definition
		for (i = 0; i < 3; i++) {
			if (i != 0)
				GetToken(true);
			if (g_strcmp0(token, "("))
				Com_Error(ERR_FATAL, "Parsing brush\n");

			for (j = 0; j < 3; j++) {
				GetToken(false);
				planepts[i][j] = atof(token);
			}

			GetToken(false);
			if (g_strcmp0(token, ")"))
				Com_Error(ERR_FATAL, "Parsing brush\n");
		}

		memset(&td, 0, sizeof(td));

		// read the texturedef
		GetToken(false);

		if (strlen(token) > sizeof(td.name) - 1)
			Com_Error(ERR_FATAL, "Texture name \"%s\" is too long.\n", token);

		g_strlcpy(td.name, token, sizeof(td.name));

		GetToken(false);
		td.shift[0] = atoi(token);
		GetToken(false);
		td.shift[1] = atoi(token);
		GetToken(false);
		td.rotate = atoi(token);
		GetToken(false);
		td.scale[0] = atof(token);
		GetToken(false);
		td.scale[1] = atof(token);

		if (TokenAvailable()) {
			GetToken(false);
			side->contents = atoi(token);
			GetToken(false);
			side->surf = td.flags = atoi(token);
			GetToken(false);
			td.value = atoi(token);
		} else {
			side->contents = CONTENTS_SOLID;
			side->surf = td.flags = 0;
			td.value = 0;
		}

		// resolve implicit surface and contents flags
		SetImpliedFlags(side, td.name);

		// translucent objects are automatically classified as detail
		if (side->surf & (SURF_ALPHA_TEST | SURF_BLEND_33 | SURF_BLEND_66))
			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYER_CLIP | CONTENTS_MONSTER_CLIP))
			side->contents |= CONTENTS_DETAIL;
		if (fulldetail)
			side->contents &= ~CONTENTS_DETAIL;
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS - 1) | CONTENTS_PLAYER_CLIP
				| CONTENTS_MONSTER_CLIP | CONTENTS_MIST)))
			side->contents |= CONTENTS_SOLID;

		// hints and skips are never detail, and have no content
		if (side->surf & (SURF_HINT | SURF_SKIP)) {
			side->contents = 0;
			side->surf &= ~CONTENTS_DETAIL;
		}

		// find the plane number
		plane_num = PlaneFromPoints(planepts[0], planepts[1], planepts[2]);
		if (plane_num == -1) {
			Com_Verbose("Entity %i, Brush %i: plane with no normal\n", b->entity_num, b->brush_num);
			continue;
		}

		// see if the plane has been used already
		for (k = 0; k < b->num_sides; k++) {
			s2 = b->original_sides + k;
			if (s2->plane_num == plane_num) {
				Com_Verbose("Entity %i, Brush %i: duplicate plane\n", b->entity_num, b->brush_num);
				break;
			}
			if (s2->plane_num == (plane_num ^ 1)) {
				Com_Verbose("Entity %i, Brush %i: mirrored plane\n", b->entity_num, b->brush_num);
				break;
			}
		}
		if (k != b->num_sides)
			continue; // duplicated

		// keep this side
		side = b->original_sides + b->num_sides;
		side->plane_num = plane_num;
		side->texinfo = TexinfoForBrushTexture(&map_planes[plane_num], &td, vec3_origin);

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		map_brush_textures[num_map_brush_sides] = td;

		num_map_brush_sides++;
		b->num_sides++;
	} while (true);

	// get the content for the entire brush
	b->contents = BrushContents(b);

	// allow detail brushes to be removed
	if (nodetail && (b->contents & CONTENTS_DETAIL)) {
		b->num_sides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & MASK_LIQUID)) {
		b->num_sides = 0;
		return;
	}

	// create windings for sides and bounds for brush
	MakeBrushWindings(b);

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYER_CLIP | CONTENTS_MONSTER_CLIP)) {
		c_clip_brushes++;
		for (i = 0; i < b->num_sides; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity. After the entire entity is parsed,
	// the plane_nums and texinfos will be adjusted for
	// the origin brush
	if (b->contents & CONTENTS_ORIGIN) {
		char string[32];
		vec3_t origin;

		if (num_entities == 1) {
			Com_Error(ERR_FATAL,
					"Entity %i, Brush %i: origin brushes not allowed in world\n",
					b->entity_num, b->brush_num);
			return;
		}

		VectorAdd(b->mins, b->maxs, origin);
		VectorScale(origin, 0.5, origin);

		sprintf(string, "%i %i %i", (int32_t)origin[0], (int32_t)origin[1],
				(int32_t)origin[2]);
		SetKeyValue(&entities[b->entity_num], "origin", string);

		VectorCopy(origin, entities[b->entity_num].origin);

		// don't keep this brush
		b->num_sides = 0;

		return;
	}

	AddBrushBevels(b);

	num_map_brushes++;
	mapent->num_brushes++;
}
示例#7
0
/*
=================
Q2_ParseBrush
=================
*/
void Q2_ParseBrush(script_t *script, entity_t *mapent)
{
	mapbrush_t      *b;
	int             i, j, k;
	int             mt;
	side_t          *side, *s2;
	int             planenum;
	brush_texture_t td;
	int             planepts[3][3];
	token_t         token;

	if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
	{
		Error("nummapbrushes == MAX_MAPFILE_BRUSHES");
	}

	b                 = &mapbrushes[nummapbrushes];
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum      = num_entities - 1;
	b->brushnum       = nummapbrushes - mapent->firstbrush;
	b->leafnum        = -1;

	do
	{
		if (!PS_ReadToken(script, &token))
		{
			break;
		}
		if (!strcmp(token.string, "}"))
		{
			break;
		}

		//IDBUG: mixed use of MAX_MAPFILE_? and MAX_MAP_? this could
		//			lead to out of bound indexing of the arrays
		if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
		{
			Error("MAX_MAPFILE_BRUSHSIDES");
		}
		side = &brushsides[nummapbrushsides];

		//read the three point plane definition
		for (i = 0; i < 3; i++)
		{
			if (i != 0)
			{
				PS_ExpectTokenString(script, "(");
			}
			for (j = 0; j < 3; j++)
			{
				PS_ExpectAnyToken(script, &token);
				planepts[i][j] = atof(token.string);
			} //end for
			PS_ExpectTokenString(script, ")");
		} //end for

		//
		//read the texturedef
		//
		PS_ExpectAnyToken(script, &token);
		strcpy(td.name, token.string);

		PS_ExpectAnyToken(script, &token);
		td.shift[0] = atol(token.string);
		PS_ExpectAnyToken(script, &token);
		td.shift[1] = atol(token.string);
		PS_ExpectAnyToken(script, &token);
		td.rotate = atol(token.string);
		PS_ExpectAnyToken(script, &token);
		td.scale[0] = atof(token.string);
		PS_ExpectAnyToken(script, &token);
		td.scale[1] = atof(token.string);

		//find default flags and values
		mt             = FindMiptex(td.name);
		td.flags       = textureref[mt].flags;
		td.value       = textureref[mt].value;
		side->contents = textureref[mt].contents;
		side->surf     = td.flags = textureref[mt].flags;

		//check if there's a number available
		if (PS_CheckTokenType(script, TT_NUMBER, 0, &token))
		{
			side->contents = token.intvalue;
			PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
			side->surf = td.flags = token.intvalue;
			PS_ExpectTokenType(script, TT_NUMBER, 0, &token);
			td.value = token.intvalue;
		}

		// translucent objects are automatically classified as detail
//		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
//			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP))
		{
			side->contents |= CONTENTS_DETAIL;
		}
		if (fulldetail)
		{
			side->contents &= ~CONTENTS_DETAIL;
		}
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS - 1)
		                        | CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP | CONTENTS_MIST)))
		{
			side->contents |= CONTENTS_SOLID;
		}

		// hints and skips are never detail, and have no content
//		if (side->surf & (SURF_HINT|SURF_SKIP) )
//		{
//			side->contents = 0;
//			side->surf &= ~CONTENTS_DETAIL;
//		}

#ifdef ME
		//for creating AAS... this side is textured
		side->flags |= SFL_TEXTURED;
#endif //ME
		//
		// find the plane number
		//
		planenum = PlaneFromPoints(planepts[0], planepts[1], planepts[2]);
		if (planenum == -1)
		{
			Log_Print("Entity %i, Brush %i: plane with no normal\n"
			          , b->entitynum, b->brushnum);
			continue;
		}

		//
		// see if the plane has been used already
		//
		for (k = 0 ; k < b->numsides ; k++)
		{
			s2 = b->original_sides + k;
			if (s2->planenum == planenum)
			{
				Log_Print("Entity %i, Brush %i: duplicate plane\n"
				          , b->entitynum, b->brushnum);
				break;
			}
			if (s2->planenum == (planenum ^ 1))
			{
				Log_Print("Entity %i, Brush %i: mirrored plane\n"
				          , b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
		{
			continue;       // duplicated

		}
		//
		// keep this side
		//

		side           = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo  = TexinfoForBrushTexture(&mapplanes[planenum],
		                                        &td, vec3_origin);

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		side_brushtextures[nummapbrushsides] = td;

		nummapbrushsides++;
		b->numsides++;
	}
	while (1);

	// get the content for the entire brush
	b->contents = Q2_BrushContents(b);

#ifdef ME
	if (BrushExists(b))
	{
		c_squattbrushes++;
		b->numsides = 0;
		return;
	} //end if

	if (create_aas)
	{
		//create AAS brushes, and add brush bevels
		AAS_CreateMapBrushes(b, mapent, true);
		//NOTE: if we return here then duplicate plane errors occur for the non world entities
		return;
	} //end if
#endif //ME

	// allow detail brushes to be removed
	if (nodetail && (b->contents & CONTENTS_DETAIL))
	{
		b->numsides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)))
	{
		b->numsides = 0;
		return;
	}

	// create windings for sides and bounds for brush
	MakeBrushWindings(b);

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYERCLIP | CONTENTS_MONSTERCLIP))
	{
		c_clipbrushes++;
		for (i = 0 ; i < b->numsides ; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	//
	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity.  After the entire entity is parsed,
	// the planenums and texinfos will be adjusted for
	// the origin brush
	//
	if (b->contents & CONTENTS_ORIGIN)
	{
		char   string[32];
		vec3_t origin;

		if (num_entities == 1)
		{
			Error("Entity %i, Brush %i: origin brushes not allowed in world"
			      , b->entitynum, b->brushnum);
			return;
		}

		VectorAdd(b->mins, b->maxs, origin);
		VectorScale(origin, 0.5, origin);

		sprintf(string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue(&entities[b->entitynum], "origin", string);

		VectorCopy(origin, entities[b->entitynum].origin);

		// don't keep this brush
		b->numsides = 0;

		return;
	}

	AddBrushBevels(b);

	nummapbrushes++;
	mapent->numbrushes++;
}
示例#8
0
/*
=================
ParseBrush
=================
*/
void ParseBrush (entity_t *mapent)
{
	char *tl;
	mapbrush_t		*b;
	int			i,j, k;
	int			mt;
	side_t		*side, *s2;
	int			planenum;
	brush_texture_t	td;
	float			planepts[3][3];
	qboolean		phongShading;

	MarkBrushBegin();

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Error ("nummapbrushes == MAX_MAP_BRUSHES");

	b = &mapbrushes[nummapbrushes];
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities-1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	// Knightmare added
	b->optimizedDetail = false;
	b->isTerrain = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname"))
				&& strlen(ValueForKey (&entities[b->entitynum], "terrain")) > 0);
	b->isGenSurf = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname"))
				&& strlen(ValueForKey (&entities[b->entitynum], "gensurf")) > 0);
	phongShading = (!strcmp("func_group", ValueForKey (&entities[b->entitynum], "classname"))
				&& strlen(ValueForKey (&entities[b->entitynum], "phongshading")) > 0);
	//if (b->isTerrain) 
	//	printf ("Brush number %i in enitity number %i has terrain flag set.\n", b->brushnum, b->entitynum);
	//if (b->phongShading) 
	//	printf ("Brush number %i in enitity number %i has phong shading flag set.\n", b->brushnum, b->entitynum);
	if (verbosebrushes)
		printf ("enitity %i, brush  %i\n", b->entitynum, b->brushnum);
	// end Knightmare

	do
	{
		if (!GetToken (true))
			break;
		if (!strcmp (token, "}") )
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Error ("MAX_MAP_BRUSHSIDES");
		side = &brushsides[nummapbrushsides];

		// read the three point plane definition
		for (i=0 ; i<3 ; i++)
		{
			if (i != 0)
				GetToken (true);
			if (strcmp (token, "(") )
				Error ("parsing brush\n  Brush: %s", i+1, brush_info);
			
			for (j=0 ; j<3 ; j++)
			{
				GetToken (false);
				planepts[i][j] = atof(token);
			}
			
			GetToken (false);
			if (strcmp (token, ")") )
				Error ("parsing brush\n  Brush: %s", i+1, brush_info);
				
		}

		//
		// read the texturedef
		//
		GetToken (false);
        strcpy (td.name, token);

		tl = td.name;

		for(tl = td.name; *tl != 0; tl++)
			*tl = tolower(*tl);

		GetToken (false);
		td.shift[0] = atoi(token);
		GetToken (false);
		td.shift[1] = atoi(token);
		GetToken (false);
		td.rotate = atoi(token);	
		GetToken (false);
		td.scale[0] = atof(token);
		GetToken (false);
		td.scale[1] = atof(token);

		// find default flags and values
		mt = FindMiptex (td.name);
		td.flags = textureref[mt].flags;
		td.value = textureref[mt].value;
		side->contents = textureref[mt].contents;
		side->surf = td.flags = textureref[mt].flags;

		if (TokenAvailable())
		{
			GetToken (false);
			side->contents = atoi(token);
			GetToken (false);
			side->surf = td.flags = atoi(token);
			GetToken (false);
			td.value = atoi(token);
		}

		// translucent objects are automatically classified as detail
		if (side->surf & (SURF_TRANS33|SURF_TRANS66|SURF_ALPHATEST) ) // Knightmare- added alphatest
			side->contents |= CONTENTS_DETAIL;
		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
			side->contents |= CONTENTS_DETAIL;
		if (fulldetail)
			side->contents &= ~CONTENTS_DETAIL;
		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
			side->contents |= CONTENTS_SOLID;

		// hints and skips are never detail, and have no content
		if (side->surf & (SURF_HINT|SURF_SKIP) )
		{
			//side->contents = 0;
			//side->surf &= ~CONTENTS_DETAIL;
			side->contents &= CONTENTS_DETAIL; // allow only detail content- Geoffery DeWan?
		}

		//
		// find the plane number
		//
		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
		if (planenum == -1)
		{
			printf ("Entity %i, Brush %i: plane with no normal\n  Brush: %s\n"
				, b->entitynum, b->brushnum, brush_info);
			continue;
		}

		//
		// see if the plane has been used already
		//
		for (k=0 ; k<b->numsides ; k++)
		{
			s2 = b->original_sides + k;
			if (s2->planenum == planenum)
			{
				printf ("Entity %i, Brush %i: duplicate plane\n  Brush: %s\n"
					, b->entitynum, b->brushnum, brush_info);
				break;
			}
			if ( s2->planenum == (planenum^1) )
			{
				printf ("Entity %i, Brush %i: mirrored plane\n  Brush: %s\n"
					, b->entitynum, b->brushnum, brush_info);
				break;
			}
		}
		if (k != b->numsides)
			continue;		// duplicated

		//
		// keep this side
		//

		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
			&td, vec3_origin, b->isTerrain); // Knightmare added

		// save the td off in case there is an origin brush and we
		// have to recalculate the texinfo
		side_brushtextures[nummapbrushsides] = td;

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	// get the content for the entire brush
	b->contents = BrushContents (b);

	// allow detail brushes to be removed 
	if (nodetail && (b->contents & CONTENTS_DETAIL) )
	{
		b->numsides = 0;
		return;
	}

	// allow water brushes to be removed
	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
	{
		b->numsides = 0;
		return;
	}

	// Knightmare- check if this is an optimized detail brush (has caulk faces)
	// also exclude trans brushes and terrain
	if ((b->contents & CONTENTS_DETAIL) && (b->contents & CONTENTS_SOLID) && !b->isTerrain && !b->isGenSurf)
		for (i=0; i<b->numsides; i++)
		{
			if ( !strcmp(texinfo[b->original_sides[i].texinfo].texture, "system/caulk")
				|| !strcmp(texinfo[b->original_sides[i].texinfo].texture, "common/caulk") )
			{
				b->optimizedDetail = true;
				//printf ("Entity %i, Brush %i: optimized detail\n", b->entitynum, b->brushnum);
				break;
			}
		}

	// Knightmare- special handling for terrain brushes
	if (b->isTerrain || b->isGenSurf || phongShading)
		for (i=0; i<b->numsides; i++)
		{
			s2 = &b->original_sides[i];
			// set ArghRad phong shading value (because EasyGen/GTKGenSurf doesn't allow this)
			if (strcmp(texinfo[b->original_sides[i].texinfo].texture, "system/caulk")
				&& strcmp(texinfo[b->original_sides[i].texinfo].texture, "common/caulk"))
			{
				texinfo[s2->texinfo].value = 777 + b->entitynum;	// lucky 7's
				texinfo[s2->texinfo].flags &= ~SURF_LIGHT;			// must not be light-emitting
			}
		}

	// create windings for sides and bounds for brush

	// MEM_LEAK
	MakeBrushWindings (b);
	t_w = b->original_sides[0].winding;

	// brushes that will not be visible at all will never be
	// used as bsp splitters
	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
	{
		c_clipbrushes++;
		for (i=0 ; i<b->numsides ; i++)
			b->original_sides[i].texinfo = TEXINFO_NODE;
	}

	//
	// origin brushes are removed, but they set
	// the rotation origin for the rest of the brushes
	// in the entity.  After the entire entity is parsed,
	// the planenums and texinfos will be adjusted for
	// the origin brush
	//
	if (b->contents & CONTENTS_ORIGIN)
	{
		char	string[32];
		vec3_t	origin;

		if (num_entities == 1)
		{
			Error ("Entity %i, Brush %i: origin brushes not allowed in world\n  BrushL %s",
				b->entitynum, b->brushnum, brush_info);
			return;
		}

		VectorAdd (b->mins, b->maxs, origin);
		VectorScale (origin, 0.5, origin);

		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue (&entities[b->entitynum], "origin", string);

		VectorCopy (origin, entities[b->entitynum].origin);

		// don't keep this brush
		b->numsides = 0;

		return;
	}

	AddBrushBevels (b);

	nummapbrushes++;
	mapent->numbrushes++;		
}
示例#9
0
文件: map.cpp 项目: nicogiraldi/ufoai
/**
 * @brief Parses a brush from the map file
 * @sa FindMiptex
 * @param[in] mapent The entity the brush to parse belongs to
 * @param[in] filename The map filename, used to derive the name for the footsteps file
 */
static void ParseBrush (entity_t* mapent, const char* filename)
{
	int j, k;
	brush_texture_t td;
	vec3_t planepts[3];
	const int checkOrFix = config.performMapCheck || config.fixMap ;

	if (nummapbrushes == MAX_MAP_BRUSHES)
		Sys_Error("nummapbrushes == MAX_MAP_BRUSHES (%i)", nummapbrushes);

	mapbrush_t* b = &mapbrushes[nummapbrushes];
	OBJZERO(*b);
	b->original_sides = &brushsides[nummapbrushsides];
	b->entitynum = num_entities - 1;
	b->brushnum = nummapbrushes - mapent->firstbrush;

	do {
		if (Q_strnull(GetToken()))
			break;
		if (*parsedToken == '}')
			break;

		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
			Sys_Error("nummapbrushsides == MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides);
		side_t* side = &brushsides[nummapbrushsides];

		/* read the three point plane definition */
		for (int i = 0; i < 3; i++) {
			if (i != 0)
				GetToken();
			if (*parsedToken != '(')
				Sys_Error("parsing brush");

			for (j = 0; j < 3; j++) {
				GetToken();
				planepts[i][j] = atof(parsedToken);
			}

			GetToken();
			if (*parsedToken != ')')
				Sys_Error("parsing brush");
		}

		/* read the texturedef */
		GetToken();
		if (strlen(parsedToken) >= MAX_TEXPATH) {
			if (config.performMapCheck || config.fixMap)
				Com_Printf("  ");/* hack to make this look like output from Check_Printf() */
			Com_Printf("ParseBrush: texture name too long (limit %i): %s\n", MAX_TEXPATH, parsedToken);
			if (config.fixMap)
				Sys_Error("Aborting, as -fix is active and saving might corrupt *.map by truncating texture name");
		}
		Q_strncpyz(td.name, parsedToken, sizeof(td.name));

		td.shift[0] = atof(GetToken());
		td.shift[1] = atof(GetToken());
		td.rotate = atof(GetToken());
		td.scale[0] = atof(GetToken());
		td.scale[1] = atof(GetToken());

		/* find default flags and values */
		const int mt = FindMiptex(td.name);
		side->surfaceFlags = td.surfaceFlags = side->contentFlags = td.value = 0;

		if (TokenAvailable()) {
			side->contentFlags = atoi(GetToken());
			side->surfaceFlags = td.surfaceFlags = atoi(GetToken());
			td.value = atoi(GetToken());
		}

		/* if in check or fix mode, let them choose to do this (with command line options),
		 * and then call is made elsewhere */
		if (!checkOrFix) {
			SetImpliedFlags(side, &td, b);
			/* if no other content flags are set - make this solid */
			if (!checkOrFix && side->contentFlags == 0)
				side->contentFlags = CONTENTS_SOLID;
		}

		/* translucent objects are automatically classified as detail and window */
		if (side->surfaceFlags & (SURF_BLEND33 | SURF_BLEND66 | SURF_ALPHATEST)) {
			side->contentFlags |= CONTENTS_DETAIL;
			side->contentFlags |= CONTENTS_TRANSLUCENT;
			side->contentFlags |= CONTENTS_WINDOW;
			side->contentFlags &= ~CONTENTS_SOLID;
		}
		if (config.fulldetail)
			side->contentFlags &= ~CONTENTS_DETAIL;
		if (!checkOrFix) {
			if (!(side->contentFlags & ((LAST_VISIBLE_CONTENTS - 1)
				| CONTENTS_ACTORCLIP | CONTENTS_WEAPONCLIP | CONTENTS_LIGHTCLIP)))
				side->contentFlags |= CONTENTS_SOLID;

			/* hints and skips are never detail, and have no content */
			if (side->surfaceFlags & (SURF_HINT | SURF_SKIP)) {
				side->contentFlags = 0;
				side->surfaceFlags &= ~CONTENTS_DETAIL;
			}
		}

		/* check whether the flags are ok */
		CheckFlags(side, b);

		/* generate a list of textures that should have footsteps when walking on them */
		if (mt > 0 && (side->surfaceFlags & SURF_FOOTSTEP))
			GenerateFootstepList(filename, mt);
		GenerateMaterialFile(filename, mt, side);

		/* find the plane number */
		int planenum = PlaneFromPoints(b, planepts[0], planepts[1], planepts[2]);
		if (planenum == PLANENUM_LEAF) {
			Com_Printf("Entity %i, Brush %i: plane with no normal\n", b->entitynum, b->brushnum);
			continue;
		}

		for (j = 0; j < 3; j++)
			VectorCopy(planepts[j], mapplanes[planenum].planeVector[j]);

		/* see if the plane has been used already */
		for (k = 0; k < b->numsides; k++) {
			const side_t* s2 = b->original_sides + k;
			if (s2->planenum == planenum) {
				Com_Printf("Entity %i, Brush %i: duplicate plane\n", b->entitynum, b->brushnum);
				break;
			}
			if (s2->planenum == (planenum ^ 1)) {
				Com_Printf("Entity %i, Brush %i: mirrored plane\n", b->entitynum, b->brushnum);
				break;
			}
		}
		if (k != b->numsides)
			continue;		/* duplicated */

		/* keep this side */
		side = b->original_sides + b->numsides;
		side->planenum = planenum;
		side->texinfo = TexinfoForBrushTexture(&mapplanes[planenum],
			&td, vec3_origin, side->contentFlags & CONTENTS_TERRAIN);
		side->brush = b;

		/* save the td off in case there is an origin brush and we
		 * have to recalculate the texinfo */
		side_brushtextures[nummapbrushsides] = td;

		Verb_Printf(VERB_DUMP, "Brush %i Side %i (%f %f %f) (%f %f %f) (%f %f %f) texinfo:%i[%s] plane:%i\n", nummapbrushes, nummapbrushsides,
			planepts[0][0], planepts[0][1], planepts[0][2],
			planepts[1][0], planepts[1][1], planepts[1][2],
			planepts[2][0], planepts[2][1], planepts[2][2],
			side->texinfo, td.name, planenum);

		nummapbrushsides++;
		b->numsides++;
	} while (1);

	/* get the content for the entire brush */
	b->contentFlags = BrushContents(b);

	/* copy all set face contentflags to the brush contentflags */
	for (int m = 0; m < b->numsides; m++)
		b->contentFlags |= b->original_sides[m].contentFlags;

	/* set DETAIL, TRANSLUCENT contentflags on all faces, if they have been set on any.
	 * called separately, if in check/fix mode */
	if (!checkOrFix)
		CheckPropagateParserContentFlags(b);

	/* allow detail brushes to be removed */
	if (config.nodetail && (b->contentFlags & CONTENTS_DETAIL)) {
		b->numsides = 0;
		return;
	}

	/* allow water brushes to be removed */
	if (config.nowater && (b->contentFlags & CONTENTS_WATER)) {
		b->numsides = 0;
		return;
	}

	/* create windings for sides and bounds for brush */
	MakeBrushWindings(b);

	Verb_Printf(VERB_DUMP, "Brush %i mins (%f %f %f) maxs (%f %f %f)\n", nummapbrushes,
		b->mbBox.mins[0], b->mbBox.mins[1], b->mbBox.mins[2],
		b->mbBox.maxs[0], b->mbBox.maxs[1], b->mbBox.maxs[2]);

	/* origin brushes are removed, but they set
	 * the rotation origin for the rest of the brushes (like func_door)
	 * in the entity. After the entire entity is parsed, the planenums
	 * and texinfos will be adjusted for the origin brush */
	if (!checkOrFix && (b->contentFlags & CONTENTS_ORIGIN)) {
		char string[32];
		vec3_t origin;

		if (num_entities == 1) {
			Sys_Error("Entity %i, Brush %i: origin brushes not allowed in world"
				, b->entitynum, b->brushnum);
			return;
		}

		b->mbBox.getCenter(origin);

		Com_sprintf(string, sizeof(string), "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
		SetKeyValue(&entities[b->entitynum], "origin", string);
		Verb_Printf(VERB_EXTRA, "Entity %i, Brush %i: set origin to %s\n", b->entitynum, b->brushnum, string);

		VectorCopy(origin, entities[b->entitynum].origin);

		/* don't keep this brush */
		b->numsides = 0;

		return;
	}

	if (!checkOrFix)
		AddBrushBevels(b);

	nummapbrushes++;
	mapent->numbrushes++;
}
示例#10
0
//===========================================================================
// uses the global cfg_t cfg
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_CreateMapBrushes(mapbrush_t *brush, entity_t *mapent, int addbevels)
{
	int i;
	//side_t *s;
	mapbrush_t *bboxbrushes[16];

	//if the brushes are not from an entity used for AAS
	if (!AAS_ValidEntity(mapent))
	{
		nummapbrushsides -= brush->numsides;
		brush->numsides = 0;
		return;
	} //end if
	//
	AAS_PositionBrush(mapent, brush);
	//from all normal solid brushes only the textured brush sides will
	//be used as bsp splitters, so set the right texinfo reference here
	AAS_SetTexinfo(brush);
	//remove contents detail flag, otherwise player clip contents won't be
	//bsped correctly for AAS!
	brush->contents &= ~CONTENTS_DETAIL;
	//if the brush has contents area portal it should be the only contents
	if (brush->contents & (CONTENTS_AREAPORTAL|CONTENTS_CLUSTERPORTAL))
	{
		brush->contents = CONTENTS_CLUSTERPORTAL;
		brush->leafnum = -1;
	} //end if
	//window and playerclip are used for player clipping, make them solid
	if (brush->contents & (CONTENTS_WINDOW | CONTENTS_PLAYERCLIP))
	{
		//
		brush->contents &= ~(CONTENTS_WINDOW | CONTENTS_PLAYERCLIP);
		brush->contents |= CONTENTS_SOLID;
		brush->leafnum = -1;
	} //end if
	//
	if (brush->contents & CONTENTS_BOTCLIP)
	{
		brush->contents = CONTENTS_SOLID;
		brush->leafnum = -1;
	} //end if
	//
	//Log_Write("brush %d contents = ", brush->brushnum);
	//PrintContents(brush->contents);
	//Log_Write("\r\n");
	//if not one of the following brushes then the brush is NOT used for AAS
	if (!(brush->contents & (CONTENTS_SOLID
									| CONTENTS_LADDER
									| CONTENTS_CLUSTERPORTAL
									| CONTENTS_DONOTENTER
									| CONTENTS_TELEPORTER
									| CONTENTS_JUMPPAD
									| CONTENTS_WATER
									| CONTENTS_LAVA
									| CONTENTS_SLIME
									| CONTENTS_MOVER
									)))
	{
		nummapbrushsides -= brush->numsides;
		brush->numsides = 0;
		return;
	} //end if
	//fix the map brush
	//AAS_FixMapBrush(brush);
	//if brush bevels should be added (for real map brushes, not bsp map brushes)
	if (addbevels)
	{
		//NOTE: we first have to get the mins and maxs of the brush before
		//			creating the brush bevels... the mins and maxs are used to
		//			create them. so we call MakeBrushWindings to get the mins
		//			and maxs and then after creating the bevels we free the
		//			windings because they are created for all sides (including
		//			bevels) a little later
		AAS_MakeBrushWindings(brush);
		AddBrushBevels(brush);
		FreeBrushWindings(brush);
	} //end if
	//NOTE: add the brush to the WORLD entity!!!
	mapent = &entities[0];
	//there's at least one new brush for now
	nummapbrushes++;
	mapent->numbrushes++;
	//liquid brushes are expanded for the maximum possible bounding box
	if (brush->contents & (CONTENTS_WATER
									| CONTENTS_LAVA
									| CONTENTS_SLIME 
									| CONTENTS_TELEPORTER
									| CONTENTS_JUMPPAD
									| CONTENTS_DONOTENTER
									| CONTENTS_MOVER
									))
	{
		brush->expansionbbox = 0;
		//NOTE: the first bounding box is the max
		//FIXME: use max bounding box created from all bboxes
		AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
		AAS_MakeBrushWindings(brush);
	} //end if
	//area portal brushes are NOT expanded
	else if (brush->contents & CONTENTS_CLUSTERPORTAL)
	{
		brush->expansionbbox = 0;
		//NOTE: the first bounding box is the max
		//FIXME: use max bounding box created from all bboxes
		AAS_ExpandMapBrush(brush, cfg.bboxes[0].mins, cfg.bboxes[0].maxs);
		AAS_MakeBrushWindings(brush);
	} //end if
	//all solid brushes are expanded for all bounding boxes
	else if (brush->contents & (CONTENTS_SOLID
										| CONTENTS_LADDER
										))
	{
		//brush for the first bounding box
		bboxbrushes[0] = brush;
		//make a copy for the other bounding boxes
		for (i = 1; i < cfg.numbboxes; i++)
		{
			bboxbrushes[i] = AAS_CopyMapBrush(brush, mapent);
		} //end for
		//expand every brush for it's bounding box and create windings
		for (i = 0; i < cfg.numbboxes; i++)
		{
			AAS_ExpandMapBrush(bboxbrushes[i], cfg.bboxes[i].mins, cfg.bboxes[i].maxs);
			bboxbrushes[i]->expansionbbox = cfg.bboxes[i].presencetype;
			AAS_MakeBrushWindings(bboxbrushes[i]);
		} //end for
	} //end else
} //end of the function AAS_CreateMapBrushes
示例#11
0
文件: model.c 项目: joseprous/xmap
void InsertModel(char *name, int frame, matrix_t transform, matrix_t nTransform, remap_t * remap, shaderInfo_t * celShader, int eNum, int castShadows,
				 int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle)
{
	int             i, j, k, s, numSurfaces;
	matrix_t        identity;
	picoModel_t    *model;
	picoShader_t   *shader;
	picoSurface_t  *surface;
	shaderInfo_t   *si;
	mapDrawSurface_t *ds;
	bspDrawVert_t  *dv;
	char           *picoShaderName;
	char            shaderName[MAX_QPATH];
	picoVec_t      *xyz, *normal, *st;
	byte           *color;
	picoIndex_t    *indexes;
	remap_t        *rm, *glob;
	double          normalEpsilon_save;
	double          distanceEpsilon_save;


	/* get model */
	model = LoadModel(name, frame);
	if(model == NULL)
		return;

	/* handle null matrix */
	if(transform == NULL)
	{
		MatrixIdentity(identity);
		transform = identity;
	}

	/* create transform matrix for normals */
#if 0
	MatrixCopy(transform, nTransform);
	if(MatrixInverse(nTransform))
	{
		Sys_FPrintf(SYS_VRB, "WARNING: Can't invert model transform matrix, using transpose instead\n");
		MatrixTranspose(transform, nTransform);
	}
#endif

	/* fix bogus lightmap scale */
	if(lightmapScale <= 0.0f)
		lightmapScale = 1.0f;

	/* fix bogus shade angle */
	if(shadeAngle <= 0.0f)
		shadeAngle = 0.0f;

	/* each surface on the model will become a new map drawsurface */
	numSurfaces = PicoGetModelNumSurfaces(model);
	//% Sys_FPrintf( SYS_VRB, "Model %s has %d surfaces\n", name, numSurfaces );
	for(s = 0; s < numSurfaces; s++)
	{
		/* get surface */
		surface = PicoGetModelSurface(model, s);
		if(surface == NULL)
			continue;

		/* only handle triangle surfaces initially (fixme: support patches) */
		if(PicoGetSurfaceType(surface) != PICO_TRIANGLES)
			continue;

		/* fix the surface's normals */
		PicoFixSurfaceNormals(surface);

		/* allocate a surface (ydnar: gs mods) */
		ds = AllocDrawSurface(SURFACE_TRIANGLES);
		ds->entityNum = eNum;
		ds->castShadows = castShadows;
		ds->recvShadows = recvShadows;

		/* get shader name */
		shader = PicoGetSurfaceShader(surface);
		if(shader == NULL)
			picoShaderName = "";
		else
			picoShaderName = PicoGetShaderName(shader);

		/* handle shader remapping */
		glob = NULL;
		for(rm = remap; rm != NULL; rm = rm->next)
		{
			if(rm->from[0] == '*' && rm->from[1] == '\0')
				glob = rm;
			else if(!Q_stricmp(picoShaderName, rm->from))
			{
				Sys_FPrintf(SYS_VRB, "Remapping %s to %s\n", picoShaderName, rm->to);
				picoShaderName = rm->to;
				glob = NULL;
				break;
			}
		}

		if(glob != NULL)
		{
			Sys_FPrintf(SYS_VRB, "Globbing %s to %s\n", picoShaderName, glob->to);
			picoShaderName = glob->to;
		}

		/* shader renaming for sof2 */
		if(renameModelShaders)
		{
			strcpy(shaderName, picoShaderName);
			StripExtension(shaderName);
			if(spawnFlags & 1)
				strcat(shaderName, "_RMG_BSP");
			else
				strcat(shaderName, "_BSP");
			si = ShaderInfoForShader(shaderName);
		}
		else
		{
			si = ShaderInfoForShader(picoShaderName);

			// Tr3B: HACK to support the messy Doom 3 materials provided by .ASE files
			if(!si->explicitDef)
			{
				picoShaderName = PicoGetShaderMapName(shader);

				Q_strncpyz(shaderName, picoShaderName, sizeof(shaderName));
				StripExtension(shaderName);

				i = 0;
				while(shaderName[i])
				{
					if(shaderName[i] == '\\')
						shaderName[i] = '/';
					i++;
				}

				if(strstr(shaderName, "base/"))
				{
					si = ShaderInfoForShader(strstr(shaderName, "base/") + strlen("base/"));
					Sys_FPrintf(SYS_WRN, "WARNING: Applied .ASE material loader HACK to '%s' -> '%s'\n", picoShaderName, si->shader);
				}

			}
		}

		/* set shader */
		ds->shaderInfo = si;

		/* force to meta? */
		if((si != NULL && si->forceMeta) || (spawnFlags & 4))	/* 3rd bit */
			ds->type = SURFACE_FORCED_META;

		/* fix the surface's normals (jal: conditioned by shader info) */
		//if(!(spawnFlags & 64) && (shadeAngle == 0.0f || ds->type != SURFACE_FORCED_META))
		//	PicoFixSurfaceNormals(surface);

		/* set sample size */
		if(lightmapSampleSize > 0.0f)
			ds->sampleSize = lightmapSampleSize;

		/* set lightmap scale */
		if(lightmapScale > 0.0f)
			ds->lightmapScale = lightmapScale;

		/* set shading angle */
		if(shadeAngle > 0.0f)
			ds->shadeAngleDegrees = shadeAngle;

		/* set particulars */
		ds->numVerts = PicoGetSurfaceNumVertexes(surface);
		ds->verts = safe_malloc(ds->numVerts * sizeof(ds->verts[0]));
		memset(ds->verts, 0, ds->numVerts * sizeof(ds->verts[0]));

		ds->numIndexes = PicoGetSurfaceNumIndexes(surface);
		ds->indexes = safe_malloc(ds->numIndexes * sizeof(ds->indexes[0]));
		memset(ds->indexes, 0, ds->numIndexes * sizeof(ds->indexes[0]));

		/* copy vertexes */
		for(i = 0; i < ds->numVerts; i++)
		{
			/* get vertex */
			dv = &ds->verts[i];

			/* xyz and normal */
			xyz = PicoGetSurfaceXYZ(surface, i);
			VectorCopy(xyz, dv->xyz);
			MatrixTransformPoint2(transform, dv->xyz);

			normal = PicoGetSurfaceNormal(surface, i);
			VectorCopy(normal, dv->normal);
			MatrixTransformNormal2(nTransform, dv->normal);
			VectorNormalize2(dv->normal, dv->normal);

			/* ydnar: tek-fu celshading support for flat shaded shit */
			if(flat)
			{
				dv->st[0] = si->stFlat[0];
				dv->st[1] = si->stFlat[1];
			}

			/* ydnar: gs mods: added support for explicit shader texcoord generation */
			else if(si->tcGen)
			{
				/* project the texture */
				dv->st[0] = DotProduct(si->vecs[0], dv->xyz);
				dv->st[1] = DotProduct(si->vecs[1], dv->xyz);
			}

			/* normal texture coordinates */
			else
			{
				st = PicoGetSurfaceST(surface, 0, i);
				dv->st[0] = st[0];
				dv->st[1] = st[1];
			}

			/* set lightmap/color bits */
			color = PicoGetSurfaceColor(surface, 0, i);

			dv->paintColor[0] = color[0] / 255.0f;
			dv->paintColor[1] = color[1] / 255.0f;
			dv->paintColor[2] = color[2] / 255.0f;
			dv->paintColor[3] = color[3] / 255.0f;

			for(j = 0; j < MAX_LIGHTMAPS; j++)
			{
				dv->lightmap[j][0] = 0.0f;
				dv->lightmap[j][1] = 0.0f;

				dv->lightColor[j][0] = 255;
				dv->lightColor[j][1] = 255;
				dv->lightColor[j][2] = 255;
				dv->lightColor[j][3] = 255;
			}
		}

		/* copy indexes */
		indexes = PicoGetSurfaceIndexes(surface, 0);
		for(i = 0; i < ds->numIndexes; i++)
			ds->indexes[i] = indexes[i];

		/* set cel shader */
		ds->celShader = celShader;

		/* ydnar: giant hack land: generate clipping brushes for model triangles */
		if(si->clipModel || (spawnFlags & 2))	/* 2nd bit */
		{
			vec3_t          points[4], backs[3];
			vec4_t          plane, reverse, pa, pb, pc;


			/* temp hack */
			if(!si->clipModel &&
			   (((si->compileFlags & C_TRANSLUCENT) && !(si->compileFlags & C_COLLISION)) || !(si->compileFlags & C_SOLID)))
				continue;

			/* walk triangle list */
			for(i = 0; i < ds->numIndexes; i += 3)
			{
				/* overflow hack */
				AUTOEXPAND_BY_REALLOC(mapplanes, (nummapplanes + 64) << 1, allocatedmapplanes, 1024);

				/* make points and back points */
				for(j = 0; j < 3; j++)
				{
					/* get vertex */
					dv = &ds->verts[ds->indexes[i + j]];

					/* copy xyz */
					VectorCopy(dv->xyz, points[j]);
					VectorCopy(dv->xyz, backs[j]);

					/* find nearest axial to normal and push back points opposite */
					/* note: this doesn't work as well as simply using the plane of the triangle, below */
					for(k = 0; k < 3; k++)
					{
						if(fabs(dv->normal[k]) >= fabs(dv->normal[(k + 1) % 3]) &&
						   fabs(dv->normal[k]) >= fabs(dv->normal[(k + 2) % 3]))
						{
							backs[j][k] += dv->normal[k] < 0.0f ? 64.0f : -64.0f;
							break;
						}
					}
				}

				VectorCopy(points[0], points[3]);	// for cyclic usage

				/* make plane for triangle */
				// div0: add some extra spawnflags:
				//   0: snap normals to axial planes for extrusion
				//   8: extrude with the original normals
				//  16: extrude only with up/down normals (ideal for terrain)
				//  24: extrude by distance zero (may need engine changes)
				if(PlaneFromPoints(plane, points[0], points[1], points[2], qtrue))
				{
					vec3_t          bestNormal;
					float           backPlaneDistance = 2;

					if(spawnFlags & 8)	// use a DOWN normal
					{
						if(spawnFlags & 16)
						{
							// 24: normal as is, and zero width (broken)
							VectorCopy(plane, bestNormal);
						}
						else
						{
							// 8: normal as is
							VectorCopy(plane, bestNormal);
						}
					}
					else
					{
						if(spawnFlags & 16)
						{
							// 16: UP/DOWN normal
							VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
						}
						else
						{
							// 0: axial normal
							if(fabs(plane[0]) > fabs(plane[1]))	// x>y
								if(fabs(plane[1]) > fabs(plane[2]))	// x>y, y>z
									VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
								else	// x>y, z>=y
								if(fabs(plane[0]) > fabs(plane[2]))	// x>z, z>=y
									VectorSet(bestNormal, (plane[0] >= 0 ? 1 : -1), 0, 0);
								else	// z>=x, x>y
									VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
							else	// y>=x
							if(fabs(plane[1]) > fabs(plane[2]))	// y>z, y>=x
								VectorSet(bestNormal, 0, (plane[1] >= 0 ? 1 : -1), 0);
							else	// z>=y, y>=x
								VectorSet(bestNormal, 0, 0, (plane[2] >= 0 ? 1 : -1));
						}
					}

					/* build a brush */
					buildBrush = AllocBrush(48);
					buildBrush->entityNum = mapEntityNum;
					buildBrush->original = buildBrush;
					buildBrush->contentShader = si;
					buildBrush->compileFlags = si->compileFlags;
					buildBrush->contentFlags = si->contentFlags;

					buildBrush->generatedClipBrush = qtrue;

					normalEpsilon_save = normalEpsilon;
					distanceEpsilon_save = distanceEpsilon;

					if(si->compileFlags & C_STRUCTURAL)	// allow forced structural brushes here
					{
						buildBrush->detail = qfalse;

						// only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model)
						if(normalEpsilon > 0)
							normalEpsilon = 0;
						if(distanceEpsilon > 0)
							distanceEpsilon = 0;
					}
					else
						buildBrush->detail = qtrue;

					/* regenerate back points */
					for(j = 0; j < 3; j++)
					{
						/* get vertex */
						dv = &ds->verts[ds->indexes[i + j]];

						// shift by some units
						VectorMA(dv->xyz, -64.0f, bestNormal, backs[j]);	// 64 prevents roundoff errors a bit
					}

					/* make back plane */
					VectorScale(plane, -1.0f, reverse);
					reverse[3] = -plane[3];
					if((spawnFlags & 24) != 24)
						reverse[3] += DotProduct(bestNormal, plane) * backPlaneDistance;
					// that's at least sqrt(1/3) backPlaneDistance, unless in DOWN mode; in DOWN mode, we are screwed anyway if we encounter a plane that's perpendicular to the xy plane)

					if(PlaneFromPoints(pa, points[2], points[1], backs[1], qtrue) &&
					   PlaneFromPoints(pb, points[1], points[0], backs[0], qtrue) && PlaneFromPoints(pc, points[0], points[2], backs[2], qtrue))
					{
						/* set up brush sides */
						buildBrush->numsides = 5;
						buildBrush->sides[0].shaderInfo = si;
						for(j = 1; j < buildBrush->numsides; j++)
							buildBrush->sides[j].shaderInfo = NULL;	// don't emit these faces as draw surfaces, should make smaller BSPs; hope this works

						buildBrush->sides[0].planenum = FindFloatPlane(plane, plane[3], 3, points);
						buildBrush->sides[1].planenum = FindFloatPlane(pa, pa[3], 2, &points[1]);	// pa contains points[1] and points[2]
						buildBrush->sides[2].planenum = FindFloatPlane(pb, pb[3], 2, &points[0]);	// pb contains points[0] and points[1]
						buildBrush->sides[3].planenum = FindFloatPlane(pc, pc[3], 2, &points[2]);	// pc contains points[2] and points[0] (copied to points[3]
						buildBrush->sides[4].planenum = FindFloatPlane(reverse, reverse[3], 3, backs);
					}
					else
					{
						free(buildBrush);
						continue;
					}

					normalEpsilon = normalEpsilon_save;
					distanceEpsilon = distanceEpsilon_save;

					/* add to entity */
					if(CreateBrushWindings(buildBrush))
					{
						AddBrushBevels();
						//% EmitBrushes( buildBrush, NULL, NULL );
						buildBrush->next = entities[mapEntityNum].brushes;
						entities[mapEntityNum].brushes = buildBrush;
						entities[mapEntityNum].numBrushes++;
					}
					else
						free(buildBrush);
				}
			}
		}
	}
}