The Quake III Arena sources as originally released under the GPL license on August 20, 2005.
This commit is contained in:
commit
dbe4ddb103
1409 changed files with 806066 additions and 0 deletions
296
q3radiant/splines/Splines.vcproj
Normal file
296
q3radiant/splines/Splines.vcproj
Normal file
|
@ -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>
|
150
q3radiant/splines/math_angles.cpp
Normal file
150
q3radiant/splines/math_angles.cpp
Normal file
|
@ -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;
|
||||
}
|
195
q3radiant/splines/math_angles.h
Normal file
195
q3radiant/splines/math_angles.h
Normal file
|
@ -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__ */
|
134
q3radiant/splines/math_matrix.cpp
Normal file
134
q3radiant/splines/math_matrix.cpp
Normal file
|
@ -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 );
|
||||
}
|
223
q3radiant/splines/math_matrix.h
Normal file
223
q3radiant/splines/math_matrix.h
Normal file
|
@ -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__ */
|
78
q3radiant/splines/math_quaternion.cpp
Normal file
78
q3radiant/splines/math_quaternion.cpp
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
190
q3radiant/splines/math_quaternion.h
Normal file
190
q3radiant/splines/math_quaternion.h
Normal file
|
@ -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__ */
|
144
q3radiant/splines/math_vector.cpp
Normal file
144
q3radiant/splines/math_vector.cpp
Normal file
|
@ -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;
|
||||
}
|
572
q3radiant/splines/math_vector.h
Normal file
572
q3radiant/splines/math_vector.h
Normal file
|
@ -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__ */
|
535
q3radiant/splines/q_parse.cpp
Normal file
535
q3radiant/splines/q_parse.cpp
Normal file
|
@ -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, ")" );
|
||||
}
|
||||
|
976
q3radiant/splines/q_shared.cpp
Normal file
976
q3radiant/splines/q_shared.cpp
Normal file
|
@ -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;
|
||||
}
|
798
q3radiant/splines/q_shared.h
Normal file
798
q3radiant/splines/q_shared.h
Normal file
|
@ -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
|
||||
|
1244
q3radiant/splines/splines.cpp
Normal file
1244
q3radiant/splines/splines.cpp
Normal file
File diff suppressed because it is too large
Load diff
1080
q3radiant/splines/splines.h
Normal file
1080
q3radiant/splines/splines.h
Normal file
File diff suppressed because it is too large
Load diff
346
q3radiant/splines/util_list.h
Normal file
346
q3radiant/splines/util_list.h
Normal file
|
@ -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__ */
|
618
q3radiant/splines/util_str.cpp
Normal file
618
q3radiant/splines/util_str.cpp
Normal file
|
@ -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
|
817
q3radiant/splines/util_str.h
Normal file
817
q3radiant/splines/util_str.h
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue