⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aas_map.c

📁 quakeIII源码这个不用我多说吧
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.

This file is part of Quake III Arena source code.

Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.

Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h"		//aas_bbox_t
#include "aas_store.h"				//AAS_MAX_BBOXES
#include "aas_cfg.h"
#include "../game/surfaceflags.h"

#define SPAWNFLAG_NOT_EASY			0x00000100
#define SPAWNFLAG_NOT_MEDIUM		0x00000200
#define SPAWNFLAG_NOT_HARD			0x00000400
#define SPAWNFLAG_NOT_DEATHMATCH	0x00000800
#define SPAWNFLAG_NOT_COOP			0x00001000

#define STATE_TOP				0
#define STATE_BOTTOM			1
#define STATE_UP				2
#define STATE_DOWN			3

#define DOOR_START_OPEN		1
#define DOOR_REVERSE			2
#define DOOR_CRUSHER			4
#define DOOR_NOMONSTER		8
#define DOOR_TOGGLE			32
#define DOOR_X_AXIS			64
#define DOOR_Y_AXIS			128

#define BBOX_NORMAL_EPSILON			0.0001

//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
vec_t BoxOriginDistanceFromPlane(vec3_t normal, vec3_t mins, vec3_t maxs, int side)
{
	vec3_t v1, v2;
	int i;

	if (side)
	{
		for (i = 0; i < 3; i++)
		{
			if (normal[i] > BBOX_NORMAL_EPSILON) v1[i] = maxs[i];
			else if (normal[i] < -BBOX_NORMAL_EPSILON) v1[i] = mins[i];
			else v1[i] = 0;
		} //end for
	} //end if
	else
	{
		for (i = 0; i < 3; i++)
		{
			if (normal[i] > BBOX_NORMAL_EPSILON) v1[i] = mins[i];
			else if (normal[i] < -BBOX_NORMAL_EPSILON) v1[i] = maxs[i];
			else v1[i] = 0;
		} //end for
	} //end else
	VectorCopy(normal, v2);
	VectorInverse(v2);
	return DotProduct(v1, v2);
} //end of the function BoxOriginDistanceFromPlane
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
vec_t CapsuleOriginDistanceFromPlane(vec3_t normal, vec3_t mins, vec3_t maxs)
{
	float offset_up, offset_down, width, radius;

	width = maxs[0] - mins[0];
	// if the box is less high then it is wide
	if (maxs[2] - mins[2] < width) {
		width = maxs[2] - mins[2];
	}
	radius = width * 0.5;
	// offset to upper and lower sphere
	offset_up = maxs[2] - radius;
	offset_down = -mins[2] - radius;

	// if normal points upward
	if ( normal[2] > 0 ) {
		// touches lower sphere first
		return normal[2] * offset_down + radius;
	}
	else {
		// touched upper sphere first
		return -normal[2] * offset_up + radius;
	}
}
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_ExpandMapBrush(mapbrush_t *brush, vec3_t mins, vec3_t maxs)
{
	int sn;
	float dist;
	side_t *s;
	plane_t *plane;

	for (sn = 0; sn < brush->numsides; sn++)
	{
		s = brush->original_sides + sn;
		plane = &mapplanes[s->planenum];
		dist = plane->dist;
		if (capsule_collision) {
			dist += CapsuleOriginDistanceFromPlane(plane->normal, mins, maxs);
		}
		else {
			dist += BoxOriginDistanceFromPlane(plane->normal, mins, maxs, 0);
		}
		s->planenum = FindFloatPlane(plane->normal, dist);
		//the side isn't a bevel after expanding
		s->flags &= ~SFL_BEVEL;
		//don't skip the surface
		s->surf &= ~SURF_SKIP;
		//make sure the texinfo is not TEXINFO_NODE
		//when player clip contents brushes are read from the bsp tree
		//they have the texinfo field set to TEXINFO_NODE
		//s->texinfo = 0;
	} //end for
} //end of the function AAS_ExpandMapBrush
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_SetTexinfo(mapbrush_t *brush)
{
	int n;
	side_t *side;

	if (brush->contents & (CONTENTS_LADDER
									| CONTENTS_AREAPORTAL
									| CONTENTS_CLUSTERPORTAL
									| CONTENTS_TELEPORTER
									| CONTENTS_JUMPPAD
									| CONTENTS_DONOTENTER
									| CONTENTS_WATER
									| CONTENTS_LAVA
									| CONTENTS_SLIME
									| CONTENTS_WINDOW
									| CONTENTS_PLAYERCLIP))
	{
		//we just set texinfo to 0 because these brush sides MUST be used as
		//bsp splitters textured or not textured
		for (n = 0; n < brush->numsides; n++)
		{
			side = brush->original_sides + n;
			//side->flags |= SFL_TEXTURED|SFL_VISIBLE;
			side->texinfo = 0;
		} //end for
	} //end if
	else
	{
		//only use brush sides as splitters if they are textured
		//texinfo of non-textured sides will be set to TEXINFO_NODE
		for (n = 0; n < brush->numsides; n++)
		{
			side = brush->original_sides + n;
			//don't use side as splitter (set texinfo to TEXINFO_NODE) if not textured
			if (side->flags & (SFL_TEXTURED|SFL_BEVEL)) side->texinfo = 0;
			else side->texinfo = TEXINFO_NODE;
		} //end for
	} //end else
} //end of the function AAS_SetTexinfo
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void FreeBrushWindings(mapbrush_t *brush)
{
	int n;
	side_t *side;
	//
	for (n = 0; n < brush->numsides; n++)
	{
		side = brush->original_sides + n;
		//
		if (side->winding) FreeWinding(side->winding);
	} //end for
} //end of the function FreeBrushWindings
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_AddMapBrushSide(mapbrush_t *brush, int planenum)
{
	side_t *side;
	//
	if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
		Error ("MAX_MAPFILE_BRUSHSIDES");
	//
	side = brush->original_sides + brush->numsides;
	side->original = NULL;
	side->winding = NULL;
	side->contents = brush->contents;
	side->flags &= ~(SFL_BEVEL|SFL_VISIBLE);
	side->surf = 0;
	side->planenum = planenum;
	side->texinfo = 0;
	//
	nummapbrushsides++;
	brush->numsides++;
} //end of the function AAS_AddMapBrushSide
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void AAS_FixMapBrush(mapbrush_t *brush)
{
	int i, j, planenum;
	float dist;
	winding_t *w;
	plane_t *plane, *plane1, *plane2;
	side_t *side;
	vec3_t normal;

	//calculate the brush bounds
	ClearBounds(brush->mins, brush->maxs);
	for (i = 0; i < brush->numsides; i++)
	{
		plane = &mapplanes[brush->original_sides[i].planenum];
		w = BaseWindingForPlane(plane->normal, plane->dist);
		for (j = 0; j < brush->numsides && w; j++)
		{
			if (i == j) continue;
			//there are no brush bevels marked but who cares :)
			if (brush->original_sides[j].flags & SFL_BEVEL) continue;
			plane = &mapplanes[brush->original_sides[j].planenum^1];
			ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
		} //end for

		side = &brush->original_sides[i];
		side->winding = w;
		if (w)
		{
			for (j = 0; j < w->numpoints; j++)
			{
				AddPointToBounds(w->p[j], brush->mins, brush->maxs);
			} //end for
		} //end if
	} //end for
	//
	for (i = 0; i < brush->numsides; i++)
	{
		for (j = 0; j < brush->numsides; j++)
		{
			if (i == j) continue;
			plane1 = &mapplanes[brush->original_sides[i].planenum];
			plane2 = &mapplanes[brush->original_sides[j].planenum];
			if (WindingsNonConvex(brush->original_sides[i].winding,
									brush->original_sides[j].winding,
									plane1->normal, plane2->normal,
									plane1->dist, plane2->dist))
			{
				Log_Print("non convex brush");
			} //end if
		} //end for
	} //end for

	//NOW close the fucking brush!!
	for (i = 0; i < 3; i++)
	{
		if (brush->mins[i] < -MAX_MAP_BOUNDS)
		{
			VectorClear(normal);
			normal[i] = -1;
			dist = MAX_MAP_BOUNDS - 10;
			planenum = FindFloatPlane(normal, dist);
			//
			Log_Print("mins out of range: added extra brush side\n");
			AAS_AddMapBrushSide(brush, planenum);
		} //end if
		if (brush->maxs[i] > MAX_MAP_BOUNDS)
		{
			VectorClear(normal);
			normal[i] = 1;
			dist = MAX_MAP_BOUNDS - 10;
			planenum = FindFloatPlane(normal, dist);
			//
			Log_Print("maxs out of range: added extra brush side\n");
			AAS_AddMapBrushSide(brush, planenum);
		} //end if
		if (brush->mins[i] > MAX_MAP_BOUNDS || brush->maxs[i] < -MAX_MAP_BOUNDS)
		{
			Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
		} //end if
	} //end for
	//free all the windings
	FreeBrushWindings(brush);
} //end of the function AAS_FixMapBrush
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
qboolean AAS_MakeBrushWindings(mapbrush_t *ob)
{
	int			i, j;
	winding_t	*w;
	side_t		*side;
	plane_t		*plane, *plane1, *plane2;

	ClearBounds (ob->mins, ob->maxs);

	for (i = 0; i < ob->numsides; i++)
	{
		plane = &mapplanes[ob->original_sides[i].planenum];
		w = BaseWindingForPlane(plane->normal, plane->dist);
		for (j = 0; j <ob->numsides && w; j++)
		{
			if (i == j) continue;
			if (ob->original_sides[j].flags & SFL_BEVEL) continue;
			plane = &mapplanes[ob->original_sides[j].planenum^1];
			ChopWindingInPlace(&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
		}

		side = &ob->original_sides[i];
		side->winding = w;
		if (w)
		{
			side->flags |= SFL_VISIBLE;
			for (j = 0; j < w->numpoints; j++)
				AddPointToBounds (w->p[j], ob->mins, ob->maxs);
		}
	}
	//check if the brush is convex
	for (i = 0; i < ob->numsides; i++)
	{
		for (j = 0; j < ob->numsides; j++)
		{
			if (i == j) continue;
			plane1 = &mapplanes[ob->original_sides[i].planenum];
			plane2 = &mapplanes[ob->original_sides[j].planenum];
			if (WindingsNonConvex(ob->original_sides[i].winding,
									ob->original_sides[j].winding,
									plane1->normal, plane2->normal,
									plane1->dist, plane2->dist))
			{
				Log_Print("non convex brush");
			} //end if
		} //end for
	} //end for
	//check for out of bound brushes
	for (i = 0; i < 3; i++)
	{
		//IDBUG: all the indexes into the mins and maxs were zero (not using i)
		if (ob->mins[i] < -MAX_MAP_BOUNDS || ob->maxs[i] > MAX_MAP_BOUNDS)
		{
			Log_Print("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
			Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i]);
			ob->numsides = 0; //remove the brush
			break;
		} //end if
		if (ob->mins[i] > MAX_MAP_BOUNDS || ob->maxs[i] < -MAX_MAP_BOUNDS)
		{
			Log_Print("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
			Log_Print("ob->mins[%d] = %f, ob->maxs[%d] = %f\n", i, ob->mins[i], i, ob->maxs[i]);
			ob->numsides = 0; //remove the brush
			break;
		} //end if
	} //end for
	return true;
} //end of the function AAS_MakeBrushWindings
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
mapbrush_t *AAS_CopyMapBrush(mapbrush_t *brush, entity_t *mapent)
{
	int n;
	mapbrush_t *newbrush;
	side_t *side, *newside;

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

	newbrush = &mapbrushes[nummapbrushes];
	newbrush->original_sides = &brushsides[nummapbrushsides];
	newbrush->entitynum = brush->entitynum;
	newbrush->brushnum = nummapbrushes - mapent->firstbrush;
	newbrush->numsides = brush->numsides;
	newbrush->contents = brush->contents;

	//copy the sides
	for (n = 0; n < brush->numsides; n++)
	{
		if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)

⌨️ 快捷键说明

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