diff options
| author | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 04:48:05 +0000 | 
|---|---|---|
| committer | zakk <zakk@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-08-26 04:48:05 +0000 | 
| commit | 952c5c128f9efaea89d41d882c4ea3ade7df4591 (patch) | |
| tree | 91b84d9be7afad7e99ac64a640a65b6cb5081900 /q3radiant/splines | |
| parent | c2c2e0d25d6cdb7d42d7dc981a863f65f94f281d (diff) | |
| download | ioquake3-aero-952c5c128f9efaea89d41d882c4ea3ade7df4591.tar.gz ioquake3-aero-952c5c128f9efaea89d41d882c4ea3ade7df4591.zip | |
Itsa me, quake3io!
git-svn-id: svn://svn.icculus.org/quake3/trunk@2 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'q3radiant/splines')
| -rwxr-xr-x | q3radiant/splines/Splines.vcproj | 296 | ||||
| -rwxr-xr-x | q3radiant/splines/math_angles.cpp | 150 | ||||
| -rwxr-xr-x | q3radiant/splines/math_angles.h | 195 | ||||
| -rwxr-xr-x | q3radiant/splines/math_matrix.cpp | 134 | ||||
| -rwxr-xr-x | q3radiant/splines/math_matrix.h | 223 | ||||
| -rwxr-xr-x | q3radiant/splines/math_quaternion.cpp | 78 | ||||
| -rwxr-xr-x | q3radiant/splines/math_quaternion.h | 190 | ||||
| -rwxr-xr-x | q3radiant/splines/math_vector.cpp | 144 | ||||
| -rwxr-xr-x | q3radiant/splines/math_vector.h | 572 | ||||
| -rwxr-xr-x | q3radiant/splines/q_parse.cpp | 535 | ||||
| -rwxr-xr-x | q3radiant/splines/q_shared.cpp | 976 | ||||
| -rwxr-xr-x | q3radiant/splines/q_shared.h | 798 | ||||
| -rwxr-xr-x | q3radiant/splines/splines.cpp | 1244 | ||||
| -rwxr-xr-x | q3radiant/splines/splines.h | 1080 | ||||
| -rwxr-xr-x | q3radiant/splines/util_list.h | 346 | ||||
| -rwxr-xr-x | q3radiant/splines/util_str.cpp | 618 | ||||
| -rwxr-xr-x | q3radiant/splines/util_str.h | 817 | 
17 files changed, 8396 insertions, 0 deletions
| diff --git a/q3radiant/splines/Splines.vcproj b/q3radiant/splines/Splines.vcproj new file mode 100755 index 0000000..be579ae --- /dev/null +++ b/q3radiant/splines/Splines.vcproj @@ -0,0 +1,296 @@ +<?xml version="1.0" encoding="Windows-1252"?>
 +<VisualStudioProject
 +	ProjectType="Visual C++"
 +	Version="7.10"
 +	Name="Splines"
 +	SccProjectName=""$/source/q3radiant/splines", XINAAAAA"
 +	SccLocalPath=".">
 +	<Platforms>
 +		<Platform
 +			Name="Win32"/>
 +	</Platforms>
 +	<Configurations>
 +		<Configuration
 +			Name="Release|Win32"
 +			OutputDirectory=".\Release"
 +			IntermediateDirectory=".\Release"
 +			ConfigurationType="4"
 +			UseOfMFC="0"
 +			ATLMinimizesCRunTimeLibraryUsage="FALSE"
 +			CharacterSet="2">
 +			<Tool
 +				Name="VCCLCompilerTool"
 +				Optimization="2"
 +				InlineFunctionExpansion="1"
 +				PreprocessorDefinitions="WIN32;NDEBUG;_LIB;Q3RADIANT"
 +				StringPooling="TRUE"
 +				RuntimeLibrary="4"
 +				EnableFunctionLevelLinking="TRUE"
 +				UsePrecompiledHeader="2"
 +				PrecompiledHeaderFile=".\Release/Splines.pch"
 +				AssemblerListingLocation=".\Release/"
 +				ObjectFile=".\Release/"
 +				ProgramDataBaseFileName=".\Release/"
 +				WarningLevel="3"
 +				SuppressStartupBanner="TRUE"/>
 +			<Tool
 +				Name="VCCustomBuildTool"/>
 +			<Tool
 +				Name="VCLibrarianTool"
 +				OutputFile=".\Release\Splines.lib"
 +				SuppressStartupBanner="TRUE"/>
 +			<Tool
 +				Name="VCMIDLTool"/>
 +			<Tool
 +				Name="VCPostBuildEventTool"/>
 +			<Tool
 +				Name="VCPreBuildEventTool"/>
 +			<Tool
 +				Name="VCPreLinkEventTool"/>
 +			<Tool
 +				Name="VCResourceCompilerTool"
 +				PreprocessorDefinitions="NDEBUG"
 +				Culture="1033"/>
 +			<Tool
 +				Name="VCWebServiceProxyGeneratorTool"/>
 +			<Tool
 +				Name="VCXMLDataGeneratorTool"/>
 +			<Tool
 +				Name="VCManagedWrapperGeneratorTool"/>
 +			<Tool
 +				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
 +		</Configuration>
 +		<Configuration
 +			Name="Debug|Win32"
 +			OutputDirectory=".\Debug"
 +			IntermediateDirectory=".\Debug"
 +			ConfigurationType="4"
 +			UseOfMFC="0"
 +			ATLMinimizesCRunTimeLibraryUsage="FALSE"
 +			CharacterSet="2">
 +			<Tool
 +				Name="VCCLCompilerTool"
 +				Optimization="0"
 +				PreprocessorDefinitions="WIN32;_DEBUG;_LIB;Q3RADIANT"
 +				BasicRuntimeChecks="3"
 +				RuntimeLibrary="1"
 +				RuntimeTypeInfo="TRUE"
 +				UsePrecompiledHeader="2"
 +				PrecompiledHeaderFile=".\Debug/Splines.pch"
 +				AssemblerListingLocation=".\Debug/"
 +				ObjectFile=".\Debug/"
 +				ProgramDataBaseFileName=".\Debug/"
 +				WarningLevel="3"
 +				SuppressStartupBanner="TRUE"
 +				DebugInformationFormat="4"/>
 +			<Tool
 +				Name="VCCustomBuildTool"/>
 +			<Tool
 +				Name="VCLibrarianTool"
 +				OutputFile=".\Debug\Splines.lib"
 +				SuppressStartupBanner="TRUE"/>
 +			<Tool
 +				Name="VCMIDLTool"/>
 +			<Tool
 +				Name="VCPostBuildEventTool"/>
 +			<Tool
 +				Name="VCPreBuildEventTool"/>
 +			<Tool
 +				Name="VCPreLinkEventTool"/>
 +			<Tool
 +				Name="VCResourceCompilerTool"
 +				PreprocessorDefinitions="_DEBUG"
 +				Culture="1033"/>
 +			<Tool
 +				Name="VCWebServiceProxyGeneratorTool"/>
 +			<Tool
 +				Name="VCXMLDataGeneratorTool"/>
 +			<Tool
 +				Name="VCManagedWrapperGeneratorTool"/>
 +			<Tool
 +				Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
 +		</Configuration>
 +	</Configurations>
 +	<References>
 +	</References>
 +	<Files>
 +		<Filter
 +			Name="Source Files"
 +			Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
 +			<File
 +				RelativePath="math_angles.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="math_matrix.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="math_quaternion.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="math_vector.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="q_parse.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="q_shared.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="splines.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +			<File
 +				RelativePath="util_str.cpp">
 +				<FileConfiguration
 +					Name="Release|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="2"
 +						PreprocessorDefinitions=""/>
 +				</FileConfiguration>
 +				<FileConfiguration
 +					Name="Debug|Win32">
 +					<Tool
 +						Name="VCCLCompilerTool"
 +						Optimization="0"
 +						PreprocessorDefinitions=""
 +						BasicRuntimeChecks="3"/>
 +				</FileConfiguration>
 +			</File>
 +		</Filter>
 +		<Filter
 +			Name="Header Files"
 +			Filter="h;hpp;hxx;hm;inl">
 +			<File
 +				RelativePath="math_angles.h">
 +			</File>
 +			<File
 +				RelativePath="math_matrix.h">
 +			</File>
 +			<File
 +				RelativePath="math_quaternion.h">
 +			</File>
 +			<File
 +				RelativePath="math_vector.h">
 +			</File>
 +			<File
 +				RelativePath="q_shared.h">
 +			</File>
 +			<File
 +				RelativePath="splines.h">
 +			</File>
 +			<File
 +				RelativePath="util_list.h">
 +			</File>
 +			<File
 +				RelativePath="util_str.h">
 +			</File>
 +		</Filter>
 +	</Files>
 +	<Globals>
 +	</Globals>
 +</VisualStudioProject>
 diff --git a/q3radiant/splines/math_angles.cpp b/q3radiant/splines/math_angles.cpp new file mode 100755 index 0000000..0142d3d --- /dev/null +++ b/q3radiant/splines/math_angles.cpp @@ -0,0 +1,150 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#include "q_shared.h"
 +#include <float.h>
 +
 +angles_t ang_zero( 0.0f, 0.0f, 0.0f );
 +
 +void toAngles( mat3_t &src, angles_t &dst ) {
 +	double		theta;
 +	double		cp;
 +	double		sp;
 +
 +	sp = src[ 0 ][ 2 ];
 +
 +	// cap off our sin value so that we don't get any NANs
 +	if ( sp > 1.0 ) {
 +		sp = 1.0;
 +	} else if ( sp < -1.0 ) {
 +		sp = -1.0;
 +	}
 +
 +	theta = -asin( sp );
 +	cp = cos( theta );
 +
 +	if ( cp > 8192 * FLT_EPSILON ) {
 +		dst.pitch	= theta * 180 / M_PI;
 +		dst.yaw		= atan2( src[ 0 ][ 1 ], src[ 0 ][ 0 ] ) * 180 / M_PI;
 +		dst.roll	= atan2( src[ 1 ][ 2 ], src[ 2 ][ 2 ] ) * 180 / M_PI;
 +	} else {
 +		dst.pitch	= theta * 180 / M_PI;
 +		dst.yaw		= -atan2( src[ 1 ][ 0 ], src[ 1 ][ 1 ] ) * 180 / M_PI;
 +		dst.roll	= 0;
 +	}
 +}
 +
 +void toAngles( quat_t &src, angles_t &dst ) {
 +	mat3_t temp;
 +
 +	toMatrix( src, temp );
 +	toAngles( temp, dst );
 +}
 +
 +void toAngles( idVec3_t &src, angles_t &dst ) {
 +	dst.pitch	= src[ 0 ];
 +	dst.yaw		= src[ 1 ];
 +	dst.roll	= src[ 2 ];
 +}
 +
 +void angles_t::toVectors( idVec3_t *forward, idVec3_t *right, idVec3_t *up ) {
 +	float			angle;
 +	static float	sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
 +	
 +	angle = yaw * ( M_PI * 2 / 360 );
 +	sy = sin( angle );
 +	cy = cos( angle );
 +
 +	angle = pitch * ( M_PI * 2 / 360 );
 +	sp = sin( angle );
 +	cp = cos( angle );
 +
 +	angle = roll * ( M_PI * 2 / 360 );
 +	sr = sin( angle );
 +	cr = cos( angle );
 +
 +	if ( forward ) {
 +		forward->set( cp * cy, cp * sy, -sp );
 +	}
 +
 +	if ( right ) {
 +		right->set( -sr * sp * cy + cr * sy, -sr * sp * sy + -cr * cy, -sr * cp );
 +	}
 +
 +	if ( up ) {
 +		up->set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
 +	}
 +}
 +
 +idVec3_t angles_t::toForward( void ) {
 +	float			angle;
 +	static float	sp, sy, cp, cy; // static to help MS compiler fp bugs
 +	
 +	angle = yaw * ( M_PI * 2 / 360 );
 +	sy = sin( angle );
 +	cy = cos( angle );
 +
 +	angle = pitch * ( M_PI * 2 / 360 );
 +	sp = sin( angle );
 +	cp = cos( angle );
 +
 +	return idVec3_t( cp * cy, cp * sy, -sp );
 +}
 +
 +/*
 +=================
 +Normalize360
 +
 +returns angles normalized to the range [0 <= angle < 360]
 +=================
 +*/
 +angles_t& angles_t::Normalize360( void ) {
 +	pitch	= (360.0 / 65536) * ( ( int )( pitch	* ( 65536 / 360.0 ) ) & 65535 );
 +	yaw		= (360.0 / 65536) * ( ( int )( yaw		* ( 65536 / 360.0 ) ) & 65535 );
 +	roll	= (360.0 / 65536) * ( ( int )( roll		* ( 65536 / 360.0 ) ) & 65535 );
 +
 +	return *this;
 +}
 +
 +
 +/*
 +=================
 +Normalize180
 +
 +returns angles normalized to the range [-180 < angle <= 180]
 +=================
 +*/
 +angles_t& angles_t::Normalize180( void ) {
 +	Normalize360();
 +
 +	if ( pitch > 180.0 ) {
 +		pitch -= 360.0;
 +	}
 +	
 +	if ( yaw > 180.0 ) {
 +		yaw  -= 360.0;
 +	}
 +
 +	if ( roll > 180.0 ) {
 +		roll -= 360.0;
 +	}
 +	return *this;
 +}
 diff --git a/q3radiant/splines/math_angles.h b/q3radiant/splines/math_angles.h new file mode 100755 index 0000000..7156e46 --- /dev/null +++ b/q3radiant/splines/math_angles.h @@ -0,0 +1,195 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __MATH_ANGLES_H__
 +#define __MATH_ANGLES_H__
 +
 +#include <stdlib.h>
 +#include <assert.h>
 +
 +#include "math_vector.h"
 +
 +class mat3_t;
 +class quat_t;
 +class idVec3_t;
 +typedef idVec3_t &vec3_p;
 +
 +class angles_t {
 +public:
 +	float			pitch;
 +	float			yaw;
 +	float			roll;
 +
 +					angles_t();
 +					angles_t( float pitch, float yaw, float roll );
 +					angles_t( const idVec3_t &vec );
 +
 +	friend void		toAngles( idVec3_t &src, angles_t &dst );
 +	friend void		toAngles( quat_t &src, angles_t &dst );
 +	friend void		toAngles( mat3_t &src, angles_t &dst );
 +
 +					operator vec3_p();
 +
 +	float			operator[]( int index ) const;
 +	float&			operator[]( int index );
 +
 +	void 			set( float pitch, float yaw, float roll );
 +
 +	void			operator=( angles_t const &a );
 +	void			operator=( idVec3_t const &a );
 +
 +	friend angles_t	operator+( const angles_t &a, const angles_t &b );
 +	angles_t		&operator+=( angles_t const &a );
 +	angles_t		&operator+=( idVec3_t const &a );
 +
 +	friend angles_t	operator-( angles_t &a, angles_t &b );
 +	angles_t		&operator-=( angles_t &a );
 +
 +	friend angles_t	operator*( const angles_t &a, float b );
 +	friend angles_t	operator*( float a, const angles_t &b );
 +	angles_t		&operator*=( float a );
 +
 +	friend int		operator==(	angles_t &a, angles_t &b );
 +					
 +	friend int		operator!=(	angles_t &a, angles_t &b );
 +
 +	void			toVectors( idVec3_t *forward, idVec3_t *right = NULL, idVec3_t *up = NULL );
 +	idVec3_t			toForward( void );
 +
 +	angles_t		&Zero( void );
 +
 +	angles_t		&Normalize360( void );
 +	angles_t		&Normalize180( void );
 +};
 +
 +extern angles_t ang_zero;
 +
 +inline angles_t::angles_t() {}
 +
 +inline angles_t::angles_t( float pitch, float yaw, float roll ) {
 +	this->pitch = pitch;
 +	this->yaw	= yaw;
 +	this->roll	= roll;
 +}
 +
 +inline angles_t::angles_t( const idVec3_t &vec ) {
 +	this->pitch = vec.x;
 +	this->yaw	= vec.y;
 +	this->roll	= vec.z;
 +}
 +
 +inline float angles_t::operator[]( int index ) const {
 +	assert( ( index >= 0 ) && ( index < 3 ) );
 +	return ( &pitch )[ index ];
 +}
 +
 +inline float& angles_t::operator[]( int index ) {
 +	assert( ( index >= 0 ) && ( index < 3 ) );
 +	return ( &pitch )[ index ];
 +}
 +
 +inline angles_t::operator vec3_p( void ) {
 +	return *( idVec3_t * )&pitch;
 +}
 +
 +inline void angles_t::set( float pitch, float yaw, float roll ) {
 +	this->pitch = pitch;
 +	this->yaw	= yaw;
 +	this->roll	= roll;
 +}
 +
 +inline void angles_t::operator=( angles_t const &a ) {
 +	pitch	= a.pitch;
 +	yaw		= a.yaw;
 +	roll	= a.roll;
 +}
 +
 +inline void angles_t::operator=( idVec3_t const &a ) {
 +	pitch	= a[ 0 ];
 +	yaw		= a[ 1 ];
 +	roll	= a[ 2 ];
 +}
 +
 +inline angles_t operator+( const angles_t &a, const angles_t &b ) {
 +	return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll );
 +}
 +
 +inline angles_t& angles_t::operator+=( angles_t const &a ) {
 +	pitch	+= a.pitch;
 +	yaw		+= a.yaw;
 +	roll	+= a.roll;
 +
 +	return *this;
 +}
 +
 +inline angles_t& angles_t::operator+=( idVec3_t const &a ) {
 +	pitch	+= a.x;
 +	yaw	+= a.y;
 +	roll	+= a.z;
 +
 +	return *this;
 +}
 +
 +inline angles_t operator-( angles_t &a, angles_t &b ) {
 +	return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll );
 +}
 +
 +inline angles_t& angles_t::operator-=( angles_t &a ) {
 +	pitch	-= a.pitch;
 +	yaw		-= a.yaw;
 +	roll	-= a.roll;
 +
 +	return *this;
 +}
 +
 +inline angles_t operator*( const angles_t &a, float b ) {
 +	return angles_t( a.pitch * b, a.yaw * b, a.roll * b );
 +}
 +
 +inline angles_t operator*( float a, const angles_t &b ) {
 +	return angles_t( a * b.pitch, a * b.yaw, a * b.roll );
 +}
 +
 +inline angles_t& angles_t::operator*=( float a ) {
 +	pitch	*= a;
 +	yaw		*= a;
 +	roll	*= a;
 +
 +	return *this;
 +}
 +
 +inline int operator==( angles_t &a, angles_t &b ) {
 +	return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) );
 +}
 +
 +inline int operator!=( angles_t &a, angles_t &b ) {
 +	return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) );
 +}
 +
 +inline angles_t& angles_t::Zero( void ) {
 +	pitch	= 0.0f;
 +	yaw		= 0.0f;
 +	roll	= 0.0f;
 +
 +	return *this;
 +}
 +
 +#endif /* !__MATH_ANGLES_H__ */
 diff --git a/q3radiant/splines/math_matrix.cpp b/q3radiant/splines/math_matrix.cpp new file mode 100755 index 0000000..24ae914 --- /dev/null +++ b/q3radiant/splines/math_matrix.cpp @@ -0,0 +1,134 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#include "q_shared.h"
 +
 +mat3_t mat3_default( idVec3_t( 1, 0, 0 ), idVec3_t( 0, 1, 0 ), idVec3_t( 0, 0, 1 ) );
 +
 +void toMatrix( quat_t const &src, mat3_t &dst ) {
 +	float	wx, wy, wz;
 +	float	xx, yy, yz;
 +	float	xy, xz, zz;
 +	float	x2, y2, z2;
 +
 +	x2 = src.x + src.x;
 +	y2 = src.y + src.y;
 +	z2 = src.z + src.z;
 +
 +	xx = src.x * x2;
 +	xy = src.x * y2;
 +	xz = src.x * z2;
 +
 +	yy = src.y * y2;
 +	yz = src.y * z2;
 +	zz = src.z * z2;
 +
 +	wx = src.w * x2;
 +	wy = src.w * y2;
 +	wz = src.w * z2;
 +
 +	dst[ 0 ][ 0 ] = 1.0f - ( yy + zz );
 +	dst[ 0 ][ 1 ] = xy - wz;
 +	dst[ 0 ][ 2 ] = xz + wy;
 +
 +	dst[ 1 ][ 0 ] = xy + wz;
 +	dst[ 1 ][ 1 ] = 1.0f - ( xx + zz );
 +	dst[ 1 ][ 2 ] = yz - wx;
 +
 +	dst[ 2 ][ 0 ] = xz - wy;
 +	dst[ 2 ][ 1 ] = yz + wx;
 +	dst[ 2 ][ 2 ] = 1.0f - ( xx + yy );
 +}
 +
 +void toMatrix( angles_t const &src, mat3_t &dst ) {
 +	float			angle;
 +	static float	sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
 +		
 +	angle = src.yaw * ( M_PI * 2.0f / 360.0f );
 +	sy = sin( angle );
 +	cy = cos( angle );
 +
 +	angle = src.pitch * ( M_PI * 2.0f / 360.0f );
 +	sp = sin( angle );
 +	cp = cos( angle );
 +
 +	angle = src.roll * ( M_PI * 2.0f / 360.0f );
 +	sr = sin( angle );
 +	cr = cos( angle );
 +
 +	dst[ 0 ].set( cp * cy, cp * sy, -sp );
 +	dst[ 1 ].set( sr * sp * cy + cr * -sy, sr * sp * sy + cr * cy, sr * cp );
 +	dst[ 2 ].set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp );
 +}
 +
 +void toMatrix( idVec3_t const &src, mat3_t &dst ) {
 +        angles_t sup = src;
 +        toMatrix(sup, dst);
 +}
 +
 +void mat3_t::ProjectVector( const idVec3_t &src, idVec3_t &dst ) const {
 +	dst.x = src * mat[ 0 ];
 +	dst.y = src * mat[ 1 ];
 +	dst.z = src * mat[ 2 ];
 +}
 +
 +void mat3_t::UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const {
 +	dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z;
 +}
 +
 +void mat3_t::Transpose( mat3_t &matrix ) {
 +	int	i;
 +	int	j;
 +   
 +	for( i = 0; i < 3; i++ ) {
 +		for( j = 0; j < 3; j++ ) {
 +			matrix[ i ][ j ] = mat[ j ][ i ];
 +        }
 +	}
 +}
 +
 +void mat3_t::Transpose( void ) {
 +	float	temp;
 +	int		i;
 +	int		j;
 +   
 +	for( i = 0; i < 3; i++ ) {
 +		for( j = i + 1; j < 3; j++ ) {
 +			temp = mat[ i ][ j ];
 +			mat[ i ][ j ] = mat[ j ][ i ];
 +			mat[ j ][ i ] = temp;
 +        }
 +	}
 +}
 +
 +mat3_t mat3_t::Inverse( void ) const {
 +	mat3_t inv( *this );
 +
 +	inv.Transpose();
 +
 +	return inv;
 +}
 +
 +void mat3_t::Clear( void ) {
 +	mat[0].set( 1, 0, 0 );
 +	mat[1].set( 0, 1, 0 );
 +	mat[2].set( 0, 0, 1 );
 +}
 diff --git a/q3radiant/splines/math_matrix.h b/q3radiant/splines/math_matrix.h new file mode 100755 index 0000000..ed1da0d --- /dev/null +++ b/q3radiant/splines/math_matrix.h @@ -0,0 +1,223 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __MATH_MATRIX_H__
 +#define __MATH_MATRIX_H__
 +
 +#include <string.h>
 +#include "math_vector.h"
 +
 +#ifndef ID_INLINE
 +#ifdef _WIN32
 +#define ID_INLINE __inline 
 +#else
 +#define ID_INLINE inline
 +#endif
 +#endif
 +
 +class quat_t;
 +class angles_t;
 +
 +class mat3_t {
 +public:
 +	idVec3_t			mat[ 3 ];
 +
 +					mat3_t();
 +					mat3_t( float src[ 3 ][ 3 ] );
 +					mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z );
 +					mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz );
 +
 +	friend void		toMatrix( quat_t const &src, mat3_t &dst );
 +	friend void		toMatrix( angles_t const &src, mat3_t &dst );
 +	friend void		toMatrix( idVec3_t const &src, mat3_t &dst );
 +
 +	idVec3_t			operator[]( int index ) const;
 +	idVec3_t			&operator[]( int index );
 +
 +	idVec3_t			operator*( const idVec3_t &vec ) const;
 +	mat3_t			operator*( const mat3_t &a ) const;
 +	mat3_t			operator*( float a ) const;
 +	mat3_t			operator+( mat3_t const &a ) const;
 +	mat3_t			operator-( mat3_t const &a ) const;
 +
 +	friend idVec3_t	operator*( const idVec3_t &vec, const mat3_t &mat );
 +	friend mat3_t	operator*( float a, mat3_t const &b );
 +
 +	mat3_t			&operator*=( float a );
 +	mat3_t			&operator+=( mat3_t const &a );
 +	mat3_t			&operator-=( mat3_t const &a );
 +
 +	void			Clear( void );
 +
 +	void			ProjectVector( const idVec3_t &src, idVec3_t &dst ) const;
 +	void			UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const;
 +
 +	void			OrthoNormalize( void );
 +	void			Transpose( mat3_t &matrix );
 +	void			Transpose( void );
 +	mat3_t			Inverse( void ) const;
 +	void			Identity( void );
 +
 +	friend void		InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst );
 +	friend mat3_t	SkewSymmetric( idVec3_t const &src );
 +};
 +
 +ID_INLINE mat3_t::mat3_t() {
 +}
 +
 +ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
 +	memcpy( mat, src, sizeof( src ) );
 +}
 +
 +ID_INLINE mat3_t::mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z ) {
 +	mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z;
 +	mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z;
 +	mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z;
 +}
 +
 +ID_INLINE mat3_t::mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) {
 +	mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz;
 +	mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz;
 +	mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz;
 +}
 +
 +ID_INLINE idVec3_t mat3_t::operator[]( int index ) const {
 +	assert( ( index >= 0 ) && ( index < 3 ) );
 +	return mat[ index ];
 +}
 +
 +ID_INLINE idVec3_t& mat3_t::operator[]( int index ) {
 +	assert( ( index >= 0 ) && ( index < 3 ) );
 +	return mat[ index ];
 +}
 +
 +ID_INLINE idVec3_t mat3_t::operator*( const idVec3_t &vec ) const {
 +	return idVec3_t( 
 +		mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
 +		mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
 +		mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
 +}
 +
 +ID_INLINE mat3_t mat3_t::operator*( const mat3_t &a ) const {
 +	return mat3_t( 
 +		mat[0].x * a[0].x + mat[0].y * a[1].x + mat[0].z * a[2].x,
 +		mat[0].x * a[0].y + mat[0].y * a[1].y + mat[0].z * a[2].y,
 +		mat[0].x * a[0].z + mat[0].y * a[1].z + mat[0].z * a[2].z,
 +		mat[1].x * a[0].x + mat[1].y * a[1].x + mat[1].z * a[2].x,
 +		mat[1].x * a[0].y + mat[1].y * a[1].y + mat[1].z * a[2].y,
 +		mat[1].x * a[0].z + mat[1].y * a[1].z + mat[1].z * a[2].z,
 +		mat[2].x * a[0].x + mat[2].y * a[1].x + mat[2].z * a[2].x,
 +		mat[2].x * a[0].y + mat[2].y * a[1].y + mat[2].z * a[2].y,
 +		mat[2].x * a[0].z + mat[2].y * a[1].z + mat[2].z * a[2].z );
 +}
 +
 +ID_INLINE mat3_t mat3_t::operator*( float a ) const {
 +	return mat3_t( 
 +		mat[0].x * a, mat[0].y * a, mat[0].z * a, 
 +		mat[1].x * a, mat[1].y * a, mat[1].z * a, 
 +		mat[2].x * a, mat[2].y * a, mat[2].z * a );
 +}
 +
 +ID_INLINE mat3_t mat3_t::operator+( mat3_t const &a ) const {
 +	return mat3_t( 
 +		mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, 
 +		mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, 
 +		mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z );
 +}
 +    
 +ID_INLINE mat3_t mat3_t::operator-( mat3_t const &a ) const {
 +	return mat3_t( 
 +		mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, 
 +		mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, 
 +		mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z );
 +}
 +
 +ID_INLINE idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat ) {
 +	return idVec3_t( 
 +		mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
 +		mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
 +		mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
 +}
 +
 +ID_INLINE mat3_t operator*( float a, mat3_t const &b ) {
 +	return mat3_t( 
 +		b[0].x * a, b[0].y * a, b[0].z * a, 
 +		b[1].x * a, b[1].y * a, b[1].z * a, 
 +		b[2].x * a, b[2].y * a, b[2].z * a );
 +}
 +
 +ID_INLINE mat3_t &mat3_t::operator*=( float a ) {
 +	mat[0].x *= a; mat[0].y *= a; mat[0].z *= a;
 +	mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; 
 +	mat[2].x *= a; mat[2].y *= a; mat[2].z *= a;
 +
 +    return *this;
 +}
 +
 +ID_INLINE mat3_t &mat3_t::operator+=( mat3_t const &a ) {
 +	mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z;
 +	mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z;
 +	mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z;
 +
 +    return *this;
 +}
 +
 +ID_INLINE mat3_t &mat3_t::operator-=( mat3_t const &a ) {
 +	mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z;
 +	mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z;
 +	mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z;
 +
 +    return *this;
 +}
 +
 +ID_INLINE void mat3_t::OrthoNormalize( void ) {
 +	mat[ 0 ].Normalize();
 +	mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
 +	mat[ 2 ].Normalize();
 +	mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
 +	mat[ 1 ].Normalize();
 +}
 +
 +ID_INLINE void mat3_t::Identity( void ) {
 +	mat[ 0 ].x = 1.f; mat[ 0 ].y = 0.f; mat[ 0 ].z = 0.f;
 +	mat[ 1 ].x = 0.f; mat[ 1 ].y = 1.f; mat[ 1 ].z = 0.f;
 +	mat[ 2 ].x = 0.f; mat[ 2 ].y = 0.f; mat[ 2 ].z = 1.f;
 +}
 +
 +ID_INLINE void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ) {
 +	dst[0].x = inv[0].x * b[0].x + inv[1].x * b[1].x + inv[2].x * b[2].x;
 +	dst[0].y = inv[0].x * b[0].y + inv[1].x * b[1].y + inv[2].x * b[2].y;
 +	dst[0].z = inv[0].x * b[0].z + inv[1].x * b[1].z + inv[2].x * b[2].z;
 +	dst[1].x = inv[0].y * b[0].x + inv[1].y * b[1].x + inv[2].y * b[2].x;
 +	dst[1].y = inv[0].y * b[0].y + inv[1].y * b[1].y + inv[2].y * b[2].y;
 +	dst[1].z = inv[0].y * b[0].z + inv[1].y * b[1].z + inv[2].y * b[2].z;
 +	dst[2].x = inv[0].z * b[0].x + inv[1].z * b[1].x + inv[2].z * b[2].x;
 +	dst[2].y = inv[0].z * b[0].y + inv[1].z * b[1].y + inv[2].z * b[2].y;
 +	dst[2].z = inv[0].z * b[0].z + inv[1].z * b[1].z + inv[2].z * b[2].z;
 +}
 +
 +ID_INLINE mat3_t SkewSymmetric( idVec3_t const &src ) {
 +	return mat3_t( 0.0f, -src.z,  src.y, src.z,   0.0f, -src.x, -src.y,  src.x,   0.0f );
 +}
 +
 +extern mat3_t mat3_default;
 +
 +#endif /* !__MATH_MATRIX_H__ */
 diff --git a/q3radiant/splines/math_quaternion.cpp b/q3radiant/splines/math_quaternion.cpp new file mode 100755 index 0000000..4ef670e --- /dev/null +++ b/q3radiant/splines/math_quaternion.cpp @@ -0,0 +1,78 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#include "math_quaternion.h"
 +#include "math_matrix.h"
 +
 +void toQuat( idVec3_t &src, quat_t &dst ) {
 +	dst.x = src.x;
 +	dst.y = src.y;
 +	dst.z = src.z;
 +	dst.w = 0.0f;
 +}
 +
 +void toQuat( angles_t &src, quat_t &dst ) {
 +	mat3_t temp;
 +
 +	toMatrix( src, temp );
 +	toQuat( temp, dst );
 +}
 +
 +void toQuat( mat3_t &src, quat_t &dst ) {
 +	float		trace;
 +	float		s;
 +	int     	i;
 +	int			j;
 +	int			k;
 +
 +	static int 	next[ 3 ] = { 1, 2, 0 };
 +
 +	trace = src[ 0 ][ 0 ] + src[ 1 ][ 1 ] + src[ 2 ][ 2 ];
 +	if ( trace > 0.0f ) {
 +		s = ( float )sqrt( trace + 1.0f );
 +		dst.w = s * 0.5f;
 +		s = 0.5f / s;
 +    
 +		dst.x = ( src[ 2 ][ 1 ] - src[ 1 ][ 2 ] ) * s;
 +		dst.y = ( src[ 0 ][ 2 ] - src[ 2 ][ 0 ] ) * s;
 +		dst.z = ( src[ 1 ][ 0 ] - src[ 0 ][ 1 ] ) * s;
 +	} else {
 +		i = 0;
 +		if ( src[ 1 ][ 1 ] > src[ 0 ][ 0 ] ) {
 +			i = 1;
 +		}
 +		if ( src[ 2 ][ 2 ] > src[ i ][ i ] ) {
 +			i = 2;
 +		}
 +
 +		j = next[ i ];  
 +		k = next[ j ];
 +    
 +		s = ( float )sqrt( ( src[ i ][ i ] - ( src[ j ][ j ] + src[ k ][ k ] ) ) + 1.0f );
 +		dst[ i ] = s * 0.5f;
 +    
 +		s = 0.5f / s;
 +    
 +		dst.w		= ( src[ k ][ j ] - src[ j ][ k ] ) * s;
 +		dst[ j ]	= ( src[ j ][ i ] + src[ i ][ j ] ) * s;
 +		dst[ k ]	= ( src[ k ][ i ] + src[ i ][ k ] ) * s;
 +	}
 +}
 diff --git a/q3radiant/splines/math_quaternion.h b/q3radiant/splines/math_quaternion.h new file mode 100755 index 0000000..74ae2ac --- /dev/null +++ b/q3radiant/splines/math_quaternion.h @@ -0,0 +1,190 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __MATH_QUATERNION_H__
 +#define __MATH_QUATERNION_H__
 +
 +#include <assert.h>
 +#include <math.h>
 +
 +class idVec3_t;
 +class angles_t;
 +class mat3_t;
 +
 +class quat_t {
 +public:
 +	float			x;
 +	float			y;
 +	float			z;
 +	float			w;
 +
 +					quat_t();
 +					quat_t( float x, float y, float z, float w );
 +
 +	friend void		toQuat( idVec3_t &src, quat_t &dst );
 +	friend void		toQuat( angles_t &src, quat_t &dst );
 +	friend void		toQuat( mat3_t &src, quat_t &dst );
 +
 +	float			*vec4( void );
 +			
 +	float			operator[]( int index ) const;
 +	float			&operator[]( int index );
 +
 +	void 			set( float x, float y, float z, float w );
 +
 +	void			operator=( quat_t a );
 +
 +	friend quat_t	operator+( quat_t a, quat_t b );
 +	quat_t			&operator+=( quat_t a );
 +
 +	friend quat_t	operator-( quat_t a, quat_t b );
 +	quat_t			&operator-=( quat_t a );
 +
 +	friend quat_t	operator*( quat_t a, float b );
 +	friend quat_t	operator*( float a, quat_t b );
 +	quat_t			&operator*=( float a );
 +
 +	friend int		operator==(	quat_t a, quat_t b );
 +	friend int		operator!=(	quat_t a, quat_t b );
 +
 +	float			Length( void );
 +	quat_t			&Normalize( void );
 +
 +	quat_t			operator-();
 +};
 +
 +inline quat_t::quat_t() {
 +}
 +
 +inline quat_t::quat_t( float x, float y, float z, float w ) {
 +	this->x = x;
 +	this->y = y;
 +	this->z = z;
 +	this->w = w;
 +}
 +
 +inline float *quat_t::vec4( void ) {
 +	return &x;
 +}
 +
 +inline float quat_t::operator[]( int index ) const {
 +	assert( ( index >= 0 ) && ( index < 4 ) );
 +	return ( &x )[ index ];
 +}
 +
 +inline float& quat_t::operator[]( int index ) {
 +	assert( ( index >= 0 ) && ( index < 4 ) );
 +	return ( &x )[ index ];
 +}
 +
 +inline void quat_t::set( float x, float y, float z, float w ) {
 +	this->x = x;
 +	this->y = y;
 +	this->z = z;
 +	this->w = w;
 +}
 +
 +inline void quat_t::operator=( quat_t a ) {
 +	x = a.x;
 +	y = a.y;
 +	z = a.z;
 +	w = a.w;
 +}
 +
 +inline quat_t operator+( quat_t a, quat_t b ) {
 +	return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
 +}
 +
 +inline quat_t& quat_t::operator+=( quat_t a ) {
 +	x += a.x;
 +	y += a.y;
 +	z += a.z;
 +	w += a.w;
 +
 +	return *this;
 +}
 +
 +inline quat_t operator-( quat_t a, quat_t b ) {
 +	return quat_t( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w );
 +}
 +
 +inline quat_t& quat_t::operator-=( quat_t a ) {
 +	x -= a.x;
 +	y -= a.y;
 +	z -= a.z;
 +	w -= a.w;
 +
 +	return *this;
 +}
 +
 +inline quat_t operator*( quat_t a, float b ) {
 +	return quat_t( a.x * b, a.y * b, a.z * b, a.w * b );
 +}
 +
 +inline quat_t operator*( float a, quat_t b ) {
 +	return b * a;
 +}
 +
 +inline quat_t& quat_t::operator*=( float a ) {
 +	x *= a;
 +	y *= a;
 +	z *= a;
 +	w *= a;
 +
 +	return *this;
 +}
 +
 +inline int operator==( quat_t a, quat_t b ) {
 +	return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) );
 +}
 +
 +inline int operator!=( quat_t a, quat_t b ) {
 +	return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) );
 +}
 +
 +inline float quat_t::Length( void ) {
 +	float length;
 +	
 +	length = x * x + y * y + z * z + w * w;
 +	return ( float )sqrt( length );
 +}
 +
 +inline quat_t& quat_t::Normalize( void ) {
 +	float length;
 +	float ilength;
 +
 +	length = this->Length();
 +	if ( length ) {
 +		ilength = 1 / length;
 +		x *= ilength;
 +		y *= ilength;
 +		z *= ilength;
 +		w *= ilength;
 +	}
 +		
 +	return *this;
 +}
 +
 +inline quat_t quat_t::operator-() {
 +	return quat_t( -x, -y, -z, -w );
 +}
 +
 +#endif /* !__MATH_QUATERNION_H__ */
 diff --git a/q3radiant/splines/math_vector.cpp b/q3radiant/splines/math_vector.cpp new file mode 100755 index 0000000..120258c --- /dev/null +++ b/q3radiant/splines/math_vector.cpp @@ -0,0 +1,144 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +//#include "../game/q_shared.h"
 +#include "math_vector.h"
 +#include <assert.h>
 +#include <math.h>
 +#include <stdio.h>
 +#include <stdarg.h>
 +#include <string.h>
 +#include <stdlib.h>
 +#include <time.h>
 +#include <ctype.h>
 +
 +#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
 +
 +#define LERP_DELTA 1e-6
 +
 +idVec3_t vec_zero( 0.0f, 0.0f, 0.0f );
 +
 +Bounds	boundsZero;
 +
 +float idVec3_t::toYaw( void ) {
 +	float yaw;
 +	
 +	if ( ( y == 0 ) && ( x == 0 ) ) {
 +		yaw = 0;
 +	} else {
 +		yaw = atan2( y, x ) * 180 / M_PI;
 +		if ( yaw < 0 ) {
 +			yaw += 360;
 +		}
 +	}
 +
 +	return yaw;
 +}
 +
 +float idVec3_t::toPitch( void ) {
 +	float	forward;
 +	float	pitch;
 +	
 +	if ( ( x == 0 ) && ( y == 0 ) ) {
 +		if ( z > 0 ) {
 +			pitch = 90;
 +		} else {
 +			pitch = 270;
 +		}
 +	} else {
 +		forward = ( float )idSqrt( x * x + y * y );
 +		pitch = atan2( z, forward ) * 180 / M_PI;
 +		if ( pitch < 0 ) {
 +			pitch += 360;
 +		}
 +	}
 +
 +	return pitch;
 +}
 +
 +/*
 +angles_t idVec3_t::toAngles( void ) {
 +	float forward;
 +	float yaw;
 +	float pitch;
 +	
 +	if ( ( x == 0 ) && ( y == 0 ) ) {
 +		yaw = 0;
 +		if ( z > 0 ) {
 +			pitch = 90;
 +		} else {
 +			pitch = 270;
 +		}
 +	} else {
 +		yaw = atan2( y, x ) * 180 / M_PI;
 +		if ( yaw < 0 ) {
 +			yaw += 360;
 +		}
 +
 +		forward = ( float )idSqrt( x * x + y * y );
 +		pitch = atan2( z, forward ) * 180 / M_PI;
 +		if ( pitch < 0 ) {
 +			pitch += 360;
 +		}
 +	}
 +
 +	return angles_t( -pitch, yaw, 0 );
 +}
 +*/
 +
 +idVec3_t LerpVector( idVec3_t &w1, idVec3_t &w2, const float t ) {
 +	float omega, cosom, sinom, scale0, scale1;
 +
 +	cosom = w1 * w2;
 +	if ( ( 1.0 - cosom ) > LERP_DELTA ) {
 +		omega = acos( cosom );
 +		sinom = sin( omega );
 +		scale0 = sin( ( 1.0 - t ) * omega ) / sinom;
 +		scale1 = sin( t * omega ) / sinom;
 +	} else {
 +		scale0 = 1.0 - t;
 +		scale1 = t;
 +	}
 +
 +	return ( w1 * scale0 + w2 * scale1 );
 +}
 +
 +/*
 +=============
 +idVec3_t::string
 +
 +This is just a convenience function
 +for printing vectors
 +=============
 +*/
 +char *idVec3_t::string( void ) {
 +	static	int		index = 0;
 +	static	char	str[ 8 ][ 36 ];
 +	char	*s;
 +
 +	// use an array so that multiple toString's won't collide
 +	s = str[ index ];
 +	index = (index + 1)&7;
 +
 +	sprintf( s, "%.2f %.2f %.2f", x, y, z );
 +
 +	return s;
 +}
 diff --git a/q3radiant/splines/math_vector.h b/q3radiant/splines/math_vector.h new file mode 100755 index 0000000..8afc541 --- /dev/null +++ b/q3radiant/splines/math_vector.h @@ -0,0 +1,572 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __MATH_VECTOR_H__
 +#define __MATH_VECTOR_H__
 +
 +#pragma warning(disable : 4244)
 +
 +#include <math.h>
 +#include <assert.h>
 +
 +//#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[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 VectorCopy(a,b)			((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
 +
 +//#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 CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
 +
 +#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
 +#define VectorSubtract4(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 VectorAdd4(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 VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
 +#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
 +#define	VectorMA4(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),(o)[3]=(v)[3]+(b)[3]*(s))
 +
 +
 +//#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	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
 +
 +
 +//#include "util_heap.h"
 +
 +#ifndef EQUAL_EPSILON
 +#define EQUAL_EPSILON	0.001
 +#endif
 +
 +float Q_fabs( float f );
 +
 +#ifndef ID_INLINE
 +#ifdef _WIN32
 +#define ID_INLINE __inline 
 +#else
 +#define ID_INLINE inline
 +#endif
 +#endif
 +
 +// if this is defined, vec3 will take four elements, which may allow
 +// easier SIMD optimizations
 +//#define	FAT_VEC3
 +//#ifdef __ppc__
 +//#pragma align(16)
 +//#endif
 +
 +class angles_t;
 +#ifdef __ppc__
 +// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, 
 +// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson 
 +// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost. 
 +// We'll then multiply 1/sqrt times the original value to get the sqrt. 
 +// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive) 
 +// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments). 
 +
 +static inline float idSqrt(float x) {
 +    const float half = 0.5;
 +    const float one = 1.0;
 +    float B, y0, y1;
 +
 +    // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
 +    if (fabs(x) == 0.0)
 +        return x;
 +    B = x;
 +    
 +#ifdef __GNUC__
 +    asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
 +#else
 +    y0 = __frsqrte(B);
 +#endif
 +    /* First refinement step */
 +    
 +    y1 = y0 + half*y0*(one - B*y0*y0);
 +    
 +    /* Second refinement step -- copy the output of the last step to the input of this step */
 +    
 +    y0 = y1;
 +    y1 = y0 + half*y0*(one - B*y0*y0);
 +    
 +    /* Get sqrt(x) from x * 1/sqrt(x) */
 +    return x * y1;
 +}
 +#else
 +static inline double idSqrt(double x) {
 +    return sqrt(x);
 +}
 +#endif
 +
 +
 +//class idVec3_t  : public idHeap<idVec3_t> {
 +class idVec3_t {
 +public:	
 +#ifndef	FAT_VEC3
 +	    float x,y,z;
 +#else
 +	    float x,y,z,dist;
 +#endif
 +
 +#ifndef	FAT_VEC3
 +					idVec3_t() {};
 +#else
 +					idVec3_t() {dist = 0.0f;};
 +#endif
 +					idVec3_t( const float x, const float y, const float z );
 +
 +					operator float *();
 +
 +	float			operator[]( const int index ) const;
 +	float			&operator[]( const int index );
 +
 +	void 			set( const float x, const float y, const float z );
 +
 +	idVec3_t			operator-() const;
 +
 +	idVec3_t			&operator=( const idVec3_t &a );
 +
 +	float			operator*( const idVec3_t &a ) const;
 +	idVec3_t			operator*( const float a ) const;
 +	friend idVec3_t	operator*( float a, idVec3_t b );
 +
 +	idVec3_t			operator+( const idVec3_t &a ) const;
 +	idVec3_t			operator-( const idVec3_t &a ) const;
 +	
 +	idVec3_t			&operator+=( const idVec3_t &a );
 +	idVec3_t			&operator-=( const idVec3_t &a );
 +	idVec3_t			&operator*=( const float a );
 +
 +	int				operator==(	const idVec3_t &a ) const;
 +	int				operator!=(	const idVec3_t &a ) const;
 +
 +	idVec3_t			Cross( const idVec3_t &a ) const;
 +	idVec3_t			&Cross( const idVec3_t &a, const idVec3_t &b );
 +
 +	float			Length( void ) const;
 +	float			Normalize( void );
 +
 +	void			Zero( void );
 +	void			Snap( void );
 +	void			SnapTowards( const idVec3_t &to );
 +
 +	float			toYaw( void );
 +	float			toPitch( void );
 +	angles_t		toAngles( void );
 +	friend idVec3_t	LerpVector( const idVec3_t &w1, const idVec3_t &w2, const float t );
 +
 +	char			*string( void );
 +};
 +
 +extern idVec3_t vec_zero;
 +
 +ID_INLINE idVec3_t::idVec3_t( const float x, const float y, const float z ) {
 +	this->x = x;
 +	this->y = y;
 +	this->z = z;
 +#ifdef	FAT_VEC3
 +	this->dist = 0.0f;
 +#endif
 +}
 +
 +ID_INLINE float idVec3_t::operator[]( const int index ) const {
 +	return ( &x )[ index ];
 +}
 +
 +ID_INLINE float &idVec3_t::operator[]( const int index ) {
 +	return ( &x )[ index ];
 +}
 +
 +ID_INLINE idVec3_t::operator float *( void ) {
 +	return &x;
 +}
 +
 +ID_INLINE idVec3_t idVec3_t::operator-() const {
 +	return idVec3_t( -x, -y, -z );
 +}
 +	
 +ID_INLINE idVec3_t &idVec3_t::operator=( const idVec3_t &a ) { 
 +	x = a.x;
 +	y = a.y;
 +	z = a.z;
 +	
 +	return *this;
 +}
 +
 +ID_INLINE void idVec3_t::set( const float x, const float y, const float z ) {
 +	this->x = x;
 +	this->y = y;
 +	this->z = z;
 +}
 +
 +ID_INLINE idVec3_t idVec3_t::operator-( const idVec3_t &a ) const {
 +	return idVec3_t( x - a.x, y - a.y, z - a.z );
 +}
 +
 +ID_INLINE float idVec3_t::operator*( const idVec3_t &a ) const {
 +	return x * a.x + y * a.y + z * a.z;
 +}
 +
 +ID_INLINE idVec3_t idVec3_t::operator*( const float a ) const {
 +	return idVec3_t( x * a, y * a, z * a );
 +}
 +
 +ID_INLINE idVec3_t operator*( const float a, const idVec3_t b ) {
 +	return idVec3_t( b.x * a, b.y * a, b.z * a );
 +}
 +
 +ID_INLINE idVec3_t idVec3_t::operator+( const idVec3_t &a ) const {
 +	return idVec3_t( x + a.x, y + a.y, z + a.z );
 +}
 +
 +ID_INLINE idVec3_t &idVec3_t::operator+=( const idVec3_t &a ) {
 +	x += a.x;
 +	y += a.y;
 +	z += a.z;
 +
 +	return *this;
 +}
 +
 +ID_INLINE idVec3_t &idVec3_t::operator-=( const idVec3_t &a ) {
 +	x -= a.x;
 +	y -= a.y;
 +	z -= a.z;
 +
 +	return *this;
 +}
 +
 +ID_INLINE idVec3_t &idVec3_t::operator*=( const float a ) {
 +	x *= a;
 +	y *= a;
 +	z *= a;
 +
 +	return *this;
 +}
 +
 +ID_INLINE int idVec3_t::operator==( const idVec3_t &a ) const {
 +	if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
 +		return false;
 +	}
 +			
 +	if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
 +		return false;
 +	}
 +
 +	if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
 +		return false;
 +	}
 +
 +	return true;
 +}
 +
 +ID_INLINE int idVec3_t::operator!=( const idVec3_t &a ) const {
 +	if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
 +		return true;
 +	}
 +			
 +	if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
 +		return true;
 +	}
 +
 +	if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
 +		return true;
 +	}
 +
 +	return false;
 +}
 +
 +ID_INLINE idVec3_t idVec3_t::Cross( const idVec3_t &a ) const {
 +	return idVec3_t( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
 +}
 +
 +ID_INLINE idVec3_t &idVec3_t::Cross( const idVec3_t &a, const idVec3_t &b ) {
 +	x = a.y * b.z - a.z * b.y;
 +	y = a.z * b.x - a.x * b.z;
 +	z = a.x * b.y - a.y * b.x;
 +
 +	return *this;
 +}
 +
 +ID_INLINE float idVec3_t::Length( void ) const {
 +	float length;
 +	
 +	length = x * x + y * y + z * z;
 +	return ( float )idSqrt( length );
 +}
 +
 +ID_INLINE float idVec3_t::Normalize( void ) {
 +	float length;
 +	float ilength;
 +
 +	length = this->Length();
 +	if ( length ) {
 +		ilength = 1.0f / length;
 +		x *= ilength;
 +		y *= ilength;
 +		z *= ilength;
 +	}
 +		
 +	return length;
 +}
 +
 +ID_INLINE void idVec3_t::Zero( void ) {
 +	x = 0.0f;
 +	y = 0.0f;
 +	z = 0.0f;
 +}
 +
 +ID_INLINE void idVec3_t::Snap( void ) {
 +	x = float( int( x ) );
 +	y = float( int( y ) );
 +	z = float( int( z ) );
 +}
 +
 +/*
 +======================
 +SnapTowards
 +
 +Round a vector to integers for more efficient network
 +transmission, but make sure that it rounds towards a given point
 +rather than blindly truncating.  This prevents it from truncating 
 +into a wall.
 +======================
 +*/
 +ID_INLINE void idVec3_t::SnapTowards( const idVec3_t &to ) {
 +	if ( to.x <= x ) {
 +		x = float( int( x ) );
 +	} else {
 +		x = float( int( x ) + 1 );
 +	}
 +
 +	if ( to.y <= y ) {
 +		y = float( int( y ) );
 +	} else {
 +		y = float( int( y ) + 1 );
 +	}
 +
 +	if ( to.z <= z ) {
 +		z = float( int( z ) );
 +	} else {
 +		z = float( int( z ) + 1 );
 +	}
 +}
 +
 +//===============================================================
 +
 +class Bounds {
 +public:
 +	idVec3_t	b[2];
 +
 +			Bounds();
 +			Bounds( const idVec3_t &mins, const idVec3_t &maxs );
 +
 +	void	Clear();
 +	void	Zero();
 +	float	Radius();		// radius from origin, not from center
 +	idVec3_t	Center();
 +	void	AddPoint( const idVec3_t &v );
 +	void	AddBounds( const Bounds &bb );
 +	bool	IsCleared();
 +	bool	ContainsPoint( const idVec3_t &p );
 +	bool	IntersectsBounds( const Bounds &b2 );	// touching is NOT intersecting
 +};
 +
 +extern Bounds	boundsZero;
 +
 +ID_INLINE Bounds::Bounds(){
 +}
 +
 +ID_INLINE bool Bounds::IsCleared() {
 +	return b[0][0] > b[1][0];
 +}
 +
 +ID_INLINE bool Bounds::ContainsPoint( const idVec3_t &p ) {
 +	if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
 +		|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
 +		return false;
 +	}
 +	return true;
 +}
 +
 +ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
 +	if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
 +		|| b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
 +		return false;
 +	}
 +	return true;
 +}
 +
 +ID_INLINE Bounds::Bounds( const idVec3_t &mins, const idVec3_t &maxs ) {
 +	b[0] = mins;
 +	b[1] = maxs;
 +}
 +
 +ID_INLINE idVec3_t Bounds::Center() {
 +	return idVec3_t( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
 +}
 +
 +ID_INLINE void Bounds::Clear() {
 +	b[0][0] = b[0][1] = b[0][2] = 99999;
 +	b[1][0] = b[1][1] = b[1][2] = -99999;
 +}
 +
 +ID_INLINE void Bounds::Zero() {
 +	b[0][0] = b[0][1] = b[0][2] =
 +	b[1][0] = b[1][1] = b[1][2] = 0;
 +}
 +
 +ID_INLINE void Bounds::AddPoint( const idVec3_t &v ) {
 +	if ( v[0] < b[0][0]) {
 +		b[0][0] = v[0];
 +	}
 +	if ( v[0] > b[1][0]) {
 +		b[1][0] = v[0];
 +	}
 +	if ( v[1] < b[0][1] ) {
 +		b[0][1] = v[1];
 +	}
 +	if ( v[1] > b[1][1]) {
 +		b[1][1] = v[1];
 +	}
 +	if ( v[2] < b[0][2] ) {
 +		b[0][2] = v[2];
 +	}
 +	if ( v[2] > b[1][2]) {
 +		b[1][2] = v[2];
 +	}
 +}
 +
 +
 +ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
 +	if ( bb.b[0][0] < b[0][0]) {
 +		b[0][0] = bb.b[0][0];
 +	}
 +	if ( bb.b[0][1] < b[0][1]) {
 +		b[0][1] = bb.b[0][1];
 +	}
 +	if ( bb.b[0][2] < b[0][2]) {
 +		b[0][2] = bb.b[0][2];
 +	}
 +
 +	if ( bb.b[1][0] > b[1][0]) {
 +		b[1][0] = bb.b[1][0];
 +	}
 +	if ( bb.b[1][1] > b[1][1]) {
 +		b[1][1] = bb.b[1][1];
 +	}
 +	if ( bb.b[1][2] > b[1][2]) {
 +		b[1][2] = bb.b[1][2];
 +	}
 +}
 +
 +ID_INLINE float Bounds::Radius( ) {
 +	int		i;
 +	float	total;
 +	float	a, aa;
 +
 +	total = 0;
 +	for (i=0 ; i<3 ; i++) {
 +		a = (float)fabs( b[0][i] );
 +		aa = (float)fabs( b[1][i] );
 +		if ( aa > a ) {
 +			a = aa;
 +		}
 +		total += a * a;
 +	}
 +
 +	return (float)idSqrt( total );
 +}
 +
 +//===============================================================
 +
 +
 +class idVec2_t {
 +public:
 +	float			x;
 +	float			y;
 +
 +					operator float *();
 +	float			operator[]( int index ) const;
 +	float			&operator[]( int index );
 +};
 +
 +ID_INLINE float idVec2_t::operator[]( int index ) const {
 +	return ( &x )[ index ];
 +}
 +
 +ID_INLINE float& idVec2_t::operator[]( int index ) {
 +	return ( &x )[ index ];
 +}
 +
 +ID_INLINE idVec2_t::operator float *( void ) {
 +	return &x;
 +}
 +
 +class vec4_t : public idVec3_t {
 +public:
 +#ifndef	FAT_VEC3
 +	float			dist;
 +#endif
 +	vec4_t();
 +	~vec4_t() {};
 +	
 +	vec4_t( float x, float y, float z, float dist );
 +	float			operator[]( int index ) const;
 +	float			&operator[]( int index );
 +};
 +
 +ID_INLINE vec4_t::vec4_t() {}
 +ID_INLINE vec4_t::vec4_t( float x, float y, float z, float dist ) {
 +	this->x = x;
 +	this->y = y;
 +	this->z = z;
 +	this->dist = dist;
 +}
 +
 +ID_INLINE float vec4_t::operator[]( int index ) const {
 +	return ( &x )[ index ];
 +}
 +
 +ID_INLINE float& vec4_t::operator[]( int index ) {
 +	return ( &x )[ index ];
 +}
 +
 +
 +class idVec5_t : public idVec3_t {
 +public:
 +	float			s;
 +	float			t;
 +	float			operator[]( int index ) const;
 +	float			&operator[]( int index );
 +};
 +
 +
 +ID_INLINE float idVec5_t::operator[]( int index ) const {
 +	return ( &x )[ index ];
 +}
 +
 +ID_INLINE float& idVec5_t::operator[]( int index ) {
 +	return ( &x )[ index ];
 +}
 +
 +#endif /* !__MATH_VECTOR_H__ */
 diff --git a/q3radiant/splines/q_parse.cpp b/q3radiant/splines/q_parse.cpp new file mode 100755 index 0000000..1f61ba4 --- /dev/null +++ b/q3radiant/splines/q_parse.cpp @@ -0,0 +1,535 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// q_parse.c -- support for parsing text files
 +
 +#include "q_shared.h"
 +
 +/*
 +============================================================================
 +
 +PARSING
 +
 +============================================================================
 +*/
 +
 +// multiple character punctuation tokens
 +static const char *punctuation[] = {
 +	"+=", "-=",  "*=",  "/=", "&=", "|=", "++", "--",
 +		"&&", "||",  "<=",  ">=", "==", "!=",
 +	NULL
 +};
 +
 +typedef struct {
 +	char	token[MAX_TOKEN_CHARS];
 +	int		lines;
 +	qboolean	ungetToken;
 +	char	parseFile[MAX_QPATH];
 +} parseInfo_t;
 +
 +#define	MAX_PARSE_INFO	16
 +static parseInfo_t	parseInfo[MAX_PARSE_INFO];
 +static int			parseInfoNum;
 +static parseInfo_t	*pi = &parseInfo[0];
 +
 +/*
 +===================
 +Com_BeginParseSession
 +===================
 +*/
 +void Com_BeginParseSession( const char *filename ) {
 +	if ( parseInfoNum == MAX_PARSE_INFO - 1 ) {
 +		Com_Error( ERR_FATAL, "Com_BeginParseSession: session overflow" );
 +	}
 +	parseInfoNum++;
 +	pi = &parseInfo[parseInfoNum];
 +
 +	pi->lines = 1;
 +	Q_strncpyz( pi->parseFile, filename, sizeof( pi->parseFile ) );
 +}
 +
 +/*
 +===================
 +Com_EndParseSession
 +===================
 +*/
 +void Com_EndParseSession( void ) {
 +	if ( parseInfoNum == 0 ) {
 +		Com_Error( ERR_FATAL, "Com_EndParseSession: session underflow" );
 +	}
 +	parseInfoNum--;
 +	pi = &parseInfo[parseInfoNum];
 +}
 +
 +/*
 +===================
 +Com_GetCurrentParseLine
 +===================
 +*/
 +int Com_GetCurrentParseLine( void ) {
 +	return pi->lines;
 +}
 +
 +/*
 +===================
 +Com_ScriptError
 +
 +Prints the script name and line number in the message
 +===================
 +*/
 +void Com_ScriptError( const char *msg, ... ) {
 +	va_list		argptr;
 +	char		string[32000];
 +
 +	va_start( argptr, msg );
 +	vsprintf( string, msg,argptr );
 +	va_end( argptr );
 +
 +	Com_Error( ERR_DROP, "File %s, line %i: %s", pi->parseFile, pi->lines, string );
 +}
 +
 +void Com_ScriptWarning( const char *msg, ... ) {
 +	va_list		argptr;
 +	char		string[32000];
 +
 +	va_start( argptr, msg );
 +	vsprintf( string, msg,argptr );
 +	va_end( argptr );
 +
 +	Com_Printf( "File %s, line %i: %s", pi->parseFile, pi->lines, string );
 +}
 +
 +
 +/*
 +===================
 +Com_UngetToken
 +
 +Calling this will make the next Com_Parse return
 +the current token instead of advancing the pointer
 +===================
 +*/
 +void Com_UngetToken( void ) {
 +	if ( pi->ungetToken ) {
 +		Com_ScriptError( "UngetToken called twice" );
 +	}
 +	pi->ungetToken = qtrue;
 +}
 +
 +
 +static const char *SkipWhitespace( const char (*data), qboolean *hasNewLines ) {
 +	int c;
 +
 +	while( (c = *data) <= ' ') {
 +		if( !c ) {
 +			return NULL;
 +		}
 +		if( c == '\n' ) {
 +			pi->lines++;
 +			*hasNewLines = qtrue;
 +		}
 +		data++;
 +	}
 +
 +	return data;
 +}
 +
 +/*
 +==============
 +Com_ParseExt
 +
 +Parse a token out of a string
 +Will never return NULL, just empty strings.
 +An empty string will only be returned at end of file.
 +
 +If "allowLineBreaks" is qtrue then an empty
 +string will be returned if the next token is
 +a newline.
 +==============
 +*/
 +static char *Com_ParseExt( const char *(*data_p), qboolean allowLineBreaks ) {
 +	int c = 0, len;
 +	qboolean hasNewLines = qfalse;
 +	const char *data;
 +	const char **punc;
 +
 +	if ( !data_p ) {
 +		Com_Error( ERR_FATAL, "Com_ParseExt: NULL data_p" );
 +	}
 +
 +	data = *data_p;
 +	len = 0;
 +	pi->token[0] = 0;
 +
 +	// make sure incoming data is valid
 +	if ( !data ) {
 +		*data_p = NULL;
 +		return pi->token;
 +	}
 +
 +	// skip any leading whitespace
 +	while ( 1 ) {
 +		// skip whitespace
 +		data = SkipWhitespace( data, &hasNewLines );
 +		if ( !data ) {
 +			*data_p = NULL;
 +			return pi->token;
 +		}
 +		if ( hasNewLines && !allowLineBreaks ) {
 +			*data_p = data;
 +			return pi->token;
 +		}
 +
 +		c = *data;
 +
 +		// skip double slash comments
 +		if ( c == '/' && data[1] == '/' ) {
 +			while (*data && *data != '\n') {
 +				data++;
 +			}
 +			continue;
 +		}
 +
 +		// skip /* */ comments
 +		if ( c=='/' && data[1] == '*' ) {
 +			while ( *data && ( *data != '*' || data[1] != '/' ) ) {
 +				if( *data == '\n' ) {
 +					pi->lines++;
 +				}
 +				data++;
 +			}
 +			if ( *data ) {
 +				data += 2;
 +			}
 +			continue;
 +		}
 +
 +		// a real token to parse
 +		break;
 +	}
 +
 +	// handle quoted strings
 +	if ( c == '\"' ) {
 +		data++;
 +		while( 1 ) {
 +			c = *data++;
 +			if ( ( c=='\\' ) && ( *data == '\"' ) ) {
 +				// allow quoted strings to use \" to indicate the " character
 +				data++;
 +			} else if ( c=='\"' || !c ) {
 +				pi->token[len] = 0;
 +				*data_p = ( char * ) data;
 +				return pi->token;
 +			} else if( *data == '\n' ) {
 +				pi->lines++;
 +			}
 +			if ( len < MAX_TOKEN_CHARS - 1 ) {
 +				pi->token[len] = c;
 +				len++;
 +			}
 +		}
 +	}
 +
 +	// check for a number
 +	// is this parsing of negative numbers going to cause expression problems
 +	if ( ( c >= '0' && c <= '9' ) || ( c == '-' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) || 
 +		( c == '.' && data[ 1 ] >= '0' && data[ 1 ] <= '9' ) ) {
 +		do  {
 +
 +			if (len < MAX_TOKEN_CHARS - 1) {
 +				pi->token[len] = c;
 +				len++;
 +			}
 +			data++;
 +
 +			c = *data;
 +		} while ( ( c >= '0' && c <= '9' ) || c == '.' );
 +
 +		// parse the exponent
 +		if ( c == 'e' || c == 'E' ) {
 +			if (len < MAX_TOKEN_CHARS - 1) {
 +				pi->token[len] = c;
 +				len++;
 +			}
 +			data++;
 +			c = *data;
 +
 +			if ( c == '-' || c == '+' ) {
 +				if (len < MAX_TOKEN_CHARS - 1) {
 +					pi->token[len] = c;
 +					len++;
 +				}
 +				data++;
 +				c = *data;
 +			}
 +
 +			do  {
 +				if (len < MAX_TOKEN_CHARS - 1) {
 +					pi->token[len] = c;
 +					len++;
 +				}
 +				data++;
 +
 +				c = *data;
 +			} while ( c >= '0' && c <= '9' );
 +		}
 +
 +		if (len == MAX_TOKEN_CHARS) {
 +			len = 0;
 +		}
 +		pi->token[len] = 0;
 +
 +		*data_p = ( char * ) data;
 +		return pi->token;
 +   	}
 +
 +	// check for a regular word
 +	// we still allow forward and back slashes in name tokens for pathnames
 +	// and also colons for drive letters
 +	if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' || c == '/' || c == '\\' ) {
 +		do  {
 +			if (len < MAX_TOKEN_CHARS - 1) {
 +				pi->token[len] = c;
 +				len++;
 +			}
 +			data++;
 +
 +			c = *data;
 +		} while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' 
 +			|| ( c >= '0' && c <= '9' ) || c == '/' || c == '\\' || c == ':' || c == '.' );
 +
 +		if (len == MAX_TOKEN_CHARS) {
 +			len = 0;
 +		}
 +		pi->token[len] = 0;
 +
 +		*data_p = ( char * ) data;
 +		return pi->token;
 +	}
 +
 +	// check for multi-character punctuation token
 +	for ( punc = punctuation ; *punc ; punc++ ) {
 +		int		l;
 +		int		j;
 +
 +		l = strlen( *punc );
 +		for ( j = 0 ; j < l ; j++ ) {
 +			if ( data[j] != (*punc)[j] ) {
 +				break;
 +			}
 +		}
 +		if ( j == l ) {
 +			// a valid multi-character punctuation
 +			memcpy( pi->token, *punc, l );
 +			pi->token[l] = 0;
 +			data += l;
 +			*data_p = (char *)data;
 +			return pi->token;
 +		}
 +	}
 +
 +	// single character punctuation
 +	pi->token[0] = *data;
 +	pi->token[1] = 0;
 +	data++;
 +	*data_p = (char *)data;
 +
 +	return pi->token;
 +}
 +
 +/*
 +===================
 +Com_Parse
 +===================
 +*/
 +const char *Com_Parse( const char *(*data_p) ) {
 +	if ( pi->ungetToken ) {
 +		pi->ungetToken = qfalse;
 +		return pi->token;
 +	}
 +	return Com_ParseExt( data_p, qtrue );
 +}
 +
 +/*
 +===================
 +Com_ParseOnLine
 +===================
 +*/
 +const char *Com_ParseOnLine( const char *(*data_p) ) {
 +	if ( pi->ungetToken ) {
 +		pi->ungetToken = qfalse;
 +		return pi->token;
 +	}
 +	return Com_ParseExt( data_p, qfalse );
 +}
 +
 +
 +
 +/*
 +==================
 +Com_MatchToken
 +==================
 +*/
 +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ) {
 +	const char	*token;
 +
 +	token = Com_Parse( buf_p );
 +	if ( strcmp( token, match ) ) {
 +		if (warning) {
 +			Com_ScriptWarning( "MatchToken: %s != %s", token, match );
 +		} else {
 +			Com_ScriptError( "MatchToken: %s != %s", token, match );
 +		}
 +	}
 +}
 +
 +
 +/*
 +=================
 +Com_SkipBracedSection
 +
 +The next token should be an open brace.
 +Skips until a matching close brace is found.
 +Internal brace depths are properly skipped.
 +=================
 +*/
 +void Com_SkipBracedSection( const char *(*program) ) {
 +	const char			*token;
 +	int				depth;
 +
 +	depth = 0;
 +	do {
 +		token = Com_Parse( program );
 +		if( token[1] == 0 ) {
 +			if( token[0] == '{' ) {
 +				depth++;
 +			}
 +			else if( token[0] == '}' ) {
 +				depth--;
 +			}
 +		}
 +	} while( depth && *program );
 +}
 +
 +/*
 +=================
 +Com_SkipRestOfLine
 +=================
 +*/
 +void Com_SkipRestOfLine ( const char *(*data) ) {
 +	const char	*p;
 +	int		c;
 +
 +	p = *data;
 +	while ( (c = *p++) != 0 ) {
 +		if ( c == '\n' ) {
 +			pi->lines++;
 +			break;
 +		}
 +	}
 +
 +	*data = p;
 +}
 +
 +/*
 +====================
 +Com_ParseRestOfLine
 +====================
 +*/
 +const char *Com_ParseRestOfLine( const char *(*data_p) ) {
 +	static char	line[MAX_TOKEN_CHARS];
 +	const char *token;
 +
 +	line[0] = 0;
 +	while( 1 ) {
 +		token = Com_ParseOnLine( data_p );
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( line[0] ) {
 +			Q_strcat( line, sizeof(line), " " );
 +		}
 +		Q_strcat( line, sizeof(line), token );
 +	}
 +
 +	return line;
 +}
 +
 +
 +float Com_ParseFloat( const char *(*buf_p) ) {
 +	const char		*token;
 +
 +	token = Com_Parse( buf_p );
 +	if ( !token[0] ) {
 +		return 0;
 +	}
 +	return atof( token );
 +}
 +
 +int Com_ParseInt( const char *(*buf_p) ) {
 +	const char		*token;
 +
 +	token = Com_Parse( buf_p );
 +	if ( !token[0] ) {
 +		return 0;
 +	}
 +	return atof( token );
 +}
 +
 +
 +
 +void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) {
 +	const 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 Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) {
 +	int		i;
 +
 +	Com_MatchToken( buf_p, "(" );
 +
 +	for (i = 0 ; i < y ; i++) {
 +		Com_Parse1DMatrix (buf_p, x, m + i * x);
 +	}
 +
 +	Com_MatchToken( buf_p, ")" );
 +}
 +
 +void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) {
 +	int		i;
 +
 +	Com_MatchToken( buf_p, "(" );
 +
 +	for (i = 0 ; i < z ; i++) {
 +		Com_Parse2DMatrix (buf_p, y, x, m + i * x*y);
 +	}
 +
 +	Com_MatchToken( buf_p, ")" );
 +}
 +
 diff --git a/q3radiant/splines/q_shared.cpp b/q3radiant/splines/q_shared.cpp new file mode 100755 index 0000000..56cbcf1 --- /dev/null +++ b/q3radiant/splines/q_shared.cpp @@ -0,0 +1,976 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +// q_shared.c -- stateless support routines that are included in each code dll
 +#include "q_shared.h"
 +
 +/*
 +============================================================================
 +
 +GROWLISTS
 +
 +============================================================================
 +*/
 +
 +// malloc / free all in one place for debugging
 +extern "C" void *Com_Allocate( int bytes );
 +extern "C" void Com_Dealloc( void *ptr );
 +
 +void Com_InitGrowList( growList_t *list, int maxElements ) {
 +	list->maxElements = maxElements;
 +	list->currentElements = 0;
 +	list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
 +}
 +
 +int Com_AddToGrowList( growList_t *list, void *data ) {
 +	void	**old;
 +
 +	if ( list->currentElements != list->maxElements ) {
 +		list->elements[list->currentElements] = data;
 +		return list->currentElements++;
 +	}
 +
 +	// grow, reallocate and move
 +	old = list->elements;
 +
 +	if ( list->maxElements < 0 ) {
 +		Com_Error( ERR_FATAL, "Com_AddToGrowList: maxElements = %i", list->maxElements );
 +	}
 +
 +	if ( list->maxElements == 0 ) {
 +		// initialize the list to hold 100 elements
 +		Com_InitGrowList( list, 100 );
 +		return Com_AddToGrowList( list, data );
 +	}
 +
 +	list->maxElements *= 2;
 +
 +	Com_DPrintf( "Resizing growlist to %i maxElements\n", list->maxElements );
 +
 +	list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) );
 +
 +	if ( !list->elements ) {
 +		Com_Error( ERR_DROP, "Growlist alloc failed" );
 +	}
 +
 +	memcpy( list->elements, old, list->currentElements * sizeof( void * ) );
 +
 +	Com_Dealloc( old );
 +
 +	return Com_AddToGrowList( list, data );
 +}
 +
 +void *Com_GrowListElement( const growList_t *list, int index ) {
 +	if ( index < 0 || index >= list->currentElements ) {
 +		Com_Error( ERR_DROP, "Com_GrowListElement: %i out of range of %i", 
 +			index, list->currentElements );
 +	}
 +	return list->elements[index];
 +}
 +
 +int Com_IndexForGrowListElement( const growList_t *list, const void *element ) {
 +	int		i;
 +
 +	for ( i = 0 ; i < list->currentElements ; i++ ) {
 +		if ( list->elements[i] == element ) {
 +			return i;
 +		}
 +	}
 +	return -1;
 +}
 +
 +//============================================================================
 +
 +
 +float Com_Clamp( float min, float max, float value ) {
 +	if ( value < min ) {
 +		return min;
 +	}
 +	if ( value > max ) {
 +		return max;
 +	}
 +	return value;
 +}
 +
 +/*
 +============
 +Com_StringContains
 +============
 +*/
 +const char *Com_StringContains( const char *str1, const char *str2, int casesensitive) {
 +	int len, i, j;
 +
 +	len = strlen(str1) - strlen(str2);
 +	for (i = 0; i <= len; i++, str1++) {
 +		for (j = 0; str2[j]; j++) {
 +			if (casesensitive) {
 +				if (str1[j] != str2[j]) {
 +					break;
 +				}
 +			}
 +			else {
 +				if (toupper(str1[j]) != toupper(str2[j])) {
 +					break;
 +				}
 +			}
 +		}
 +		if (!str2[j]) {
 +			return str1;
 +		}
 +	}
 +	return NULL;
 +}
 +
 +/*
 +============
 +Com_Filter
 +============
 +*/
 +int Com_Filter( const char *filter, const char *name, int casesensitive)
 +{
 +	char buf[MAX_TOKEN_CHARS];
 +	const char *ptr;
 +	int i, found;
 +
 +	while(*filter) {
 +		if (*filter == '*') {
 +			filter++;
 +			for (i = 0; *filter; i++) {
 +				if (*filter == '*' || *filter == '?') break;
 +				buf[i] = *filter;
 +				filter++;
 +			}
 +			buf[i] = '\0';
 +			if (strlen(buf)) {
 +				ptr = Com_StringContains(name, buf, casesensitive);
 +				if (!ptr) return qfalse;
 +				name = ptr + strlen(buf);
 +			}
 +		}
 +		else if (*filter == '?') {
 +			filter++;
 +			name++;
 +		}
 +		else if (*filter == '[' && *(filter+1) == '[') {
 +			filter++;
 +		}
 +		else if (*filter == '[') {
 +			filter++;
 +			found = qfalse;
 +			while(*filter && !found) {
 +				if (*filter == ']' && *(filter+1) != ']') break;
 +				if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']')) {
 +					if (casesensitive) {
 +						if (*name >= *filter && *name <= *(filter+2)) found = qtrue;
 +					}
 +					else {
 +						if (toupper(*name) >= toupper(*filter) &&
 +							toupper(*name) <= toupper(*(filter+2))) found = qtrue;
 +					}
 +					filter += 3;
 +				}
 +				else {
 +					if (casesensitive) {
 +						if (*filter == *name) found = qtrue;
 +					}
 +					else {
 +						if (toupper(*filter) == toupper(*name)) found = qtrue;
 +					}
 +					filter++;
 +				}
 +			}
 +			if (!found) return qfalse;
 +			while(*filter) {
 +				if (*filter == ']' && *(filter+1) != ']') break;
 +				filter++;
 +			}
 +			filter++;
 +			name++;
 +		}
 +		else {
 +			if (casesensitive) {
 +				if (*filter != *name) return qfalse;
 +			}
 +			else {
 +				if (toupper(*filter) != toupper(*name)) return qfalse;
 +			}
 +			filter++;
 +			name++;
 +		}
 +	}
 +	return qtrue;
 +}
 +
 +
 +/*
 +================
 +Com_HashString
 +
 +================
 +*/
 +int Com_HashString( const char *fname ) {
 +	int		i;
 +	long	hash;
 +	char	letter;
 +
 +	hash = 0;
 +	i = 0;
 +	while (fname[i] != '\0') {
 +		letter = tolower(fname[i]);
 +		if (letter =='.') break;				// don't include extension
 +		if (letter =='\\') letter = '/';		// damn path names
 +		hash+=(long)(letter)*(i+119);
 +		i++;
 +	}
 +	hash &= (FILE_HASH_SIZE-1);
 +	return hash;
 +}
 +
 +
 +/*
 +============
 +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 ) {
 +	while ( *in && *in != '.' ) {
 +		*out++ = *in++;
 +	}
 +	*out = 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 float	(*_BigFloat) (float l);
 +static float	(*_LittleFloat) (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);}
 +float	BigFloat (float l) {return _BigFloat(l);}
 +float	LittleFloat (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;
 +}
 +
 +float FloatSwap (float f)
 +{
 +	union
 +	{
 +		float	f;
 +		byte	b[4];
 +	} dat1, dat2;
 +	
 +	
 +	dat1.f = f;
 +	dat2.b[0] = dat1.b[3];
 +	dat2.b[1] = dat1.b[2];
 +	dat2.b[2] = dat1.b[1];
 +	dat2.b[3] = dat1.b[0];
 +	return dat2.f;
 +}
 +
 +float FloatNoSwap (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;
 +		_BigFloat = FloatSwap;
 +		_LittleFloat = FloatNoSwap;
 +	}
 +	else
 +	{
 +		_BigShort = ShortNoSwap;
 +		_LittleShort = ShortSwap;
 +		_BigLong = LongNoSwap;
 +		_LittleLong = LongSwap;
 +		_BigFloat = FloatNoSwap;
 +		_LittleFloat = FloatSwap;
 +	}
 +
 +}
 +
 +/*
 +===============
 +Com_ParseInfos
 +===============
 +*/
 +int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ) {
 +	const 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_Parse( &buf );
 +			if ( !token[0] ) {
 +				Com_Printf( "Unexpected end of info file\n" );
 +				break;
 +			}
 +			if ( !strcmp( token, "}" ) ) {
 +				break;
 +			}
 +			Q_strncpyz( key, token, sizeof( key ) );
 +
 +			token = Com_ParseOnLine( &buf );
 +			if ( !token[0] ) {
 +				token = "<NULL>";
 +			}
 +			Info_SetValueForKey( infos[count], key, token );
 +		}
 +		count++;
 +	}
 +
 +	return count;
 +}
 +
 +
 +
 +/*
 +============================================================================
 +
 +					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 );
 +}
 +
 +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 ) {
 +	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;
 +	
 +	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 Q_stricmpn (s1, s2, 99999);
 +}
 +
 +
 +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);
 +	}
 +	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;
 +}
 +
 +
 +/*
 +=====================================================================
 +
 +  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[MAX_INFO_KEY];
 +	static	char value[2][MAX_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 ) >= MAX_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[MAX_INFO_KEY], char value[MAX_INFO_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_Validate
 +
 +Some characters are illegal in info strings because they
 +can mess up the server's parsing
 +==================
 +*/
 +qboolean Info_Validate( const char *s ) {
 +	if ( strchr( s, '\"' ) ) {
 +		return qfalse;
 +	}
 +	if ( strchr( s, ';' ) ) {
 +		return qfalse;
 +	}
 +	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];
 +
 +	if ( strlen( s ) >= MAX_INFO_STRING ) {
 +		Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" );
 +	}
 +
 +	if (strchr (key, '\\') || strchr (value, '\\'))
 +	{
 +		Com_Printf ("Can't use keys or values with a \\\n");
 +		return;
 +	}
 +
 +	if (strchr (key, ';') || strchr (value, ';'))
 +	{
 +		Com_Printf ("Can't use keys or values with a semicolon\n");
 +		return;
 +	}
 +
 +	if (strchr (key, '\"') || strchr (value, '\"'))
 +	{
 +		Com_Printf ("Can't use keys or values with a \"\n");
 +		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 (s, newi);
 +}
 +
 +//====================================================================
 +
 +
 +/*
 +===============
 +ParseHex
 +===============
 +*/
 +int	ParseHex( const char *text ) {
 +	int		value;
 +	int		c;
 +
 +	value = 0;
 +	while ( ( c = *text++ ) != 0 ) {
 +		if ( c >= '0' && c <= '9' ) {
 +			value = value * 16 + c - '0';
 +			continue;
 +		}
 +		if ( c >= 'a' && c <= 'f' ) {
 +			value = value * 16 + 10 + c - 'a';
 +			continue;
 +		}
 +		if ( c >= 'A' && c <= 'F' ) {
 +			value = value * 16 + 10 + c - 'A';
 +			continue;
 +		}
 +	}
 +
 +	return value;
 +}
 diff --git a/q3radiant/splines/q_shared.h b/q3radiant/splines/q_shared.h new file mode 100755 index 0000000..6d9a563 --- /dev/null +++ b/q3radiant/splines/q_shared.h @@ -0,0 +1,798 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __Q_SHARED_H
 +#define __Q_SHARED_H
 +
 +// q_shared.h -- included first by ALL program modules.
 +// these are the definitions that have no dependance on
 +// central system services, and can be used by any part
 +// of the program without any state issues.
 +
 +// A user mod should never modify this file
 +
 +#define	Q3_VERSION		"DOOM 0.01"
 +
 +// alignment macros for SIMD
 +#define	ALIGN_ON
 +#define	ALIGN_OFF
 +
 +#ifdef _WIN32
 +
 +#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 : 4201)
 +#pragma warning(disable : 4214)
 +#pragma warning(disable : 4244)
 +#pragma warning(disable : 4305)		// truncation from const double to float
 +#pragma warning(disable : 4310)		// cast truncates constant value
 +#pragma warning(disable : 4514)
 +#pragma warning(disable : 4711)		// selected for automatic inline expansion
 +#pragma warning(disable : 4220)		// varargs matches remaining parameters
 +
 +#endif
 +
 +#include <assert.h>
 +#include <math.h>
 +#include <stdio.h>
 +#include <stdarg.h>
 +#include <string.h>
 +#include <stdlib.h>
 +#include <time.h>
 +#include <ctype.h>
 +#ifdef WIN32				// mac doesn't have malloc.h
 +#include <malloc.h>			// for _alloca()
 +#endif
 +#ifdef _WIN32
 +
 +//#pragma intrinsic( memset, memcpy )
 +
 +#endif
 +
 +
 +// this is the define for determining if we have an asm version of a C function
 +#if (defined _M_IX86 || defined __i386__) && !defined __sun__  && !defined __LCC__
 +#define id386	1
 +#else
 +#define id386	0
 +#endif
 +
 +// for windows fastcall option
 +
 +#define	QDECL
 +
 +//======================= WIN32 DEFINES =================================
 +
 +#ifdef WIN32
 +
 +#define	MAC_STATIC
 +
 +#undef QDECL
 +#define	QDECL	__cdecl
 +
 +// buildstring will be incorporated into the version string
 +#ifdef NDEBUG
 +#ifdef _M_IX86
 +#define	CPUSTRING	"win-x86"
 +#elif defined _M_ALPHA
 +#define	CPUSTRING	"win-AXP"
 +#endif
 +#else
 +#ifdef _M_IX86
 +#define	CPUSTRING	"win-x86-debug"
 +#elif defined _M_ALPHA
 +#define	CPUSTRING	"win-AXP-debug"
 +#endif
 +#endif
 +
 +
 +#define	PATH_SEP '\\'
 +
 +#endif
 +
 +//======================= MAC OS X SERVER DEFINES =====================
 +
 +#if defined(__MACH__) && defined(__APPLE__)
 +
 +#define MAC_STATIC
 +
 +#ifdef __ppc__
 +#define CPUSTRING	"MacOSXS-ppc"
 +#elif defined __i386__
 +#define CPUSTRING	"MacOSXS-i386"
 +#else
 +#define CPUSTRING	"MacOSXS-other"
 +#endif
 +
 +#define	PATH_SEP	'/'
 +
 +#define	GAME_HARD_LINKED
 +#define	CGAME_HARD_LINKED
 +#define	UI_HARD_LINKED
 +#define _alloca alloca
 +
 +#undef ALIGN_ON
 +#undef ALIGN_OFF
 +#define	ALIGN_ON		#pragma align(16)
 +#define	ALIGN_OFF		#pragma align()
 +
 +#ifdef __cplusplus
 +	extern "C" {
 +#endif
 +
 +void *osxAllocateMemory(long size);
 +void osxFreeMemory(void *pointer);
 +
 +#ifdef __cplusplus
 +        }
 +#endif
 +
 +#endif
 +
 +//======================= MAC DEFINES =================================
 +
 +#ifdef __MACOS__
 +
 +#define	MAC_STATIC static
 +
 +#define	CPUSTRING	"MacOS-PPC"
 +
 +#define	PATH_SEP ':'
 +
 +void Sys_PumpEvents( void );
 +
 +#endif
 +
 +#ifdef __MRC__
 +
 +#define	MAC_STATIC
 +
 +#define	CPUSTRING	"MacOS-PPC"
 +
 +#define	PATH_SEP ':'
 +
 +void Sys_PumpEvents( void );
 +
 +#undef QDECL
 +#define	QDECL	__cdecl
 +
 +#define _alloca alloca
 +#endif
 +
 +//======================= LINUX DEFINES =================================
 +
 +// the mac compiler can't handle >32k of locals, so we
 +// just waste space and make big arrays static...
 +#ifdef __linux__
 +
 +#define	MAC_STATIC
 +
 +#ifdef __i386__
 +#define	CPUSTRING	"linux-i386"
 +#elif defined __axp__
 +#define	CPUSTRING	"linux-alpha"
 +#else
 +#define	CPUSTRING	"linux-other"
 +#endif
 +
 +#define	PATH_SEP '/'
 +
 +#endif
 +
 +//=============================================================
 +
 +
 +  
 +typedef enum {qfalse, qtrue}	qboolean;
 +
 +typedef unsigned char 		byte;
 +
 +#define	EQUAL_EPSILON	0.001
 +
 +typedef int		qhandle_t;
 +typedef int		sfxHandle_t;
 +typedef int		fileHandle_t;
 +typedef int		clipHandle_t;
 +
 +typedef enum {
 +	INVALID_JOINT = -1
 +} jointHandle_t;
 +
 +#ifndef NULL
 +#define NULL ((void *)0)
 +#endif
 +
 +#define	MAX_QINT			0x7fffffff
 +#define	MIN_QINT			(-MAX_QINT-1)
 +
 +#ifndef max
 +#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) )
 +#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) )
 +#endif
 +
 +#ifndef sign
 +#define sign( f )	( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) )
 +#endif
 +
 +// 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	256		// 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	MAX_QPATH			64		// max length of a quake game pathname
 +#define	MAX_OSPATH			128		// max length of a filesystem pathname
 +
 +#define	MAX_NAME_LENGTH		32		// max length of a client name
 +
 +// 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
 +
 +#undef ERR_FATAL						// malloc.h on unix
 +
 +// parameters to the main Error routine
 +typedef enum {
 +	ERR_NONE,
 +	ERR_FATAL,					// exit the entire game with a popup window
 +	ERR_DROP,					// print to console and disconnect from game
 +	ERR_DISCONNECT,				// don't kill 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
 +
 +
 +/*
 +==============================================================
 +
 +MATHLIB
 +
 +==============================================================
 +*/
 +#ifdef __cplusplus			// so we can include this in C code
 +#define	SIDE_FRONT		0
 +#define	SIDE_BACK		1
 +#define	SIDE_ON			2
 +#define	SIDE_CROSS		3
 +
 +#define	Q_PI	3.14159265358979323846
 +#ifndef M_PI
 +#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
 +#endif
 +
 +#include "math_vector.h"
 +#include "math_angles.h"
 +#include "math_matrix.h"
 +#include "math_quaternion.h"
 +
 +class idVec3_t;						// for defining vectors
 +typedef idVec3_t &vec3_p;				// for passing vectors as function arguments
 +typedef const idVec3_t &vec3_c;		// for passing vectors as const function arguments
 +									
 +class angles_t;						// for defining angle vectors
 +typedef angles_t &angles_p;			// for passing angles as function arguments
 +typedef const angles_t &angles_c;	// for passing angles as const function arguments
 +
 +class mat3_t;						// for defining matrices
 +typedef mat3_t &mat3_p;				// for passing matrices as function arguments
 +typedef const mat3_t &mat3_c;		// for passing matrices as const function arguments
 +
 +
 +
 +#define NUMVERTEXNORMALS	162
 +extern	idVec3_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	idVec3_t	vec3_origin;
 +extern	vec4_t	vec4_origin;
 +extern	mat3_t	axisDefault;
 +
 +#define	nanmask (255<<23)
 +
 +#define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
 +
 +float Q_fabs( float f );
 +float Q_rsqrt( float f );		// reciprocal square root
 +
 +#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) )
 +
 +signed char ClampChar( int i );
 +signed short ClampShort( int i );
 +
 +// this isn't a real cheap function to call!
 +int DirToByte( const idVec3_t &dir );
 +void ByteToDir( int b, vec3_p dir );
 +
 +#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[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 VectorCopy(a,b)			((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
 +
 +#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 CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
 +
 +#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
 +#define VectorSubtract4(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 VectorAdd4(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 VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
 +#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
 +#define	VectorMA4(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),(o)[3]=(v)[3]+(b)[3]*(s))
 +
 +
 +#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	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
 +
 +float NormalizeColor( vec3_c in, vec3_p out );
 +
 +int VectorCompare( vec3_c v1, vec3_c v2 );
 +float VectorLength( vec3_c v );
 +float Distance( vec3_c p1, vec3_c p2 );
 +float DistanceSquared( vec3_c p1, vec3_c p2 );
 +float VectorNormalize (vec3_p v);		// returns vector length
 +void VectorNormalizeFast(vec3_p v);		// does NOT return vector length, uses rsqrt approximation
 +float VectorNormalize2( vec3_c v, vec3_p out );
 +void VectorInverse (vec3_p v);
 +void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out );
 +void VectorPolar(vec3_p v, float radius, float theta, float phi);
 +void VectorSnap(vec3_p v);
 +void Vector53Copy( const idVec5_t &in, vec3_p out);
 +void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out);
 +void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out);
 +void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out);
 +void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out);
 +
 +
 +int Q_log2(int val);
 +
 +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))
 +
 +float Q_rint( float in );
 +
 +void vectoangles( vec3_c value1, angles_p angles);
 +void AnglesToAxis( angles_c angles, mat3_p axis );
 +
 +void AxisCopy( mat3_c in, mat3_p out );
 +qboolean AxisRotated( mat3_c in );			// assumes a non-degenerate axis
 +
 +int SignbitsForNormal( vec3_c normal );
 +int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p );
 +
 +float	AngleMod(float a);
 +float	LerpAngle (float from, float to, float frac);
 +float	AngleSubtract( float a1, float a2 );
 +void	AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 );
 +
 +float AngleNormalize360 ( float angle );
 +float AngleNormalize180 ( float angle );
 +float AngleDelta ( float angle1, float angle2 );
 +
 +qboolean PlaneFromPoints( vec4_t &plane, vec3_c a, vec3_c b, vec3_c c );
 +void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal );
 +void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees );
 +void RotateAroundDirection( mat3_p axis, float yaw );
 +void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up );
 +// perpendicular vector could be replaced by this
 +
 +int	PlaneTypeForNormal( vec3_c normal );
 +
 +void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out );
 +void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out );	// in2 is transposed during multiply
 +void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out );
 +void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system.
 +void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up);
 +void PerpendicularVector( vec3_p dst, vec3_c src );
 +
 +float TriangleArea( vec3_c a, vec3_c b, vec3_c c );
 +#endif										// __cplusplus
 +
 +//=============================================
 +
 +float Com_Clamp( float min, float max, float value );
 +
 +#define FILE_HASH_SIZE		1024
 +int Com_HashString( const char *fname );
 +
 +char	*Com_SkipPath( char *pathname );
 +
 +// it is ok for out == in
 +void	Com_StripExtension( const char *in, char *out );
 +
 +// "extension" should include the dot: ".map"
 +void	Com_DefaultExtension( char *path, int maxSize, const char *extension );
 +
 +int		Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] );
 +
 +/*
 +=====================================================================================
 +
 +SCRIPT PARSING
 +
 +=====================================================================================
 +*/
 +
 +// this just controls the comment printing, it doesn't actually load a file
 +void Com_BeginParseSession( const char *filename );
 +void Com_EndParseSession( void );
 +
 +int Com_GetCurrentParseLine( void );
 +
 +// Will never return NULL, just empty strings.
 +// An empty string will only be returned at end of file.
 +// ParseOnLine will return empty if there isn't another token on this line
 +
 +// this funny typedef just means a moving pointer into a const char * buffer
 +const char *Com_Parse( const char *(*data_p) );
 +const char *Com_ParseOnLine( const char *(*data_p) );
 +const char *Com_ParseRestOfLine( const char *(*data_p) );
 +
 +void Com_UngetToken( void );
 +
 +#ifdef __cplusplus
 +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse );
 +#else
 +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning );
 +#endif
 +
 +void Com_ScriptError( const char *msg, ... );
 +void Com_ScriptWarning( const char *msg, ... );
 +
 +void Com_SkipBracedSection( const char *(*program) );
 +void Com_SkipRestOfLine( const char *(*data) );
 +
 +float Com_ParseFloat( const char *(*buf_p) );
 +int	Com_ParseInt( const char *(*buf_p) );
 +
 +void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m );
 +void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m );
 +void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m );
 +
 +//=====================================================================================
 +#ifdef __cplusplus
 +	extern "C" {
 +#endif
 +
 +void	QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
 +
 +
 +// 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 );
 +
 +// 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 );
 +
 +int			Com_Filter( const char *filter, const char *name, int casesensitive );
 +const char *Com_StringContains( const char *str1, const char *str2, int casesensitive );
 +
 +
 +//=============================================
 +
 +short	BigShort(short l);
 +short	LittleShort(short l);
 +int		BigLong (int l);
 +int		LittleLong (int l);
 +float	BigFloat (float l);
 +float	LittleFloat (float l);
 +
 +void	Swap_Init (void);
 +char	* QDECL va(char *format, ...);
 +
 +#ifdef __cplusplus
 +    }
 +#endif
 +
 +
 +//=============================================
 +#ifdef __cplusplus
 +//
 +// mapfile parsing
 +//
 +typedef struct ePair_s {
 +	char	*key;
 +	char	*value;
 +} ePair_t;
 +
 +typedef struct mapSide_s {
 +	char		material[MAX_QPATH];
 +	vec4_t		plane;
 +	vec4_t		textureVectors[2];
 +} mapSide_t;
 +
 +typedef struct {
 +	int			numSides;
 +	mapSide_t	**sides;
 +} mapBrush_t;
 +
 +typedef struct {
 +	idVec3_t		xyz;
 +	float		st[2];
 +} patchVertex_t;
 +
 +typedef struct {
 +	char		material[MAX_QPATH];
 +	int			width, height;
 +	patchVertex_t	*patchVerts;
 +} mapPatch_t;
 +
 +typedef struct {
 +	char		modelName[MAX_QPATH];
 +	float		matrix[16];
 +} mapModel_t;
 +
 +typedef struct mapPrimitive_s {
 +	int				numEpairs;
 +	ePair_t			**ePairs;
 +
 +	// only one of these will be non-NULL
 +	mapBrush_t		*brush;
 +	mapPatch_t		*patch;
 +	mapModel_t		*model;
 +} mapPrimitive_t;
 +
 +typedef struct mapEntity_s {
 +	int				numPrimitives;
 +	mapPrimitive_t	**primitives;
 +
 +	int				numEpairs;
 +	ePair_t			**ePairs;
 +} mapEntity_t;
 +
 +typedef struct {
 +	int				numEntities;
 +	mapEntity_t		**entities;
 +} mapFile_t;
 +
 +
 +// the order of entities, brushes, and sides will be maintained, the
 +// lists won't be swapped on each load or save
 +mapFile_t *ParseMapFile( const char *text );
 +void FreeMapFile( mapFile_t *mapFile );
 +void WriteMapFile( const mapFile_t *mapFile, FILE *f );
 +
 +// key names are case-insensitive
 +const char 	*ValueForMapEntityKey( const mapEntity_t *ent, const char *key );
 +float	FloatForMapEntityKey( const mapEntity_t *ent, const char *key );
 +qboolean 	GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3_t &vec );
 +
 +typedef struct {
 +	idVec3_t		xyz;
 +	idVec2_t		st;
 +	idVec3_t		normal;
 +	idVec3_t		tangents[2];
 +	byte		smoothing[4];		// colors for silhouette smoothing
 +} drawVert_t;
 +
 +typedef struct {
 +	int			width, height;
 +	drawVert_t	*verts;
 +} drawVertMesh_t;
 +
 +// Tesselate a map patch into smoothed, drawable vertexes
 +// MaxError of around 4 is reasonable
 +drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError );
 +#endif			// __cplusplus
 +
 +//=========================================
 +
 +#ifdef __cplusplus
 +	extern "C" {
 +#endif
 +
 +void	QDECL Com_Error( int level, const char *error, ... );
 +void	QDECL Com_Printf( const char *msg, ... );
 +void	QDECL Com_DPrintf( const char *msg, ... );
 +
 +#ifdef __cplusplus
 +	}
 +#endif
 +
 +
 +typedef struct {
 +	qboolean	frameMemory;
 +	int		currentElements;
 +	int		maxElements;		// will reallocate and move when exceeded
 +	void	**elements;
 +} growList_t;
 +
 +// you don't need to init the growlist if you don't mind it growing and moving
 +// the list as it expands
 +void		Com_InitGrowList( growList_t *list, int maxElements );
 +int			Com_AddToGrowList( growList_t *list, void *data );
 +void		*Com_GrowListElement( const growList_t *list, int index );
 +int			Com_IndexForGrowListElement( const growList_t *list, const void *element );
 +
 +
 +//
 +// key / value info strings
 +//
 +char *Info_ValueForKey( const char *s, const char *key );
 +void Info_RemoveKey( char *s, const char *key );
 +void Info_SetValueForKey( char *s, const char *key, const char *value );
 +qboolean Info_Validate( const char *s );
 +void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] );
 +
 +// get cvar defs, collision defs, etc
 +//#include "../shared/interface.h"
 +
 +// get key code numbers for events
 +//#include "../shared/keycodes.h"
 +
 +#ifdef __cplusplus
 +// get the polygon winding functions
 +//#include "../shared/windings.h"
 +
 +// get the flags class
 +//#include "../shared/idflags.h"
 +#endif	// __cplusplus
 +
 +#endif	// __Q_SHARED_H
 +
 diff --git a/q3radiant/splines/splines.cpp b/q3radiant/splines/splines.cpp new file mode 100755 index 0000000..9c2b804 --- /dev/null +++ b/q3radiant/splines/splines.cpp @@ -0,0 +1,1244 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +
 +//#include "stdafx.h"
 +//#include "qe3.h"
 +
 +#include "q_shared.h"
 +#include "splines.h"
 +
 +extern "C" {
 +int FS_Write( const void *buffer, int len, fileHandle_t h );
 +int FS_ReadFile( const char *qpath, void **buffer );
 +void FS_FreeFile( void *buffer );
 +fileHandle_t FS_FOpenFileWrite( const char *filename );
 +void FS_FCloseFile( fileHandle_t f );
 +}
 +
 +float Q_fabs( float f ) {
 +	int tmp = * ( int * ) &f;
 +	tmp &= 0x7FFFFFFF;
 +	return * ( float * ) &tmp;
 +}
 +
 +
 +//#include "../shared/windings.h"
 +//#include "../qcommon/qcommon.h"
 +//#include "../sys/sys_public.h"
 +//#include "../game/game_entity.h"
 +
 +idCameraDef splineList;
 +idCameraDef *g_splineList = &splineList;
 +
 +idVec3_t idSplineList::zero(0,0,0);
 +
 +void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label) {
 +	qglColor3fv(color);
 +	qglPointSize(size);
 +	qglBegin(GL_POINTS);
 +	qglVertex3fv(point);
 +	qglEnd();
 +	idVec3_t v = point;
 +	v.x += 1;
 +	v.y += 1;
 +	v.z += 1;
 +	qglRasterPos3fv (v);
 +	qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);
 +}
 +
 +
 +void glBox(idVec3_t &color, idVec3_t &point, float size) {
 +	idVec3_t mins(point);
 +	idVec3_t maxs(point);
 +	mins[0] -= size;
 +	mins[1] += size;
 +	mins[2] -= size;
 +	maxs[0] += size;
 +	maxs[1] -= size;
 +	maxs[2] += size;
 +	qglColor3fv(color);
 +	qglBegin(GL_LINE_LOOP);
 +	qglVertex3f(mins[0],mins[1],mins[2]);
 +	qglVertex3f(maxs[0],mins[1],mins[2]);
 +	qglVertex3f(maxs[0],maxs[1],mins[2]);
 +	qglVertex3f(mins[0],maxs[1],mins[2]);
 +	qglEnd();
 +	qglBegin(GL_LINE_LOOP);
 +	qglVertex3f(mins[0],mins[1],maxs[2]);
 +	qglVertex3f(maxs[0],mins[1],maxs[2]);
 +	qglVertex3f(maxs[0],maxs[1],maxs[2]);
 +	qglVertex3f(mins[0],maxs[1],maxs[2]);
 +	qglEnd();
 +
 +	qglBegin(GL_LINES);
 +  	qglVertex3f(mins[0],mins[1],mins[2]);
 +	qglVertex3f(mins[0],mins[1],maxs[2]);
 +	qglVertex3f(mins[0],maxs[1],maxs[2]);
 +	qglVertex3f(mins[0],maxs[1],mins[2]);
 +	qglVertex3f(maxs[0],mins[1],mins[2]);
 +	qglVertex3f(maxs[0],mins[1],maxs[2]);
 +	qglVertex3f(maxs[0],maxs[1],maxs[2]);
 +	qglVertex3f(maxs[0],maxs[1],mins[2]);
 +	qglEnd();
 +
 +}
 +
 +void splineTest() {
 +	//g_splineList->load("p:/doom/base/maps/test_base1.camera");
 +}
 +
 +void splineDraw() {
 +	//g_splineList->addToRenderer();
 +}
 +
 +
 +//extern void D_DebugLine( const idVec3_t &color, const idVec3_t &start, const idVec3_t &end );
 +
 +void debugLine(idVec3_t &color, float x, float y, float z, float x2, float y2, float z2) {
 +	idVec3_t from(x, y, z);
 +	idVec3_t to(x2, y2, z2);
 +	//D_DebugLine(color, from, to);
 +}
 +
 +void idSplineList::addToRenderer() {
 +
 +	if (controlPoints.Num() == 0) {
 +		return;
 +	}
 +
 +	idVec3_t mins, maxs;
 +	idVec3_t yellow(1.0, 1.0, 0);
 +	idVec3_t white(1.0, 1.0, 1.0);
 +        int i;
 +        
 +	for(i = 0; i < controlPoints.Num(); i++) {
 +		VectorCopy(*controlPoints[i], mins);
 +		VectorCopy(mins, maxs);
 +		mins[0] -= 8;
 +		mins[1] += 8;
 +		mins[2] -= 8;
 +		maxs[0] += 8;
 +		maxs[1] -= 8;
 +		maxs[2] += 8;
 +		debugLine( yellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]);
 +		debugLine( yellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]);
 +		debugLine( yellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]);
 +		debugLine( yellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]);
 +		
 +		debugLine( yellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]);
 +		debugLine( yellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]);
 +		debugLine( yellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]);
 +		debugLine( yellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]);
 +	    
 +	}
 +
 +	int step = 0;
 +	idVec3_t step1;
 +	for(i = 3; i < controlPoints.Num(); i++) {
 +		for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) {
 +			float x = 0;
 +			float y = 0;
 +			float z = 0;
 +			for (int j = 0; j < 4; j++) {
 +				x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
 +				y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
 +				z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
 +			}
 +			if (step == 0) {
 +				step1[0] = x;
 +				step1[1] = y;
 +				step1[2] = z;
 +				step = 1;
 +			} else {
 +				debugLine( white, step1[0], step1[1], step1[2], x, y, z);
 +				step = 0;
 +			}
 +
 +		}
 +	}
 +}
 +
 +void idSplineList::buildSpline() {
 +	//int start = Sys_Milliseconds();
 +	clearSpline();
 +	for(int i = 3; i < controlPoints.Num(); i++) {
 +		for (float tension = 0.0f; tension < 1.001f; tension += granularity) {
 +			float x = 0;
 +			float y = 0;
 +			float z = 0;
 +			for (int j = 0; j < 4; j++) {
 +				x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
 +				y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
 +				z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
 +			}
 +			splinePoints.Append(new idVec3_t(x, y, z));
 +		}
 +	}
 +	dirty = false;
 +	//Com_Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000);
 +}
 +
 +
 +void idSplineList::draw(bool editMode) {
 +	int i;
 +	vec4_t yellow(1, 1, 0, 1);
 +        
 +	if (controlPoints.Num() == 0) {
 +		return;
 +	}
 +
 +	if (dirty) {
 +		buildSpline();
 +	}
 +
 +
 +	qglColor3fv(controlColor);
 +	qglPointSize(5);
 +	
 +	qglBegin(GL_POINTS);
 +	for (i = 0; i < controlPoints.Num(); i++) {
 +		qglVertex3fv(*controlPoints[i]);
 +	}
 +	qglEnd();
 +	
 +	if (editMode) {
 +		for(i = 0; i < controlPoints.Num(); i++) {
 +			glBox(activeColor, *controlPoints[i], 4);
 +		}
 +	}
 +
 +	//Draw the curve
 +	qglColor3fv(pathColor);
 +	qglBegin(GL_LINE_STRIP);
 +	int count = splinePoints.Num();
 +	for (i = 0; i < count; i++) {
 +		qglVertex3fv(*splinePoints[i]);
 +	}
 +	qglEnd();
 +
 +	if (editMode) {
 +		qglColor3fv(segmentColor);
 +		qglPointSize(3);
 +		qglBegin(GL_POINTS);
 +		for (i = 0; i < count; i++) {
 +			qglVertex3fv(*splinePoints[i]);
 +		}
 +		qglEnd();
 +	}
 +	if (count > 0) {
 +		//assert(activeSegment >=0 && activeSegment < count);
 +		if (activeSegment >=0 && activeSegment < count) {
 +			glBox(activeColor, *splinePoints[activeSegment], 6);
 +			glBox(yellow, *splinePoints[activeSegment], 8);
 +		}
 +	}
 +
 +}
 +
 +float idSplineList::totalDistance() {
 +
 +	if (controlPoints.Num() == 0) {
 +		return 0.0;
 +	}
 +
 +	if (dirty) {
 +		buildSpline();
 +	}
 +
 +	float dist = 0.0;
 +	idVec3_t temp;
 +	int count = splinePoints.Num();
 +	for(int i = 1; i < count; i++) {
 +		temp = *splinePoints[i-1];
 +		temp -= *splinePoints[i];
 +		dist += temp.Length();
 +	}
 +	return dist;
 +}
 +
 +void idSplineList::initPosition(long bt, long totalTime) {
 +
 +	if (dirty) {
 +		buildSpline();
 +	}
 +
 +	if (splinePoints.Num() == 0) {
 +		return;
 +	}
 +
 +	baseTime = bt;
 +	time = totalTime;
 +
 +	// calc distance to travel ( this will soon be broken into time segments )
 +	splineTime.Clear();
 +	splineTime.Append(0);
 +	float dist = totalDistance();
 +	float distSoFar = 0.0;
 +	idVec3_t temp;
 +	int count = splinePoints.Num();
 +	//for(int i = 2; i < count - 1; i++) {
 +	for(int i = 1; i < count; i++) {
 +		temp = *splinePoints[i-1];
 +		temp -= *splinePoints[i];
 +		distSoFar += temp.Length();
 +		float percent = distSoFar / dist;
 +		percent *= totalTime;
 +		splineTime.Append(percent + bt);
 +	}
 +	assert(splineTime.Num() == splinePoints.Num());
 +	activeSegment = 0;
 +}
 +
 +
 +
 +float idSplineList::calcSpline(int step, float tension) {
 +	switch(step) {
 +		case 0:	return (pow(1 - tension, 3)) / 6;
 +		case 1:	return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6;
 +		case 2:	return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6;
 +		case 3:	return pow(tension, 3) / 6;
 +	}
 +	return 0.0;
 +}
 +
 +
 +
 +void idSplineList::updateSelection(const idVec3_t &move) {
 +	if (selected) {
 +		dirty = true;
 +		VectorAdd(*selected, move, *selected);
 +	}
 +}
 +
 +
 +void idSplineList::setSelectedPoint(idVec3_t *p) {
 +	if (p) {
 +		p->Snap();
 +		for(int i = 0; i < controlPoints.Num(); i++) {
 +			if (*p == *controlPoints[i]) {
 +				selected = controlPoints[i];
 +			}
 +		}
 +	} else {
 +		selected = NULL;
 +	}
 +}
 +
 +const idVec3_t *idSplineList::getPosition(long t) {
 +	static idVec3_t interpolatedPos;
 +
 +	int count = splineTime.Num();
 +	if (count == 0) {
 +		return &zero;
 +	}
 +
 +	assert(splineTime.Num() == splinePoints.Num());
 +
 +	while (activeSegment < count) {
 +		if (splineTime[activeSegment] >= t) {
 +			if (activeSegment > 0 && activeSegment < count - 1) {
 +				float timeHi = splineTime[activeSegment + 1];
 +				float timeLo = splineTime[activeSegment - 1];
 +				//float percent = (float)(baseTime + time - t) / time;
 +				float percent = (timeHi - t) / (timeHi - timeLo); 
 +				// pick two bounding points
 +				idVec3_t v1 = *splinePoints[activeSegment-1];
 +				idVec3_t v2 = *splinePoints[activeSegment+1];
 +				v2 *= (1.0 - percent);
 +				v1 *= percent;
 +				v2 += v1;
 +				interpolatedPos = v2;
 +				return &interpolatedPos;
 +			}
 +			return splinePoints[activeSegment];
 +		} else {
 +			activeSegment++;
 +		}
 +	}
 +	return splinePoints[count-1];
 +}
 +
 +void idSplineList::parse(const char *(*text)  ) {
 +	const char *token;
 +	//Com_MatchToken( text, "{" );
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !Q_stricmp (token, "}") ) {
 +			break;
 +		}
 +
 +		do {
 +			// if token is not a brace, it is a key for a key/value pair
 +			if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) {
 +				break;
 +			}
 +
 +			Com_UngetToken();
 +			idStr key = Com_ParseOnLine(text);
 +			const char *token = Com_Parse(text);
 +			if (Q_stricmp(key.c_str(), "granularity") == 0) {
 +				granularity = atof(token);
 +			} else if (Q_stricmp(key.c_str(), "name") == 0) {
 +				name = token;
 +			}
 +			token = Com_Parse(text);
 +
 +		} while (1);
 +
 +		if ( !Q_stricmp (token, "}") ) {
 +			break;
 +		}
 +
 +		Com_UngetToken();
 +		// read the control point
 +		idVec3_t point;
 +		Com_Parse1DMatrix( text, 3, point );
 +		addPoint(point.x, point.y, point.z);
 +	} while (1);
 + 
 +	//Com_UngetToken();
 +	//Com_MatchToken( text, "}" );
 +	dirty = true;
 +}
 +
 +void idSplineList::write(fileHandle_t file, const char *p) {
 +	idStr s = va("\t\t%s {\n", p);
 +	FS_Write(s.c_str(), s.length(), file);
 +	//s = va("\t\tname %s\n", name.c_str());
 +	//FS_Write(s.c_str(), s.length(), file);
 +	s = va("\t\t\tgranularity %f\n", granularity);
 +	FS_Write(s.c_str(), s.length(), file);
 +	int count = controlPoints.Num();
 +	for (int i = 0; i < count; i++) {
 +		s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z);
 +		FS_Write(s.c_str(), s.length(), file);
 +	}
 +	s = "\t\t}\n";
 +	FS_Write(s.c_str(), s.length(), file);
 +}
 +
 +
 +void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) {
 +#if 0
 +	if (!cameraSpline.validTime()) {
 +		buildCamera();
 +	}
 +	double d = (double)segment / numSegments();
 +	getCameraInfo(d * totalTime * 1000, origin, direction, fov);
 +#endif
 +/*
 +	if (!cameraSpline.validTime()) {
 +		buildCamera();
 +	}
 +	origin = *cameraSpline.getSegmentPoint(segment);
 +	
 +
 +	idVec3_t temp;
 +
 +	int numTargets = getTargetSpline()->controlPoints.Num();
 +	int count = cameraSpline.splineTime.Num();
 +	if (numTargets == 0) {
 +		// follow the path
 +		if (cameraSpline.getActiveSegment() < count - 1) {
 +			temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
 +		}
 +	} else if (numTargets == 1) {
 +		temp = *getTargetSpline()->controlPoints[0];
 +	} else {
 +		temp = *getTargetSpline()->getSegmentPoint(segment);
 +	}
 +
 +	temp -= origin;
 +	temp.Normalize();
 +	direction = temp;
 +*/
 +}
 +
 +bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) {
 +
 +
 +	if ((time - startTime) / 1000 > totalTime) {
 +		return false;
 +	}
 +
 +
 +	for (int i = 0; i < events.Num(); i++) {
 +		if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
 +			events[i]->setTriggered(true);
 +			if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
 +				setActiveTargetByName(events[i]->getParam());
 +				getActiveTarget()->start(startTime + events[i]->getTime());
 +				//Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam());
 +			} else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
 +				//idEntity *ent = NULL;
 +				//ent = level.FindTarget( ent, events[i]->getParam());
 +				//if (ent) {
 +				//	ent->signal( SIG_TRIGGER );
 +				//	ent->ProcessEvent( &EV_Activate, world );
 +				//}
 +			} else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
 +				//*fv = fov = atof(events[i]->getParam());
 +			} else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
 +				return false;
 +			}
 +		}
 +	}
 +
 +	origin = *cameraPosition->getPosition(time);
 +	
 +	*fv = fov.getFOV(time);
 +
 +	idVec3_t temp = origin;
 +
 +	int numTargets = targetPositions.Num();
 +	if (numTargets == 0) {
 +/*
 +		// follow the path
 +		if (cameraSpline.getActiveSegment() < count - 1) {
 +			temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
 +			if (temp == origin) {
 +				int index = cameraSpline.getActiveSegment() + 2;
 +				while (temp == origin && index < count - 1) {
 +					temp = *cameraSpline.splinePoints[index++];
 +				}
 +			}
 +		}
 +*/
 +	} else {
 +		temp = *getActiveTarget()->getPosition(time);
 +	}
 +	
 +	temp -= origin;
 +	temp.Normalize();
 +	direction = temp;
 +
 +	return true;
 +}
 +
 +bool idCameraDef::waitEvent(int index) {
 +	//for (int i = 0; i < events.Num(); i++) {
 +	//	if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
 +	//		return true;
 +	//	}
 +    //}
 +	return false;
 +}
 +
 +
 +#define NUM_CCELERATION_SEGS 10
 +#define CELL_AMT 5
 +
 +void idCameraDef::buildCamera() {
 +	int i;
 +	int lastSwitch = 0;
 +	idList<float> waits;
 +	idList<int> targets;
 +
 +	totalTime = baseTime;
 +	cameraPosition->setTime(totalTime * 1000);
 +	// we have a base time layout for the path and the target path
 +	// now we need to layer on any wait or speed changes
 +	for (i = 0; i < events.Num(); i++) {
 +		idCameraEvent *ev = events[i];
 +		events[i]->setTriggered(false);
 +		switch (events[i]->getType()) {
 +			case idCameraEvent::EVENT_TARGET : {
 +				targets.Append(i);
 +				break;
 +			}
 +			case idCameraEvent::EVENT_WAIT : {
 +				waits.Append(atof(events[i]->getParam()));
 +				cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
 +				break;
 +			}
 +			case idCameraEvent::EVENT_TARGETWAIT : {
 +				//targetWaits.Append(i);
 +				break;
 +			}
 +			case idCameraEvent::EVENT_SPEED : {
 +/*
 +				// take the average delay between up to the next five segments
 +				float adjust = atof(events[i]->getParam());
 +				int index = events[i]->getSegment();
 +				total = 0;
 +				count = 0;
 +
 +				// get total amount of time over the remainder of the segment
 +				for (j = index; j < cameraSpline.numSegments() - 1; j++) {
 +					total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
 +					count++;
 +				}
 +
 +				// multiply that by the adjustment
 +				double newTotal = total * adjust;
 +				// what is the difference.. 
 +				newTotal -= total;
 +				totalTime += newTotal / 1000;
 +
 +				// per segment difference
 +				newTotal /= count;
 +				int additive = newTotal;
 +
 +				// now propogate that difference out to each segment
 +				for (j = index; j < cameraSpline.numSegments(); j++) {
 +					cameraSpline.addSegmentTime(j, additive);
 +					additive += newTotal;
 +				}
 +				break;
 +*/
 +			}
 +		}
 +	}
 +
 +
 +	for (i = 0; i < waits.Num(); i++) {
 +		totalTime += waits[i];
 +	}
 +
 +	// on a new target switch, we need to take time to this point ( since last target switch ) 
 +	// and allocate it across the active target, then reset time to this point
 +	long timeSoFar = 0;
 +	long total = totalTime * 1000;
 +	for (i = 0; i < targets.Num(); i++) {
 +		long t;
 +		if (i < targets.Num() - 1) {
 +			t = events[targets[i+1]]->getTime();
 +		} else {
 +			t = total - timeSoFar;
 +		}
 +		// t is how much time to use for this target
 +		setActiveTargetByName(events[targets[i]]->getParam());
 +		getActiveTarget()->setTime(t);
 +		timeSoFar += t;
 +	}
 +
 +	
 +}
 +
 +void idCameraDef::startCamera(long t) {
 +	buildCamera();
 +	cameraPosition->start(t);
 +	//for (int i = 0; i < targetPositions.Num(); i++) {
 +	//	targetPositions[i]->
 +	//}
 +	startTime = t;
 +	cameraRunning = true;
 +}
 +
 +
 +void idCameraDef::parse(const char *(*text)  ) {
 +
 +	const char	*token;
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !Q_stricmp (token, "}") ) {
 +			break;
 +		}
 +
 +		if (Q_stricmp(token, "time") == 0) {
 +			baseTime = Com_ParseFloat(text);
 +		}
 +
 +		if (Q_stricmp(token, "camera_fixed") == 0) {
 +			cameraPosition = new idFixedPosition();
 +			cameraPosition->parse(text);
 +		}
 +
 +		if (Q_stricmp(token, "camera_interpolated") == 0) {
 +			cameraPosition = new idInterpolatedPosition();
 +			cameraPosition->parse(text);
 +		}
 +
 +		if (Q_stricmp(token, "camera_spline") == 0) {
 +			cameraPosition = new idSplinePosition();
 +			cameraPosition->parse(text);
 +		}
 +
 +		if (Q_stricmp(token, "target_fixed") == 0) {
 +			idFixedPosition *pos = new idFixedPosition();
 +			pos->parse(text);
 +			targetPositions.Append(pos);
 +		}
 +		
 +		if (Q_stricmp(token, "target_interpolated") == 0) {
 +			idInterpolatedPosition *pos = new idInterpolatedPosition();
 +			pos->parse(text);
 +			targetPositions.Append(pos);
 +		}
 +
 +		if (Q_stricmp(token, "target_spline") == 0) {
 +			idSplinePosition *pos = new idSplinePosition();
 +			pos->parse(text);
 +			targetPositions.Append(pos);
 +		}
 +
 +		if (Q_stricmp(token, "fov") == 0) {
 +			fov.parse(text);
 +		}
 +
 +		if (Q_stricmp(token, "event") == 0) {
 +			idCameraEvent *event = new idCameraEvent();
 +			event->parse(text);
 +			addEvent(event);
 +		}
 +
 +
 +	} while (1);
 +
 +	Com_UngetToken();
 +	Com_MatchToken( text, "}" );
 +
 +}
 +
 +bool idCameraDef::load(const char *filename) {
 +	char *buf;
 +	const char *buf_p;
 +	int length = FS_ReadFile( filename, (void **)&buf );
 +	if ( !buf ) {
 +		return false;
 +	}
 +
 +	clear();
 +	Com_BeginParseSession( filename );
 +	buf_p = buf;
 +	parse(&buf_p);
 +	Com_EndParseSession();
 +	FS_FreeFile( buf );
 +
 +	return true;
 +}
 +
 +void idCameraDef::save(const char *filename) {
 +	fileHandle_t file = FS_FOpenFileWrite(filename);
 +	if (file) {
 +		int i;
 +		idStr s = "cameraPathDef { \n"; 
 +		FS_Write(s.c_str(), s.length(), file);
 +		s = va("\ttime %f\n", baseTime);
 +		FS_Write(s.c_str(), s.length(), file);
 +
 +		cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr()));
 +
 +		for (i = 0; i < numTargets(); i++) {
 +			targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr()));
 +		}
 +
 +		for (i = 0; i < events.Num(); i++) {
 +			events[i]->write(file, "event");
 +		}
 +
 +		fov.write(file, "fov");
 +
 +		s = "}\n";
 +		FS_Write(s.c_str(), s.length(), file);
 +	}
 +	FS_FCloseFile(file);
 +}
 +
 +int idCameraDef::sortEvents(const void *p1, const void *p2) {
 +	idCameraEvent *ev1 = (idCameraEvent*)(p1);
 +	idCameraEvent *ev2 = (idCameraEvent*)(p2);
 +
 +	if (ev1->getTime() > ev2->getTime()) {
 +		return -1;
 +	}
 +	if (ev1->getTime() < ev2->getTime()) {
 +		return 1;
 +	}
 +	return 0; 
 +}
 +
 +void idCameraDef::addEvent(idCameraEvent *event) {
 +	events.Append(event);
 +	//events.Sort(&sortEvents);
 +
 +}
 +void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
 +	addEvent(new idCameraEvent(t, param, time));
 +	buildCamera();
 +}
 +
 +
 +const char *idCameraEvent::eventStr[] = {
 +	"NA",
 +	"WAIT",
 +	"TARGETWAIT",
 +	"SPEED",
 +	"TARGET",
 +	"SNAPTARGET",
 +	"FOV",
 +	"SCRIPT",
 +	"TRIGGER",
 +	"STOP"
 +};
 +
 +void idCameraEvent::parse(const char *(*text)  ) {
 +	const char *token;
 +	Com_MatchToken( text, "{" );
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +		// here we may have to jump over brush epairs ( only used in editor )
 +		do {
 +			// if token is not a brace, it is a key for a key/value pair
 +			if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
 +				break;
 +			}
 +
 +			Com_UngetToken();
 +			idStr key = Com_ParseOnLine(text);
 +			const char *token = Com_Parse(text);
 +			if (Q_stricmp(key.c_str(), "type") == 0) {
 +				type = static_cast<idCameraEvent::eventType>(atoi(token));
 +			} else if (Q_stricmp(key.c_str(), "param") == 0) {
 +				paramStr = token;
 +			} else if (Q_stricmp(key.c_str(), "time") == 0) {
 +				time = atoi(token);
 +			}
 +			token = Com_Parse(text);
 +
 +		} while (1);
 +
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +	} while (1);
 + 
 +	Com_UngetToken();
 +	Com_MatchToken( text, "}" );
 +}
 +
 +void idCameraEvent::write(fileHandle_t file, const char *name) {
 +	idStr s = va("\t%s {\n", name);
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = va("\t\ttype %d\n", static_cast<int>(type));
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = va("\t\tparam %s\n", paramStr.c_str());
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = va("\t\ttime %d\n", time);
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = "\t}\n";
 +	FS_Write(s.c_str(), s.length(), file);
 +}
 +
 +
 +const char *idCameraPosition::positionStr[] = {
 +	"Fixed",
 +	"Interpolated",
 +	"Spline",
 +};
 +
 +
 +
 +const idVec3_t *idInterpolatedPosition::getPosition(long t) { 
 +	static idVec3_t interpolatedPos;
 +
 +	float velocity = getVelocity(t);
 +	float timePassed = t - lastTime;
 +	lastTime = t;
 +
 +	// convert to seconds	
 +	timePassed /= 1000;
 +
 +	float distToTravel = timePassed *= velocity;
 +
 +	idVec3_t temp = startPos;
 +	temp -= endPos;
 +	float distance = temp.Length();
 +
 +	distSoFar += distToTravel;
 +	float percent = (float)(distSoFar) / distance;
 +
 +	if (percent > 1.0) {
 +		percent = 1.0;
 +	} else if (percent < 0.0) {
 +		percent = 0.0;
 +	}
 +
 +	// the following line does a straigt calc on percentage of time
 +	// float percent = (float)(startTime + time - t) / time;
 +
 +	idVec3_t v1 = startPos;
 +	idVec3_t v2 = endPos;
 +	v1 *= (1.0 - percent);
 +	v2 *= percent;
 +	v1 += v2;
 +	interpolatedPos = v1;
 +	return &interpolatedPos;
 +}
 +
 +
 +void idCameraFOV::parse(const char *(*text)  ) {
 +	const char *token;
 +	Com_MatchToken( text, "{" );
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +		// here we may have to jump over brush epairs ( only used in editor )
 +		do {
 +			// if token is not a brace, it is a key for a key/value pair
 +			if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
 +				break;
 +			}
 +
 +			Com_UngetToken();
 +			idStr key = Com_ParseOnLine(text);
 +			const char *token = Com_Parse(text);
 +			if (Q_stricmp(key.c_str(), "fov") == 0) {
 +				fov = atof(token);
 +			} else if (Q_stricmp(key.c_str(), "startFOV") == 0) {
 +				startFOV = atof(token);
 +			} else if (Q_stricmp(key.c_str(), "endFOV") == 0) {
 +				endFOV = atof(token);
 +			} else if (Q_stricmp(key.c_str(), "time") == 0) {
 +				time = atoi(token);
 +			}
 +			token = Com_Parse(text);
 +
 +		} while (1);
 +
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +	} while (1);
 + 
 +	Com_UngetToken();
 +	Com_MatchToken( text, "}" );
 +}
 +
 +bool idCameraPosition::parseToken(const char *key, const char *(*text)) {
 +	const char *token = Com_Parse(text);
 +	if (Q_stricmp(key, "time") == 0) {
 +		time = atol(token);
 +		return true;
 +	} else if (Q_stricmp(key, "type") == 0) {
 +		type = static_cast<idCameraPosition::positionType>(atoi(token));
 +		return true;
 +	} else if (Q_stricmp(key, "velocity") == 0) {
 +		long t = atol(token);
 +		token = Com_Parse(text);
 +		long d = atol(token);
 +		token = Com_Parse(text);
 +		float s = atof(token);
 +		addVelocity(t, d, s);
 +		return true;
 +	} else if (Q_stricmp(key, "baseVelocity") == 0) {
 +		baseVelocity = atof(token);
 +		return true;
 +	} else if (Q_stricmp(key, "name") == 0) {
 +		name = token;
 +		return true;
 +	} else if (Q_stricmp(key, "time") == 0) {
 +		time = atoi(token);
 +		return true;
 +	}
 +	Com_UngetToken();
 +	return false;
 +}
 +
 +
 +
 +void idFixedPosition::parse(const char *(*text)  ) {
 +	const char *token;
 +	Com_MatchToken( text, "{" );
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +		// here we may have to jump over brush epairs ( only used in editor )
 +		do {
 +			// if token is not a brace, it is a key for a key/value pair
 +			if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
 +				break;
 +			}
 +
 +			Com_UngetToken();
 +			idStr key = Com_ParseOnLine(text);
 +			
 +			const char *token = Com_Parse(text);
 +			if (Q_stricmp(key.c_str(), "pos") == 0) {
 +				Com_UngetToken();
 +				Com_Parse1DMatrix( text, 3, pos );
 +			} else {
 +				Com_UngetToken();
 +				idCameraPosition::parseToken(key.c_str(), text);	
 +			}
 +			token = Com_Parse(text);
 +
 +		} while (1);
 +
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +	} while (1);
 + 
 +	Com_UngetToken();
 +	Com_MatchToken( text, "}" );
 +}
 +
 +void idInterpolatedPosition::parse(const char *(*text)  ) {
 +	const char *token;
 +	Com_MatchToken( text, "{" );
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +		// here we may have to jump over brush epairs ( only used in editor )
 +		do {
 +			// if token is not a brace, it is a key for a key/value pair
 +			if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
 +				break;
 +			}
 +
 +			Com_UngetToken();
 +			idStr key = Com_ParseOnLine(text);
 +			
 +			const char *token = Com_Parse(text);
 +			if (Q_stricmp(key.c_str(), "startPos") == 0) {
 +				Com_UngetToken();
 +				Com_Parse1DMatrix( text, 3, startPos );
 +			} else if (Q_stricmp(key.c_str(), "endPos") == 0) {
 +				Com_UngetToken();
 +				Com_Parse1DMatrix( text, 3, endPos );
 +			} else {
 +				Com_UngetToken();
 +				idCameraPosition::parseToken(key.c_str(), text);	
 +			}
 +			token = Com_Parse(text);
 +
 +		} while (1);
 +
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +	} while (1);
 + 
 +	Com_UngetToken();
 +	Com_MatchToken( text, "}" );
 +}
 +
 +
 +void idSplinePosition::parse(const char *(*text)  ) {
 +	const char *token;
 +	Com_MatchToken( text, "{" );
 +	do {
 +		token = Com_Parse( text );
 +	
 +		if ( !token[0] ) {
 +			break;
 +		}
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +		// here we may have to jump over brush epairs ( only used in editor )
 +		do {
 +			// if token is not a brace, it is a key for a key/value pair
 +			if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
 +				break;
 +			}
 +
 +			Com_UngetToken();
 +			idStr key = Com_ParseOnLine(text);
 +			
 +			const char *token = Com_Parse(text);
 +			if (Q_stricmp(key.c_str(), "target") == 0) {
 +				target.parse(text);
 +			} else {
 +				Com_UngetToken();
 +				idCameraPosition::parseToken(key.c_str(), text);	
 +			}
 +			token = Com_Parse(text);
 +
 +		} while (1);
 +
 +		if ( !strcmp (token, "}") ) {
 +			break;
 +		}
 +
 +	} while (1);
 + 
 +	Com_UngetToken();
 +	Com_MatchToken( text, "}" );
 +}
 +
 +
 +
 +void idCameraFOV::write(fileHandle_t file, const char *p) {
 +	idStr s = va("\t%s {\n", p);
 +	FS_Write(s.c_str(), s.length(), file);
 +	
 +	s = va("\t\tfov %f\n", fov);
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = va("\t\tstartFOV %f\n", startFOV);
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = va("\t\tendFOV %f\n", endFOV);
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = va("\t\ttime %i\n", time);
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = "\t}\n";
 +	FS_Write(s.c_str(), s.length(), file);
 +}
 +
 +
 +void idCameraPosition::write(fileHandle_t file, const char *p) {
 +	
 +	idStr s = va("\t\ttime %i\n", time);
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = va("\t\ttype %i\n", static_cast<int>(type));
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = va("\t\tname %s\n", name.c_str());
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	s = va("\t\tbaseVelocity %f\n", baseVelocity);
 +	FS_Write(s.c_str(), s.length(), file);
 +
 +	for (int i = 0; i < velocities.Num(); i++) {
 +		s = va("\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed);
 +		FS_Write(s.c_str(), s.length(), file);
 +	}
 +
 +}
 +
 +void idFixedPosition::write(fileHandle_t file, const char *p) {
 +	idStr s = va("\t%s {\n", p);
 +	FS_Write(s.c_str(), s.length(), file);
 +	idCameraPosition::write(file, p);
 +	s = va("\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z);
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = "\t}\n";
 +	FS_Write(s.c_str(), s.length(), file);
 +}
 +
 +void idInterpolatedPosition::write(fileHandle_t file, const char *p) {
 +	idStr s = va("\t%s {\n", p);
 +	FS_Write(s.c_str(), s.length(), file);
 +	idCameraPosition::write(file, p);
 +	s = va("\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z);
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = va("\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z);
 +	FS_Write(s.c_str(), s.length(), file);
 +	s = "\t}\n";
 +	FS_Write(s.c_str(), s.length(), file);
 +}
 +
 +void idSplinePosition::write(fileHandle_t file, const char *p) {
 +	idStr s = va("\t%s {\n", p);
 +	FS_Write(s.c_str(), s.length(), file);
 +	idCameraPosition::write(file, p);
 +	target.write(file, "target");
 +	s = "\t}\n";
 +	FS_Write(s.c_str(), s.length(), file);
 +}
 +
 +void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) {
 +	const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name;
 +	idCameraPosition *pos = newFromType(type);
 +	if (pos) {
 +		pos->setName(name);
 +		targetPositions.Append(pos);
 +		activeTarget = numTargets()-1;
 +		if (activeTarget == 0) {
 +			// first one
 +			addEvent(idCameraEvent::EVENT_TARGET, name, 0);
 +		}
 +	}
 +}
 +
 +
 +
 +idCameraDef camera;
 +
 +extern "C" {
 +qboolean loadCamera(const char *name) {
 +  camera.clear();
 +  return static_cast<qboolean>(camera.load(name));
 +}
 +
 +qboolean getCameraInfo(int time, float *origin, float*angles) {
 +	idVec3_t dir, org;
 +	org[0] = origin[0];
 +	org[1] = origin[1];
 +	org[2] = origin[2];
 +	float fov = 90;
 +	if (camera.getCameraInfo(time, org, dir, &fov)) {
 +		origin[0] = org[0];
 +		origin[1] = org[1];
 +		origin[2] = org[2];
 +		angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
 +		angles[0] = asin (dir[2])*180/3.14159;
 +		return qtrue;
 +	}
 +	return qfalse;
 +}
 +
 +void startCamera(int time) {
 +	camera.startCamera(time);
 +}
 +
 +}
 +
 +
 diff --git a/q3radiant/splines/splines.h b/q3radiant/splines/splines.h new file mode 100755 index 0000000..1cd0d58 --- /dev/null +++ b/q3radiant/splines/splines.h @@ -0,0 +1,1080 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __SPLINES_H
 +#define __SPLINES_H
 +
 +extern "C" {
 +#ifdef Q3RADIANT
 +#include "../qgl.h"
 +#else
 +#include "../renderer/qgl.h"
 +#endif
 +}
 +#include "util_list.h"
 +#include "util_str.h"
 +#include "math_vector.h"
 +
 +typedef int fileHandle_t;
 +
 +extern void glBox(idVec3_t &color, idVec3_t &point, float size);
 +extern void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label);
 +
 +static vec4_t blue(0, 0, 1, 1);
 +static vec4_t red(1, 0, 0, 1);
 +
 +class idPointListInterface {
 +public:
 +	idPointListInterface() {
 +		selectedPoints.Clear();
 +	};
 +	~idPointListInterface() {};
 +	
 +	virtual int numPoints() {
 +		return 0;
 +	}
 +	
 +	virtual void addPoint(const float x, const float y, const float z) {}
 +	virtual void addPoint(const idVec3_t &v) {}
 +	virtual void removePoint(int index) {}
 +	virtual idVec3_t *getPoint(int index) { return NULL; }
 +	
 +	int	selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
 +		idVec3_t origin(ox, oy, oz);
 +		idVec3_t dir(dx, dy, dz);
 +		return selectPointByRay(origin, dir, single);
 +	}
 +
 +	int	selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) {
 +		int		i, besti, count;
 +		float	d, bestd;
 +		idVec3_t	temp, temp2;
 +
 +		// find the point closest to the ray
 +		besti = -1;
 +		bestd = 8;
 +		count = numPoints();
 +
 +		for (i=0; i < count; i++) {
 +			temp = *getPoint(i);
 +			temp2 = temp;
 +			temp -= origin;
 +			d = DotProduct(temp, direction);
 +			__VectorMA (origin, d, direction, temp);
 +			temp2 -= temp;
 +			d = temp2.Length();
 +			if (d <= bestd) {
 +				bestd = d;
 +				besti = i;
 +			}
 +		}
 +
 +		if (besti >= 0) {
 +			selectPoint(besti, single);
 +		}
 +
 +		return besti;
 +	}
 +
 +	int isPointSelected(int index) {
 +		int count = selectedPoints.Num();
 +		for (int i = 0; i < count; i++) {
 +			if (selectedPoints[i] == index) {
 +				return i;
 +			}
 +		}
 +		return -1;
 +	}
 +	
 +	int selectPoint(int index, bool single) {
 +		if (index >= 0 && index < numPoints()) {
 +			if (single) {
 +				deselectAll();
 +			} else {
 +				if (isPointSelected(index) >= 0) {
 +					selectedPoints.Remove(index);
 +				}
 +			}
 +			return selectedPoints.Append(index);
 +		}
 +		return -1;
 +	}
 +	
 +	void selectAll() {
 +		selectedPoints.Clear();
 +		for (int i = 0; i < numPoints(); i++) {
 +			selectedPoints.Append(i);
 +		}
 +	}
 +
 +	void deselectAll() {
 +		selectedPoints.Clear();
 +	}
 +
 +	int numSelectedPoints();
 +    
 +	idVec3_t *getSelectedPoint(int index) {
 +		assert(index >= 0 && index < numSelectedPoints());
 +		return getPoint(selectedPoints[index]);
 +	}
 +	
 +	virtual void updateSelection(float x, float y, float z) {
 +		idVec3_t move(x, y, z);
 +		updateSelection(move);
 +	}
 +
 +	virtual void updateSelection(const idVec3_t &move) {
 +		int count = selectedPoints.Num();
 +		for (int i = 0; i < count; i++) {
 +			*getPoint(selectedPoints[i]) += move;
 +		}
 +	}
 +
 +	void drawSelection() {
 +		int count = selectedPoints.Num();
 +		for (int i = 0; i < count; i++) {
 +			glBox(red, *getPoint(selectedPoints[i]), 4);
 +		}
 +	}
 +
 +protected:
 +	idList<int> selectedPoints;
 +
 +};
 +
 +
 +class idSplineList {
 +
 +public:
 +
 +	idSplineList() {
 +		clear();
 +	}
 +
 +	idSplineList(const char *p) {
 +		clear();
 +		name = p;
 +	};
 +
 +	~idSplineList() {
 +		clear();
 +	};
 +
 +	void clearControl() {
 +		for (int i = 0; i < controlPoints.Num(); i++) {
 +			delete controlPoints[i];
 +		}
 +		controlPoints.Clear();
 +	}
 +
 +	void clearSpline() {
 +		for (int i = 0; i < splinePoints.Num(); i++) {
 +			delete splinePoints[i];
 +		}
 +		splinePoints.Clear();
 +	}
 +
 +	void parse(const char *(*text));
 +	void write(fileHandle_t file, const char *name);
 +
 +	void clear() {
 +		clearControl();
 +		clearSpline();
 +		splineTime.Clear();
 +		selected = NULL;
 +		dirty = true;
 +		activeSegment = 0;
 +		granularity = 0.025;
 +		pathColor.set(1.0, 0.5, 0.0);
 +		controlColor.set(0.7, 0.0, 1.0);
 +		segmentColor.set(0.0, 0.0, 1.0);
 +		activeColor.set(1.0, 0.0, 0.0);
 +	}
 +
 +	void initPosition(long startTime, long totalTime);
 +	const idVec3_t *getPosition(long time);
 +
 +
 +	void draw(bool editMode);
 +	void addToRenderer();
 +
 +	void setSelectedPoint(idVec3_t *p);
 +	idVec3_t *getSelectedPoint() {
 +	  return selected;
 +	}
 +
 +	void addPoint(const idVec3_t &v) {
 +		controlPoints.Append(new idVec3_t(v));
 +		dirty = true;
 +	}
 +
 +	void addPoint(float x, float y, float z) {
 +		controlPoints.Append(new idVec3_t(x, y, z));
 +		dirty = true;
 +	}
 +
 +	void updateSelection(const idVec3_t &move);
 +
 +	void startEdit() {
 +		editMode = true;
 +	}
 +		
 +	void stopEdit() {
 +		editMode = false;
 +	}
 +
 +	void buildSpline();
 +
 +	void setGranularity(float f) {
 +		granularity = f;
 +	}
 +
 +	float getGranularity() {
 +		return granularity;
 +	}
 +
 +	int numPoints() {
 +		return controlPoints.Num();
 +	}
 +
 +	idVec3_t *getPoint(int index) {
 +		assert(index >= 0 && index < controlPoints.Num());
 +		return controlPoints[index];
 +	}
 +
 +	idVec3_t *getSegmentPoint(int index) {
 +		assert(index >= 0 && index < splinePoints.Num());
 +		return splinePoints[index];
 +	}
 +
 +
 +	void setSegmentTime(int index, int time) {
 +		assert(index >= 0 && index < splinePoints.Num());
 +		splineTime[index] = time;
 +	}
 +
 +	int getSegmentTime(int index) {
 +		assert(index >= 0 && index < splinePoints.Num());
 +		return splineTime[index];
 +	}
 +	void addSegmentTime(int index, int time) {
 +		assert(index >= 0 && index < splinePoints.Num());
 +		splineTime[index] += time;
 +	}
 +
 +	float totalDistance();
 +
 +	static idVec3_t zero;
 +
 +	int getActiveSegment() {
 +		return activeSegment;
 +	}
 +
 +	void setActiveSegment(int i) {
 +		//assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
 +		activeSegment = i;
 +	}
 +
 +	int numSegments() {
 +		return splinePoints.Num();
 +	}
 +
 +	void setColors(idVec3_t &path, idVec3_t &segment, idVec3_t &control, idVec3_t &active) {
 +		pathColor = path;
 +		segmentColor = segment;
 +		controlColor = control;
 +		activeColor = active;
 +	}
 +
 +	const char *getName() {
 +		return name.c_str();
 +	}
 +
 +	void setName(const char *p) {
 +		name = p;
 +	}
 +
 +	bool validTime() {
 +		if (dirty) {
 +			buildSpline();
 +		}
 +		// gcc doesn't allow static casting away from bools
 +		// why?  I've no idea...
 +		return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
 +	}
 +
 +	void setTime(long t) {
 +		time = t;
 +	}
 +
 +	void setBaseTime(long t) {
 +		baseTime = t;
 +	}
 +
 +protected:
 +	idStr name;
 +	float calcSpline(int step, float tension);
 +	idList<idVec3_t*> controlPoints;
 +	idList<idVec3_t*> splinePoints;
 +	idList<float> splineTime;
 +	idVec3_t *selected;
 +	idVec3_t pathColor, segmentColor, controlColor, activeColor;
 +	float granularity;
 +	bool editMode;
 +	bool dirty;
 +	int activeSegment;
 +	long baseTime;
 +	long time;
 +	friend class idCamera;
 +};
 +
 +// time in milliseconds 
 +// velocity where 1.0 equal rough walking speed
 +struct idVelocity {
 +	idVelocity(long start, long duration, float s) {
 +		startTime = start;
 +		time = duration;
 +		speed = s;
 +	}
 +	long	startTime;
 +	long	time;
 +	float	speed;
 +};
 +
 +// can either be a look at or origin position for a camera
 +// 
 +class idCameraPosition : public idPointListInterface {
 +public:
 +	
 +	virtual void clear() {
 +		editMode = false;
 +		for (int i = 0; i < velocities.Num(); i++) {
 +			delete velocities[i];
 +			velocities[i] = NULL;
 +		}
 +		velocities.Clear();
 +	}
 +
 +	idCameraPosition(const char *p) {
 +		name = p;
 +	}
 +
 +	idCameraPosition() {
 +		time = 0;
 +		name = "position";
 +	}
 +
 +	idCameraPosition(long t) {
 +		time = t;
 +	}
 +
 +	virtual ~idCameraPosition() {
 +		clear();
 +	}
 +
 +	
 +	// this can be done with RTTI syntax but i like the derived classes setting a type
 +	// makes serialization a bit easier to see
 +	//
 +	enum positionType {
 +		FIXED = 0x00,
 +		INTERPOLATED,
 +		SPLINE,
 +		POSITION_COUNT
 +	};
 +
 +
 +	virtual void start(long t) {
 +		startTime = t;
 +	}
 +
 +	long getTime() {
 +		return time;
 +	}
 +
 +	virtual void setTime(long t) {
 +		time = t;
 +	}
 +
 +	float getVelocity(long t) {
 +		long check = t - startTime;
 +		for (int i = 0; i < velocities.Num(); i++) {
 +			if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
 +				return velocities[i]->speed;
 +			}
 +		}
 +		return baseVelocity;
 +	}
 +
 +	void addVelocity(long start, long duration, float speed) {
 +		velocities.Append(new idVelocity(start, duration, speed));
 +	}
 +
 +	virtual const idVec3_t *getPosition(long t) { 
 +		assert(true);
 +		return NULL;
 +	}
 +
 +	virtual void draw(bool editMode) {};
 +
 +	virtual void parse(const char *(*text)) {};
 +	virtual void write(fileHandle_t file, const char *name);
 +	virtual bool parseToken(const char *key, const char *(*text));
 +
 +	const char *getName() {
 +		return name.c_str();
 +	}
 +
 +	void setName(const char *p) {
 +		name = p;
 +	}
 +
 +	virtual startEdit() {
 +		editMode = true;
 +	}
 +
 +	virtual stopEdit() {
 +		editMode = false;
 +	}
 +
 +	virtual void draw() {};
 +
 +	const char *typeStr() {
 +		return positionStr[static_cast<int>(type)];
 +	}
 +
 +	void calcVelocity(float distance) {
 +		float secs = (float)time / 1000;
 +		baseVelocity = distance / secs;
 +	}
 +
 +protected:
 +	static const char* positionStr[POSITION_COUNT];
 +	long		startTime;
 +	long		time;
 +	idCameraPosition::positionType type;
 +	idStr		name;
 +	bool	editMode;
 +	idList<idVelocity*> velocities;
 +	float		baseVelocity;
 +};
 +
 +class idFixedPosition : public idCameraPosition {
 +public:
 +
 +	void init() {
 +		pos.Zero();
 +		type = idCameraPosition::FIXED;
 +	}
 +	
 +	idFixedPosition() : idCameraPosition() {
 +		init();
 +	}
 +	
 +	idFixedPosition(idVec3_t p) : idCameraPosition() {
 +		init();
 +		pos = p;
 +	}
 +
 +	virtual void addPoint(const idVec3_t &v) {
 +		pos = v;
 +	}
 +	
 +	virtual void addPoint(const float x, const float y, const float z) {
 +		pos.set(x, y, z);
 +	}
 +
 +
 +	~idFixedPosition() {
 +	}
 +
 +	virtual const idVec3_t *getPosition(long t) { 
 +		return &pos;
 +	}
 +
 +	void parse(const char *(*text));
 +	void write(fileHandle_t file, const char *name);
 +
 +	virtual int numPoints() {
 +		return 1;
 +	}
 +
 +	virtual idVec3_t *getPoint(int index) {
 +		if (index != 0) {
 +			assert(true);
 +		};
 +		return &pos;
 +	}
 +
 +	virtual void draw(bool editMode) {
 +		glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
 +	}
 +
 +protected:
 +	idVec3_t pos;
 +};
 +
 +class idInterpolatedPosition : public idCameraPosition {
 +public:
 +
 +	void init() {
 +		type = idCameraPosition::INTERPOLATED;
 +		first = true;
 +		startPos.Zero();
 +		endPos.Zero();
 +	}
 +	
 +	idInterpolatedPosition() : idCameraPosition() {
 +		init();
 +	}
 +	
 +	idInterpolatedPosition(idVec3_t start, idVec3_t end, long time) : idCameraPosition(time) {
 +		init();
 +		startPos = start;
 +		endPos = end;
 +	}
 +
 +	~idInterpolatedPosition() {
 +	}
 +
 +	virtual const idVec3_t *getPosition(long t);
 +
 +	void parse(const char *(*text));
 +	void write(fileHandle_t file, const char *name);
 +
 +	virtual int numPoints() {
 +		return 2;
 +	}
 +
 +	virtual idVec3_t *getPoint(int index) {
 +		assert(index >= 0 && index < 2);
 +		if (index == 0) {
 +			return &startPos;
 +		}
 +		return &endPos;
 +	}
 +
 +	virtual void addPoint(const float x, const float y, const float z) {
 +		if (first) {
 +			startPos.set(x, y, z);
 +			first = false;
 +		} else {
 +			endPos.set(x, y, z);
 +			first = true;
 +		}
 +	}
 +
 +	virtual void addPoint(const idVec3_t &v) {
 +		if (first) {
 +			startPos = v;
 +			first = false;
 +		} else {
 +			endPos = v;
 +			first = true;
 +		}
 +	}
 +
 +	virtual void draw(bool editMode) {
 +		glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
 +		glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
 +		qglBegin(GL_LINES);
 +		qglVertex3fv(startPos);
 +		qglVertex3fv(endPos);
 +		qglEnd();
 +	}
 +
 +	virtual void start(long t) {
 +		idCameraPosition::start(t);
 +		lastTime = startTime;
 +		distSoFar = 0.0;
 +		idVec3_t temp = startPos;
 +		temp -= endPos;
 +		calcVelocity(temp.Length());
 +	}
 +
 +protected:
 +	bool first;
 +	idVec3_t startPos;
 +	idVec3_t endPos;
 +	long lastTime;
 +	float distSoFar;
 +};
 +
 +class idSplinePosition : public idCameraPosition {
 +public:
 +
 +	void init() {
 +		type = idCameraPosition::SPLINE;
 +	}
 +	
 +	idSplinePosition() : idCameraPosition() {
 +		init();
 +	}
 +	
 +	idSplinePosition(long time) : idCameraPosition(time) {
 +		init();
 +	}
 +
 +	~idSplinePosition() {
 +	}
 +
 +	virtual void start(long t) {
 +		idCameraPosition::start(t);
 +		target.initPosition(t, time);
 +		calcVelocity(target.totalDistance());
 +	}
 +
 +	virtual const idVec3_t *getPosition(long t) { 
 +		return target.getPosition(t);
 +	}
 +
 +	//virtual const idVec3_t *getPosition(long t) const { 
 +
 +	void addControlPoint(idVec3_t &v) {
 +		target.addPoint(v);
 +	}
 +
 +	void parse(const char *(*text));
 +	void write(fileHandle_t file, const char *name);
 +
 +	virtual int numPoints() {
 +		return target.numPoints();
 +	}
 +
 +	virtual idVec3_t *getPoint(int index) {
 +		return target.getPoint(index);
 +	}
 +
 +	virtual void addPoint(const idVec3_t &v) {
 +		target.addPoint(v);
 +	}
 +
 +	virtual void addPoint(const float x, const float y, const float z) {
 +		target.addPoint(x, y, z);
 +	}
 +
 +	virtual void draw(bool editMode) {
 +		target.draw(editMode);
 +	}
 +
 +	virtual void updateSelection(const idVec3_t &move) {
 +		idCameraPosition::updateSelection(move);
 +		target.buildSpline();
 +	}
 +
 +protected:
 +	idSplineList target;
 +};
 +
 +class idCameraFOV {
 +public:
 +	
 +	idCameraFOV() {
 +		time = 0;
 +		fov = 90;
 +	}
 +
 +	idCameraFOV(int v) {
 +		time = 0;
 +		fov = v;
 +	}
 +
 +	idCameraFOV(int s, int e, long t) {
 +		startFOV = s;
 +		endFOV = e;
 +		time = t;
 +	}
 +
 +
 +	~idCameraFOV(){}
 +
 +	void setFOV(float f) {
 +		fov = f;
 +	}
 +
 +	float getFOV(long t) {
 +		if (time) {
 +			assert(startTime);
 +			float percent = t / startTime;
 +			float temp = startFOV - endFOV;
 +			temp *= percent;
 +			fov = startFOV + temp;
 +		}
 +		return fov;
 +	}
 +
 +	int start(long t) {
 +		startTime = t;
 +	}
 +
 +	void parse(const char *(*text));
 +	void write(fileHandle_t file, const char *name);
 +
 +protected:
 +	float fov;
 +	float startFOV;
 +	float endFOV;
 +	int startTime;
 +	int time;
 +};
 +
 +
 +
 +
 +class idCameraEvent {
 +public:
 +	enum eventType {
 +		EVENT_NA = 0x00,
 +		EVENT_WAIT,
 +		EVENT_TARGETWAIT,
 +		EVENT_SPEED,
 +		EVENT_TARGET,
 +		EVENT_SNAPTARGET,
 +		EVENT_FOV,
 +		EVENT_SCRIPT,
 +		EVENT_TRIGGER,
 +		EVENT_STOP,
 +		EVENT_COUNT
 +	};
 +
 +	static const char* eventStr[EVENT_COUNT];
 +
 +	idCameraEvent() {
 +		paramStr = "";
 +		type = EVENT_NA;
 +		time = 0;
 +	}
 +
 +	idCameraEvent(eventType t, const char *param, long n) {
 +		type = t;
 +		paramStr = param;
 +		time = n;
 +	}
 +
 +	~idCameraEvent() {};
 +
 +	eventType getType() {
 +		return type;
 +	}
 +
 +	const char *typeStr() {
 +		return eventStr[static_cast<int>(type)];
 +	}
 +
 +	const char *getParam() {
 +		return paramStr.c_str();
 +	}
 +
 +	long getTime() {
 +		return time;
 +	}
 +
 +	void setTime(long n) {
 +		time = n;
 +	}
 +
 +	void parse(const char *(*text));
 +	void write(fileHandle_t file, const char *name);
 +
 +	void setTriggered(bool b) {
 +		triggered = b;
 +	}
 +
 +	bool getTriggered() {
 +		return triggered;
 +	}
 +
 +protected:
 +	eventType type;
 +	idStr paramStr;
 +	long time;
 +	bool triggered;
 +
 +};
 +
 +class idCameraDef {
 +public:
 +
 +	void clear() {
 +		currentCameraPosition = 0;
 +		cameraRunning = false;
 +		lastDirection.Zero();
 +		baseTime = 30;
 +		activeTarget = 0;
 +		name = "camera01";
 +		fov.setFOV(90);
 +		int i;
 +		for (i = 0; i < targetPositions.Num(); i++) {
 +			delete targetPositions[i];
 +		}
 +		for (i = 0; i < events.Num(); i++) {
 +			delete events[i];
 +		}
 +		delete cameraPosition;
 +		cameraPosition = NULL;
 +		events.Clear();
 +		targetPositions.Clear();
 +	}
 +
 +	idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
 +		clear();
 +		if (type == idCameraPosition::SPLINE) {
 +			cameraPosition = new idSplinePosition();
 +		} else if (type == idCameraPosition::INTERPOLATED) {
 +			cameraPosition = new idInterpolatedPosition();
 +		} else {
 +			cameraPosition = new idFixedPosition();
 +		}
 +		return cameraPosition;
 +	}
 +
 +	idCameraDef() {
 +		clear();
 +	}
 +
 +	~idCameraDef() {
 +		clear();
 +	}
 +
 +	void addEvent(idCameraEvent::eventType t, const char *param, long time);
 +
 +	void addEvent(idCameraEvent *event);
 +
 +	static int sortEvents(const void *p1, const void *p2);
 +
 +	int numEvents() {
 +		return events.Num();
 +	}
 +
 +	idCameraEvent *getEvent(int index) {
 +		assert(index >= 0 && index < events.Num());
 +		return events[index];
 +	}
 +
 +	void parse(const char *(*text));
 +	bool load(const char *filename);
 +	void save(const char *filename);
 +
 +	void buildCamera();
 +
 +	//idSplineList *getcameraPosition() {
 +	//	return &cameraPosition;
 +	//}
 +
 +	static idCameraPosition *newFromType(idCameraPosition::positionType t) {
 +		switch (t) {
 +			case idCameraPosition::FIXED : return new idFixedPosition();
 +			case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
 +			case idCameraPosition::SPLINE : return new idSplinePosition();
 +		};
 +		return NULL;
 +	}
 +
 +	void addTarget(const char *name, idCameraPosition::positionType type);
 +
 +	idCameraPosition *getActiveTarget() {
 +		if (targetPositions.Num() == 0) {
 +			addTarget(NULL, idCameraPosition::FIXED);
 +		}
 +		return targetPositions[activeTarget];
 +	}
 +
 +	idCameraPosition *getActiveTarget(int index) {
 +		if (targetPositions.Num() == 0) {
 +			addTarget(NULL, idCameraPosition::FIXED);
 +			return targetPositions[0];
 +		}
 +		return targetPositions[index];
 +	}
 +
 +	int numTargets() {
 +		return targetPositions.Num();
 +	}
 +
 +
 +	void setActiveTargetByName(const char *name) {
 +		for (int i = 0; i < targetPositions.Num(); i++) {
 +			if (stricmp(name, targetPositions[i]->getName()) == 0) {
 +				setActiveTarget(i);
 +				return;
 +			}
 +		}
 +	}
 +
 +	void setActiveTarget(int index) {
 +		assert(index >= 0 && index < targetPositions.Num());
 +		activeTarget = index;
 +	}
 +
 +	void setRunning(bool b) {
 +		cameraRunning = b;
 +	}
 +
 +	void setBaseTime(float f) {
 +		baseTime = f;
 +	}
 +
 +	float getBaseTime() {
 +		return baseTime;
 +	}
 +
 +	float getTotalTime() {
 +		return totalTime;
 +	}
 +	
 +	void startCamera(long t);
 +	void stopCamera() {
 +		cameraRunning = true;
 +	}
 +	void getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fv);
 +
 +	bool getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv);
 +	bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
 +		idVec3_t org, dir;
 +		org[0] = origin[0];
 +		org[1] = origin[1];
 +		org[2] = origin[2];
 +		dir[0] = direction[0];
 +		dir[1] = direction[1];
 +		dir[2] = direction[2];
 +		bool b = getCameraInfo(time, org, dir, fv);
 +		origin[0] = org[0];
 +		origin[1] = org[1];
 +		origin[2] = org[2];
 +		direction[0] = dir[0];
 +		direction[1] = dir[1];
 +		direction[2] = dir[2];
 +		return b;
 +	}
 +
 +	void draw(bool editMode) {
 +                // gcc doesn't allow casting away from bools
 +                // why?  I've no idea...
 +		if (cameraPosition) {
 +			cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
 +			int count = targetPositions.Num();
 +			for (int i = 0; i < count; i++) {
 +				targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
 +			}
 +		}
 +	}
 +
 +/*
 +	int numSegments() {
 +		if (cameraEdit) {
 +			return cameraPosition.numSegments();
 +		}
 +		return getTargetSpline()->numSegments();
 +	}
 +
 +	int getActiveSegment() {
 +		if (cameraEdit) {
 +			return cameraPosition.getActiveSegment();
 +		}
 +		return getTargetSpline()->getActiveSegment();
 +	}
 +
 +	void setActiveSegment(int i) {
 +		if (cameraEdit) {
 +			cameraPosition.setActiveSegment(i);
 +		} else {
 +			getTargetSpline()->setActiveSegment(i);
 +		}
 +	}
 +*/
 +	int numPoints() {
 +		if (cameraEdit) {
 +			return cameraPosition->numPoints();
 +		}
 +		return getActiveTarget()->numPoints();
 +	}
 +
 +	const idVec3_t *getPoint(int index) {
 +		if (cameraEdit) {
 +			return cameraPosition->getPoint(index);
 +		}
 +		return getActiveTarget()->getPoint(index);
 +	}
 +
 +	void stopEdit() {
 +		editMode = false;
 +		if (cameraEdit) {
 +			cameraPosition->stopEdit();
 +		} else {
 +			getActiveTarget()->stopEdit();
 +		}
 +	}
 +
 +	void startEdit(bool camera) {
 +		cameraEdit = camera;
 +		if (camera) {
 +			cameraPosition->startEdit();
 +			for (int i = 0; i < targetPositions.Num(); i++) {
 +				targetPositions[i]->stopEdit();
 +			}
 +		} else {
 +			getActiveTarget()->startEdit();
 +			cameraPosition->stopEdit();
 +		}
 +		editMode = true;
 +	}
 +
 +	bool waitEvent(int index);
 +
 +	const char *getName() {
 +		return name.c_str();
 +	}
 +
 +	void setName(const char *p) {
 +		name = p;
 +	}
 +
 +	idCameraPosition *getPositionObj() {
 +		if (cameraPosition == NULL) {
 +			cameraPosition = new idFixedPosition();
 +		}
 +		return cameraPosition;
 +	}
 +
 +protected:
 +	idStr name;
 +	int currentCameraPosition;
 +	idVec3_t lastDirection;
 +	bool cameraRunning;
 +	idCameraPosition *cameraPosition;
 +	idList<idCameraPosition*> targetPositions;
 +	idList<idCameraEvent*> events;
 +	idCameraFOV fov;
 +	int activeTarget;
 +	float totalTime;
 +	float baseTime;
 +	long startTime;
 +
 +	bool cameraEdit;
 +	bool editMode;
 +};
 +
 +extern bool g_splineMode;
 +
 +extern idCameraDef *g_splineList;
 +
 +
 +#endif
