diff options
Diffstat (limited to 'src/qcommon')
| -rw-r--r-- | src/qcommon/q_math.c | 1562 | ||||
| -rw-r--r-- | src/qcommon/q_platform.h | 386 | ||||
| -rw-r--r-- | src/qcommon/q_shared.c | 1347 | ||||
| -rw-r--r-- | src/qcommon/q_shared.h | 1342 | ||||
| -rw-r--r-- | src/qcommon/qfiles.h | 626 | ||||
| -rw-r--r-- | src/qcommon/surfaceflags.h | 91 | 
6 files changed, 5354 insertions, 0 deletions
diff --git a/src/qcommon/q_math.c b/src/qcommon/q_math.c new file mode 100644 index 0000000..196d2f5 --- /dev/null +++ b/src/qcommon/q_math.c @@ -0,0 +1,1562 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// +// q_math.c -- stateless support routines that are included in each code module + +// Some of the vector functions are static inline in q_shared.h. q3asm +// doesn't understand static functions though, so we only want them in +// one file. That's what this is about. +#ifdef Q3_VM +#define __Q3_VM_MATH +#endif + +#include "q_shared.h" + +vec3_t	vec3_origin = {0,0,0}; +vec3_t	axisDefault[3] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; + + +vec4_t		colorBlack	= {0, 0, 0, 1}; +vec4_t		colorRed	= {1, 0, 0, 1}; +vec4_t		colorGreen	= {0, 1, 0, 1}; +vec4_t		colorBlue	= {0, 0, 1, 1}; +vec4_t		colorYellow	= {1, 1, 0, 1}; +vec4_t		colorMagenta= {1, 0, 1, 1}; +vec4_t		colorCyan	= {0, 1, 1, 1}; +vec4_t		colorWhite	= {1, 1, 1, 1}; +vec4_t		colorLtGrey	= {0.75, 0.75, 0.75, 1}; +vec4_t		colorMdGrey	= {0.5, 0.5, 0.5, 1}; +vec4_t		colorDkGrey	= {0.25, 0.25, 0.25, 1}; + +vec4_t	g_color_table[8] = +	{ +	{0.0, 0.0, 0.0, 1.0}, +	{1.0, 0.0, 0.0, 1.0}, +	{0.0, 1.0, 0.0, 1.0}, +	{1.0, 1.0, 0.0, 1.0}, +	{0.0, 0.0, 1.0, 1.0}, +	{0.0, 1.0, 1.0, 1.0}, +	{1.0, 0.0, 1.0, 1.0}, +	{1.0, 1.0, 1.0, 1.0}, +	}; + + +vec3_t	bytedirs[NUMVERTEXNORMALS] = +{ +{-0.525731f, 0.000000f, 0.850651f}, {-0.442863f, 0.238856f, 0.864188f},  +{-0.295242f, 0.000000f, 0.955423f}, {-0.309017f, 0.500000f, 0.809017f},  +{-0.162460f, 0.262866f, 0.951056f}, {0.000000f, 0.000000f, 1.000000f},  +{0.000000f, 0.850651f, 0.525731f}, {-0.147621f, 0.716567f, 0.681718f},  +{0.147621f, 0.716567f, 0.681718f}, {0.000000f, 0.525731f, 0.850651f},  +{0.309017f, 0.500000f, 0.809017f}, {0.525731f, 0.000000f, 0.850651f},  +{0.295242f, 0.000000f, 0.955423f}, {0.442863f, 0.238856f, 0.864188f},  +{0.162460f, 0.262866f, 0.951056f}, {-0.681718f, 0.147621f, 0.716567f},  +{-0.809017f, 0.309017f, 0.500000f},{-0.587785f, 0.425325f, 0.688191f},  +{-0.850651f, 0.525731f, 0.000000f},{-0.864188f, 0.442863f, 0.238856f},  +{-0.716567f, 0.681718f, 0.147621f},{-0.688191f, 0.587785f, 0.425325f},  +{-0.500000f, 0.809017f, 0.309017f}, {-0.238856f, 0.864188f, 0.442863f},  +{-0.425325f, 0.688191f, 0.587785f}, {-0.716567f, 0.681718f, -0.147621f},  +{-0.500000f, 0.809017f, -0.309017f}, {-0.525731f, 0.850651f, 0.000000f},  +{0.000000f, 0.850651f, -0.525731f}, {-0.238856f, 0.864188f, -0.442863f},  +{0.000000f, 0.955423f, -0.295242f}, {-0.262866f, 0.951056f, -0.162460f},  +{0.000000f, 1.000000f, 0.000000f}, {0.000000f, 0.955423f, 0.295242f},  +{-0.262866f, 0.951056f, 0.162460f}, {0.238856f, 0.864188f, 0.442863f},  +{0.262866f, 0.951056f, 0.162460f}, {0.500000f, 0.809017f, 0.309017f},  +{0.238856f, 0.864188f, -0.442863f},{0.262866f, 0.951056f, -0.162460f},  +{0.500000f, 0.809017f, -0.309017f},{0.850651f, 0.525731f, 0.000000f},  +{0.716567f, 0.681718f, 0.147621f}, {0.716567f, 0.681718f, -0.147621f},  +{0.525731f, 0.850651f, 0.000000f}, {0.425325f, 0.688191f, 0.587785f},  +{0.864188f, 0.442863f, 0.238856f}, {0.688191f, 0.587785f, 0.425325f},  +{0.809017f, 0.309017f, 0.500000f}, {0.681718f, 0.147621f, 0.716567f},  +{0.587785f, 0.425325f, 0.688191f}, {0.955423f, 0.295242f, 0.000000f},  +{1.000000f, 0.000000f, 0.000000f}, {0.951056f, 0.162460f, 0.262866f},  +{0.850651f, -0.525731f, 0.000000f},{0.955423f, -0.295242f, 0.000000f},  +{0.864188f, -0.442863f, 0.238856f}, {0.951056f, -0.162460f, 0.262866f},  +{0.809017f, -0.309017f, 0.500000f}, {0.681718f, -0.147621f, 0.716567f},  +{0.850651f, 0.000000f, 0.525731f}, {0.864188f, 0.442863f, -0.238856f},  +{0.809017f, 0.309017f, -0.500000f}, {0.951056f, 0.162460f, -0.262866f},  +{0.525731f, 0.000000f, -0.850651f}, {0.681718f, 0.147621f, -0.716567f},  +{0.681718f, -0.147621f, -0.716567f},{0.850651f, 0.000000f, -0.525731f},  +{0.809017f, -0.309017f, -0.500000f}, {0.864188f, -0.442863f, -0.238856f},  +{0.951056f, -0.162460f, -0.262866f}, {0.147621f, 0.716567f, -0.681718f},  +{0.309017f, 0.500000f, -0.809017f}, {0.425325f, 0.688191f, -0.587785f},  +{0.442863f, 0.238856f, -0.864188f}, {0.587785f, 0.425325f, -0.688191f},  +{0.688191f, 0.587785f, -0.425325f}, {-0.147621f, 0.716567f, -0.681718f},  +{-0.309017f, 0.500000f, -0.809017f}, {0.000000f, 0.525731f, -0.850651f},  +{-0.525731f, 0.000000f, -0.850651f}, {-0.442863f, 0.238856f, -0.864188f},  +{-0.295242f, 0.000000f, -0.955423f}, {-0.162460f, 0.262866f, -0.951056f},  +{0.000000f, 0.000000f, -1.000000f}, {0.295242f, 0.000000f, -0.955423f},  +{0.162460f, 0.262866f, -0.951056f}, {-0.442863f, -0.238856f, -0.864188f},  +{-0.309017f, -0.500000f, -0.809017f}, {-0.162460f, -0.262866f, -0.951056f},  +{0.000000f, -0.850651f, -0.525731f}, {-0.147621f, -0.716567f, -0.681718f},  +{0.147621f, -0.716567f, -0.681718f}, {0.000000f, -0.525731f, -0.850651f},  +{0.309017f, -0.500000f, -0.809017f}, {0.442863f, -0.238856f, -0.864188f},  +{0.162460f, -0.262866f, -0.951056f}, {0.238856f, -0.864188f, -0.442863f},  +{0.500000f, -0.809017f, -0.309017f}, {0.425325f, -0.688191f, -0.587785f},  +{0.716567f, -0.681718f, -0.147621f}, {0.688191f, -0.587785f, -0.425325f},  +{0.587785f, -0.425325f, -0.688191f}, {0.000000f, -0.955423f, -0.295242f},  +{0.000000f, -1.000000f, 0.000000f}, {0.262866f, -0.951056f, -0.162460f},  +{0.000000f, -0.850651f, 0.525731f}, {0.000000f, -0.955423f, 0.295242f},  +{0.238856f, -0.864188f, 0.442863f}, {0.262866f, -0.951056f, 0.162460f},  +{0.500000f, -0.809017f, 0.309017f}, {0.716567f, -0.681718f, 0.147621f},  +{0.525731f, -0.850651f, 0.000000f}, {-0.238856f, -0.864188f, -0.442863f},  +{-0.500000f, -0.809017f, -0.309017f}, {-0.262866f, -0.951056f, -0.162460f},  +{-0.850651f, -0.525731f, 0.000000f}, {-0.716567f, -0.681718f, -0.147621f},  +{-0.716567f, -0.681718f, 0.147621f}, {-0.525731f, -0.850651f, 0.000000f},  +{-0.500000f, -0.809017f, 0.309017f}, {-0.238856f, -0.864188f, 0.442863f},  +{-0.262866f, -0.951056f, 0.162460f}, {-0.864188f, -0.442863f, 0.238856f},  +{-0.809017f, -0.309017f, 0.500000f}, {-0.688191f, -0.587785f, 0.425325f},  +{-0.681718f, -0.147621f, 0.716567f}, {-0.442863f, -0.238856f, 0.864188f},  +{-0.587785f, -0.425325f, 0.688191f}, {-0.309017f, -0.500000f, 0.809017f},  +{-0.147621f, -0.716567f, 0.681718f}, {-0.425325f, -0.688191f, 0.587785f},  +{-0.162460f, -0.262866f, 0.951056f}, {0.442863f, -0.238856f, 0.864188f},  +{0.162460f, -0.262866f, 0.951056f}, {0.309017f, -0.500000f, 0.809017f},  +{0.147621f, -0.716567f, 0.681718f}, {0.000000f, -0.525731f, 0.850651f},  +{0.425325f, -0.688191f, 0.587785f}, {0.587785f, -0.425325f, 0.688191f},  +{0.688191f, -0.587785f, 0.425325f}, {-0.955423f, 0.295242f, 0.000000f},  +{-0.951056f, 0.162460f, 0.262866f}, {-1.000000f, 0.000000f, 0.000000f},  +{-0.850651f, 0.000000f, 0.525731f}, {-0.955423f, -0.295242f, 0.000000f},  +{-0.951056f, -0.162460f, 0.262866f}, {-0.864188f, 0.442863f, -0.238856f},  +{-0.951056f, 0.162460f, -0.262866f}, {-0.809017f, 0.309017f, -0.500000f},  +{-0.864188f, -0.442863f, -0.238856f}, {-0.951056f, -0.162460f, -0.262866f},  +{-0.809017f, -0.309017f, -0.500000f}, {-0.681718f, 0.147621f, -0.716567f},  +{-0.681718f, -0.147621f, -0.716567f}, {-0.850651f, 0.000000f, -0.525731f},  +{-0.688191f, 0.587785f, -0.425325f}, {-0.587785f, 0.425325f, -0.688191f},  +{-0.425325f, 0.688191f, -0.587785f}, {-0.425325f, -0.688191f, -0.587785f},  +{-0.587785f, -0.425325f, -0.688191f}, {-0.688191f, -0.587785f, -0.425325f} +}; + +//============================================================== + +int		Q_rand( int *seed ) { +	*seed = (69069 * *seed + 1); +	return *seed; +} + +float	Q_random( int *seed ) { +	return ( Q_rand( seed ) & 0xffff ) / (float)0x10000; +} + +float	Q_crandom( int *seed ) { +	return 2.0 * ( Q_random( seed ) - 0.5 ); +} + +//======================================================= + +signed char ClampChar( int i ) { +	if ( i < -128 ) { +		return -128; +	} +	if ( i > 127 ) { +		return 127; +	} +	return i; +} + +signed short ClampShort( int i ) { +	if ( i < -32768 ) { +		return -32768; +	} +	if ( i > 0x7fff ) { +		return 0x7fff; +	} +	return i; +} + + +// this isn't a real cheap function to call! +int DirToByte( vec3_t dir ) { +	int		i, best; +	float	d, bestd; + +	if ( !dir ) { +		return 0; +	} + +	bestd = 0; +	best = 0; +	for (i=0 ; i<NUMVERTEXNORMALS ; i++) +	{ +		d = DotProduct (dir, bytedirs[i]); +		if (d > bestd) +		{ +			bestd = d; +			best = i; +		} +	} + +	return best; +} + +void ByteToDir( int b, vec3_t dir ) { +	if ( b < 0 || b >= NUMVERTEXNORMALS ) { +		VectorCopy( vec3_origin, dir ); +		return; +	} +	VectorCopy (bytedirs[b], dir); +} + + +unsigned ColorBytes3 (float r, float g, float b) { +	unsigned	i; + +	( (byte *)&i )[0] = r * 255; +	( (byte *)&i )[1] = g * 255; +	( (byte *)&i )[2] = b * 255; + +	return i; +} + +unsigned ColorBytes4 (float r, float g, float b, float a) { +	unsigned	i; + +	( (byte *)&i )[0] = r * 255; +	( (byte *)&i )[1] = g * 255; +	( (byte *)&i )[2] = b * 255; +	( (byte *)&i )[3] = a * 255; + +	return i; +} + +float NormalizeColor( const vec3_t in, vec3_t out ) { +	float	max; +	 +	max = in[0]; +	if ( in[1] > max ) { +		max = in[1]; +	} +	if ( in[2] > max ) { +		max = in[2]; +	} + +	if ( !max ) { +		VectorClear( out ); +	} else { +		out[0] = in[0] / max; +		out[1] = in[1] / max; +		out[2] = in[2] / max; +	} +	return max; +} + + +/* +===================== +PlaneFromPoints + +Returns false if the triangle is degenrate. +The normal will point out of the clock for clockwise ordered points +===================== +*/ +qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) { +	vec3_t	d1, d2; + +	VectorSubtract( b, a, d1 ); +	VectorSubtract( c, a, d2 ); +	CrossProduct( d2, d1, plane ); +	if ( VectorNormalize( plane ) == 0 ) { +		return qfalse; +	} + +	plane[3] = DotProduct( a, plane ); +	return qtrue; +} + +/* +=============== +RotatePointAroundVector + +This is not implemented very well... +=============== +*/ +void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, +							 float degrees ) { +	float sin_a; +	float cos_a; +	float cos_ia; +	float i_i_ia; +	float j_j_ia; +	float k_k_ia; +	float i_j_ia; +	float i_k_ia; +	float j_k_ia; +	float a_sin; +	float b_sin; +	float c_sin; +	float rot[3][3]; + +	cos_ia = DEG2RAD(degrees); +	sin_a = sin(cos_ia); +	cos_a = cos(cos_ia); +	cos_ia = 1.0F - cos_a; + +	i_i_ia = dir[0] * dir[0] * cos_ia; +	j_j_ia = dir[1] * dir[1] * cos_ia; +	k_k_ia = dir[2] * dir[2] * cos_ia; +	i_j_ia = dir[0] * dir[1] * cos_ia; +	i_k_ia = dir[0] * dir[2] * cos_ia; +	j_k_ia = dir[1] * dir[2] * cos_ia; + +	a_sin = dir[0] * sin_a; +	b_sin = dir[1] * sin_a; +	c_sin = dir[2] * sin_a; + +	rot[0][0] = i_i_ia + cos_a; +	rot[0][1] = i_j_ia - c_sin; +	rot[0][2] = i_k_ia + b_sin; +	rot[1][0] = i_j_ia + c_sin; +	rot[1][1] = j_j_ia + cos_a; +	rot[1][2] = j_k_ia - a_sin; +	rot[2][0] = i_k_ia - b_sin; +	rot[2][1] = j_k_ia + a_sin; +	rot[2][2] = k_k_ia + cos_a; + +	dst[0] = point[0] * rot[0][0] + point[1] * rot[0][1] + point[2] * rot[0][2]; +	dst[1] = point[0] * rot[1][0] + point[1] * rot[1][1] + point[2] * rot[1][2]; +	dst[2] = point[0] * rot[2][0] + point[1] * rot[2][1] + point[2] * rot[2][2]; +} + +/* +=============== +RotateAroundDirection +=============== +*/ +void RotateAroundDirection( vec3_t axis[3], vec_t angle ) { +	vec_t scale; + +	angle = DEG2RAD( angle ); + +	// create an arbitrary axis[1] +	PerpendicularVector( axis[ 1 ], axis[ 0 ] ); + +	// cross to get axis[2] +	CrossProduct( axis[ 0 ], axis[ 1 ], axis[ 2 ] ); + +	// rotate +	scale = cos( angle ); +	VectorScale( axis[ 1 ], scale, axis[ 1 ] ); + +	scale = sin( angle ); +	VectorMA( axis[ 1 ], scale, axis[ 2 ], axis[ 1 ] ); + +	// recalculate axis[2] +	CrossProduct( axis[ 0 ], axis[ 1 ], axis[ 2 ] ); +} + + + +void vectoangles( const vec3_t value1, vec3_t angles ) { +	float	forward; +	float	yaw, pitch; +	 +	if ( value1[1] == 0 && value1[0] == 0 ) { +		yaw = 0; +		if ( value1[2] > 0 ) { +			pitch = 90; +		} +		else { +			pitch = 270; +		} +	} +	else { +		if ( value1[0] ) { +			yaw = ( atan2 ( value1[1], value1[0] ) * 180 / M_PI ); +		} +		else if ( value1[1] > 0 ) { +			yaw = 90; +		} +		else { +			yaw = 270; +		} +		if ( yaw < 0 ) { +			yaw += 360; +		} + +		forward = sqrt ( value1[0]*value1[0] + value1[1]*value1[1] ); +		pitch = ( atan2(value1[2], forward) * 180 / M_PI ); +		if ( pitch < 0 ) { +			pitch += 360; +		} +	} + +	angles[PITCH] = -pitch; +	angles[YAW] = yaw; +	angles[ROLL] = 0; +} + + +/* +================= +AxisToAngles + +Takes an axis (forward + right + up) +and returns angles -- including a roll +================= +*/ +void AxisToAngles( vec3_t axis[3], vec3_t angles ) { +	float length1; +	float yaw, pitch, roll = 0.0f; + +	if ( axis[0][1] == 0 && axis[0][0] == 0 ) { +		yaw = 0; +		if ( axis[0][2] > 0 ) { +			pitch = 90; +		} +		else { +			pitch = 270; +		} +	} +	else { +		if ( axis[0][0] ) { +			yaw = ( atan2 ( axis[0][1], axis[0][0] ) * 180 / M_PI ); +		} +		else if ( axis[0][1] > 0 ) { +			yaw = 90; +		} +		else { +			yaw = 270; +		} +		if ( yaw < 0 ) { +			yaw += 360; +		} + +		length1 = sqrt ( axis[0][0]*axis[0][0] + axis[0][1]*axis[0][1] ); +		pitch = ( atan2(axis[0][2], length1) * 180 / M_PI ); +		if ( pitch < 0 ) { +			pitch += 360; +		} + +		roll = ( atan2( axis[1][2], axis[2][2] ) * 180 / M_PI ); +		if ( roll < 0 ) { +			roll += 360; +		} +	} + +	angles[PITCH] = -pitch; +	angles[YAW] = yaw; +	angles[ROLL] = roll; +} + +/* +================= +AnglesToAxis +================= +*/ +void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ) { +	vec3_t	right; + +	// angle vectors returns "right" instead of "y axis" +	AngleVectors( angles, axis[0], right, axis[2] ); +	VectorSubtract( vec3_origin, right, axis[1] ); +} + +void AxisClear( vec3_t axis[3] ) { +	axis[0][0] = 1; +	axis[0][1] = 0; +	axis[0][2] = 0; +	axis[1][0] = 0; +	axis[1][1] = 1; +	axis[1][2] = 0; +	axis[2][0] = 0; +	axis[2][1] = 0; +	axis[2][2] = 1; +} + +void AxisCopy( vec3_t in[3], vec3_t out[3] ) { +	VectorCopy( in[0], out[0] ); +	VectorCopy( in[1], out[1] ); +	VectorCopy( in[2], out[2] ); +} + +void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ) +{ +	float d; +	vec3_t n; +	float inv_denom; + +	inv_denom = 1.0f / DotProduct( normal, normal ); +#ifndef Q3_VM +	assert( Q_fabs(inv_denom) != 0.0f ); // bk010122 - zero vectors get here +#endif +	inv_denom = 1.0f / inv_denom; + +	d = DotProduct( normal, p ) * inv_denom; + +	n[0] = normal[0] * inv_denom; +	n[1] = normal[1] * inv_denom; +	n[2] = normal[2] * inv_denom; + +	dst[0] = p[0] - d * n[0]; +	dst[1] = p[1] - d * n[1]; +	dst[2] = p[2] - d * n[2]; +} + +/* +================ +MakeNormalVectors + +Given a normalized forward vector, create two +other perpendicular vectors +================ +*/ +void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up) { +	float		d; + +	// this rotate and negate guarantees a vector +	// not colinear with the original +	right[1] = -forward[0]; +	right[2] = forward[1]; +	right[0] = forward[2]; + +	d = DotProduct (right, forward); +	VectorMA (right, -d, forward, right); +	VectorNormalize (right); +	CrossProduct (right, forward, up); +} + + +void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out ) +{ +	out[0] = DotProduct( in, matrix[0] ); +	out[1] = DotProduct( in, matrix[1] ); +	out[2] = DotProduct( in, matrix[2] ); +} + +//============================================================================ + +#if !idppc +/* +** float q_rsqrt( float number ) +*/ +float Q_rsqrt( float number ) +{ +	union { +		float f; +		int i; +	} t; +	float x2, y; +	const float threehalfs = 1.5F; + +	x2 = number * 0.5F; +	t.f  = number; +	t.i  = 0x5f3759df - ( t.i >> 1 );               // what the fuck? +	y  = t.f; +	y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration +//	y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed + +	//assert( !isnan(y) ); // bk010122 - FPE? +	return y; +} + +float Q_fabs( float f ) { +	int tmp = * ( int * ) &f; +	tmp &= 0x7FFFFFFF; +	return * ( float * ) &tmp; +} +#endif + +//============================================================ + +/* +=============== +LerpAngle + +=============== +*/ +float LerpAngle (float from, float to, float frac) { +	float	a; + +	if ( to - from > 180 ) { +		to -= 360; +	} +	if ( to - from < -180 ) { +		to += 360; +	} +	a = from + frac * (to - from); + +	return a; +} + + +/* +================= +AngleSubtract + +Always returns a value from -180 to 180 +================= +*/ +float	AngleSubtract( float a1, float a2 ) { +	float	a; + +	a = a1 - a2; +	while ( a > 180 ) { +		a -= 360; +	} +	while ( a < -180 ) { +		a += 360; +	} +	return a; +} + + +void AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ) { +	v3[0] = AngleSubtract( v1[0], v2[0] ); +	v3[1] = AngleSubtract( v1[1], v2[1] ); +	v3[2] = AngleSubtract( v1[2], v2[2] ); +} + + +float	AngleMod(float a) { +	a = (360.0/65536) * ((int)(a*(65536/360.0)) & 65535); +	return a; +} + + +/* +================= +AngleNormalize360 + +returns angle normalized to the range [0 <= angle < 360] +================= +*/ +float AngleNormalize360 ( float angle ) { +	return (360.0 / 65536) * ((int)(angle * (65536 / 360.0)) & 65535); +} + + +/* +================= +AngleNormalize180 + +returns angle normalized to the range [-180 < angle <= 180] +================= +*/ +float AngleNormalize180 ( float angle ) { +	angle = AngleNormalize360( angle ); +	if ( angle > 180.0 ) { +		angle -= 360.0; +	} +	return angle; +} + + +/* +================= +AngleDelta + +returns the normalized delta from angle1 to angle2 +================= +*/ +float AngleDelta ( float angle1, float angle2 ) { +	return AngleNormalize180( angle1 - angle2 ); +} + + +//============================================================ + + +/* +================= +SetPlaneSignbits +================= +*/ +void SetPlaneSignbits (cplane_t *out) { +	int	bits, j; + +	// for fast box on planeside test +	bits = 0; +	for (j=0 ; j<3 ; j++) { +		if (out->normal[j] < 0) { +			bits |= 1<<j; +		} +	} +	out->signbits = bits; +} + + +/* +================== +BoxOnPlaneSide + +Returns 1, 2, or 1 + 2 + +// this is the slow, general version +int BoxOnPlaneSide2 (vec3_t emins, vec3_t emaxs, struct cplane_s *p) +{ +	int		i; +	float	dist1, dist2; +	int		sides; +	vec3_t	corners[2]; + +	for (i=0 ; i<3 ; i++) +	{ +		if (p->normal[i] < 0) +		{ +			corners[0][i] = emins[i]; +			corners[1][i] = emaxs[i]; +		} +		else +		{ +			corners[1][i] = emins[i]; +			corners[0][i] = emaxs[i]; +		} +	} +	dist1 = DotProduct (p->normal, corners[0]) - p->dist; +	dist2 = DotProduct (p->normal, corners[1]) - p->dist; +	sides = 0; +	if (dist1 >= 0) +		sides = 1; +	if (dist2 < 0) +		sides |= 2; + +	return sides; +} + +================== +*/ + +#if !id386 + +int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p) +{ +	float	dist1, dist2; +	int		sides; + +// fast axial cases +	if (p->type < 3) +	{ +		if (p->dist <= emins[p->type]) +			return 1; +		if (p->dist >= emaxs[p->type]) +			return 2; +		return 3; +	} + +// general case +	switch (p->signbits) +	{ +	case 0: +		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +		dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +		break; +	case 1: +		dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +		break; +	case 2: +		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +		dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +		break; +	case 3: +		dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +		break; +	case 4: +		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +		dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +		break; +	case 5: +		dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2]; +		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2]; +		break; +	case 6: +		dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +		dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +		break; +	case 7: +		dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2]; +		dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2]; +		break; +	default: +		dist1 = dist2 = 0;		// shut up compiler +		break; +	} + +	sides = 0; +	if (dist1 >= p->dist) +		sides = 1; +	if (dist2 < p->dist) +		sides |= 2; + +	return sides; +} +#elif __GNUC__ +// use matha.s +#else +#pragma warning( disable: 4035 ) + +__declspec( naked ) int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *p) +{ +	static int bops_initialized; +	static int Ljmptab[8]; + +	__asm { + +		push ebx +			 +		cmp bops_initialized, 1 +		je  initialized +		mov bops_initialized, 1 +		 +		mov Ljmptab[0*4], offset Lcase0 +		mov Ljmptab[1*4], offset Lcase1 +		mov Ljmptab[2*4], offset Lcase2 +		mov Ljmptab[3*4], offset Lcase3 +		mov Ljmptab[4*4], offset Lcase4 +		mov Ljmptab[5*4], offset Lcase5 +		mov Ljmptab[6*4], offset Lcase6 +		mov Ljmptab[7*4], offset Lcase7 +			 +initialized: + +		mov edx,dword ptr[4+12+esp] +		mov ecx,dword ptr[4+4+esp] +		xor eax,eax +		mov ebx,dword ptr[4+8+esp] +		mov al,byte ptr[17+edx] +		cmp al,8 +		jge Lerror +		fld dword ptr[0+edx] +		fld st(0) +		jmp dword ptr[Ljmptab+eax*4] +Lcase0: +		fmul dword ptr[ebx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ebx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ebx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ecx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase1: +		fmul dword ptr[ecx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ebx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ebx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ecx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase2: +		fmul dword ptr[ebx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ecx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ebx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ecx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase3: +		fmul dword ptr[ecx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ecx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ebx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ecx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase4: +		fmul dword ptr[ebx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ebx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ecx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ebx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase5: +		fmul dword ptr[ecx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ebx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ecx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ebx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase6: +		fmul dword ptr[ebx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ecx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ecx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ecx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ebx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +		jmp LSetSides +Lcase7: +		fmul dword ptr[ecx] +		fld dword ptr[0+4+edx] +		fxch st(2) +		fmul dword ptr[ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[4+ecx] +		fld dword ptr[0+8+edx] +		fxch st(2) +		fmul dword ptr[4+ebx] +		fxch st(2) +		fld st(0) +		fmul dword ptr[8+ecx] +		fxch st(5) +		faddp st(3),st(0) +		fmul dword ptr[8+ebx] +		fxch st(1) +		faddp st(3),st(0) +		fxch st(3) +		faddp st(2),st(0) +LSetSides: +		faddp st(2),st(0) +		fcomp dword ptr[12+edx] +		xor ecx,ecx +		fnstsw ax +		fcomp dword ptr[12+edx] +		and ah,1 +		xor ah,1 +		add cl,ah +		fnstsw ax +		and ah,1 +		add ah,ah +		add cl,ah +		pop ebx +		mov eax,ecx +		ret +Lerror: +		int 3 +	} +} +#pragma warning( default: 4035 ) + +#endif + +/* +================= +RadiusFromBounds +================= +*/ +float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ) { +	int		i; +	vec3_t	corner; +	float	a, b; + +	for (i=0 ; i<3 ; i++) { +		a = fabs( mins[i] ); +		b = fabs( maxs[i] ); +		corner[i] = a > b ? a : b; +	} + +	return VectorLength (corner); +} + + +void ClearBounds( vec3_t mins, vec3_t maxs ) { +	mins[0] = mins[1] = mins[2] = 99999; +	maxs[0] = maxs[1] = maxs[2] = -99999; +} + +void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ) { +	if ( v[0] < mins[0] ) { +		mins[0] = v[0]; +	} +	if ( v[0] > maxs[0]) { +		maxs[0] = v[0]; +	} + +	if ( v[1] < mins[1] ) { +		mins[1] = v[1]; +	} +	if ( v[1] > maxs[1]) { +		maxs[1] = v[1]; +	} + +	if ( v[2] < mins[2] ) { +		mins[2] = v[2]; +	} +	if ( v[2] > maxs[2]) { +		maxs[2] = v[2]; +	} +} + + +vec_t VectorNormalize( vec3_t v ) { +	// NOTE: TTimo - Apple G4 altivec source uses double? +	float	length, ilength; + +	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; +	length = sqrt (length); + +	if ( length ) { +		ilength = 1/length; +		v[0] *= ilength; +		v[1] *= ilength; +		v[2] *= ilength; +	} +		 +	return length; +} + +vec_t VectorNormalize2( const vec3_t v, vec3_t out) { +	float	length, ilength; + +	length = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; +	length = sqrt (length); + +	if (length) +	{ +#ifndef Q3_VM // bk0101022 - FPE related +//	  assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) ); +#endif +		ilength = 1/length; +		out[0] = v[0]*ilength; +		out[1] = v[1]*ilength; +		out[2] = v[2]*ilength; +	} else { +#ifndef Q3_VM // bk0101022 - FPE related +//	  assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) ); +#endif +		VectorClear( out ); +	} +		 +	return length; + +} + +void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc) { +	vecc[0] = veca[0] + scale*vecb[0]; +	vecc[1] = veca[1] + scale*vecb[1]; +	vecc[2] = veca[2] + scale*vecb[2]; +} + + +vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ) { +	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; +} + +void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ) { +	out[0] = veca[0]-vecb[0]; +	out[1] = veca[1]-vecb[1]; +	out[2] = veca[2]-vecb[2]; +} + +void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ) { +	out[0] = veca[0]+vecb[0]; +	out[1] = veca[1]+vecb[1]; +	out[2] = veca[2]+vecb[2]; +} + +void _VectorCopy( const vec3_t in, vec3_t out ) { +	out[0] = in[0]; +	out[1] = in[1]; +	out[2] = in[2]; +} + +void _VectorScale( const vec3_t in, vec_t scale, vec3_t out ) { +	out[0] = in[0]*scale; +	out[1] = in[1]*scale; +	out[2] = in[2]*scale; +} + +void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ) { +	out[0] = in[0]*scale; +	out[1] = in[1]*scale; +	out[2] = in[2]*scale; +	out[3] = in[3]*scale; +} + + +int Q_log2( int val ) { +	int answer; + +	answer = 0; +	while ( ( val>>=1 ) != 0 ) { +		answer++; +	} +	return answer; +} + + + +/* +================= +PlaneTypeForNormal +================= +*/ +/* +int	PlaneTypeForNormal (vec3_t normal) { +	if ( normal[0] == 1.0 ) +		return PLANE_X; +	if ( normal[1] == 1.0 ) +		return PLANE_Y; +	if ( normal[2] == 1.0 ) +		return PLANE_Z; +	 +	return PLANE_NON_AXIAL; +} +*/ + + +/* +================ +MatrixMultiply +================ +*/ +void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) { +	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + +				in1[0][2] * in2[2][0]; +	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + +				in1[0][2] * in2[2][1]; +	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + +				in1[0][2] * in2[2][2]; +	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + +				in1[1][2] * in2[2][0]; +	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + +				in1[1][2] * in2[2][1]; +	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + +				in1[1][2] * in2[2][2]; +	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + +				in1[2][2] * in2[2][0]; +	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + +				in1[2][2] * in2[2][1]; +	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + +				in1[2][2] * in2[2][2]; +} + +/* +================ +VectorMatrixMultiply +================ +*/ +void VectorMatrixMultiply( const vec3_t p, vec3_t m[ 3 ], vec3_t out ) +{ +	out[ 0 ] = m[ 0 ][ 0 ] * p[ 0 ] + m[ 1 ][ 0 ] * p[ 1 ] + m[ 2 ][ 0 ] * p[ 2 ]; +	out[ 1 ] = m[ 0 ][ 1 ] * p[ 0 ] + m[ 1 ][ 1 ] * p[ 1 ] + m[ 2 ][ 1 ] * p[ 2 ]; +	out[ 2 ] = m[ 0 ][ 2 ] * p[ 0 ] + m[ 1 ][ 2 ] * p[ 1 ] + m[ 2 ][ 2 ] * p[ 2 ]; +} + + +void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up) { +	float		angle; +	static float		sr, sp, sy, cr, cp, cy; +	// static to help MS compiler fp bugs + +	angle = angles[YAW] * (M_PI*2 / 360); +	sy = sin(angle); +	cy = cos(angle); +	angle = angles[PITCH] * (M_PI*2 / 360); +	sp = sin(angle); +	cp = cos(angle); +	angle = angles[ROLL] * (M_PI*2 / 360); +	sr = sin(angle); +	cr = cos(angle); + +	if (forward) +	{ +		forward[0] = cp*cy; +		forward[1] = cp*sy; +		forward[2] = -sp; +	} +	if (right) +	{ +		right[0] = (-1*sr*sp*cy+-1*cr*-sy); +		right[1] = (-1*sr*sp*sy+-1*cr*cy); +		right[2] = -1*sr*cp; +	} +	if (up) +	{ +		up[0] = (cr*sp*cy+-sr*-sy); +		up[1] = (cr*sp*sy+-sr*cy); +		up[2] = cr*cp; +	} +} + +/* +** assumes "src" is normalized +*/ +void PerpendicularVector( vec3_t dst, const vec3_t src ) +{ +	int	pos; +	int i; +	float minelem = 1.0F; +	vec3_t tempvec; + +	/* +	** find the smallest magnitude axially aligned vector +	*/ +	for ( pos = 0, i = 0; i < 3; i++ ) +	{ +		if ( fabs( src[i] ) < minelem ) +		{ +			pos = i; +			minelem = fabs( src[i] ); +		} +	} +	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F; +	tempvec[pos] = 1.0F; + +	/* +	** project the point onto the plane defined by src +	*/ +	ProjectPointOnPlane( dst, tempvec, src ); + +	/* +	** normalize the result +	*/ +	VectorNormalize( dst ); +} + +/* +================= +pointToLineDistance + +Distance from a point to some line +================= +*/ +float pointToLineDistance( const vec3_t p0, const vec3_t p1, const vec3_t p2 ) +{ +	vec3_t	v, w, y; +	float	 c1, c2; + +	VectorSubtract( p2, p1, v ); +	VectorSubtract( p1, p0, w ); + +	CrossProduct( w, v, y ); +	c1 = VectorLength( y ); +	c2 = VectorLength( v ); + +	if( c2 == 0.0f ) +		return 0.0f; +	else +		return c1 / c2; +} + +/* +================= +GetPerpendicularViewVector + +Used to find an "up" vector for drawing a sprite so that it always faces the view as best as possible +================= +*/ +void GetPerpendicularViewVector( const vec3_t point, const vec3_t p1, const vec3_t p2, vec3_t up ) +{ +	vec3_t	v1, v2; + +	VectorSubtract( point, p1, v1 ); +	VectorNormalize( v1 ); + +	VectorSubtract( point, p2, v2 ); +	VectorNormalize( v2 ); + +	CrossProduct( v1, v2, up ); +	VectorNormalize( up ); +} + +/* +================ +ProjectPointOntoVector +================ +*/ +void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj ) +{ +	vec3_t pVec, vec; + +	VectorSubtract( point, vStart, pVec ); +	VectorSubtract( vEnd, vStart, vec ); +	VectorNormalize( vec ); +	// project onto the directional vector for this segment +	VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj ); +} + +/* +================ +VectorMaxComponent + +Return the biggest component of some vector +================ +*/ +float VectorMaxComponent( vec3_t v ) +{ +	float biggest = v[ 0 ]; + +	if( v[ 1 ] > biggest ) +		biggest = v[ 1 ]; + +	if( v[ 2 ] > biggest ) +		biggest = v[ 2 ]; + +	return biggest; +} + +/* +================ +VectorMinComponent + +Return the smallest component of some vector +================ +*/ +float VectorMinComponent( vec3_t v ) +{ +	float smallest = v[ 0 ]; + +	if( v[ 1 ] < smallest ) +		smallest = v[ 1 ]; + +	if( v[ 2 ] < smallest ) +		smallest = v[ 2 ]; + +	return smallest; +} + + +#define LINE_DISTANCE_EPSILON 1e-05f + +/* +================ +DistanceBetweenLineSegmentsSquared + +Return the smallest distance between two line segments, squared +================ +*/ +vec_t DistanceBetweenLineSegmentsSquared( +    const vec3_t sP0, const vec3_t sP1, +    const vec3_t tP0, const vec3_t tP1, +    float *s, float *t ) +{ +  vec3_t  sMag, tMag, diff; +  float   a, b, c, d, e; +  float   D; +  float   sN, sD; +  float   tN, tD; +  vec3_t  separation; + +  VectorSubtract( sP1, sP0, sMag ); +  VectorSubtract( tP1, tP0, tMag ); +  VectorSubtract( sP0, tP0, diff ); +  a = DotProduct( sMag, sMag ); +  b = DotProduct( sMag, tMag ); +  c = DotProduct( tMag, tMag ); +  d = DotProduct( sMag, diff ); +  e = DotProduct( tMag, diff ); +  sD = tD = D = a * c - b * b; + +  if( D < LINE_DISTANCE_EPSILON ) +  { +    // the lines are almost parallel +    sN = 0.0;   // force using point P0 on segment S1 +    sD = 1.0;   // to prevent possible division by 0.0 later +    tN = e; +    tD = c; +  } +  else +  { +    // get the closest points on the infinite lines +    sN = ( b * e - c * d ); +    tN = ( a * e - b * d ); + +    if( sN < 0.0 ) +    { +      // sN < 0 => the s=0 edge is visible +      sN = 0.0; +      tN = e; +      tD = c; +    } +    else if( sN > sD ) +    { +      // sN > sD => the s=1 edge is visible +      sN = sD; +      tN = e + b; +      tD = c; +    } +  } + +  if( tN < 0.0 ) +  { +    // tN < 0 => the t=0 edge is visible +    tN = 0.0; + +    // recompute sN for this edge +    if( -d < 0.0 ) +      sN = 0.0; +    else if( -d > a ) +      sN = sD; +    else +    { +      sN = -d; +      sD = a; +    } +  } +  else if( tN > tD ) +  { +    // tN > tD => the t=1 edge is visible +    tN = tD; + +    // recompute sN for this edge +    if( ( -d + b ) < 0.0 ) +      sN = 0; +    else if( ( -d + b ) > a ) +      sN = sD; +    else +    { +      sN = ( -d + b ); +      sD = a; +    } +  } + +  // finally do the division to get *s and *t +  *s = ( fabs( sN ) < LINE_DISTANCE_EPSILON ? 0.0 : sN / sD ); +  *t = ( fabs( tN ) < LINE_DISTANCE_EPSILON ? 0.0 : tN / tD ); + +  // get the difference of the two closest points +  VectorScale( sMag, *s, sMag ); +  VectorScale( tMag, *t, tMag ); +  VectorAdd( diff, sMag, separation ); +  VectorSubtract( separation, tMag, separation ); + +  return VectorLengthSquared( separation ); +} + +/* +================ +DistanceBetweenLineSegments + +Return the smallest distance between two line segments +================ +*/ +vec_t DistanceBetweenLineSegments( +    const vec3_t sP0, const vec3_t sP1, +    const vec3_t tP0, const vec3_t tP1, +    float *s, float *t ) +{ +  return (vec_t)sqrt( DistanceBetweenLineSegmentsSquared( +        sP0, sP1, tP0, tP1, s, t ) ); +} + +/* +================= +Q_isnan + +Don't pass doubles to this +================ +*/ +int Q_isnan( float x ) +{ +	union +	{ +		float f; +		unsigned int i; +	} t; + +	t.f = x; +	t.i &= 0x7FFFFFFF; +	t.i = 0x7F800000 - t.i; + +	return (int)( (unsigned int)t.i >> 31 ); +} diff --git a/src/qcommon/q_platform.h b/src/qcommon/q_platform.h new file mode 100644 index 0000000..84b87b9 --- /dev/null +++ b/src/qcommon/q_platform.h @@ -0,0 +1,386 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// +#ifndef __Q_PLATFORM_H +#define __Q_PLATFORM_H + +// this is for determining if we have an asm version of a C function +#ifdef Q3_VM + +#define id386 0 +#define idppc 0 +#define idppc_altivec 0 + +#else + +#if (defined _M_IX86 || defined __i386__) && !defined(C_ONLY) +#define id386 1 +#else +#define id386 0 +#endif + +#if (defined(powerc) || defined(powerpc) || defined(ppc) || \ +	defined(__ppc) || defined(__ppc__)) && !defined(C_ONLY) +#define idppc 1 +#if defined(__VEC__) +#define idppc_altivec 1 +#ifdef __APPLE__  // Apple's GCC does this differently than the FSF. +#define VECCONST_UINT8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ +	(vector unsigned char) (a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) +#else +#define VECCONST_UINT8(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \ +	(vector unsigned char) {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p} +#endif +#else +#define idppc_altivec 0 +#endif +#else +#define idppc 0 +#define idppc_altivec 0 +#endif + +#endif + +#ifndef __ASM_I386__ // don't include the C bits if included from qasm.h + +// for windows fastcall option +#define QDECL + +//================================================================= WIN64/32 === + +#if defined(_WIN64) || defined(__WIN64__) + +    #undef idx64 +    #define idx64 1 +     +    #undef QDECL +    #define QDECL __cdecl +     +    #undef QCALL +    #define QCALL __stdcall +     +    #if defined( _MSC_VER ) +    #define OS_STRING "win_msvc64" +    #elif defined __MINGW64__ +    #define OS_STRING "win_mingw64" +    #endif +     +    #define ID_INLINE __inline +    #define PATH_SEP '\\' +     +    #if defined( __WIN64__ )  +    #define ARCH_STRING "x86_64" +    #elif defined _M_ALPHA +    #define ARCH_STRING "AXP" +    #endif +     +    #define Q3_LITTLE_ENDIAN +     +    #define DLL_EXT ".dll" +    #define EXE_EXT ".exe" + +    // For cl_updates.cpp +    #define RELEASE_PACKAGE_NAME ( "release-mingw32-" ARCH_STRING ".zip" ) +     +#elif defined(_WIN32) || defined(__WIN32__) + +    #undef QDECL +    #define QDECL __cdecl +     +    #undef QCALL +    #define QCALL __stdcall +     +    #if defined( _MSC_VER ) +    #define OS_STRING "win_msvc" +    #elif defined __MINGW32__ +    #define OS_STRING "win_mingw" +    #endif +     +    #define ID_INLINE __inline +    #define PATH_SEP '\\' +     +    #if defined( _M_IX86 ) || defined( __i386__ ) +    #define ARCH_STRING "x86" +    #elif defined _M_ALPHA +    #define ARCH_STRING "AXP" +    #endif +     +    #define Q3_LITTLE_ENDIAN +     +    #define DLL_EXT ".dll" +    #define EXE_EXT ".exe" + +    // For cl_updates.cpp +    #define RELEASE_PACKAGE_NAME ( "release-mingw32-" ARCH_STRING ".zip" ) +  +#endif + + +//============================================================== MAC OS X === + +#if defined(__APPLE__) || defined(__APPLE_CC__) + +    #define OS_STRING "macosx" +    #define ID_INLINE inline +    #define PATH_SEP '/' + +    #ifdef __ppc__ +    #define ARCH_STRING "ppc" +    #define Q3_BIG_ENDIAN +    #elif defined __i386__ +    #define ARCH_STRING "x86" +    #define Q3_LITTLE_ENDIAN +    #elif defined __x86_64__ +    #undef idx64 +    #define idx64 1 +    #define ARCH_STRING "x86_64" +    #define Q3_LITTLE_ENDIAN +    #endif + +    #define DLL_EXT ".dylib" +    #define EXE_EXT + +    // For cl_updates.cpp +    #define RELEASE_PACKAGE_NAME ( "release-darwin-" ARCH_STRING ".zip" ) +  +#endif + +//================================================================= LINUX === + + +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) +     +    #include <endian.h> +     +    #if defined(__linux__) +    #       define OS_STRING "linux" +    #elif defined(__FreeBSD_kernel__) +    #       define OS_STRING "kFreeBSD" +    #else +    #       define OS_STRING "GNU" +    #endif +     +    #define ID_INLINE inline +    #define PATH_SEP '/' +     +    #ifdef __ppc__ +     #define ARCH_STRING "ppc" +     #define Q3_BIG_ENDIAN +    #elif defined __i386__ +     # define ARCH_STRING "x86" +     # define Q3_LITTLE_ENDIAN +    #elif defined __x86_64__ +     # define ARCH_STRING "x86_64" +     # define Q3_LITTLE_ENDIAN +     #undef idx64 +     #define idx64 1 +    #endif +     +    #define DLL_EXT ".so" +    #define EXE_EXT +     +    // For cl_updates.cpp +    #define RELEASE_PACKAGE_NAME ( "release-linux-" ARCH_STRING ".zip" ) +  +#endif + +//=================================================================== BSD === + +#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) + +    #include <sys/types.h> +    #include <machine/endian.h> + +    #ifndef __BSD__ +      #define __BSD__ +    #endif + +    #if defined(__FreeBSD__) +    #define OS_STRING "freebsd" +    #elif defined(__OpenBSD__) +    #define OS_STRING "openbsd" +    #elif defined(__NetBSD__) +    #define OS_STRING "netbsd" +    #endif + +    #define ID_INLINE inline +    #define PATH_SEP '/' + +    #ifdef __i386__ +    #define ARCH_STRING "x86" +    #elif defined __amd64__ +    #undef idx64 +    #define idx64 1 +    #define ARCH_STRING "x86_64" +    #elif defined __axp__ +    #define ARCH_STRING "alpha" +    #endif + +    #if BYTE_ORDER == BIG_ENDIAN +    #define Q3_BIG_ENDIAN +    #else +    #define Q3_LITTLE_ENDIAN +    #endif + +    #define DLL_EXT ".so" +    #define EXE_EXT + +#endif + +//================================================================= SUNOS === + +#ifdef __sun + +    #include <stdint.h> +    #include <sys/byteorder.h> + +    #define OS_STRING "solaris" +    #define ID_INLINE inline +    #define PATH_SEP '/' + +    #ifdef __i386__ +    #define ARCH_STRING "x86" +    #elif defined __sparc +    #define ARCH_STRING "sparc" +    #endif + +    #if defined( _BIG_ENDIAN ) +    #define Q3_BIG_ENDIAN +    #elif defined( _LITTLE_ENDIAN ) +    #define Q3_LITTLE_ENDIAN +    #endif + +    #define DLL_EXT ".so" +    #define EXE_EXT + +#endif + +//================================================================== IRIX === + +#ifdef __sgi + +    #define OS_STRING "irix" +    #define ID_INLINE __inline +    #define PATH_SEP '/' + +    #define ARCH_STRING "mips" + +    #define Q3_BIG_ENDIAN // SGI's MIPS are always big endian + +    #define DLL_EXT ".so" +    #define EXE_EXT + +#endif + +//================================================================== Q3VM === + +#ifdef Q3_VM + +    #define OS_STRING "q3vm" +    #define ID_INLINE +    #define PATH_SEP '/' + +    #define ARCH_STRING "bytecode" + +    #define DLL_EXT ".qvm" +    #define EXE_EXT + +#endif + +//=========================================================================== + +//catch missing defines in above blocks +#if !defined( OS_STRING ) +#error "Operating system not supported" +#endif + +#if !defined( ARCH_STRING ) +#error "Architecture not supported" +#endif + +#ifndef ID_INLINE +#error "ID_INLINE not defined" +#endif + +#ifndef PATH_SEP +#error "PATH_SEP not defined" +#endif + +#ifndef DLL_EXT +#error "DLL_EXT not defined" +#endif + +#ifndef EXE_EXT +#error "EXE_EXT not defined" +#endif + + +//endianness +short ShortSwap (short l); +int LongSwap (int l); +float FloatSwap (const float *f); + +#if defined( Q3_BIG_ENDIAN ) && defined( Q3_LITTLE_ENDIAN ) +#error "Endianness defined as both big and little" +#elif defined( Q3_BIG_ENDIAN ) + +#define LittleShort(x) ShortSwap(x) +#define LittleLong(x) LongSwap(x) +#define LittleFloat(x) FloatSwap(&x) +#define BigShort +#define BigLong +#define BigFloat + +#elif defined( Q3_LITTLE_ENDIAN ) + +#define LittleShort +#define LittleLong +#define LittleFloat +#define BigShort(x) ShortSwap(x) +#define BigLong(x) LongSwap(x) +#define BigFloat(x) FloatSwap(&x) + +#elif defined( Q3_VM ) + +#define LittleShort +#define LittleLong +#define LittleFloat +#define BigShort +#define BigLong +#define BigFloat + +#else +#error "Endianness not defined" +#endif + + +//platform string +#ifdef NDEBUG +#define PLATFORM_STRING OS_STRING "-" ARCH_STRING +#else +#define PLATFORM_STRING OS_STRING "-" ARCH_STRING "-debug" +#endif + +#endif + +#endif diff --git a/src/qcommon/q_shared.c b/src/qcommon/q_shared.c new file mode 100644 index 0000000..2ac5537 --- /dev/null +++ b/src/qcommon/q_shared.c @@ -0,0 +1,1347 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// +// q_shared.c -- stateless support routines that are included in each code dll +#include "q_shared.h" + +float Com_Clamp( float min, float max, float value ) { +	if ( value < min ) { +		return min; +	} +	if ( value > max ) { +		return max; +	} +	return value; +} + + +/* +============ +COM_SkipPath +============ +*/ +char *COM_SkipPath (char *pathname) +{ +	char	*last; +	 +	last = pathname; +	while (*pathname) +	{ +		if (*pathname=='/') +			last = pathname+1; +		pathname++; +	} +	return last; +} + +/* +============ +COM_StripExtension +============ +*/ +void COM_StripExtension( const char *in, char *out, int destsize ) { +	int             length; + +	Q_strncpyz(out, in, destsize); + +	length = strlen(out)-1; +	while (length > 0 && out[length] != '.') +	{ +		length--; +		if (out[length] == '/') +			return;		// no extension +	} +	if (length) +		out[length] = 0; +} + + +/* +================== +COM_DefaultExtension +================== +*/ +void COM_DefaultExtension (char *path, int maxSize, const char *extension ) { +	char	oldPath[MAX_QPATH]; +	char    *src; + +// +// if path doesn't have a .EXT, append extension +// (extension should include the .) +// +	src = path + strlen(path) - 1; + +	while (*src != '/' && src != path) { +		if ( *src == '.' ) { +			return;                 // it has an extension +		} +		src--; +	} + +	Q_strncpyz( oldPath, path, sizeof( oldPath ) ); +	Com_sprintf( path, maxSize, "%s%s", oldPath, extension ); +} + +/* +============================================================================ + +					BYTE ORDER FUNCTIONS + +============================================================================ +*/ +/* +// can't just use function pointers, or dll linkage can +// mess up when qcommon is included in multiple places +static short	(*_BigShort) (short l); +static short	(*_LittleShort) (short l); +static int		(*_BigLong) (int l); +static int		(*_LittleLong) (int l); +static qint64	(*_BigLong64) (qint64 l); +static qint64	(*_LittleLong64) (qint64 l); +static float	(*_BigFloat) (const float *l); +static float	(*_LittleFloat) (const float *l); + +short	BigShort(short l){return _BigShort(l);} +short	LittleShort(short l) {return _LittleShort(l);} +int		BigLong (int l) {return _BigLong(l);} +int		LittleLong (int l) {return _LittleLong(l);} +qint64 	BigLong64 (qint64 l) {return _BigLong64(l);} +qint64 	LittleLong64 (qint64 l) {return _LittleLong64(l);} +float	BigFloat (const float *l) {return _BigFloat(l);} +float	LittleFloat (const float *l) {return _LittleFloat(l);} +*/ + +short   ShortSwap (short l) +{ +	byte    b1,b2; + +	b1 = l&255; +	b2 = (l>>8)&255; + +	return (b1<<8) + b2; +} + +short	ShortNoSwap (short l) +{ +	return l; +} + +int    LongSwap (int l) +{ +	byte    b1,b2,b3,b4; + +	b1 = l&255; +	b2 = (l>>8)&255; +	b3 = (l>>16)&255; +	b4 = (l>>24)&255; + +	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int	LongNoSwap (int l) +{ +	return l; +} + +qint64 Long64Swap (qint64 ll) +{ +	qint64	result; + +	result.b0 = ll.b7; +	result.b1 = ll.b6; +	result.b2 = ll.b5; +	result.b3 = ll.b4; +	result.b4 = ll.b3; +	result.b5 = ll.b2; +	result.b6 = ll.b1; +	result.b7 = ll.b0; + +	return result; +} + +qint64 Long64NoSwap (qint64 ll) +{ +	return ll; +} + +typedef union { +    float	f; +    unsigned int i; +} _FloatByteUnion; + +float FloatSwap (const float *f) { +	_FloatByteUnion out; + +	out.f = *f; +	out.i = LongSwap(out.i); + +	return out.f; +} + +float FloatNoSwap (const float *f) +{ +	return *f; +} + +/* +================ +Swap_Init +================ +*/ +/* +void Swap_Init (void) +{ +	byte	swaptest[2] = {1,0}; + +// set the byte swapping variables in a portable manner	 +	if ( *(short *)swaptest == 1) +	{ +		_BigShort = ShortSwap; +		_LittleShort = ShortNoSwap; +		_BigLong = LongSwap; +		_LittleLong = LongNoSwap; +		_BigLong64 = Long64Swap; +		_LittleLong64 = Long64NoSwap; +		_BigFloat = FloatSwap; +		_LittleFloat = FloatNoSwap; +	} +	else +	{ +		_BigShort = ShortNoSwap; +		_LittleShort = ShortSwap; +		_BigLong = LongNoSwap; +		_LittleLong = LongSwap; +		_BigLong64 = Long64NoSwap; +		_LittleLong64 = Long64Swap; +		_BigFloat = FloatNoSwap; +		_LittleFloat = FloatSwap; +	} + +} +*/ + +/* +============================================================================ + +PARSING + +============================================================================ +*/ + +static	char	com_token[MAX_TOKEN_CHARS]; +static	char	com_parsename[MAX_TOKEN_CHARS]; +static	int		com_lines; + +void COM_BeginParseSession( const char *name ) +{ +	com_lines = 0; +	Com_sprintf(com_parsename, sizeof(com_parsename), "%s", name); +} + +int COM_GetCurrentParseLine( void ) +{ +	return com_lines; +} + +char *COM_Parse( char **data_p ) +{ +	return COM_ParseExt( data_p, qtrue ); +} + +void COM_ParseError( char *format, ... ) +{ +	va_list argptr; +	static char string[4096]; + +	va_start (argptr, format); +	vsprintf (string, format, argptr); +	va_end (argptr); + +	Com_Printf("ERROR: %s, line %d: %s\n", com_parsename, com_lines, string); +} + +void COM_ParseWarning( char *format, ... ) +{ +	va_list argptr; +	static char string[4096]; + +	va_start (argptr, format); +	vsprintf (string, format, argptr); +	va_end (argptr); + +	Com_Printf("WARNING: %s, line %d: %s\n", com_parsename, com_lines, string); +} + +/* +============== +COM_Parse + +Parse a token out of a string +Will never return NULL, just empty strings + +If "allowLineBreaks" is qtrue then an empty +string will be returned if the next token is +a newline. +============== +*/ +static char *SkipWhitespace( char *data, qboolean *hasNewLines ) { +	int c; + +	while( (c = *data) <= ' ') { +		if( !c ) { +			return NULL; +		} +		if( c == '\n' ) { +			com_lines++; +			*hasNewLines = qtrue; +		} +		data++; +	} + +	return data; +} + +int COM_Compress( char *data_p ) { +	char *in, *out; +	int c; +	qboolean newline = qfalse, whitespace = qfalse; + +	in = out = data_p; +	if (in) { +		while ((c = *in) != 0) { +			// skip double slash comments +			if ( c == '/' && in[1] == '/' ) { +				while (*in && *in != '\n') { +					in++; +				} +			// skip /* */ comments +			} else if ( c == '/' && in[1] == '*' ) { +				while ( *in && ( *in != '*' || in[1] != '/' ) )  +					in++; +				if ( *in )  +					in += 2; +                        // record when we hit a newline +                        } else if ( c == '\n' || c == '\r' ) { +                            newline = qtrue; +                            in++; +                        // record when we hit whitespace +                        } else if ( c == ' ' || c == '\t') { +                            whitespace = qtrue; +                            in++; +                        // an actual token +			} else { +                            // if we have a pending newline, emit it (and it counts as whitespace) +                            if (newline) { +                                *out++ = '\n'; +                                newline = qfalse; +                                whitespace = qfalse; +                            } if (whitespace) { +                                *out++ = ' '; +                                whitespace = qfalse; +                            } +                             +                            // copy quoted strings unmolested +                            if (c == '"') { +                                    *out++ = c; +                                    in++; +                                    while (1) { +                                        c = *in; +                                        if (c && c != '"') { +                                            *out++ = c; +                                            in++; +                                        } else { +                                            break; +                                        } +                                    } +                                    if (c == '"') { +                                        *out++ = c; +                                        in++; +                                    } +                            } else { +                                *out = c; +                                out++; +                                in++; +                            } +			} +		} +	} +	*out = 0; +	return out - data_p; +} + +char *COM_ParseExt( char **data_p, qboolean allowLineBreaks ) +{ +	int c = 0, len; +	qboolean hasNewLines = qfalse; +	char *data; + +	data = *data_p; +	len = 0; +	com_token[0] = 0; + +	// make sure incoming data is valid +	if ( !data ) +	{ +		*data_p = NULL; +		return com_token; +	} + +	while ( 1 ) +	{ +		// skip whitespace +		data = SkipWhitespace( data, &hasNewLines ); +		if ( !data ) +		{ +			*data_p = NULL; +			return com_token; +		} +		if ( hasNewLines && !allowLineBreaks ) +		{ +			*data_p = data; +			return com_token; +		} + +		c = *data; + +		// skip double slash comments +		if ( c == '/' && data[1] == '/' ) +		{ +			data += 2; +			while (*data && *data != '\n') { +				data++; +			} +		} +		// skip /* */ comments +		else if ( c=='/' && data[1] == '*' )  +		{ +			data += 2; +			while ( *data && ( *data != '*' || data[1] != '/' ) )  +			{ +				data++; +			} +			if ( *data )  +			{ +				data += 2; +			} +		} +		else +		{ +			break; +		} +	} + +	// handle quoted strings +	if (c == '\"') +	{ +		data++; +		while (1) +		{ +			c = *data++; +			if (c=='\"' || !c) +			{ +				com_token[len] = 0; +				*data_p = ( char * ) data; +				return com_token; +			} +			if (len < MAX_TOKEN_CHARS - 1) +			{ +				com_token[len] = c; +				len++; +			} +		} +	} + +	// parse a regular word +	do +	{ +		if (len < MAX_TOKEN_CHARS - 1) +		{ +			com_token[len] = c; +			len++; +		} +		data++; +		c = *data; +		if ( c == '\n' ) +			com_lines++; +	} while (c>32); + +	com_token[len] = 0; + +	*data_p = ( char * ) data; +	return com_token; +} + + +#if 0 +// no longer used +/* +=============== +COM_ParseInfos +=============== +*/ +int COM_ParseInfos( char *buf, int max, char infos[][MAX_INFO_STRING] ) { +	char	*token; +	int		count; +	char	key[MAX_TOKEN_CHARS]; + +	count = 0; + +	while ( 1 ) { +		token = COM_Parse( &buf ); +		if ( !token[0] ) { +			break; +		} +		if ( strcmp( token, "{" ) ) { +			Com_Printf( "Missing { in info file\n" ); +			break; +		} + +		if ( count == max ) { +			Com_Printf( "Max infos exceeded\n" ); +			break; +		} + +		infos[count][0] = 0; +		while ( 1 ) { +			token = COM_ParseExt( &buf, qtrue ); +			if ( !token[0] ) { +				Com_Printf( "Unexpected end of info file\n" ); +				break; +			} +			if ( !strcmp( token, "}" ) ) { +				break; +			} +			Q_strncpyz( key, token, sizeof( key ) ); + +			token = COM_ParseExt( &buf, qfalse ); +			if ( !token[0] ) { +				strcpy( token, "<NULL>" ); +			} +			Info_SetValueForKey( infos[count], key, token ); +		} +		count++; +	} + +	return count; +} +#endif + + +/* +================== +COM_MatchToken +================== +*/ +void COM_MatchToken( char **buf_p, char *match ) { +	char	*token; + +	token = COM_Parse( buf_p ); +	if ( strcmp( token, match ) ) { +		Com_Error( ERR_DROP, "MatchToken: %s != %s", token, match ); +	} +} + + +/* +================= +SkipBracedSection + +The next token should be an open brace. +Skips until a matching close brace is found. +Internal brace depths are properly skipped. +================= +*/ +void SkipBracedSection (char **program) { +	char			*token; +	int				depth; + +	depth = 0; +	do { +		token = COM_ParseExt( program, qtrue ); +		if( token[1] == 0 ) { +			if( token[0] == '{' ) { +				depth++; +			} +			else if( token[0] == '}' ) { +				depth--; +			} +		} +	} while( depth && *program ); +} + +/* +================= +SkipRestOfLine +================= +*/ +void SkipRestOfLine ( char **data ) { +	char	*p; +	int		c; + +	p = *data; +	while ( (c = *p++) != 0 ) { +		if ( c == '\n' ) { +			com_lines++; +			break; +		} +	} + +	*data = p; +} + + +void Parse1DMatrix (char **buf_p, int x, float *m) { +	char	*token; +	int		i; + +	COM_MatchToken( buf_p, "(" ); + +	for (i = 0 ; i < x ; i++) { +		token = COM_Parse(buf_p); +		m[i] = atof(token); +	} + +	COM_MatchToken( buf_p, ")" ); +} + +void Parse2DMatrix (char **buf_p, int y, int x, float *m) { +	int		i; + +	COM_MatchToken( buf_p, "(" ); + +	for (i = 0 ; i < y ; i++) { +		Parse1DMatrix (buf_p, x, m + i * x); +	} + +	COM_MatchToken( buf_p, ")" ); +} + +void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m) { +	int		i; + +	COM_MatchToken( buf_p, "(" ); + +	for (i = 0 ; i < z ; i++) { +		Parse2DMatrix (buf_p, y, x, m + i * x*y); +	} + +	COM_MatchToken( buf_p, ")" ); +} + + +/* +============================================================================ + +					LIBRARY REPLACEMENT FUNCTIONS + +============================================================================ +*/ + +int Q_isprint( int c ) +{ +	if ( c >= 0x20 && c <= 0x7E ) +		return ( 1 ); +	return ( 0 ); +} + +int Q_islower( int c ) +{ +	if (c >= 'a' && c <= 'z') +		return ( 1 ); +	return ( 0 ); +} + +int Q_isupper( int c ) +{ +	if (c >= 'A' && c <= 'Z') +		return ( 1 ); +	return ( 0 ); +} + +int Q_isalpha( int c ) +{ +	if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) +		return ( 1 ); +	return ( 0 ); +} + +int Q_isdigit( int c ) +{ +	if ((c >= '0' && c <= '9')) +		return ( 1 ); +	return ( 0 ); +} + +char* Q_strrchr( const char* string, int c ) +{ +	char cc = c; +	char *s; +	char *sp=(char *)0; + +	s = (char*)string; + +	while (*s) +	{ +		if (*s == cc) +			sp = s; +		s++; +	} +	if (cc == 0) +		sp = s; + +	return sp; +} + +/* +============= +Q_strncpyz +  +Safe strncpy that ensures a trailing zero +============= +*/ +void Q_strncpyz( char *dest, const char *src, int destsize ) { +  // bk001129 - also NULL dest +  if ( !dest ) { +    Com_Error( ERR_FATAL, "Q_strncpyz: NULL dest" ); +  } +	if ( !src ) { +		Com_Error( ERR_FATAL, "Q_strncpyz: NULL src" ); +	} +	if ( destsize < 1 ) { +		Com_Error(ERR_FATAL,"Q_strncpyz: destsize < 1" );  +	} + +	strncpy( dest, src, destsize-1 ); +  dest[destsize-1] = 0; +} +                  +int Q_stricmpn (const char *s1, const char *s2, int n) { +	int		c1, c2; + +	// bk001129 - moved in 1.17 fix not in id codebase +        if ( s1 == NULL ) { +           if ( s2 == NULL ) +             return 0; +           else +             return -1; +        } +        else if ( s2==NULL ) +          return 1; + + +	 +	do { +		c1 = *s1++; +		c2 = *s2++; + +		if (!n--) { +			return 0;		// strings are equal until end point +		} +		 +		if (c1 != c2) { +			if (c1 >= 'a' && c1 <= 'z') { +				c1 -= ('a' - 'A'); +			} +			if (c2 >= 'a' && c2 <= 'z') { +				c2 -= ('a' - 'A'); +			} +			if (c1 != c2) { +				return c1 < c2 ? -1 : 1; +			} +		} +	} while (c1); +	 +	return 0;		// strings are equal +} + +int Q_strncmp (const char *s1, const char *s2, int n) { +	int		c1, c2; +	 +	do { +		c1 = *s1++; +		c2 = *s2++; + +		if (!n--) { +			return 0;		// strings are equal until end point +		} +		 +		if (c1 != c2) { +			return c1 < c2 ? -1 : 1; +		} +	} while (c1); +	 +	return 0;		// strings are equal +} + +int Q_stricmp (const char *s1, const char *s2) { +	return (s1 && s2) ? Q_stricmpn (s1, s2, 99999) : -1; +} + + +char *Q_strlwr( char *s1 ) { +    char	*s; + +    s = s1; +	while ( *s ) { +		*s = tolower(*s); +		s++; +	} +    return s1; +} + +char *Q_strupr( char *s1 ) { +    char	*s; + +    s = s1; +	while ( *s ) { +		*s = toupper(*s); +		s++; +	} +    return s1; +} + + +// never goes past bounds or leaves without a terminating 0 +void Q_strcat( char *dest, int size, const char *src ) { +	int		l1; + +	l1 = strlen( dest ); +	if ( l1 >= size ) { +		Com_Error( ERR_FATAL, "Q_strcat: already overflowed" ); +	} +	Q_strncpyz( dest + l1, src, size - l1 ); +} + + +int Q_PrintStrlen( const char *string ) { +	int			len; +	const char	*p; + +	if( !string ) { +		return 0; +	} + +	len = 0; +	p = string; +	while( *p ) { +		if( Q_IsColorString( p ) ) { +			p += 2; +			continue; +		} +		p++; +		len++; +	} + +	return len; +} + + +char *Q_CleanStr( char *string ) { +	char*	d; +	char*	s; +	int		c; + +	s = string; +	d = string; +	while ((c = *s) != 0 ) { +		if ( Q_IsColorString( s ) ) { +			s++; +		}		 +		else if ( c >= 0x20 && c <= 0x7E ) { +			*d++ = c; +		} +		s++; +	} +	*d = '\0'; + +	return string; +} + + +void QDECL Com_sprintf( char *dest, int size, const char *fmt, ...) { +	int		len; +	va_list		argptr; +	char	bigbuffer[32000];	// big, but small enough to fit in PPC stack + +	va_start (argptr,fmt); +	len = vsprintf (bigbuffer,fmt,argptr); +	va_end (argptr); +	if ( len >= sizeof( bigbuffer ) ) { +		Com_Error( ERR_FATAL, "Com_sprintf: overflowed bigbuffer" ); +	} +	if (len >= size) { +		Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size); +#ifdef	_DEBUG +		__asm { +			int 3; +		} +#endif +	} +	Q_strncpyz (dest, bigbuffer, size ); +} + + +/* +============ +va + +does a varargs printf into a temp buffer, so I don't need to have +varargs versions of all text functions. +FIXME: make this buffer size safe someday +============ +*/ +char	* QDECL va( char *format, ... ) { +	va_list		argptr; +	static char		string[2][32000];	// in case va is called by nested functions +	static int		index = 0; +	char	*buf; + +	buf = string[index & 1]; +	index++; + +	va_start (argptr, format); +	vsprintf (buf, format,argptr); +	va_end (argptr); + +	return buf; +} + +/* +============ +Com_TruncateLongString + +Assumes buffer is atleast TRUNCATE_LENGTH big +============ +*/ +void Com_TruncateLongString( char *buffer, const char *s ) +{ +	int length = strlen( s ); + +	if( length <= TRUNCATE_LENGTH ) +		Q_strncpyz( buffer, s, TRUNCATE_LENGTH ); +	else +	{ +		Q_strncpyz( buffer, s, ( TRUNCATE_LENGTH / 2 ) - 3 ); +		Q_strcat( buffer, TRUNCATE_LENGTH, " ... " ); +		Q_strcat( buffer, TRUNCATE_LENGTH, s + length - ( TRUNCATE_LENGTH / 2 ) + 3 ); +	} +} + +/* +===================================================================== + +  INFO STRINGS + +===================================================================== +*/ + +/* +=============== +Info_ValueForKey + +Searches the string for the given +key and returns the associated value, or an empty string. +FIXME: overflow check? +=============== +*/ +char *Info_ValueForKey( const char *s, const char *key ) { +	char	pkey[BIG_INFO_KEY]; +	static	char value[2][BIG_INFO_VALUE];	// use two buffers so compares +											// work without stomping on each other +	static	int	valueindex = 0; +	char	*o; +	 +	if ( !s || !key ) { +		return ""; +	} + +	if ( strlen( s ) >= BIG_INFO_STRING ) { +		Com_Error( ERR_DROP, "Info_ValueForKey: oversize infostring" ); +	} + +	valueindex ^= 1; +	if (*s == '\\') +		s++; +	while (1) +	{ +		o = pkey; +		while (*s != '\\') +		{ +			if (!*s) +				return ""; +			*o++ = *s++; +		} +		*o = 0; +		s++; + +		o = value[valueindex]; + +		while (*s != '\\' && *s) +		{ +			*o++ = *s++; +		} +		*o = 0; + +		if (!Q_stricmp (key, pkey) ) +			return value[valueindex]; + +		if (!*s) +			break; +		s++; +	} + +	return ""; +} + + +/* +=================== +Info_NextPair + +Used to itterate through all the key/value pairs in an info string +=================== +*/ +void Info_NextPair( const char **head, char *key, char *value ) { +	char	*o; +	const char	*s; + +	s = *head; + +	if ( *s == '\\' ) { +		s++; +	} +	key[0] = 0; +	value[0] = 0; + +	o = key; +	while ( *s != '\\' ) { +		if ( !*s ) { +			*o = 0; +			*head = s; +			return; +		} +		*o++ = *s++; +	} +	*o = 0; +	s++; + +	o = value; +	while ( *s != '\\' && *s ) { +		*o++ = *s++; +	} +	*o = 0; + +	*head = s; +} + + +/* +=================== +Info_RemoveKey +=================== +*/ +void Info_RemoveKey( char *s, const char *key ) { +	char	*start; +	char	pkey[MAX_INFO_KEY]; +	char	value[MAX_INFO_VALUE]; +	char	*o; + +	if ( strlen( s ) >= MAX_INFO_STRING ) { +		Com_Error( ERR_DROP, "Info_RemoveKey: oversize infostring" ); +	} + +	if (strchr (key, '\\')) { +		return; +	} + +	while (1) +	{ +		start = s; +		if (*s == '\\') +			s++; +		o = pkey; +		while (*s != '\\') +		{ +			if (!*s) +				return; +			*o++ = *s++; +		} +		*o = 0; +		s++; + +		o = value; +		while (*s != '\\' && *s) +		{ +			if (!*s) +				return; +			*o++ = *s++; +		} +		*o = 0; + +		if (!strcmp (key, pkey) ) +		{ +			strcpy (start, s);	// remove this part +			return; +		} + +		if (!*s) +			return; +	} + +} + +/* +=================== +Info_RemoveKey_Big +=================== +*/ +void Info_RemoveKey_Big( char *s, const char *key ) { +	char	*start; +	char	pkey[BIG_INFO_KEY]; +	char	value[BIG_INFO_VALUE]; +	char	*o; + +	if ( strlen( s ) >= BIG_INFO_STRING ) { +		Com_Error( ERR_DROP, "Info_RemoveKey_Big: oversize infostring" ); +	} + +	if (strchr (key, '\\')) { +		return; +	} + +	while (1) +	{ +		start = s; +		if (*s == '\\') +			s++; +		o = pkey; +		while (*s != '\\') +		{ +			if (!*s) +				return; +			*o++ = *s++; +		} +		*o = 0; +		s++; + +		o = value; +		while (*s != '\\' && *s) +		{ +			if (!*s) +				return; +			*o++ = *s++; +		} +		*o = 0; + +		if (!strcmp (key, pkey) ) +		{ +			strcpy (start, s);	// remove this part +			return; +		} + +		if (!*s) +			return; +	} + +} + + + + +/* +================== +Info_Validate + +Some characters are illegal in info strings because they +can mess up the server's parsing +================== +*/ +qboolean Info_Validate( const char *s ) { +	const char* ch = s; + +	while ( *ch != '\0' ) +	{ +		if( !Q_isprint( *ch ) ) +			return qfalse; + +		if( *ch == '\"' ) +			return qfalse; + +		if( *ch == ';' ) +			return qfalse; + +		++ch; +	} + +	return qtrue; +} + +/* +================== +Info_SetValueForKey + +Changes or adds a key/value pair +================== +*/ +void Info_SetValueForKey( char *s, const char *key, const char *value ) { +	char	newi[MAX_INFO_STRING]; +	const char* blacklist = "\\;\""; + +	if ( strlen( s ) >= MAX_INFO_STRING ) { +		Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" ); +	} + +	for(; *blacklist; ++blacklist) +	{ +		if (strchr (key, *blacklist) || strchr (value, *blacklist)) +		{ +			Com_Printf (S_COLOR_YELLOW "Can't use keys or values with a '%c': %s = %s\n", *blacklist, key, value); +			return; +		} +	} +	 +	Info_RemoveKey (s, key); +	if (!value || !strlen(value)) +		return; + +	Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value); + +	if (strlen(newi) + strlen(s) >= MAX_INFO_STRING) +	{ +		Com_Printf ("Info string length exceeded\n"); +		return; +	} + +	strcat (newi, s); +	strcpy (s, newi); +} + +/* +================== +Info_SetValueForKey_Big + +Changes or adds a key/value pair +================== +*/ +void Info_SetValueForKey_Big( char *s, const char *key, const char *value ) { +	char	newi[BIG_INFO_STRING]; +	const char* blacklist = "\\;\""; + +	if ( strlen( s ) >= BIG_INFO_STRING ) { +		Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" ); +	} + +	for(; *blacklist; ++blacklist) +	{ +		if (strchr (key, *blacklist) || strchr (value, *blacklist)) +		{ +			Com_Printf (S_COLOR_YELLOW "Can't use keys or values with a '%c': %s = %s\n", *blacklist, key, value); +			return; +		} +	} + +	Info_RemoveKey_Big (s, key); +	if (!value || !strlen(value)) +		return; + +	Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value); + +	if (strlen(newi) + strlen(s) >= BIG_INFO_STRING) +	{ +		Com_Printf ("BIG Info string length exceeded\n"); +		return; +	} + +	strcat (s, newi); +} + + + + +//==================================================================== + +/* +================== +Com_CharIsOneOfCharset +================== +*/ +static qboolean Com_CharIsOneOfCharset( char c, char *set ) +{ +	int i; + +	for( i = 0; i < strlen( set ); i++ ) +	{ +		if( set[ i ] == c ) +			return qtrue; +	} + +	return qfalse; +} + +/* +================== +Com_SkipCharset +================== +*/ +char *Com_SkipCharset( char *s, char *sep ) +{ +	char	*p = s; + +	while( p ) +	{ +		if( Com_CharIsOneOfCharset( *p, sep ) ) +			p++; +		else +			break; +	} + +	return p; +} + +/* +================== +Com_SkipTokens +================== +*/ +char *Com_SkipTokens( char *s, int numTokens, char *sep ) +{ +	int		sepCount = 0; +	char	*p = s; + +	while( sepCount < numTokens ) +	{ +		if( Com_CharIsOneOfCharset( *p++, sep ) ) +		{ +			sepCount++; +			while( Com_CharIsOneOfCharset( *p, sep ) ) +				p++; +		} +		else if( *p == '\0' ) +			break; +	} + +	if( sepCount == numTokens ) +		return p; +	else +		return s; +} diff --git a/src/qcommon/q_shared.h b/src/qcommon/q_shared.h new file mode 100644 index 0000000..b84e476 --- /dev/null +++ b/src/qcommon/q_shared.h @@ -0,0 +1,1342 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// +#ifndef __Q_SHARED_H +#define __Q_SHARED_H + +// q_shared.h -- included first by ALL program modules. +// A user mod should never modify this file + +#define VERSION_NUMBER        "1.1.0" +#define Q3_VERSION            "tremulous " VERSION_NUMBER +#ifndef SVN_VERSION +#define SVN_VERSION           Q3_VERSION +#endif +#define CLIENT_WINDOW_TITLE   "Tremulous " VERSION_NUMBER +#define CLIENT_WINDOW_ICON    "Tremulous" +#define CONSOLE_WINDOW_TITLE  "Tremulous " VERSION_NUMBER " console" +#define CONSOLE_WINDOW_ICON   "Tremulous console" + +#define MAX_TEAMNAME 32 + +#ifdef _MSC_VER + +#pragma warning(disable : 4018)     // signed/unsigned mismatch +#pragma warning(disable : 4032) +#pragma warning(disable : 4051) +#pragma warning(disable : 4057)		// slightly different base types +#pragma warning(disable : 4100)		// unreferenced formal parameter +#pragma warning(disable : 4115) +#pragma warning(disable : 4125)		// decimal digit terminates octal escape sequence +#pragma warning(disable : 4127)		// conditional expression is constant +#pragma warning(disable : 4136) +#pragma warning(disable : 4152)		// nonstandard extension, function/data pointer conversion in expression +//#pragma warning(disable : 4201) +//#pragma warning(disable : 4214) +#pragma warning(disable : 4244) +#pragma warning(disable : 4142)		// benign redefinition +//#pragma warning(disable : 4305)		// truncation from const double to float +//#pragma warning(disable : 4310)		// cast truncates constant value +//#pragma warning(disable:  4505) 	// unreferenced local function has been removed +#pragma warning(disable : 4514) +#pragma warning(disable : 4702)		// unreachable code +#pragma warning(disable : 4711)		// selected for automatic inline expansion +#pragma warning(disable : 4220)		// varargs matches remaining parameters +//#pragma intrinsic( memset, memcpy ) +#endif + +//Ignore __attribute__ on non-gcc platforms +#ifndef __GNUC__ +#ifndef __attribute__ +#define __attribute__(x) +#endif +#endif + +#if (defined _MSC_VER) +#define Q_EXPORT __declspec(dllexport) +#elif (defined __SUNPRO_C) +#define Q_EXPORT __global +#elif ((__GNUC__ >= 3) && (!__EMX__) && (!sun)) +#define Q_EXPORT __attribute__((visibility("default"))) +#else +#define Q_EXPORT +#endif + +/********************************************************************** +  VM Considerations + +  The VM can not use the standard system headers because we aren't really +  using the compiler they were meant for.  We use bg_lib.h which contains +  prototypes for the functions we define for our own use in bg_lib.c. + +  When writing mods, please add needed headers HERE, do not start including +  stuff like <stdio.h> in the various .c files that make up each of the VMs +  since you will be including system headers files can will have issues. + +  Remember, if you use a C library function that is not defined in bg_lib.c, +  you will have to add your own version for support in the VM. + + **********************************************************************/ + +#ifdef Q3_VM + +#include "../game/bg_lib.h" + +#else + +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> +#include <limits.h> + +#endif + +#include "q_platform.h" + +//============================================================= + +#ifdef Q3_VM +   typedef int intptr_t; +#else +  #ifndef _MSC_VER +    #include <stdint.h> +  #else +    #include <io.h> +    typedef __int64 int64_t; +    typedef __int32 int32_t; +    typedef __int16 int16_t; +    typedef __int8 int8_t; +    typedef unsigned __int64 uint64_t; +    typedef unsigned __int32 uint32_t; +    typedef unsigned __int16 uint16_t; +    typedef unsigned __int8 uint8_t; +  #endif +#endif + +typedef unsigned char 		byte; + +typedef enum {qfalse, qtrue}	qboolean; + +typedef int		qhandle_t; +typedef int		sfxHandle_t; +typedef int		fileHandle_t; +typedef int		clipHandle_t; + +#define PAD(x,y) (((x)+(y)-1) & ~((y)-1)) + +#ifdef __GNUC__ +#define ALIGN(x) __attribute__((aligned(x))) +#else +#define ALIGN(x) +#endif + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define	MAX_QINT			0x7fffffff +#define	MIN_QINT			(-MAX_QINT-1) + + +// angle indexes +#define	PITCH				0		// up / down +#define	YAW					1		// left / right +#define	ROLL				2		// fall over + +// the game guarantees that no string from the network will ever +// exceed MAX_STRING_CHARS +#define	MAX_STRING_CHARS	1024	// max length of a string passed to Cmd_TokenizeString +#define	MAX_STRING_TOKENS	1024	// max tokens resulting from Cmd_TokenizeString +#define	MAX_TOKEN_CHARS		1024	// max length of an individual token + +#define	MAX_INFO_STRING		1024 +#define	MAX_INFO_KEY		  1024 +#define	MAX_INFO_VALUE		1024 + +#define	BIG_INFO_STRING		8192  // used for system info key only +#define	BIG_INFO_KEY		  8192 +#define	BIG_INFO_VALUE		8192 + + +#define	MAX_QPATH			64		// max length of a quake game pathname +#ifdef PATH_MAX +#define MAX_OSPATH			PATH_MAX +#else +#define	MAX_OSPATH			256		// max length of a filesystem pathname +#endif + +#define	MAX_NAME_LENGTH			32		// max length of a client name +#define	MAX_HOSTNAME_LENGTH	80		// max length of a host name + +#define	MAX_SAY_TEXT	150 + +// paramters for command buffer stuffing +typedef enum { +	EXEC_NOW,			// don't return until completed, a VM should NEVER use this, +						// because some commands might cause the VM to be unloaded... +	EXEC_INSERT,		// insert at current position, but don't run yet +	EXEC_APPEND			// add to end of the command buffer (normal case) +} cbufExec_t; + + +// +// these aren't needed by any of the VMs.  put in another header? +// +#define	MAX_MAP_AREA_BYTES		32		// bit vector of area visibility + + +// print levels from renderer (FIXME: set up for game / cgame?) +typedef enum { +	PRINT_ALL, +	PRINT_DEVELOPER,		// only print when "developer 1" +	PRINT_WARNING, +	PRINT_ERROR +} printParm_t; + + +#ifdef ERR_FATAL +#undef ERR_FATAL			// this is be defined in malloc.h +#endif + +// parameters to the main Error routine +typedef enum { +	ERR_FATAL,					// exit the entire game with a popup window +	ERR_DROP,					// print to console and disconnect from game +	ERR_SERVERDISCONNECT,		// don't kill server +	ERR_DISCONNECT,				// client disconnected from the server +	ERR_NEED_CD					// pop up the need-cd dialog +} errorParm_t; + + +// font rendering values used by ui and cgame + +#define PROP_GAP_WIDTH			3 +#define PROP_SPACE_WIDTH		8 +#define PROP_HEIGHT				27 +#define PROP_SMALL_SIZE_SCALE	0.75 + +#define BLINK_DIVISOR			200 +#define PULSE_DIVISOR			75 + +#define UI_LEFT			0x00000000	// default +#define UI_CENTER		0x00000001 +#define UI_RIGHT		0x00000002 +#define UI_FORMATMASK	0x00000007 +#define UI_SMALLFONT	0x00000010 +#define UI_BIGFONT		0x00000020	// default +#define UI_GIANTFONT	0x00000040 +#define UI_DROPSHADOW	0x00000800 +#define UI_BLINK		0x00001000 +#define UI_INVERSE		0x00002000 +#define UI_PULSE		0x00004000 + +#if defined(_DEBUG) && !defined(BSPC) +	#define HUNK_DEBUG +#endif + +typedef enum { +	h_high, +	h_low, +	h_dontcare +} ha_pref; + +#ifdef HUNK_DEBUG +#define Hunk_Alloc( size, preference )				Hunk_AllocDebug(size, preference, #size, __FILE__, __LINE__) +void *Hunk_AllocDebug( int size, ha_pref preference, char *label, char *file, int line ); +#else +void *Hunk_Alloc( int size, ha_pref preference ); +#endif + +#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__APPLE__) +// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371 +// custom Snd_Memset implementation for glibc memset bug workaround +void Snd_Memset (void* dest, const int val, const size_t count); +#else +#define Snd_Memset Com_Memset +#endif + +#define Com_Memset memset +#define Com_Memcpy memcpy + +#define CIN_system	1 +#define CIN_loop	2 +#define	CIN_hold	4 +#define CIN_silent	8 +#define CIN_shader	16 + +/* +============================================================== + +MATHLIB + +============================================================== +*/ + + +typedef float vec_t; +typedef vec_t vec2_t[2]; +typedef vec_t vec3_t[3]; +typedef vec_t vec4_t[4]; +typedef vec_t vec5_t[5]; + +typedef	int	fixed4_t; +typedef	int	fixed8_t; +typedef	int	fixed16_t; + +#ifndef M_PI +#define M_PI		3.14159265358979323846f	// matches value in gcc v2 math.h +#endif + +#ifndef M_SQRT2 +#define M_SQRT2 1.414213562f +#endif + +#ifndef M_ROOT3 +#define M_ROOT3 1.732050808f +#endif + +#define NUMVERTEXNORMALS	162 +extern	vec3_t	bytedirs[NUMVERTEXNORMALS]; + +// all drawing is done to a 640*480 virtual screen size +// and will be automatically scaled to the real resolution +#define	SCREEN_WIDTH		640 +#define	SCREEN_HEIGHT		480 + +#define TINYCHAR_WIDTH		(SMALLCHAR_WIDTH) +#define TINYCHAR_HEIGHT		(SMALLCHAR_HEIGHT/2) + +#define SMALLCHAR_WIDTH		8 +#define SMALLCHAR_HEIGHT	16 + +#define BIGCHAR_WIDTH		16 +#define BIGCHAR_HEIGHT		16 + +#define	GIANTCHAR_WIDTH		32 +#define	GIANTCHAR_HEIGHT	48 + +extern	vec4_t		colorBlack; +extern	vec4_t		colorRed; +extern	vec4_t		colorGreen; +extern	vec4_t		colorBlue; +extern	vec4_t		colorYellow; +extern	vec4_t		colorMagenta; +extern	vec4_t		colorCyan; +extern	vec4_t		colorWhite; +extern	vec4_t		colorLtGrey; +extern	vec4_t		colorMdGrey; +extern	vec4_t		colorDkGrey; + +#define Q_COLOR_ESCAPE	'^' +#define Q_IsColorString(p)	( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE ) + +#define COLOR_BLACK		'0' +#define COLOR_RED		'1' +#define COLOR_GREEN		'2' +#define COLOR_YELLOW	'3' +#define COLOR_BLUE		'4' +#define COLOR_CYAN		'5' +#define COLOR_MAGENTA	'6' +#define COLOR_WHITE		'7' +#define ColorIndex(c)	( ( (c) - '0' ) & 7 ) + +#define S_COLOR_BLACK	"^0" +#define S_COLOR_RED		"^1" +#define S_COLOR_GREEN	"^2" +#define S_COLOR_YELLOW	"^3" +#define S_COLOR_BLUE	"^4" +#define S_COLOR_CYAN	"^5" +#define S_COLOR_MAGENTA	"^6" +#define S_COLOR_WHITE	"^7" + +extern vec4_t	g_color_table[8]; + +#define	MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b +#define	MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a + +#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F ) +#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI ) + +struct cplane_s; + +extern	vec3_t	vec3_origin; +extern	vec3_t	axisDefault[3]; + +#define	nanmask (255<<23) + +#define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) + +#if idppc + +static ID_INLINE float Q_rsqrt( float number ) { +		float x = 0.5f * number; +                float y; +#ifdef __GNUC__             +                asm("frsqrte %0,%1" : "=f" (y) : "f" (number)); +#else +		y = __frsqrte( number ); +#endif +		return y * (1.5f - (x * y * y)); +	} + +#ifdef __GNUC__             +static ID_INLINE float Q_fabs(float x) { +    float abs_x; +     +    asm("fabs %0,%1" : "=f" (abs_x) : "f" (x)); +    return abs_x; +} +#else +#define Q_fabs __fabsf +#endif + +#else +float Q_fabs( float f ); +float Q_rsqrt( float f );		// reciprocal square root +#endif + +#define SQRTFAST( x ) ( (x) * Q_rsqrt( x ) ) + +signed char ClampChar( int i ); +signed short ClampShort( int i ); + +// this isn't a real cheap function to call! +int DirToByte( vec3_t dir ); +void ByteToDir( int b, vec3_t dir ); + +#if	1 + +#define DotProduct(x,y)			((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]) +#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2]) +#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2]) +#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2]) +#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s)) +#define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s)) +#define VectorLerp( f, s, e, r ) ((r)[0]=(s)[0]+(f)*((e)[0]-(s)[0]),\ +  (r)[1]=(s)[1]+(f)*((e)[1]-(s)[1]),\ +  (r)[2]=(s)[2]+(f)*((e)[2]-(s)[2]))  + +#else + +#define DotProduct(x,y)			_DotProduct(x,y) +#define VectorSubtract(a,b,c)	_VectorSubtract(a,b,c) +#define VectorAdd(a,b,c)		_VectorAdd(a,b,c) +#define VectorCopy(a,b)			_VectorCopy(a,b) +#define	VectorScale(v, s, o)	_VectorScale(v,s,o) +#define	VectorMA(v, s, b, o)	_VectorMA(v,s,b,o) + +#endif + +#ifdef Q3_VM +#ifdef VectorCopy +#undef VectorCopy +// this is a little hack to get more efficient copies in our interpreter +typedef struct { +	float	v[3]; +} vec3struct_t; +#define VectorCopy(a,b)	(*(vec3struct_t *)b=*(vec3struct_t *)a) +#endif +#endif + +#define Vector2Set(v, x, y) ((v)[0]=(x), (v)[1]=(y)) +#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0) +#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) +#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) +#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) +#define Vector4Add(a,b,c)    ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3]) + +#define	SnapVector(v) {v[0]=((int)(v[0]));v[1]=((int)(v[1]));v[2]=((int)(v[2]));} +// just in case you do't want to use the macros +vec_t _DotProduct( const vec3_t v1, const vec3_t v2 ); +void _VectorSubtract( const vec3_t veca, const vec3_t vecb, vec3_t out ); +void _VectorAdd( const vec3_t veca, const vec3_t vecb, vec3_t out ); +void _VectorCopy( const vec3_t in, vec3_t out ); +void _VectorScale( const vec3_t in, float scale, vec3_t out ); +void _VectorMA( const vec3_t veca, float scale, const vec3_t vecb, vec3_t vecc ); + +unsigned ColorBytes3 (float r, float g, float b); +unsigned ColorBytes4 (float r, float g, float b, float a); + +float NormalizeColor( const vec3_t in, vec3_t out ); + +float RadiusFromBounds( const vec3_t mins, const vec3_t maxs ); +void ClearBounds( vec3_t mins, vec3_t maxs ); +void AddPointToBounds( const vec3_t v, vec3_t mins, vec3_t maxs ); + +#if !defined( Q3_VM ) || ( defined( Q3_VM ) && defined( __Q3_VM_MATH ) ) +static ID_INLINE int VectorCompare( const vec3_t v1, const vec3_t v2 ) { +	if (v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2]) { +		return 0; +	}			 +	return 1; +} + +static ID_INLINE int VectorCompareEpsilon( +		const vec3_t v1, const vec3_t v2, float epsilon ) +{ +	vec3_t d; + +	VectorSubtract( v1, v2, d ); +	d[ 0 ] = fabs( d[ 0 ] ); +	d[ 1 ] = fabs( d[ 1 ] ); +	d[ 2 ] = fabs( d[ 2 ] ); + +	if( d[ 0 ] > epsilon || d[ 1 ] > epsilon || d[ 2 ] > epsilon ) +		return 0; + +	return 1; +} + +static ID_INLINE vec_t VectorLength( const vec3_t v ) { +	return (vec_t)sqrt (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); +} + +static ID_INLINE vec_t VectorLengthSquared( const vec3_t v ) { +	return (v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); +} + +static ID_INLINE vec_t Distance( const vec3_t p1, const vec3_t p2 ) { +	vec3_t	v; + +	VectorSubtract (p2, p1, v); +	return VectorLength( v ); +} + +static ID_INLINE vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 ) { +	vec3_t	v; + +	VectorSubtract (p2, p1, v); +	return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; +} + +// fast vector normalize routine that does not check to make sure +// that length != 0, nor does it return length, uses rsqrt approximation +static ID_INLINE void VectorNormalizeFast( vec3_t v ) +{ +	float ilength; + +	ilength = Q_rsqrt( DotProduct( v, v ) ); + +	v[0] *= ilength; +	v[1] *= ilength; +	v[2] *= ilength; +} + +static ID_INLINE void VectorInverse( vec3_t v ){ +	v[0] = -v[0]; +	v[1] = -v[1]; +	v[2] = -v[2]; +} + +static ID_INLINE void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ) { +	cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; +	cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; +	cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} + +#else +int VectorCompare( const vec3_t v1, const vec3_t v2 ); + +vec_t VectorLength( const vec3_t v ); + +vec_t VectorLengthSquared( const vec3_t v ); + +vec_t Distance( const vec3_t p1, const vec3_t p2 ); + +vec_t DistanceSquared( const vec3_t p1, const vec3_t p2 ); +  +void VectorNormalizeFast( vec3_t v ); + +void VectorInverse( vec3_t v ); + +void CrossProduct( const vec3_t v1, const vec3_t v2, vec3_t cross ); + +#endif + +vec_t VectorNormalize (vec3_t v);		// returns vector length +vec_t VectorNormalize2( const vec3_t v, vec3_t out ); +void Vector4Scale( const vec4_t in, vec_t scale, vec4_t out ); +void VectorRotate( vec3_t in, vec3_t matrix[3], vec3_t out ); +int Q_log2(int val); + +float Q_acos(float c); + +int		Q_rand( int *seed ); +float	Q_random( int *seed ); +float	Q_crandom( int *seed ); + +#define random()	((rand () & 0x7fff) / ((float)0x7fff)) +#define crandom()	(2.0 * (random() - 0.5)) + +void vectoangles( const vec3_t value1, vec3_t angles); +void AnglesToAxis( const vec3_t angles, vec3_t axis[3] ); +void AxisToAngles( vec3_t axis[3], vec3_t angles ); + +void AxisClear( vec3_t axis[3] ); +void AxisCopy( vec3_t in[3], vec3_t out[3] ); + +void SetPlaneSignbits( struct cplane_s *out ); +int BoxOnPlaneSide (vec3_t emins, vec3_t emaxs, struct cplane_s *plane); + +float	AngleMod(float a); +float	LerpAngle (float from, float to, float frac); +float	AngleSubtract( float a1, float a2 ); +void	AnglesSubtract( vec3_t v1, vec3_t v2, vec3_t v3 ); + +float AngleNormalize360 ( float angle ); +float AngleNormalize180 ( float angle ); +float AngleDelta ( float angle1, float angle2 ); + +qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ); +void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal ); +void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees ); +void RotateAroundDirection( vec3_t axis[3], vec_t angle ); +void MakeNormalVectors( const vec3_t forward, vec3_t right, vec3_t up ); +// perpendicular vector could be replaced by this + +//int	PlaneTypeForNormal (vec3_t normal); + +void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]); +void VectorMatrixMultiply( const vec3_t p, vec3_t m[ 3 ], vec3_t out ); +void AngleVectors( const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up); +void PerpendicularVector( vec3_t dst, const vec3_t src ); +int Q_isnan( float x ); + +void GetPerpendicularViewVector( const vec3_t point, const vec3_t p1, +		const vec3_t p2, vec3_t up ); +void ProjectPointOntoVector( vec3_t point, vec3_t vStart, +		vec3_t vEnd, vec3_t vProj ); +float VectorDistance( vec3_t v1, vec3_t v2 ); + +float pointToLineDistance( const vec3_t point, const vec3_t p1, const vec3_t p2 ); +float VectorMinComponent( vec3_t v ); +float VectorMaxComponent( vec3_t v ); + +vec_t DistanceBetweenLineSegmentsSquared( +    const vec3_t sP0, const vec3_t sP1, +    const vec3_t tP0, const vec3_t tP1, +    float *s, float *t ); +vec_t DistanceBetweenLineSegments( +    const vec3_t sP0, const vec3_t sP1, +    const vec3_t tP0, const vec3_t tP1, +    float *s, float *t ); + +#ifndef MAX +#define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + +#ifndef MIN +#define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +//============================================= + +float Com_Clamp( float min, float max, float value ); + +char	*COM_SkipPath( char *pathname ); +void	COM_StripExtension(const char *in, char *out, int destsize); +void	COM_DefaultExtension( char *path, int maxSize, const char *extension ); + +void	COM_BeginParseSession( const char *name ); +int		COM_GetCurrentParseLine( void ); +char	*COM_Parse( char **data_p ); +char	*COM_ParseExt( char **data_p, qboolean allowLineBreak ); +int		COM_Compress( char *data_p ); +void	COM_ParseError( char *format, ... ) __attribute__ ((format (printf, 1, 2))); +void	COM_ParseWarning( char *format, ... ) __attribute__ ((format (printf, 1, 2))); +//int		COM_ParseInfos( char *buf, int max, char infos[][MAX_INFO_STRING] ); + +#define MAX_TOKENLENGTH		1024 + +#ifndef TT_STRING +//token types +#define TT_STRING					1			// string +#define TT_LITERAL					2			// literal +#define TT_NUMBER					3			// number +#define TT_NAME						4			// name +#define TT_PUNCTUATION				5			// punctuation +#endif + +typedef struct pc_token_s +{ +	int type; +	int subtype; +	int intvalue; +	float floatvalue; +	char string[MAX_TOKENLENGTH]; +} pc_token_t; + +// data is an in/out parm, returns a parsed out token + +void	COM_MatchToken( char**buf_p, char *match ); + +void SkipBracedSection (char **program); +void SkipRestOfLine ( char **data ); + +void Parse1DMatrix (char **buf_p, int x, float *m); +void Parse2DMatrix (char **buf_p, int y, int x, float *m); +void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m); + +void	QDECL Com_sprintf (char *dest, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); + +char *Com_SkipTokens( char *s, int numTokens, char *sep ); +char *Com_SkipCharset( char *s, char *sep ); + +void Com_RandomBytes( byte *string, int len ); + +// mode parm for FS_FOpenFile +typedef enum { +	FS_READ, +	FS_WRITE, +	FS_APPEND, +	FS_APPEND_SYNC +} fsMode_t; + +typedef enum { +	FS_SEEK_CUR, +	FS_SEEK_END, +	FS_SEEK_SET +} fsOrigin_t; + +//============================================= + +int Q_isprint( int c ); +int Q_islower( int c ); +int Q_isupper( int c ); +int Q_isalpha( int c ); +int Q_isdigit( int c ); + +// portable case insensitive compare +int		Q_stricmp (const char *s1, const char *s2); +int		Q_strncmp (const char *s1, const char *s2, int n); +int		Q_stricmpn (const char *s1, const char *s2, int n); +char	*Q_strlwr( char *s1 ); +char	*Q_strupr( char *s1 ); +char	*Q_strrchr( const char* string, int c ); + +// buffer size safe library replacements +void	Q_strncpyz( char *dest, const char *src, int destsize ); +void	Q_strcat( char *dest, int size, const char *src ); + +// strlen that discounts Quake color sequences +int Q_PrintStrlen( const char *string ); +// removes color sequences from string +char *Q_CleanStr( char *string ); + +//============================================= + +// 64-bit integers for global rankings interface +// implemented as a struct for qvm compatibility +typedef struct +{ +	byte	b0; +	byte	b1; +	byte	b2; +	byte	b3; +	byte	b4; +	byte	b5; +	byte	b6; +	byte	b7; +} qint64; + +//============================================= +/* +short	BigShort(short l); +short	LittleShort(short l); +int		BigLong (int l); +int		LittleLong (int l); +qint64  BigLong64 (qint64 l); +qint64  LittleLong64 (qint64 l); +float	BigFloat (const float *l); +float	LittleFloat (const float *l); + +void	Swap_Init (void); +*/ +char	* QDECL va(char *format, ...) __attribute__ ((format (printf, 1, 2))); + +#define TRUNCATE_LENGTH	64 +void Com_TruncateLongString( char *buffer, const char *s ); + +//============================================= + +// +// key / value info strings +// +char *Info_ValueForKey( const char *s, const char *key ); +void Info_RemoveKey( char *s, const char *key ); +void Info_RemoveKey_big( char *s, const char *key ); +void Info_SetValueForKey( char *s, const char *key, const char *value ); +void Info_SetValueForKey_Big( char *s, const char *key, const char *value ); +qboolean Info_Validate( const char *s ); +void Info_NextPair( const char **s, char *key, char *value ); + +// this is only here so the functions in q_shared.c and bg_*.c can link +void	QDECL Com_Error( int level, const char *error, ... ) __attribute__ ((format (printf, 2, 3))); +void	QDECL Com_Printf( const char *msg, ... ) __attribute__ ((format (printf, 1, 2))); + + +/* +========================================================== + +CVARS (console variables) + +Many variables can be used for cheating purposes, so when +cheats is zero, force all unspecified variables to their +default values. +========================================================== +*/ + +#define	CVAR_ARCHIVE		1	// set to cause it to be saved to vars.rc +								// used for system variables, not for player +								// specific configurations +#define	CVAR_USERINFO		2	// sent to server on connect or change +#define	CVAR_SERVERINFO		4	// sent in response to front end requests +#define	CVAR_SYSTEMINFO		8	// these cvars will be duplicated on all clients +#define	CVAR_INIT			16	// don't allow change from console at all, +								// but can be set from the command line +#define	CVAR_LATCH			32	// will only change when C code next does +								// a Cvar_Get(), so it can't be changed +								// without proper initialization.  modified +								// will be set, even though the value hasn't +								// changed yet +#define	CVAR_ROM			64	// display only, cannot be set by user at all +#define	CVAR_USER_CREATED	128	// created by a set command +#define	CVAR_TEMP			256	// can be set even when cheats are disabled, but is not archived +#define CVAR_CHEAT			512	// can not be changed if cheats are disabled +#define CVAR_NORESTART		1024	// do not clear when a cvar_restart is issued + +#define CVAR_SERVER_CREATED	2048	// cvar was created by a server the client connected to. +#define CVAR_NONEXISTENT	0xFFFFFFFF	// Cvar doesn't exist. + +// nothing outside the Cvar_*() functions should modify these fields! +typedef struct cvar_s { +	char		*name; +	char		*string; +	char		*resetString;		// cvar_restart will reset to this value +	char		*latchedString;		// for CVAR_LATCH vars +	int			flags; +	qboolean	modified;			// set each time the cvar is changed +	int			modificationCount;	// incremented each time the cvar is changed +	float		value;				// atof( string ) +	int			integer;			// atoi( string ) +	struct cvar_s *next; +	struct cvar_s *hashNext; +} cvar_t; + +#define	MAX_CVAR_VALUE_STRING	256 + +typedef int	cvarHandle_t; + +// the modules that run in the virtual machine can't access the cvar_t directly, +// so they must ask for structured updates +typedef struct { +	cvarHandle_t	handle; +	int			modificationCount; +	float		value; +	int			integer; +	char		string[MAX_CVAR_VALUE_STRING]; +} vmCvar_t; + +/* +============================================================== + +COLLISION DETECTION + +============================================================== +*/ + +#include "surfaceflags.h"			// shared with the q3map utility + +// plane types are used to speed some tests +// 0-2 are axial planes +#define	PLANE_X			0 +#define	PLANE_Y			1 +#define	PLANE_Z			2 +#define	PLANE_NON_AXIAL	3 + + +/* +================= +PlaneTypeForNormal +================= +*/ + +#define PlaneTypeForNormal(x) (x[0] == 1.0 ? PLANE_X : (x[1] == 1.0 ? PLANE_Y : (x[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL) ) ) + +// plane_t structure +// !!! if this is changed, it must be changed in asm code too !!! +typedef struct cplane_s { +	vec3_t	normal; +	float	dist; +	byte	type;			// for fast side tests: 0,1,2 = axial, 3 = nonaxial +	byte	signbits;		// signx + (signy<<1) + (signz<<2), used as lookup during collision +	byte	pad[2]; +} cplane_t; + +typedef enum { +	TT_NONE, + +	TT_AABB, +	TT_CAPSULE, +	TT_BISPHERE, + +	TT_NUM_TRACE_TYPES +} traceType_t; + +// a trace is returned when a box is swept through the world +typedef struct { +	qboolean	allsolid;	// if true, plane is not valid +	qboolean	startsolid;	// if true, the initial point was in a solid area +	float		fraction;	// time completed, 1.0 = didn't hit anything +	vec3_t		endpos;		// final position +	cplane_t	plane;		// surface normal at impact, transformed to world space +	int			surfaceFlags;	// surface hit +	int			contents;	// contents on other side of surface hit +	int			entityNum;	// entity the contacted sirface is a part of +	float		lateralFraction; // fraction of collision tangetially to the trace direction +} trace_t; + +// trace->entityNum can also be 0 to (MAX_GENTITIES-1) +// or ENTITYNUM_NONE, ENTITYNUM_WORLD + + +// markfragments are returned by CM_MarkFragments() +typedef struct { +	int		firstPoint; +	int		numPoints; +} markFragment_t; + + + +typedef struct { +	vec3_t		origin; +	vec3_t		axis[3]; +} orientation_t; + +//===================================================================== + + +// in order from highest priority to lowest +// if none of the catchers are active, bound key strings will be executed +#define KEYCATCH_CONSOLE		0x0001 +#define	KEYCATCH_UI					0x0002 +#define	KEYCATCH_MESSAGE		0x0004 +#define	KEYCATCH_CGAME			0x0008 + + +// sound channels +// channel 0 never willingly overrides +// other channels will allways override a playing sound on that channel +typedef enum { +	CHAN_AUTO, +	CHAN_LOCAL,		// menu sounds, etc +	CHAN_WEAPON, +	CHAN_VOICE, +	CHAN_ITEM, +	CHAN_BODY, +	CHAN_LOCAL_SOUND,	// chat messages, etc +	CHAN_ANNOUNCER		// announcer voices, etc +} soundChannel_t; + + +/* +======================================================================== + +  ELEMENTS COMMUNICATED ACROSS THE NET + +======================================================================== +*/ + +#define	ANGLE2SHORT(x)	((int)((x)*65536/360) & 65535) +#define	SHORT2ANGLE(x)	((x)*(360.0/65536)) + +#define	SNAPFLAG_RATE_DELAYED	1 +#define	SNAPFLAG_NOT_ACTIVE		2	// snapshot used during connection and for zombies +#define SNAPFLAG_SERVERCOUNT	4	// toggled every map_restart so transitions can be detected + +// +// per-level limits +// +#define	MAX_CLIENTS			64		// absolute limit +#define MAX_LOCATIONS		64 + +#define	GENTITYNUM_BITS		10		// don't need to send any more +#define	MAX_GENTITIES		(1<<GENTITYNUM_BITS) + +// entitynums are communicated with GENTITY_BITS, so any reserved +// values that are going to be communcated over the net need to +// also be in this range +#define	ENTITYNUM_NONE		(MAX_GENTITIES-1) +#define	ENTITYNUM_WORLD		(MAX_GENTITIES-2) +#define	ENTITYNUM_MAX_NORMAL	(MAX_GENTITIES-2) + + +#define	MAX_MODELS									256		// these are sent over the net as 8 bits +#define	MAX_SOUNDS									256		// so they cannot be blindly increased +#define	MAX_GAME_SHADERS						64 +#define	MAX_GAME_PARTICLE_SYSTEMS		64 + + +#define	MAX_CONFIGSTRINGS	1024 + +// these are the only configstrings that the system reserves, all the +// other ones are strictly for servergame to clientgame communication +#define	CS_SERVERINFO		0		// an info string with all the serverinfo cvars +#define	CS_SYSTEMINFO		1		// an info string for server system to client system configuration (timescale, etc) + +#define	RESERVED_CONFIGSTRINGS	2	// game can't modify below this, only the system can + +#define	MAX_GAMESTATE_CHARS	16000 +typedef struct { +	int			stringOffsets[MAX_CONFIGSTRINGS]; +	char		stringData[MAX_GAMESTATE_CHARS]; +	int			dataCount; +} gameState_t; + +//========================================================= + +// bit field limits +#define	MAX_STATS				16 +#define	MAX_PERSISTANT			16 +#define	MAX_MISC    			16 +#define	MAX_WEAPONS				16		 + +#define	MAX_PS_EVENTS			2 + +#define PS_PMOVEFRAMECOUNTBITS	6 + +// playerState_t is the information needed by both the client and server +// to predict player motion and actions +// nothing outside of pmove should modify these, or some degree of prediction error +// will occur + +// you can't add anything to this without modifying the code in msg.c + +// playerState_t is a full superset of entityState_t as it is used by players, +// so if a playerState_t is transmitted, the entityState_t can be fully derived +// from it. +typedef struct playerState_s { +	int			commandTime;	// cmd->serverTime of last executed command +	int			pm_type; +	int			bobCycle;		// for view bobbing and footstep generation +	int			pm_flags;		// ducked, jump_held, etc +	int			pm_time; + +	vec3_t		origin; +	vec3_t		velocity; +	int			weaponTime; +	int			gravity; +	int			speed; +	int			delta_angles[3];	// add to command angles to get view direction +									// changed by spawns, rotating objects, and teleporters + +	int			groundEntityNum;// ENTITYNUM_NONE = in air + +	int			legsTimer;		// don't change low priority animations until this runs out +	int			legsAnim;		// mask off ANIM_TOGGLEBIT + +	int			torsoTimer;		// don't change low priority animations until this runs out +	int			torsoAnim;		// mask off ANIM_TOGGLEBIT + +	int			tauntTimer;		// don't allow another taunt until this runs out + +	int			weaponAnim;		// mask off ANIM_TOGGLEBIT + +	int			movementDir;	// a number 0 to 7 that represents the relative angle +								// of movement to the view angle (axial and diagonals) +								// when at rest, the value will remain unchanged +								// used to twist the legs during strafing + +	vec3_t		grapplePoint;	// location of grapple to pull towards if PMF_GRAPPLE_PULL + +	int			eFlags;			// copied to entityState_t->eFlags + +	int			eventSequence;	// pmove generated events +	int			events[MAX_PS_EVENTS]; +	int			eventParms[MAX_PS_EVENTS]; + +	int			externalEvent;	// events set on player from another source +	int			externalEventParm; +	int			externalEventTime; + +	int			clientNum;		// ranges from 0 to MAX_CLIENTS-1 +	int			weapon;			// copied to entityState_t->weapon +	int			weaponstate; + +	vec3_t		viewangles;		// for fixed views +	int			viewheight; + +	// damage feedback +	int			damageEvent;	// when it changes, latch the other parms +	int			damageYaw; +	int			damagePitch; +	int			damageCount; + +	int			stats[MAX_STATS]; +	int			persistant[MAX_PERSISTANT];	// stats that aren't cleared on death +	int			misc[MAX_MISC];	// misc data +	int			ammo;			// ammo held +	int			clips;			// clips held + +	int			generic1; +	int			loopSound; +	int			otherEntityNum; + +	// not communicated over the net at all +	int			ping;			// server to game info for scoreboard +	int			pmove_framecount; +	int			jumppad_frame; +	int			entityEventSequence; +} playerState_t; + + +//==================================================================== + + +// +// usercmd_t->button bits, many of which are generated by the client system, +// so they aren't game/cgame only definitions +// +#define	BUTTON_ATTACK		1 +#define	BUTTON_TALK			2			// displays talk balloon and disables actions +#define	BUTTON_USE_HOLDABLE	4 +#define	BUTTON_GESTURE		8 +#define	BUTTON_WALKING		16			// walking can't just be infered from MOVE_RUN +										// because a key pressed late in the frame will +										// only generate a small move value for that frame +										// walking will use different animations and +										// won't generate footsteps +#define BUTTON_ATTACK2	32 +#define	BUTTON_NEGATIVE		64 + +#define BUTTON_GETFLAG		128 +#define BUTTON_GUARDBASE	256 +#define BUTTON_PATROL		512 +#define BUTTON_FOLLOWME		1024 + +#define	BUTTON_ANY			2048			// any key whatsoever + +#define	MOVE_RUN			120			// if forwardmove or rightmove are >= MOVE_RUN, +										// then BUTTON_WALKING should be set + +// usercmd_t is sent to the server each client frame +typedef struct usercmd_s { +	int				serverTime; +	int				angles[3]; +	int 			buttons; +	byte			weapon;           // weapon  +	signed char	forwardmove, rightmove, upmove; +} usercmd_t; + +//=================================================================== + +// if entityState->solid == SOLID_BMODEL, modelindex is an inline model number +#define	SOLID_BMODEL	0xffffff + +typedef enum { +	TR_STATIONARY, +	TR_INTERPOLATE,				// non-parametric, but interpolate between snapshots +	TR_LINEAR, +	TR_LINEAR_STOP, +	TR_SINE,					// value = base + sin( time / duration ) * delta +	TR_GRAVITY, +	TR_BUOYANCY //TA: what the hell is this doing in here anyway? +} trType_t; + +typedef struct { +	trType_t	trType; +	int		trTime; +	int		trDuration;			// if non 0, trTime + trDuration = stop time +	vec3_t	trBase; +	vec3_t	trDelta;			// velocity, etc +} trajectory_t; + +// entityState_t is the information conveyed from the server +// in an update message about entities that the client will +// need to render in some way +// Different eTypes may use the information in different ways +// The messages are delta compressed, so it doesn't really matter if +// the structure size is fairly large + +typedef struct entityState_s { +	int		number;			// entity index +	int		eType;			// entityType_t +	int		eFlags; + +	trajectory_t	pos;	// for calculating position +	trajectory_t	apos;	// for calculating angles + +	int		time; +	int		time2; + +	vec3_t	origin; +	vec3_t	origin2; + +	vec3_t	angles; +	vec3_t	angles2; + +	int		otherEntityNum;	// shotgun sources, etc +	int		otherEntityNum2; + +	int		groundEntityNum;	// -1 = in air + +	int		constantLight;	// r + (g<<8) + (b<<16) + (intensity<<24) +	int		loopSound;		// constantly loop this sound + +	int		modelindex; +	int		modelindex2; +	int		clientNum;		// 0 to (MAX_CLIENTS - 1), for players and corpses +	int		frame; + +	int		solid;			// for client side prediction, trap_linkentity sets this properly + +	int		event;			// impulse events -- muzzle flashes, footsteps, etc +	int		eventParm; + +	// for players +	int		misc;			// bit flags +	int		weapon;			// determines weapon and flash model, etc +	int		legsAnim;		// mask off ANIM_TOGGLEBIT +	int		torsoAnim;		// mask off ANIM_TOGGLEBIT +	int		weaponAnim;		// mask off ANIM_TOGGLEBIT + +	int		generic1; +} entityState_t; + +typedef enum { +	CA_UNINITIALIZED, +	CA_DISCONNECTED, 	// not talking to a server +	CA_AUTHORIZING,		// not used any more, was checking cd key  +	CA_CONNECTING,		// sending request packets to the server +	CA_CHALLENGING,		// sending challenge packets to the server +	CA_CONNECTED,		// netchan_t established, getting gamestate +	CA_LOADING,			// only during cgame initialization, never during main loop +	CA_PRIMED,			// got gamestate, waiting for first frame +	CA_ACTIVE,			// game views should be displayed +	CA_CINEMATIC		// playing a cinematic or a static pic, not connected to a server +} connstate_t; + +// font support  + +#define GLYPH_START 0 +#define GLYPH_END 255 +#define GLYPH_CHARSTART 32 +#define GLYPH_CHAREND 127 +#define GLYPHS_PER_FONT GLYPH_END - GLYPH_START + 1 +typedef struct { +  int height;       // number of scan lines +  int top;          // top of glyph in buffer +  int bottom;       // bottom of glyph in buffer +  int pitch;        // width for copying +  int xSkip;        // x adjustment +  int imageWidth;   // width of actual image +  int imageHeight;  // height of actual image +  float s;          // x offset in image where glyph starts +  float t;          // y offset in image where glyph starts +  float s2; +  float t2; +  qhandle_t glyph;  // handle to the shader with the glyph +  char shaderName[32]; +} glyphInfo_t; + +typedef struct { +  glyphInfo_t glyphs [GLYPHS_PER_FONT]; +  float glyphScale; +  char name[MAX_QPATH]; +} fontInfo_t; + +#define Square(x) ((x)*(x)) + +// real time +//============================================= + + +typedef struct qtime_s { +	int tm_sec;     /* seconds after the minute - [0,59] */ +	int tm_min;     /* minutes after the hour - [0,59] */ +	int tm_hour;    /* hours since midnight - [0,23] */ +	int tm_mday;    /* day of the month - [1,31] */ +	int tm_mon;     /* months since January - [0,11] */ +	int tm_year;    /* years since 1900 */ +	int tm_wday;    /* days since Sunday - [0,6] */ +	int tm_yday;    /* days since January 1 - [0,365] */ +	int tm_isdst;   /* daylight savings time flag */ +} qtime_t; + + +// server browser sources +// TTimo: AS_MPLAYER is no longer used +#define AS_GLOBAL			0 +#define AS_MPLAYER		1 +#define AS_LOCAL			2 +#define AS_FAVORITES	3 + + +// cinematic states +typedef enum { +	FMV_IDLE, +	FMV_PLAY,		// play +	FMV_EOF,		// all other conditions, i.e. stop/EOF/abort +	FMV_ID_BLT, +	FMV_ID_IDLE, +	FMV_LOOPED, +	FMV_ID_WAIT +} e_status; + +typedef enum _flag_status { +	FLAG_ATBASE = 0, +	FLAG_TAKEN,			// CTF +	FLAG_TAKEN_RED,		// One Flag CTF +	FLAG_TAKEN_BLUE,	// One Flag CTF +	FLAG_DROPPED +} flagStatus_t; + +typedef enum { +	DS_NONE, + +	DS_PLAYBACK, +	DS_RECORDING, + +	DS_NUM_DEMO_STATES +} demoState_t; + + +#define	MAX_GLOBAL_SERVERS				4096 +#define	MAX_OTHER_SERVERS					128 +#define MAX_PINGREQUESTS					32 +#define MAX_SERVERSTATUSREQUESTS	16 + +#define SAY_ALL		0 +#define SAY_TEAM	1 +#define SAY_TELL	2 +#define SAY_ACTION      3 +#define SAY_ACTION_T    4 +#define SAY_ADMINS      5 +#define SAY_HADMINS     6 + +#endif	// __Q_SHARED_H diff --git a/src/qcommon/qfiles.h b/src/qcommon/qfiles.h new file mode 100644 index 0000000..7e901b7 --- /dev/null +++ b/src/qcommon/qfiles.h @@ -0,0 +1,626 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __QFILES_H__ +#define __QFILES_H__ + +// +// qfiles.h: quake file formats +// This file must be identical in the quake and utils directories +// + +//Ignore __attribute__ on non-gcc platforms +#ifndef __GNUC__ +#ifndef __attribute__ +#define __attribute__(x) +#endif +#endif + +// surface geometry should not exceed these limits +#define	SHADER_MAX_VERTEXES	1000 +#define	SHADER_MAX_INDEXES	(6*SHADER_MAX_VERTEXES) + + +// the maximum size of game relative pathnames +#define	MAX_QPATH		64 + +/* +======================================================================== + +QVM files + +======================================================================== +*/ + +#define	VM_MAGIC			0x12721444 +#define	VM_MAGIC_VER2	0x12721445 +typedef struct { +	int		vmMagic; + +	int		instructionCount; + +	int		codeOffset; +	int		codeLength; + +	int		dataOffset; +	int		dataLength; +	int		litLength;			// ( dataLength - litLength ) should be byteswapped on load +	int		bssLength;			// zero filled memory appended to datalength + +	//!!! below here is VM_MAGIC_VER2 !!! +	int		jtrgLength;			// number of jump table targets +} vmHeader_t; + + +/* +======================================================================== + +PCX files are used for 8 bit images + +======================================================================== +*/ + +typedef struct { +    char	manufacturer; +    char	version; +    char	encoding; +    char	bits_per_pixel; +    unsigned short	xmin,ymin,xmax,ymax; +    unsigned short	hres,vres; +    unsigned char	palette[48]; +    char	reserved; +    char	color_planes; +    unsigned short	bytes_per_line; +    unsigned short	palette_type; +    char	filler[58]; +    unsigned char	data;			// unbounded +} pcx_t; + + +/* +======================================================================== + +TGA files are used for 24/32 bit images + +======================================================================== +*/ + +typedef struct _TargaHeader { +	unsigned char 	id_length, colormap_type, image_type; +	unsigned short	colormap_index, colormap_length; +	unsigned char	colormap_size; +	unsigned short	x_origin, y_origin, width, height; +	unsigned char	pixel_size, attributes; +} TargaHeader; + + + +/* +======================================================================== + +.MD3 triangle model file format + +======================================================================== +*/ + +#define MD3_IDENT			(('3'<<24)+('P'<<16)+('D'<<8)+'I') +#define MD3_VERSION			15 + +// limits +#define MD3_MAX_LODS		3 +#define	MD3_MAX_TRIANGLES	8192	// per surface +#define MD3_MAX_VERTS		4096	// per surface +#define MD3_MAX_SHADERS		256		// per surface +#define MD3_MAX_FRAMES		1024	// per model +#define	MD3_MAX_SURFACES	32		// per model +#define MD3_MAX_TAGS		16		// per frame + +// vertex scales +#define	MD3_XYZ_SCALE		(1.0/64) + +typedef struct md3Frame_s { +	vec3_t		bounds[2]; +	vec3_t		localOrigin; +	float		radius; +	char		name[16]; +} md3Frame_t; + +typedef struct md3Tag_s { +	char		name[MAX_QPATH];	// tag name +	vec3_t		origin; +	vec3_t		axis[3]; +} md3Tag_t; + +/* +** md3Surface_t +** +** CHUNK			SIZE +** header			sizeof( md3Surface_t ) +** shaders			sizeof( md3Shader_t ) * numShaders +** triangles[0]		sizeof( md3Triangle_t ) * numTriangles +** st				sizeof( md3St_t ) * numVerts +** XyzNormals		sizeof( md3XyzNormal_t ) * numVerts * numFrames +*/ +typedef struct { +	int		ident;				//  + +	char	name[MAX_QPATH];	// polyset name + +	int		flags; +	int		numFrames;			// all surfaces in a model should have the same + +	int		numShaders;			// all surfaces in a model should have the same +	int		numVerts; + +	int		numTriangles; +	int		ofsTriangles; + +	int		ofsShaders;			// offset from start of md3Surface_t +	int		ofsSt;				// texture coords are common for all frames +	int		ofsXyzNormals;		// numVerts * numFrames + +	int		ofsEnd;				// next surface follows +} md3Surface_t; + +typedef struct { +	char			name[MAX_QPATH]; +	int				shaderIndex;	// for in-game use +} md3Shader_t; + +typedef struct { +	int			indexes[3]; +} md3Triangle_t; + +typedef struct { +	float		st[2]; +} md3St_t; + +typedef struct { +	short		xyz[3]; +	short		normal; +} md3XyzNormal_t; + +typedef struct { +	int			ident; +	int			version; + +	char		name[MAX_QPATH];	// model name + +	int			flags; + +	int			numFrames; +	int			numTags;			 +	int			numSurfaces; + +	int			numSkins; + +	int			ofsFrames;			// offset for first frame +	int			ofsTags;			// numFrames * numTags +	int			ofsSurfaces;		// first surface, others follow + +	int			ofsEnd;				// end of file +} md3Header_t; + +/* +============================================================================== + +MD4 file format + +============================================================================== +*/ + +#define MD4_IDENT			(('4'<<24)+('P'<<16)+('D'<<8)+'I') +#define MD4_VERSION			1 +#define	MD4_MAX_BONES		128 + +typedef struct { +	int			boneIndex;		// these are indexes into the boneReferences, +	float		   boneWeight;		// not the global per-frame bone list +	vec3_t		offset; +} md4Weight_t; + +typedef struct { +	vec3_t		normal; +	vec2_t		texCoords; +	int			numWeights; +	md4Weight_t	weights[1];		// variable sized +} md4Vertex_t; + +typedef struct { +	int			indexes[3]; +} md4Triangle_t; + +typedef struct { +	int			ident; + +	char		name[MAX_QPATH];	// polyset name +	char		shader[MAX_QPATH]; +	int			shaderIndex;		// for in-game use + +	int			ofsHeader;			// this will be a negative number + +	int			numVerts; +	int			ofsVerts; + +	int			numTriangles; +	int			ofsTriangles; + +	// Bone references are a set of ints representing all the bones +	// present in any vertex weights for this surface.  This is +	// needed because a model may have surfaces that need to be +	// drawn at different sort times, and we don't want to have +	// to re-interpolate all the bones for each surface. +	int			numBoneReferences; +	int			ofsBoneReferences; + +	int			ofsEnd;				// next surface follows +} md4Surface_t; + +typedef struct { +	float		matrix[3][4]; +} md4Bone_t; + +typedef struct { +	vec3_t		bounds[2];			// bounds of all surfaces of all LOD's for this frame +	vec3_t		localOrigin;		// midpoint of bounds, used for sphere cull +	float		radius;				// dist from localOrigin to corner +	md4Bone_t	bones[1];			// [numBones] +} md4Frame_t; + +typedef struct { +	int			numSurfaces; +	int			ofsSurfaces;		// first surface, others follow +	int			ofsEnd;				// next lod follows +} md4LOD_t; + +typedef struct { +	int			ident; +	int			version; + +	char		name[MAX_QPATH];	// model name + +	// frames and bones are shared by all levels of detail +	int			numFrames; +	int			numBones; +	int			ofsBoneNames;		// char	name[ MAX_QPATH ] +	int			ofsFrames;			// md4Frame_t[numFrames] + +	// each level of detail has completely separate sets of surfaces +	int			numLODs; +	int			ofsLODs; + +	int			ofsEnd;				// end of file +} md4Header_t; + +/* + * Here are the definitions for Ravensoft's model format of md4. Raven stores their + * playermodels in .mdr files, in some games, which are pretty much like the md4 + * format implemented by ID soft. It seems like ID's original md4 stuff is not used at all. + * MDR is being used in EliteForce, JediKnight2 and Soldiers of Fortune2 (I think). + * So this comes in handy for anyone who wants to make it possible to load player + * models from these games. + * This format has bone tags, which is similar to the thing you have in md3 I suppose. + * Raven has released their version of md3view under GPL enabling me to add support + * to this codebase. Thanks to Steven Howes aka Skinner for helping with example + * source code. + * + * - Thilo Schulz (arny@ats.s.bawue.de) + */ + +// If you want to enable support for Raven's .mdr / md4 format, uncomment the next +// line. +//#define RAVENMD4 + +#ifdef RAVENMD4 + +#define MDR_IDENT	(('5'<<24)+('M'<<16)+('D'<<8)+'R') +#define MDR_VERSION	2 +#define	MDR_MAX_BONES	128 + +typedef struct { +	int			boneIndex;	// these are indexes into the boneReferences, +	float		   boneWeight;		// not the global per-frame bone list +	vec3_t		offset; +} mdrWeight_t; + +typedef struct { +	vec3_t		normal; +	vec2_t		texCoords; +	int			numWeights; +	mdrWeight_t	weights[1];		// variable sized +} mdrVertex_t; + +typedef struct { +	int			indexes[3]; +} mdrTriangle_t; + +typedef struct { +	int			ident; + +	char		name[MAX_QPATH];	// polyset name +	char		shader[MAX_QPATH]; +	int			shaderIndex;	// for in-game use + +	int			ofsHeader;	// this will be a negative number + +	int			numVerts; +	int			ofsVerts; + +	int			numTriangles; +	int			ofsTriangles; + +	// Bone references are a set of ints representing all the bones +	// present in any vertex weights for this surface.  This is +	// needed because a model may have surfaces that need to be +	// drawn at different sort times, and we don't want to have +	// to re-interpolate all the bones for each surface. +	int			numBoneReferences; +	int			ofsBoneReferences; + +	int			ofsEnd;		// next surface follows +} mdrSurface_t; + +typedef struct { +	float		matrix[3][4]; +} mdrBone_t; + +typedef struct { +	vec3_t		bounds[2];		// bounds of all surfaces of all LOD's for this frame +	vec3_t		localOrigin;		// midpoint of bounds, used for sphere cull +	float		radius;			// dist from localOrigin to corner +	char		name[16]; +	mdrBone_t	bones[1];		// [numBones] +} mdrFrame_t; + +typedef struct { +        unsigned char Comp[24]; // MC_COMP_BYTES is in MatComp.h, but don't want to couple +} mdrCompBone_t; + +typedef struct { +        vec3_t          bounds[2];		// bounds of all surfaces of all LOD's for this frame +        vec3_t          localOrigin;		// midpoint of bounds, used for sphere cull +        float           radius;			// dist from localOrigin to corner +        mdrCompBone_t   bones[1];		// [numBones] +} mdrCompFrame_t; + +typedef struct { +	int			numSurfaces; +	int			ofsSurfaces;		// first surface, others follow +	int			ofsEnd;				// next lod follows +} mdrLOD_t; + +typedef struct { +        int                     boneIndex; +        char            name[32]; +} mdrTag_t; + +typedef struct { +	int			ident; +	int			version; + +	char		name[MAX_QPATH];	// model name + +	// frames and bones are shared by all levels of detail +	int			numFrames; +	int			numBones; +	int			ofsFrames;			// mdrFrame_t[numFrames] + +	// each level of detail has completely separate sets of surfaces +	int			numLODs; +	int			ofsLODs; + +        int                     numTags; +        int                     ofsTags; + +	int			ofsEnd;				// end of file +} mdrHeader_t; + +#endif + +/* +============================================================================== + +  .BSP file format + +============================================================================== +*/ + + +#define BSP_IDENT	(('P'<<24)+('S'<<16)+('B'<<8)+'I') +		// little-endian "IBSP" + +#define BSP_VERSION			46 + + +// there shouldn't be any problem with increasing these values at the +// expense of more memory allocation in the utilities +#define	MAX_MAP_MODELS		0x400 +#define	MAX_MAP_BRUSHES		0x8000 +#define	MAX_MAP_ENTITIES	0x800 +#define	MAX_MAP_ENTSTRING	0x40000 +#define	MAX_MAP_SHADERS		0x400 + +#define	MAX_MAP_AREAS		0x100	// MAX_MAP_AREA_BYTES in q_shared must match! +#define	MAX_MAP_FOGS		0x100 +#define	MAX_MAP_PLANES		0x20000 +#define	MAX_MAP_NODES		0x20000 +#define	MAX_MAP_BRUSHSIDES	0x20000 +#define	MAX_MAP_LEAFS		0x20000 +#define	MAX_MAP_LEAFFACES	0x20000 +#define	MAX_MAP_LEAFBRUSHES 0x40000 +#define	MAX_MAP_PORTALS		0x20000 +#define	MAX_MAP_LIGHTING	0x800000 +#define	MAX_MAP_LIGHTGRID	0x800000 +#define	MAX_MAP_VISIBILITY	0x200000 + +#define	MAX_MAP_DRAW_SURFS	0x20000 +#define	MAX_MAP_DRAW_VERTS	0x80000 +#define	MAX_MAP_DRAW_INDEXES	0x80000 + + +// key / value pair sizes in the entities lump +#define	MAX_KEY				32 +#define	MAX_VALUE			1024 + +// the editor uses these predefined yaw angles to orient entities up or down +#define	ANGLE_UP			-1 +#define	ANGLE_DOWN			-2 + +#define	LIGHTMAP_WIDTH		128 +#define	LIGHTMAP_HEIGHT		128 + +#define MAX_WORLD_COORD		( 128*1024 ) +#define MIN_WORLD_COORD		( -128*1024 ) +#define WORLD_SIZE			( MAX_WORLD_COORD - MIN_WORLD_COORD ) + +//============================================================================= + + +typedef struct { +	int		fileofs, filelen; +} lump_t; + +#define	LUMP_ENTITIES		0 +#define	LUMP_SHADERS		1 +#define	LUMP_PLANES			2 +#define	LUMP_NODES			3 +#define	LUMP_LEAFS			4 +#define	LUMP_LEAFSURFACES	5 +#define	LUMP_LEAFBRUSHES	6 +#define	LUMP_MODELS			7 +#define	LUMP_BRUSHES		8 +#define	LUMP_BRUSHSIDES		9 +#define	LUMP_DRAWVERTS		10 +#define	LUMP_DRAWINDEXES	11 +#define	LUMP_FOGS			12 +#define	LUMP_SURFACES		13 +#define	LUMP_LIGHTMAPS		14 +#define	LUMP_LIGHTGRID		15 +#define	LUMP_VISIBILITY		16 +#define	HEADER_LUMPS		17 + +typedef struct { +	int			ident; +	int			version; + +	lump_t		lumps[HEADER_LUMPS]; +} dheader_t; + +typedef struct { +	float		mins[3], maxs[3]; +	int			firstSurface, numSurfaces; +	int			firstBrush, numBrushes; +} dmodel_t; + +typedef struct { +	char		shader[MAX_QPATH]; +	int			surfaceFlags; +	int			contentFlags; +} dshader_t; + +// planes x^1 is allways the opposite of plane x + +typedef struct { +	float		normal[3]; +	float		dist; +} dplane_t; + +typedef struct { +	int			planeNum; +	int			children[2];	// negative numbers are -(leafs+1), not nodes +	int			mins[3];		// for frustom culling +	int			maxs[3]; +} dnode_t; + +typedef struct { +	int			cluster;			// -1 = opaque cluster (do I still store these?) +	int			area; + +	int			mins[3];			// for frustum culling +	int			maxs[3]; + +	int			firstLeafSurface; +	int			numLeafSurfaces; + +	int			firstLeafBrush; +	int			numLeafBrushes; +} dleaf_t; + +typedef struct { +	int			planeNum;			// positive plane side faces out of the leaf +	int			shaderNum; +} dbrushside_t; + +typedef struct { +	int			firstSide; +	int			numSides; +	int			shaderNum;		// the shader that determines the contents flags +} dbrush_t; + +typedef struct { +	char		shader[MAX_QPATH]; +	int			brushNum; +	int			visibleSide;	// the brush side that ray tests need to clip against (-1 == none) +} dfog_t; + +typedef struct { +	vec3_t		xyz; +	float		st[2]; +	float		lightmap[2]; +	vec3_t		normal; +	byte		color[4]; +} drawVert_t; + +#define drawVert_t_cleared(x) drawVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}} + +typedef enum { +	MST_BAD, +	MST_PLANAR, +	MST_PATCH, +	MST_TRIANGLE_SOUP, +	MST_FLARE +} mapSurfaceType_t; + +typedef struct { +	int			shaderNum; +	int			fogNum; +	int			surfaceType; + +	int			firstVert; +	int			numVerts; + +	int			firstIndex; +	int			numIndexes; + +	int			lightmapNum; +	int			lightmapX, lightmapY; +	int			lightmapWidth, lightmapHeight; + +	vec3_t		lightmapOrigin; +	vec3_t		lightmapVecs[3];	// for patches, [0] and [1] are lodbounds + +	int			patchWidth; +	int			patchHeight; +} dsurface_t; + + +#endif diff --git a/src/qcommon/surfaceflags.h b/src/qcommon/surfaceflags.h new file mode 100644 index 0000000..31ece5c --- /dev/null +++ b/src/qcommon/surfaceflags.h @@ -0,0 +1,91 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. +Copyright (C) 2000-2006 Tim Angus + +This file is part of Tremulous. + +Tremulous 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. + +Tremulous 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 Tremulous; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// +// This file must be identical in the quake and utils directories + +// contents flags are seperate bits +// a given brush can contribute multiple content bits + +// these definitions also need to be in q_shared.h! + +#define	CONTENTS_SOLID			1		// an eye is never valid in a solid +#define	CONTENTS_LAVA			8 +#define	CONTENTS_SLIME			16 +#define	CONTENTS_WATER			32 +#define	CONTENTS_FOG			64 + +#define CONTENTS_NOTTEAM1		0x0080 +#define CONTENTS_NOTTEAM2		0x0100 +#define CONTENTS_NOBOTCLIP		0x0200 + +#define	CONTENTS_AREAPORTAL		0x8000 + +#define	CONTENTS_PLAYERCLIP		0x10000 +#define	CONTENTS_MONSTERCLIP	0x20000 +//bot specific contents types +#define	CONTENTS_TELEPORTER		0x40000 +#define	CONTENTS_JUMPPAD		0x80000 +#define CONTENTS_CLUSTERPORTAL	0x100000 +#define CONTENTS_DONOTENTER		0x200000 +#define CONTENTS_BOTCLIP		0x400000 +#define CONTENTS_MOVER			0x800000 + +#define	CONTENTS_ORIGIN			0x1000000	// removed before bsping an entity + +#define	CONTENTS_BODY			0x2000000	// should never be on a brush, only in game +#define	CONTENTS_CORPSE			0x4000000 +#define	CONTENTS_DETAIL			0x8000000	// brushes not used for the bsp +#define	CONTENTS_STRUCTURAL		0x10000000	// brushes used for the bsp +#define	CONTENTS_TRANSLUCENT	0x20000000	// don't consume surface fragments inside +#define	CONTENTS_TRIGGER		0x40000000 +#define	CONTENTS_NODROP			0x80000000	// don't leave bodies or items (death fog, lava) + +//TA: custominfoparms below +#define	CONTENTS_NOALIENBUILD			0x1000	//disallow alien building +#define	CONTENTS_NOHUMANBUILD			0x2000	//disallow alien building +#define	CONTENTS_NOBUILD					0x4000	//disallow alien building + +#define	SURF_NODAMAGE			0x1		// never give falling damage +#define	SURF_SLICK				0x2		// effects game physics +#define	SURF_SKY				0x4		// lighting from environment map +#define	SURF_LADDER				0x8 +#define	SURF_NOIMPACT			0x10	// don't make missile explosions +#define	SURF_NOMARKS			0x20	// don't leave missile marks +#define	SURF_FLESH				0x40	// make flesh sounds and effects +#define	SURF_NODRAW				0x80	// don't generate a drawsurface at all +#define	SURF_HINT				0x100	// make a primary bsp splitter +#define	SURF_SKIP				0x200	// completely ignore, allowing non-closed brushes +#define	SURF_NOLIGHTMAP			0x400	// surface doesn't need a lightmap +#define	SURF_POINTLIGHT			0x800	// generate lighting info at vertexes +#define	SURF_METALSTEPS			0x1000	// clanking footsteps +#define	SURF_NOSTEPS			0x2000	// no footstep sounds +#define	SURF_NONSOLID			0x4000	// don't collide against curves with this set +#define	SURF_LIGHTFILTER		0x8000	// act as a light filter during q3map -light +#define	SURF_ALPHASHADOW		0x10000	// do per-pixel light shadow casting in q3map +#define	SURF_NODLIGHT			0x20000	// don't dlight even if solid (solid lava, skies) +#define SURF_DUST				0x40000 // leave a dust trail when walking on this surface + +//TA: custominfoparms below +#define	SURF_NOALIENBUILD	0x80000  //disallow alien building +#define	SURF_NOHUMANBUILD	0x100000 //disallow alien building +#define	SURF_NOBUILD			0x200000 //disallow alien building  | 