\ No newline at end of file diff --git a/q3radiant/splines/util_list.h b/q3radiant/splines/util_list.h new file mode 100755 index 0000000..4f93244 --- /dev/null +++ b/q3radiant/splines/util_list.h @@ -0,0 +1,346 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +#ifndef __UTIL_LIST_H__
 +#define __UTIL_LIST_H__
 +
 +#include <stdlib.h>
 +#include <assert.h>
 +
 +template< class type >
 +class idList {
 +private:
 +	int			m_num;
 +	int			m_size;
 +	int			m_granularity;
 +	type		*m_list;
 +
 +public:
 +				idList( int granularity = 16 );
 +				~idList<type>();
 +	void		Clear( void );
 +	int			Num( void );
 +	void		SetNum( int num );
 +	void		SetGranularity( int granularity );
 +	void		Condense( void );
 +	int			Size( void );
 +	void		Resize( int size );
 +	type		operator[]( int index ) const;
 +	type		&operator[]( int index );
 +	int			Append( type const & obj );
 +	int			AddUnique( type const & obj );
 +	type		*Find( type const & obj, int *index = NULL );
 +	bool		RemoveIndex( int index );
 +	bool		Remove( type const & obj );
 +	typedef int cmp_t(const void *, const void *);
 +	void		Sort( cmp_t *compare );
 +};
 +
 +/*
 +================
 +idList<type>::idList( int )
 +================
 +*/
 +template< class type >
 +inline idList<type>::idList( int granularity ) {
 +	assert( granularity > 0 );
 +
 +	m_list			= NULL;
 +	m_granularity	= granularity;
 +	Clear();
 +}
 +
 +/*
 +================
 +idList<type>::~idList<type>
 +================
 +*/
 +template< class type >
 +inline idList<type>::~idList() {
 +	Clear();
 +}
 +
 +/*
 +================
 +idList<type>::Clear
 +================
 +*/
 +template< class type >
 +inline void idList<type>::Clear( void ) {
 +	if ( m_list ) {
 +		delete[] m_list;
 +	}
 +
 +	m_list	= NULL;
 +	m_num	= 0;
 +	m_size	= 0;
 +}
 +
 +/*
 +================
 +idList<type>::Num
 +================
 +*/
 +template< class type >
 +inline int idList<type>::Num( void ) {
 +	return m_num;
 +}
 +
 +/*
 +================
 +idList<type>::SetNum
 +================
 +*/
 +template< class type >
 +inline void idList<type>::SetNum( int num ) {
 +	assert( num >= 0 );
 +	if ( num > m_size ) {
 +		// resize it up to the closest level of granularity
 +		Resize( ( ( num + m_granularity - 1 ) / m_granularity ) * m_granularity );
 +	}
 +	m_num = num;
 +}
 +
 +/*
 +================
 +idList<type>::SetGranularity
 +================
 +*/
 +template< class type >
 +inline void idList<type>::SetGranularity( int granularity ) {
 +	int newsize;
 +
 +	assert( granularity > 0 );
 +	m_granularity = granularity;
 +
 +	if ( m_list ) {
 +		// resize it to the closest level of granularity
 +		newsize = ( ( m_num + m_granularity - 1 ) / m_granularity ) * m_granularity;
 +		if ( newsize != m_size ) {
 +			Resize( newsize );
 +		}
 +	}
 +}
 +
 +/*
 +================
 +idList<type>::Condense
 +
 +Resizes the array to exactly the number of elements it contains
 +================
 +*/
 +template< class type >
 +inline void idList<type>::Condense( void ) {
 +	if ( m_list ) {
 +		if ( m_num ) {
 +			Resize( m_num );
 +		} else {
 +			Clear();
 +		}
 +	}
 +}
 +
 +/*
 +================
 +idList<type>::Size
 +================
 +*/
 +template< class type >
 +inline int idList<type>::Size( void ) {
 +	return m_size;
 +}
 +
 +/*
 +================
 +idList<type>::Resize
 +================
 +*/
 +template< class type >
 +inline void idList<type>::Resize( int size ) {
 +	type	*temp;
 +	int		i;
 +
 +	assert( size > 0 );
 +
 +	if ( size <= 0 ) {
 +		Clear();
 +		return;
 +	}
 +
 +	temp	= m_list;
 +	m_size	= size;
 +	if ( m_size < m_num ) {
 +		m_num = m_size;
 +	}
 +
 +	m_list = new type[ m_size ];
 +	for( i = 0; i < m_num; i++ ) {
 +		m_list[ i ] = temp[ i ];
 +	}
 +
 +	if ( temp ) {
 +		delete[] temp;
 +	}
 +}
 +
 +/*
 +================
 +idList<type>::operator[] const
 +================
 +*/
 +template< class type >
 +inline type idList<type>::operator[]( int index ) const {
 +	assert( index >= 0 );
 +	assert( index < m_num );
 +
 +	return m_list[ index ];
 +}
 +
 +/*
 +================
 +idList<type>::operator[]
 +================
 +*/
 +template< class type >
 +inline type &idList<type>::operator[]( int index ) {
 +	assert( index >= 0 );
 +	assert( index < m_num );
 +
 +	return m_list[ index ];
 +}
 +
 +/*
 +================
 +idList<type>::Append
 +================
 +*/
 +template< class type >
 +inline int idList<type>::Append( type const & obj ) {
 +	if ( !m_list ) {
 +		Resize( m_granularity );
 +	}
 +
 +	if ( m_num == m_size ) {
 +		Resize( m_size + m_granularity );
 +	}
 +
 +	m_list[ m_num ] = obj;
 +	m_num++;
 +
 +	return m_num - 1;
 +}
 +
 +/*
 +================
 +idList<type>::AddUnique
 +================
 +*/
 +template< class type >
 +inline int idList<type>::AddUnique( type const & obj ) {
 +	int index;
 +
 +	if ( !Find( obj, &index ) ) {
 +		index = Append( obj );
 +	}
 +
 +	return index;
 +}
 +
 +/*
 +================
 +idList<type>::Find
 +================
 +*/
 +template< class type >
 +inline type *idList<type>::Find( type const & obj, int *index ) {
 +	int i;
 +
 +	for( i = 0; i < m_num; i++ ) {
 +		if ( m_list[ i ] == obj ) {
 +			if ( index ) {
 +				*index = i;
 +			}
 +			return &m_list[ i ];
 +		}
 +	}
 +
 +	return NULL;
 +}
 +
 +/*
 +================
 +idList<type>::RemoveIndex
 +================
 +*/
 +template< class type >
 +inline bool idList<type>::RemoveIndex( int index ) {
 +	int i;
 +
 +	if ( !m_list || !m_num ) {
 +		return false;
 +	}
 +
 +	assert( index >= 0 );
 +	assert( index < m_num );
 +
 +	if ( ( index < 0 ) || ( index >= m_num ) ) {
 +		return false;
 +	}
 +
 +	m_num--;
 +	for( i = index; i < m_num; i++ ) {
 +		m_list[ i ] = m_list[ i + 1 ];
 +	}
 +
 +	return true;
 +}
 +
 +/*
 +================
 +idList<type>::Remove
 +================
 +*/
 +template< class type >
 +inline bool idList<type>::Remove( type const & obj ) {
 +	int index;
 +
 +	if ( Find( obj, &index ) ) {
 +		return RemoveIndex( index );
 +	}
 +	
 +	return false;
 +}
 +
 +/*
 +================
 +idList<type>::Sort
 +================
 +*/
 +template< class type >
 +inline void idList<type>::Sort( cmp_t *compare ) {
 +	if ( !m_list ) {
 +		return;
 +	}
 +
 +	qsort( ( void * )m_list, ( size_t )m_num, sizeof( type ), compare );
 +}
 +
 +#endif /* !__UTIL_LIST_H__ */
 diff --git a/q3radiant/splines/util_str.cpp b/q3radiant/splines/util_str.cpp new file mode 100755 index 0000000..230a77f --- /dev/null +++ b/q3radiant/splines/util_str.cpp @@ -0,0 +1,618 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +//need to rewrite this
 +
 +#include "util_str.h"
 +#include <stdlib.h>
 +#include <ctype.h>
 +#include <stdio.h>
 +#include <stdarg.h>
 +
 +#ifdef _WIN32
 +#pragma warning(disable : 4244)     // 'conversion' conversion from 'type1' to 'type2', possible loss of data
 +#pragma warning(disable : 4710)     // function 'blah' not inlined
 +#endif
 +
 +static const int STR_ALLOC_GRAN = 20;
 +
 +char *idStr::tolower
 +   (
 +   char *s1
 +   )
 +   
 +   {
 +   char *s;
 +
 +   s = s1;
 +	while( *s )
 +      {
 +      *s = ::tolower( *s );
 +		s++;
 +	   }
 +   
 +   return s1;
 +   }
 +
 +char *idStr::toupper
 +   (
 +   char *s1
 +   )
 +   
 +   {
 +   char *s;
 +
 +   s = s1;
 +	while( *s )
 +      {
 +      *s = ::toupper( *s );
 +		s++;
 +	   }
 +   
 +   return s1;
 +   }
 +
 +int idStr::icmpn
 +   (
 +   const char *s1, 
 +   const char *s2, 
 +   int n
 +   )
 +   
 +   {
 +	int c1;
 +   int c2;
 +	
 +	do 
 +      {
 +		c1 = *s1++;
 +		c2 = *s2++;
 +
 +		if ( !n-- )
 +         {
 +         // idStrings are equal until end point
 +			return 0;
 +		   }
 +		
 +		if ( c1 != c2 )
 +         {
 +			if ( c1 >= 'a' && c1 <= 'z' )
 +            {
 +				c1 -= ( 'a' - 'A' );
 +			   }
 +
 +			if ( c2 >= 'a' && c2 <= 'z' )
 +            {
 +				c2 -= ( 'a' - 'A' );
 +			   }
 +
 +			if ( c1 < c2 )
 +            {
 +            // strings less than
 +				return -1;
 +			   }
 +         else if ( c1 > c2 ) 
 +            {
 +            // strings greater than
 +            return 1;
 +            }
 +		   }
 +	   } 
 +   while( c1 );
 +	
 +   // strings are equal
 +	return 0;
 +   }
 +
 +int idStr::icmp
 +   (
 +   const char *s1,
 +   const char *s2
 +   )
 +   
 +   {
 +	int c1;
 +   int c2;
 +	
 +	do 
 +      {
 +		c1 = *s1++;
 +		c2 = *s2++;
 +
 +		if ( c1 != c2 )
 +         {
 +			if ( c1 >= 'a' && c1 <= 'z' )
 +            {
 +				c1 -= ( 'a' - 'A' );
 +			   }
 +
 +			if ( c2 >= 'a' && c2 <= 'z' )
 +            {
 +				c2 -= ( 'a' - 'A' );
 +			   }
 +
 +			if ( c1 < c2 )
 +            {
 +            // strings less than
 +				return -1;
 +			   }
 +         else if ( c1 > c2 ) 
 +            {
 +            // strings greater than
 +            return 1;
 +            }
 +		   }
 +	   } 
 +   while( c1 );
 +	
 +   // strings are equal
 +	return 0;
 +   }
 +
 +int idStr::cmpn
 +   (
 +   const char *s1, 
 +   const char *s2, 
 +   int n
 +   )
 +   
 +   {
 +	int c1;
 +   int c2;
 +	
 +	do 
 +      {
 +		c1 = *s1++;
 +		c2 = *s2++;
 +
 +		if ( !n-- )
 +         {
 +         // strings are equal until end point
 +			return 0;
 +		   }
 +		
 +		if ( c1 < c2 )
 +         {
 +         // strings less than
 +			return -1;
 +			}
 +      else if ( c1 > c2 ) 
 +         {
 +         // strings greater than
 +         return 1;
 +         }
 +	   } 
 +   while( c1 );
 +	
 +   // strings are equal
 +	return 0;
 +   }
 +
 +int idStr::cmp
 +   (
 +   const char *s1, 
 +   const char *s2
 +   )
 +   
 +   {
 +	int c1;
 +   int c2;
 +	
 +	do 
 +      {
 +		c1 = *s1++;
 +		c2 = *s2++;
 +
 +		if ( c1 < c2 )
 +         {
 +         // strings less than
 +			return -1;
 +			}
 +      else if ( c1 > c2 ) 
 +         {
 +         // strings greater than
 +         return 1;
 +         }
 +	   } 
 +   while( c1 );
 +	
 +   // strings are equal
 +	return 0;
 +   }
 +
 +/*
 +============
 +IsNumeric
 +
 +Checks a string to see if it contains only numerical values.
 +============
 +*/
 +bool idStr::isNumeric
 +   (
 +   const char *str
 +   )
 +
 +   {
 +	int len;
 +	int i;
 +	bool dot;
 +
 +	if ( *str == '-' )
 +		{
 +		str++;
 +		}
 +
 +	dot = false;
 +	len = strlen( str );
 +	for( i = 0; i < len; i++ )
 +		{
 +		if ( !isdigit( str[ i ] ) )
 +			{
 +			if ( ( str[ i ] == '.' ) && !dot )
 +				{
 +				dot = true;
 +				continue;
 +				}
 +			return false;
 +			}
 +		}
 +
 +	return true;
 +   }
 +
 +idStr operator+
 +   (
 +   const idStr& a,
 +   const float b
 +   )
 +
 +   {
 +   char text[ 20 ];
 +
 +	idStr result( a );
 +
 +   sprintf( text, "%f", b );
 +	result.append( text );
 +
 +	return result;
 +   }
 +
 +idStr operator+
 +   (
 +   const idStr& a,
 +   const int b
 +   )
 +
 +   {
 +   char text[ 20 ];
 +
 +	idStr result( a );
 +
 +   sprintf( text, "%d", b );
 +	result.append( text );
 +
 +	return result;
 +   }
 +
 +idStr operator+
 +   (
 +   const idStr& a,
 +   const unsigned b
 +   )
 +
 +   {
 +   char text[ 20 ];
 +
 +	idStr result( a );
 +
 +   sprintf( text, "%u", b );
 +	result.append( text );
 +
 +	return result;
 +   }
 +
 +idStr& idStr::operator+=
 +	(
 +	const float a
 +	)
 +
 +	{
 +   char text[ 20 ];
 +
 +   sprintf( text, "%f", a );
 +	append( text );
 +
 +   return *this;
 +	}
 +
 +idStr& idStr::operator+=
 +	(
 +	const int a
 +	)
 +
 +	{
 +   char text[ 20 ];
 +
 +   sprintf( text, "%d", a );
 +	append( text );
 +
 +   return *this;
 +	}
 +
 +idStr& idStr::operator+=
 +	(
 +	const unsigned a
 +	)
 +
 +	{
 +   char text[ 20 ];
 +
 +   sprintf( text, "%u", a );
 +	append( text );
 +
 +   return *this;
 +	}
 +
 +void idStr::CapLength 
 +   (
 +   int newlen 
 +   )
 +
 +   {
 +   assert ( m_data );
 +   
 +   if ( length() <= newlen )
 +      return;
 +
 +   EnsureDataWritable ();
 +
 +   m_data->data[newlen] = 0;
 +   m_data->len = newlen;
 +   }
 +
 +void idStr::EnsureDataWritable 
 +   (
 +   void
 +   )
 +
 +   {
 +   assert ( m_data );
 +   strdata *olddata;
 +   int len;
 +
 +   if ( !m_data->refcount )
 +      return;
 +
 +   olddata = m_data;
 +   len = length();
 +
 +   m_data = new strdata;
 +
 +   EnsureAlloced ( len + 1, false );
 +   strncpy ( m_data->data, olddata->data, len+1 );
 +   m_data->len = len;
 +
 +   olddata->DelRef ();
 +   }
 +
 +void idStr::EnsureAlloced (int amount, bool keepold) {
 +
 +	if ( !m_data ) {
 +      m_data = new strdata();
 +	}
 +   
 +	// Now, let's make sure it's writable
 +	EnsureDataWritable ();
 +
 +	char *newbuffer;
 +	bool wasalloced = ( m_data->alloced != 0 );
 +
 +	if ( amount < m_data->alloced ) {
 +		return;
 +	}
 +
 +	assert ( amount );
 +	if ( amount == 1 ) {
 +		m_data->alloced = 1;
 +	} else {
 +		int newsize, mod;
 +		mod = amount % STR_ALLOC_GRAN;
 +		if ( !mod ) {
 +			newsize = amount;
 +		} else {
 +         newsize = amount + STR_ALLOC_GRAN - mod;
 +		}
 +		m_data->alloced = newsize;
 +	}
 +
 +	newbuffer = new char[m_data->alloced];
 +	if ( wasalloced && keepold ) {
 +		strcpy ( newbuffer, m_data->data );
 +	}
 +
 +	if ( m_data->data ) {
 +		delete [] m_data->data;
 +    }
 +	m_data->data = newbuffer;
 +}
 +
 +void idStr::BackSlashesToSlashes
 +   (
 +   void
 +   )
 +
 +   {
 +   int i;
 +
 +   EnsureDataWritable ();
 +
 +   for ( i=0; i < m_data->len; i++ )
 +      {
 +      if ( m_data->data[i] == '\\' )
 +         m_data->data[i] = '/';
 +      }
 +   }
 +
 +void idStr::snprintf 
 +   (
 +   char *dst,
 +   int size,
 +   const char *fmt, 
 +   ...
 +   )
 +
 +   {
 +   char buffer[0x10000];
 +	int		len;
 +	va_list		argptr;
 +
 +	va_start (argptr,fmt);
 +	len = vsprintf (buffer,fmt,argptr);
 +	va_end (argptr);
 +	
 +   assert ( len < size );
 +
 +   strncpy (dst, buffer, size-1);
 +   }
 +
 +#ifdef _WIN32
 +#pragma warning(disable : 4189)		// local variable is initialized but not referenced
 +#endif
 +
 +/*
 +=================
 +TestStringClass
 +
 +This is a fairly rigorous test of the idStr class's functionality.
 +Because of the fairly global and subtle ramifications of a bug occuring
 +in this class, it should be run after any changes to the class.
 +Add more tests as functionality is changed.  Tests should include
 +any possible bounds violation and NULL data tests.
 +=================
 +*/
 +void TestStringClass
 +	(
 +	void 
 +	)
 +
 +	{
 +	char	ch;							// ch == ?
 +	idStr	*t;							// t == ?
 +	idStr	a;								// a.len == 0, a.data == "\0"
 +	idStr	b;								// b.len == 0, b.data == "\0"
 +	idStr	c( "test" );				// c.len == 4, c.data == "test\0"
 +	idStr	d( c );						// d.len == 4, d.data == "test\0"
 +	idStr	e( reinterpret_cast<const char *>(NULL) );					
 +                                 // e.len == 0, e.data == "\0"					ASSERT!
 +	int	i;								// i == ?
 +
 +	i = a.length();					// i == 0
 +	i = c.length();					// i == 4
 +
 +	const char *s1 = a.c_str();	// s1 == "\0"
 +	const char *s2 = c.c_str();	// s2 == "test\0"
 +
 +	t = new idStr();						// t->len == 0, t->data == "\0"
 +	delete t;							// t == ?
 +
 +	b = "test";							// b.len == 4, b.data == "test\0"
 +	t = new idStr( "test" );			// t->len == 4, t->data == "test\0"
 +	delete t;							// t == ?
 +
 +	a = c;								// a.len == 4, a.data == "test\0"
 +//   a = "";
 +   a = NULL;							// a.len == 0, a.data == "\0"					ASSERT!
 +	a = c + d;							// a.len == 8, a.data == "testtest\0"
 +	a = c + "wow";						// a.len == 7, a.data == "testwow\0"
 +	a = c + reinterpret_cast<const char *>(NULL);
 +                                 // a.len == 4, a.data == "test\0"			ASSERT!
 +	a = "this" + d;					// a.len == 8, a.data == "thistest\0"
 +	a = reinterpret_cast<const char *>(NULL) + d;
 +                                 // a.len == 4, a.data == "test\0"			ASSERT!
 +	a += c;								// a.len == 8, a.data == "testtest\0"
 +	a += "wow";							// a.len == 11, a.data == "testtestwow\0"
 +	a += reinterpret_cast<const char *>(NULL);
 +                                 // a.len == 11, a.data == "testtestwow\0"	ASSERT!
 +
 +	a = "test";							// a.len == 4, a.data == "test\0"
 +	ch = a[ 0 ];						// ch == 't'
 +	ch = a[ -1 ];						// ch == 0											ASSERT!
 +	ch = a[ 1000 ];					// ch == 0											ASSERT!
 +	ch = a[ 0 ];						// ch == 't'
 +	ch = a[ 1 ];						// ch == 'e'
 +	ch = a[ 2 ];						// ch == 's'
 +	ch = a[ 3 ];						// ch == 't'
 +	ch = a[ 4 ];						// ch == '\0'										ASSERT!
 +	ch = a[ 5 ];						// ch == '\0'										ASSERT!
 +
 +	a[ 1 ] = 'b';						// a.len == 4, a.data == "tbst\0"
 +	a[ -1 ] = 'b';						// a.len == 4, a.data == "tbst\0"			ASSERT!
 +	a[ 0 ] = '0';						// a.len == 4, a.data == "0bst\0"
 +	a[ 1 ] = '1';						// a.len == 4, a.data == "01st\0"
 +	a[ 2 ] = '2';						// a.len == 4, a.data == "012t\0"
 +	a[ 3 ] = '3';						// a.len == 4, a.data == "0123\0"
 +	a[ 4 ] = '4';						// a.len == 4, a.data == "0123\0"			ASSERT!
 +	a[ 5 ] = '5';						// a.len == 4, a.data == "0123\0"			ASSERT!
 +	a[ 7 ] = '7';						// a.len == 4, a.data == "0123\0"			ASSERT!
 +
 +	a = "test";							// a.len == 4, a.data == "test\0"
 +	b = "no";							// b.len == 2, b.data == "no\0"
 +
 +	i = ( a == b );					// i == 0
 +	i = ( a == c );					// i == 1
 +
 +	i = ( a == "blow" );				// i == 0
 +	i = ( a == "test" );				// i == 1
 +	i = ( a == NULL );				// i == 0											ASSERT!
 +
 +	i = ( "test" == b );				// i == 0
 +	i = ( "test" == a );				// i == 1
 +	i = ( NULL == a );				// i == 0											ASSERT!
 +
 +	i = ( a != b );					// i == 1
 +	i = ( a != c );					// i == 0
 +
 +	i = ( a != "blow" );				// i == 1
 +	i = ( a != "test" );				// i == 0
 +	i = ( a != NULL );				// i == 1											ASSERT!
 +
 +	i = ( "test" != b );				// i == 1
 +	i = ( "test" != a );				// i == 0
 +	i = ( NULL != a );				// i == 1											ASSERT!
 +
 +   a = "test";                   // a.data == "test"
 +   b = a;                        // b.data == "test"
 +
 +   a = "not";                   // a.data == "not", b.data == "test"
 +
 +   a = b;                        // a.data == b.data == "test"
 +
 +   a += b;                       // a.data == "testtest", b.data = "test"
 +
 +   a = b;
 +
 +   a[1] = '1';                   // a.data = "t1st", b.data = "test"
 +	}
 +
 +#ifdef _WIN32
 +#pragma warning(default : 4189)		// local variable is initialized but not referenced
 +#pragma warning(disable : 4514)     // unreferenced inline function has been removed
 +#endif
 diff --git a/q3radiant/splines/util_str.h b/q3radiant/splines/util_str.h new file mode 100755 index 0000000..896bf89 --- /dev/null +++ b/q3radiant/splines/util_str.h @@ -0,0 +1,817 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA +=========================================================================== +*/ +//need to rewrite this
 +
 +#ifndef __UTIL_STR_H__
 +#define __UTIL_STR_H__
 +
 +#include <assert.h>
 +#include <string.h>
 +#include <stdio.h>
 +
 +#ifdef _WIN32
 +#pragma warning(disable : 4710)     // function 'blah' not inlined
 +#endif
 +
 +void TestStringClass ();
 +
 +class strdata
 +   {
 +   public:
 +      strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
 +      ~strdata () 
 +         {
 +         if ( data )
 +            delete [] data;
 +         }
 +
 +      void AddRef () { refcount++; }
 +      bool DelRef () // True if killed
 +         {
 +         refcount--;
 +         if ( refcount < 0 )
 +            {
 +            delete this;
 +            return true;
 +            }
 +         
 +         return false;
 +         }
 +
 +      int len;
 +      int refcount;
 +      char *data;
 +      int alloced;
 +   };
 +
 +class idStr {
 +protected:
 +	strdata	*m_data;
 +	void EnsureAlloced ( int, bool keepold = true );
 +	void EnsureDataWritable ();
 +
 +public:
 +	~idStr();
 +	idStr();
 +	idStr( const char *text );
 +	idStr( const idStr& string );
 +	idStr( const idStr string, int start, int end );
 +	idStr( const char ch );
 +	idStr( const int num );
 +	idStr( const float num );
 +	idStr( const unsigned num );
 +	int	length( void ) const;
 +	int	allocated( void ) const;
 +	const char * c_str( void ) const;
 +
 +	void		append( const char *text );
 +	void		append( const idStr& text );
 +	char		operator[]( int index ) const;
 +	char&		operator[]( int index );
 +
 +	void		operator=( const idStr& text );
 +	void		operator=( const char *text );
 +
 +	friend	idStr		operator+( const idStr& a, const idStr& b );
 +	friend	idStr		operator+( const idStr& a, const char *b );
 +	friend	idStr		operator+( const char *a, const idStr& b );
 +
 +    friend	idStr		operator+( const idStr& a, const float b );
 +    friend	idStr		operator+( const idStr& a, const int b );
 +    friend	idStr		operator+( const idStr& a, const unsigned b );
 +    friend	idStr		operator+( const idStr& a, const bool b );
 +    friend	idStr		operator+( const idStr& a, const char b );
 +
 +	idStr&		operator+=( const idStr& a );
 +	idStr&		operator+=( const char *a );
 +	idStr&		operator+=( const float a );
 +	idStr&		operator+=( const char a );
 +	idStr&		operator+=( const int a );
 +	idStr&		operator+=( const unsigned a );
 +	idStr&		operator+=( const bool a );
 +
 +	friend	bool		operator==(	const idStr& a, const idStr& b );
 +	friend	bool		operator==(	const idStr& a, const char *b );
 +	friend	bool		operator==(	const char *a, const idStr& b );
 +
 +	friend	bool		operator!=(	const idStr& a, const idStr& b );
 +	friend	bool		operator!=(	const idStr& a, const char *b );
 +	friend	bool		operator!=(	const char *a, const idStr& b );
 +
 +	operator const char * () const;
 +	operator const char * ();
 +
 +    int      icmpn( const char *text, int n ) const;
 +	int      icmpn( const idStr& text, int n ) const;
 +	int      icmp( const char *text ) const;
 +	int      icmp( const idStr& text ) const;
 +	int      cmpn( const char *text, int n ) const;
 +	int      cmpn( const idStr& text, int n ) const;
 +	int      cmp( const char *text ) const;
 +	int      cmp( const idStr& text ) const;
 +
 +	void     tolower( void );
 +	void     toupper( void );
 +
 +	static   char     *tolower( char *s1 );
 +	static   char     *toupper( char *s1 );
 +
 +	static   int      icmpn( const char *s1, const char *s2, int n );
 +	static   int      icmp( const char *s1, const char *s2 );
 +	static   int      cmpn( const char *s1, const char *s2, int n );
 +	static   int      cmp( const char *s1, const char *s2 );
 +
 +	static   void     snprintf ( char *dst, int size, const char *fmt, ... );
 +
 +	static   bool	   isNumeric( const char *str );
 +    bool    isNumeric( void ) const;
 +
 +	void     CapLength ( int );
 +
 +	void     BackSlashesToSlashes ();
 +
 +};
 +
 +inline idStr::~idStr()
 +	{
 +   if ( m_data )
 +      {
 +      m_data->DelRef ();
 +      m_data = NULL;
 +      }
 +	}
 +
 +inline idStr::idStr() : m_data ( NULL )
 +	{
 +   EnsureAlloced ( 1 );
 +	m_data->data[ 0 ] = 0;
 +	}
 +
 +inline idStr::idStr
 +	(
 +	const char *text
 +   ) : m_data ( NULL )
 +
 +	{
 +   int len;
 +
 +	assert( text );
 +
 +	if ( text )
 +		{
 +      len = strlen( text );
 +		EnsureAlloced ( len + 1 );
 +		strcpy( m_data->data, text );
 +      m_data->len = len;
 +		}
 +	else
 +		{
 +      EnsureAlloced ( 1 );
 +		m_data->data[ 0 ] = 0;
 +		m_data->len = 0;
 +		}
 +	}
 +
 +inline idStr::idStr
 +	(
 +	const idStr& text
 +   ) : m_data ( NULL )
 +
 +	{
 +   m_data = text.m_data;
 +   m_data->AddRef ();
 +   }
 +
 +inline idStr::idStr
 +	(
 +	const idStr text, 
 +	int start,
 +	int end
 +   ) : m_data ( NULL )
 +
 +	{
 +	int i;
 +   int len;
 +
 +	if ( end > text.length() )
 +		{
 +		end = text.length();
 +		}
 +
 +	if ( start > text.length() )
 +		{
 +		start = text.length();
 +		}
 +
 +	len = end - start;
 +	if ( len < 0 )
 +		{
 +		len = 0;
 +		}
 +
 +   EnsureAlloced ( len + 1 );
 +
 +	for( i = 0; i < len; i++ )
 +		{
 +		m_data->data[ i ] = text[ start + i ];
 +		}
 +
 +	m_data->data[ len ] = 0;
 +   m_data->len = len;
 +	}
 +
 +inline idStr::idStr
 +   (
 +   const char ch
 +   ) : m_data ( NULL )
 +
 +   {
 +   EnsureAlloced ( 2 );
 +
 +   m_data->data[ 0 ] = ch;
 +   m_data->data[ 1 ] = 0;
 +   m_data->len = 1;
 +   }
 +
 +inline idStr::idStr
 +   (
 +   const float num
 +   ) : m_data ( NULL )
 +
 +   {
 +   char text[ 32 ];
 +   int len;
 +
 +   sprintf( text, "%.3f", num );
 +   len = strlen( text );
 +   EnsureAlloced( len + 1 );
 +   strcpy( m_data->data, text );
 +   m_data->len = len;
 +   }
 +
 +inline idStr::idStr
 +   (
 +   const int num
 +   ) : m_data ( NULL )
 +
 +   {
 +   char text[ 32 ];
 +   int len;
 +
 +   sprintf( text, "%d", num );
 +   len = strlen( text );
 +   EnsureAlloced( len + 1 );
 +   strcpy( m_data->data, text );
 +   m_data->len = len;
 +   }
 +
 +inline idStr::idStr
 +   (
 +   const unsigned num
 +   ) : m_data ( NULL )
 +
 +   {
 +   char text[ 32 ];
 +   int len;
 +
 +   sprintf( text, "%u", num );
 +   len = strlen( text );
 +   EnsureAlloced( len + 1 );
 +   strcpy( m_data->data, text );
 +   m_data->len = len;
 +   }
 +
 +inline int idStr::length( void ) const
 +	{
 +   return ( m_data != NULL ) ? m_data->len : 0;
 +	}
 +
 +inline int idStr::allocated( void ) const
 +	{
 +   return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
 +	}
 +
 +inline const char *idStr::c_str( void ) const
 +	{
 +	assert( m_data );
 +
 +	return m_data->data;
 +	}
 +
 +inline void idStr::append
 +	(
 +	const char *text
 +	)
 +
 +	{
 +   int len;
 +
 +	assert( text );
 +
 +	if ( text )
 +		{
 +		len = length() + strlen( text );
 +		EnsureAlloced( len + 1 );
 +
 +      strcat( m_data->data, text );
 +      m_data->len = len;
 +		}
 +	}
 +
 +inline void idStr::append
 +	(
 +	const idStr& text
 +	)
 +
 +	{
 +   int len;
 +
 +   len = length() + text.length();
 +   EnsureAlloced ( len + 1 );
 +
 +   strcat ( m_data->data, text.c_str () );
 +   m_data->len = len;
 +	}
 +
 +inline char idStr::operator[]( int index ) const
 +	{
 +   assert ( m_data );
 +   
 +   if ( !m_data )
 +      return 0;
 +
 +	// don't include the '/0' in the test, because technically, it's out of bounds
 +	assert( ( index >= 0 ) && ( index < m_data->len ) );
 +
 +	// In release mode, give them a null character
 +	// don't include the '/0' in the test, because technically, it's out of bounds
 +	if ( ( index < 0 ) || ( index >= m_data->len ) )
 +		{
 +		return 0;
 +		}
 +
 +	return m_data->data[ index ];
 +	}
 +
 +inline char& idStr::operator[]
 +	(
 +	int index
 +	)
 +
 +	{
 +	// Used for result for invalid indices
 +	static char dummy = 0;
 +   assert ( m_data );
 +
 +   // We don't know if they'll write to it or not
 +   // if it's not a const object
 +   EnsureDataWritable ();
 +
 +   if ( !m_data )
 +      return dummy;
 +
 +	// don't include the '/0' in the test, because technically, it's out of bounds
 +	assert( ( index >= 0 ) && ( index < m_data->len ) );
 +
 +	// In release mode, let them change a safe variable
 +	// don't include the '/0' in the test, because technically, it's out of bounds
 +	if ( ( index < 0 ) || ( index >= m_data->len ) )
 +		{
 +		return dummy;
 +		}
 +
 +	return m_data->data[ index ];
 +	}
 +
 +inline void idStr::operator=
 +	(
 +	const idStr& text
 +	)
 +
 +	{
 +   // adding the reference before deleting our current reference prevents
 +   // us from deleting our string if we are copying from ourself
 +   text.m_data->AddRef();
 +   m_data->DelRef();
 +   m_data = text.m_data;
 +   }
 +
 +inline void idStr::operator=
 +	(
 +	const char *text
 +	)
 +
 +	{
 +   int len;
 +
 +	assert( text );
 +
 +	if ( !text )
 +		{
 +		// safe behaviour if NULL
 +		EnsureAlloced ( 1, false );
 +      m_data->data[0] = 0;
 +      m_data->len = 0;
 +      return;
 +		}
 +
 +   if ( !m_data )
 +      {
 +      len = strlen ( text );
 +      EnsureAlloced( len + 1, false );
 +      strcpy ( m_data->data, text );
 +      m_data->len = len;
 +      return;
 +      }
 +
 +   if ( text == m_data->data )
 +      return; // Copying same thing.  Punt.
 +
 +   // If we alias and I don't do this, I could corrupt other strings...  This 
 +   // will get called with EnsureAlloced anyway
 +   EnsureDataWritable ();
 +
 +   // Now we need to check if we're aliasing..
 +   if ( text >= m_data->data && text <= m_data->data + m_data->len )
 +      {
 +      // Great, we're aliasing.  We're copying from inside ourselves.
 +      // This means that I don't have to ensure that anything is alloced,
 +      // though I'll assert just in case.
 +      int diff = text - m_data->data;
 +      int i;
 +
 +      assert ( strlen ( text ) < (unsigned) m_data->len );
 +      
 +      for ( i = 0; text[i]; i++ )
 +         {
 +         m_data->data[i] = text[i];
 +         }
 +
 +      m_data->data[i] = 0;
 +
 +      m_data->len -= diff;
 +
 +      return;
 +      }
 +
 +	len = strlen( text );
 +   EnsureAlloced ( len + 1, false );
 +	strcpy( m_data->data, text );
 +   m_data->len = len;
 +	}
 +
 +inline idStr operator+
 +	(
 +	const idStr& a,
 +	const idStr& b
 +	)
 +
 +	{
 +	idStr result( a );
 +
 +	result.append( b );
 +
 +	return result;
 +	}
 +
 +inline idStr operator+
 +	(
 +	const idStr& a,
 +	const char *b
 +	)
 +
 +	{
 +	idStr result( a );
 +
 +	result.append( b );
 +
 +	return result;
 +	}
 +
 +inline idStr operator+
 +	(
 +	const char *a,
 +	const idStr& b
 +	)
 +
 +	{
 +	idStr result( a );
 +
 +	result.append( b );
 +
 +	return result;
 +	}
 +
 +inline idStr operator+
 +   (
 +   const idStr& a,
 +   const bool b
 +   )
 +
 +   {
 +	idStr result( a );
 +
 +   result.append( b ? "true" : "false" );
 +
 +	return result;
 +   }
 +
 +inline idStr operator+
 +	(
 +   const idStr& a,
 +	const char b
 +	)
 +
 +	{
 +   char text[ 2 ];
 +
 +   text[ 0 ] = b;
 +   text[ 1 ] = 0;
 +
 +	return a + text;
 +	}
 +
 +inline idStr& idStr::operator+=
 +	(
 +	const idStr& a
 +	)
 +
 +	{
 +	append( a );
 +	return *this;
 +	}
 +
 +inline idStr& idStr::operator+=
 +	(
 +	const char *a
 +	)
 +
 +	{
 +	append( a );
 +	return *this;
 +	}
 +
 +inline idStr& idStr::operator+=
 +	(
 +	const char a
 +	)
 +
 +	{
 +   char text[ 2 ];
 +
 +   text[ 0 ] = a;
 +   text[ 1 ] = 0;
 +	append( text );
 +
 +   return *this;
 +	}
 +
 +inline idStr& idStr::operator+=
 +	(
 +	const bool a
 +	)
 +
 +	{
 +   append( a ? "true" : "false" );
 +	return *this;
 +	}
 +
 +inline bool operator==
 +	(
 +	const idStr& a,
 +	const idStr& b
 +	)
 +
 +	{
 +	return ( !strcmp( a.c_str(), b.c_str() ) );
 +	}
 +
 +inline bool operator==
 +	(
 +	const idStr& a,
 +	const char *b
 +	)
 +
 +	{
 +	assert( b );
 +	if ( !b )
 +		{
 +		return false;
 +		}
 +	return ( !strcmp( a.c_str(), b ) );
 +	}
 +
 +inline bool operator==
 +	(
 +	const char *a,
 +	const idStr& b
 +	)
 +
 +	{
 +	assert( a );
 +	if ( !a )
 +		{
 +		return false;
 +		}
 +	return ( !strcmp( a, b.c_str() ) );
 +	}
 +
 +inline bool operator!=
 +	(
 +	const idStr& a,
 +	const idStr& b
 +	)
 +
 +	{
 +	return !( a == b );
 +	}
 +
 +inline bool operator!=
 +	(
 +	const idStr& a,
 +	const char *b
 +	)
 +
 +	{
 +	return !( a == b );
 +	}
 +
 +inline bool operator!=
 +	(
 +	const char *a,
 +	const idStr& b
 +	)
 +
 +	{
 +	return !( a == b );
 +	}
 +
 +inline int idStr::icmpn
 +   (
 +   const char *text, 
 +   int n
 +   ) const
 +
 +   {
 +	assert( m_data );
 +	assert( text );
 +
 +   return idStr::icmpn( m_data->data, text, n );
 +   }
 +
 +inline int idStr::icmpn
 +   (
 +   const idStr& text, 
 +   int n
 +   ) const
 +
 +   {
 +	assert( m_data );
 +	assert( text.m_data );
 +
 +   return idStr::icmpn( m_data->data, text.m_data->data, n );
 +   }
 +
 +inline int idStr::icmp
 +   (
 +   const char *text
 +   ) const
 +
 +   {
 +	assert( m_data );
 +	assert( text );
 +
 +   return idStr::icmp( m_data->data, text );
 +   }
 +
 +inline int idStr::icmp
 +   (
 +   const idStr& text
 +   ) const
 +
 +   {
 +	assert( c_str () );
 +	assert( text.c_str () );
 +
 +   return idStr::icmp( c_str () , text.c_str () );
 +   }
 +
 +inline int idStr::cmp
 +   (
 +   const char *text
 +   ) const
 +
 +   {
 +	assert( m_data );
 +	assert( text );
 +
 +   return idStr::cmp( m_data->data, text );
 +   }
 +
 +inline int idStr::cmp
 +   (
 +   const idStr& text
 +   ) const
 +
 +   {
 +	assert( c_str () );
 +	assert( text.c_str () );
 +
 +   return idStr::cmp( c_str () , text.c_str () );
 +   }
 +
 +inline int idStr::cmpn
 +   (
 +   const char *text, 
 +   int n
 +   ) const
 +
 +   {
 +	assert( c_str () );
 +	assert( text );
 +
 +   return idStr::cmpn( c_str () , text, n );
 +   }
 +
 +inline int idStr::cmpn
 +   (
 +   const idStr& text, 
 +   int n
 +   ) const
 +
 +   {
 +	assert( c_str () );
 +	assert( text.c_str ()  );
 +
 +   return idStr::cmpn( c_str () , text.c_str () , n );
 +   }
 +
 +inline void idStr::tolower
 +   (
 +   void
 +   )
 +
 +   {
 +   assert( m_data );
 +
 +   EnsureDataWritable ();
 +
 +   idStr::tolower( m_data->data );
 +   }
 +
 +inline void idStr::toupper
 +   (
 +   void
 +   )
 +
 +   {
 +   assert( m_data );
 +
 +   EnsureDataWritable ();
 +
 +   idStr::toupper( m_data->data );
 +   }
 +
 +inline bool idStr::isNumeric
 +   (
 +   void
 +   ) const
 +
 +   {
 +   assert( m_data );
 +   return idStr::isNumeric( m_data->data );
 +   }
 +
 +inline idStr::operator const char *() {
 +	return c_str();
 +}
 +
 +inline idStr::operator const char *
 +   (
 +   void
 +   ) const
 +
 +   {
 +   return c_str ();
 +   }
 +
 +#endif
\ No newline at end of file | 
