diff options
Diffstat (limited to 'code/splines')
-rwxr-xr-x | code/splines/Splines.vcproj | 592 | ||||
-rwxr-xr-x | code/splines/math_angles.cpp | 300 | ||||
-rwxr-xr-x | code/splines/math_angles.h | 390 | ||||
-rwxr-xr-x | code/splines/math_matrix.cpp | 268 | ||||
-rwxr-xr-x | code/splines/math_matrix.h | 446 | ||||
-rwxr-xr-x | code/splines/math_quaternion.cpp | 156 | ||||
-rwxr-xr-x | code/splines/math_quaternion.h | 380 | ||||
-rwxr-xr-x | code/splines/math_vector.cpp | 288 | ||||
-rwxr-xr-x | code/splines/math_vector.h | 1148 | ||||
-rwxr-xr-x | code/splines/q_parse.cpp | 1070 | ||||
-rwxr-xr-x | code/splines/q_shared.cpp | 1952 | ||||
-rwxr-xr-x | code/splines/q_shared.h | 1620 | ||||
-rwxr-xr-x | code/splines/q_shared.hpp | 1620 | ||||
-rwxr-xr-x | code/splines/splines.cpp | 2500 | ||||
-rwxr-xr-x | code/splines/splines.h | 2150 | ||||
-rwxr-xr-x | code/splines/util_list.h | 692 | ||||
-rwxr-xr-x | code/splines/util_str.cpp | 1240 | ||||
-rwxr-xr-x | code/splines/util_str.h | 1634 |
18 files changed, 9223 insertions, 9223 deletions
diff --git a/code/splines/Splines.vcproj b/code/splines/Splines.vcproj index 0da2901..b39ad18 100755 --- a/code/splines/Splines.vcproj +++ b/code/splines/Splines.vcproj @@ -1,296 +1,296 @@ -<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.10"
- Name="Splines"
- SccProjectName=""$/MissionPack/code/Splines", WJNAAAAA"
- 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"
- 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"
- 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>
+<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="7.10" + Name="Splines" + SccProjectName=""$/MissionPack/code/Splines", WJNAAAAA" + 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" + 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" + BasicRuntimeChecks="3" + RuntimeLibrary="1" + RuntimeTypeInfo="TRUE" + UsePrecompiledHeader="2" + PrecompiledHeaderFile=".\Debug/Splines.pch" + AssemblerListingLocation=".\Debug/" + ObjectFile=".\Debug/" + ProgramDataBaseFileName=".\Debug/" + WarningLevel="3" + SuppressStartupBanner="TRUE" + DebugInformationFormat="4"/> + <Tool + Name="VCCustomBuildTool"/> + <Tool + Name="VCLibrarianTool" + OutputFile=".\Debug\Splines.lib" + SuppressStartupBanner="TRUE"/> + <Tool + Name="VCMIDLTool"/> + <Tool + Name="VCPostBuildEventTool"/> + <Tool + Name="VCPreBuildEventTool"/> + <Tool + Name="VCPreLinkEventTool"/> + <Tool + Name="VCResourceCompilerTool" + PreprocessorDefinitions="_DEBUG" + Culture="1033"/> + <Tool + Name="VCWebServiceProxyGeneratorTool"/> + <Tool + Name="VCXMLDataGeneratorTool"/> + <Tool + Name="VCManagedWrapperGeneratorTool"/> + <Tool + Name="VCAuxiliaryManagedWrapperGeneratorTool"/> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> + <File + RelativePath="math_angles.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="math_matrix.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="math_quaternion.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="math_vector.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="q_parse.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="q_shared.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="splines.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + <File + RelativePath="util_str.cpp"> + <FileConfiguration + Name="Release|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="2" + PreprocessorDefinitions=""/> + </FileConfiguration> + <FileConfiguration + Name="Debug|Win32"> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + PreprocessorDefinitions="" + BasicRuntimeChecks="3"/> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl"> + <File + RelativePath="math_angles.h"> + </File> + <File + RelativePath="math_matrix.h"> + </File> + <File + RelativePath="math_quaternion.h"> + </File> + <File + RelativePath="math_vector.h"> + </File> + <File + RelativePath="q_shared.h"> + </File> + <File + RelativePath="splines.h"> + </File> + <File + RelativePath="util_list.h"> + </File> + <File + RelativePath="util_str.h"> + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/code/splines/math_angles.cpp b/code/splines/math_angles.cpp index 4a1f5e7..5e6b597 100755 --- a/code/splines/math_angles.cpp +++ b/code/splines/math_angles.cpp @@ -1,150 +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;
-}
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "q_shared.h" +#include <float.h> + +angles_t ang_zero( 0.0f, 0.0f, 0.0f ); + +void toAngles( mat3_t &src, angles_t &dst ) { + double theta; + double cp; + double sp; + + sp = src[ 0 ][ 2 ]; + + // cap off our sin value so that we don't get any NANs + if ( sp > 1.0 ) { + sp = 1.0; + } else if ( sp < -1.0 ) { + sp = -1.0; + } + + theta = -asin( sp ); + cp = cos( theta ); + + if ( cp > 8192 * FLT_EPSILON ) { + dst.pitch = theta * 180 / M_PI; + dst.yaw = atan2( src[ 0 ][ 1 ], src[ 0 ][ 0 ] ) * 180 / M_PI; + dst.roll = atan2( src[ 1 ][ 2 ], src[ 2 ][ 2 ] ) * 180 / M_PI; + } else { + dst.pitch = theta * 180 / M_PI; + dst.yaw = -atan2( src[ 1 ][ 0 ], src[ 1 ][ 1 ] ) * 180 / M_PI; + dst.roll = 0; + } +} + +void toAngles( quat_t &src, angles_t &dst ) { + mat3_t temp; + + toMatrix( src, temp ); + toAngles( temp, dst ); +} + +void toAngles( idVec3_t &src, angles_t &dst ) { + dst.pitch = src[ 0 ]; + dst.yaw = src[ 1 ]; + dst.roll = src[ 2 ]; +} + +void angles_t::toVectors( idVec3_t *forward, idVec3_t *right, idVec3_t *up ) { + float angle; + static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs + + angle = yaw * ( M_PI * 2 / 360 ); + sy = sin( angle ); + cy = cos( angle ); + + angle = pitch * ( M_PI * 2 / 360 ); + sp = sin( angle ); + cp = cos( angle ); + + angle = roll * ( M_PI * 2 / 360 ); + sr = sin( angle ); + cr = cos( angle ); + + if ( forward ) { + forward->set( cp * cy, cp * sy, -sp ); + } + + if ( right ) { + right->set( -sr * sp * cy + cr * sy, -sr * sp * sy + -cr * cy, -sr * cp ); + } + + if ( up ) { + up->set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp ); + } +} + +idVec3_t angles_t::toForward( void ) { + float angle; + static float sp, sy, cp, cy; // static to help MS compiler fp bugs + + angle = yaw * ( M_PI * 2 / 360 ); + sy = sin( angle ); + cy = cos( angle ); + + angle = pitch * ( M_PI * 2 / 360 ); + sp = sin( angle ); + cp = cos( angle ); + + return idVec3_t( cp * cy, cp * sy, -sp ); +} + +/* +================= +Normalize360 + +returns angles normalized to the range [0 <= angle < 360] +================= +*/ +angles_t& angles_t::Normalize360( void ) { + pitch = (360.0 / 65536) * ( ( int )( pitch * ( 65536 / 360.0 ) ) & 65535 ); + yaw = (360.0 / 65536) * ( ( int )( yaw * ( 65536 / 360.0 ) ) & 65535 ); + roll = (360.0 / 65536) * ( ( int )( roll * ( 65536 / 360.0 ) ) & 65535 ); + + return *this; +} + + +/* +================= +Normalize180 + +returns angles normalized to the range [-180 < angle <= 180] +================= +*/ +angles_t& angles_t::Normalize180( void ) { + Normalize360(); + + if ( pitch > 180.0 ) { + pitch -= 360.0; + } + + if ( yaw > 180.0 ) { + yaw -= 360.0; + } + + if ( roll > 180.0 ) { + roll -= 360.0; + } + return *this; +} diff --git a/code/splines/math_angles.h b/code/splines/math_angles.h index 8857f90..8e12271 100755 --- a/code/splines/math_angles.h +++ b/code/splines/math_angles.h @@ -1,195 +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__ */
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#ifndef __MATH_ANGLES_H__ +#define __MATH_ANGLES_H__ + +#include <stdlib.h> +#include <assert.h> + +#include "math_vector.h" + +class mat3_t; +class quat_t; +class idVec3_t; +typedef idVec3_t &vec3_p; + +class angles_t { +public: + float pitch; + float yaw; + float roll; + + angles_t(); + angles_t( float pitch, float yaw, float roll ); + angles_t( const idVec3_t &vec ); + + friend void toAngles( idVec3_t &src, angles_t &dst ); + friend void toAngles( quat_t &src, angles_t &dst ); + friend void toAngles( mat3_t &src, angles_t &dst ); + + operator vec3_p(); + + float operator[]( int index ) const; + float& operator[]( int index ); + + void set( float pitch, float yaw, float roll ); + + void operator=( angles_t const &a ); + void operator=( idVec3_t const &a ); + + friend angles_t operator+( const angles_t &a, const angles_t &b ); + angles_t &operator+=( angles_t const &a ); + angles_t &operator+=( idVec3_t const &a ); + + friend angles_t operator-( angles_t &a, angles_t &b ); + angles_t &operator-=( angles_t &a ); + + friend angles_t operator*( const angles_t &a, float b ); + friend angles_t operator*( float a, const angles_t &b ); + angles_t &operator*=( float a ); + + friend int operator==( angles_t &a, angles_t &b ); + + friend int operator!=( angles_t &a, angles_t &b ); + + void toVectors( idVec3_t *forward, idVec3_t *right = NULL, idVec3_t *up = NULL ); + idVec3_t toForward( void ); + + angles_t &Zero( void ); + + angles_t &Normalize360( void ); + angles_t &Normalize180( void ); +}; + +extern angles_t ang_zero; + +inline angles_t::angles_t() {} + +inline angles_t::angles_t( float pitch, float yaw, float roll ) { + this->pitch = pitch; + this->yaw = yaw; + this->roll = roll; +} + +inline angles_t::angles_t( const idVec3_t &vec ) { + this->pitch = vec.x; + this->yaw = vec.y; + this->roll = vec.z; +} + +inline float angles_t::operator[]( int index ) const { + assert( ( index >= 0 ) && ( index < 3 ) ); + return ( &pitch )[ index ]; +} + +inline float& angles_t::operator[]( int index ) { + assert( ( index >= 0 ) && ( index < 3 ) ); + return ( &pitch )[ index ]; +} + +inline angles_t::operator vec3_p( void ) { + return *( idVec3_t * )&pitch; +} + +inline void angles_t::set( float pitch, float yaw, float roll ) { + this->pitch = pitch; + this->yaw = yaw; + this->roll = roll; +} + +inline void angles_t::operator=( angles_t const &a ) { + pitch = a.pitch; + yaw = a.yaw; + roll = a.roll; +} + +inline void angles_t::operator=( idVec3_t const &a ) { + pitch = a[ 0 ]; + yaw = a[ 1 ]; + roll = a[ 2 ]; +} + +inline angles_t operator+( const angles_t &a, const angles_t &b ) { + return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll ); +} + +inline angles_t& angles_t::operator+=( angles_t const &a ) { + pitch += a.pitch; + yaw += a.yaw; + roll += a.roll; + + return *this; +} + +inline angles_t& angles_t::operator+=( idVec3_t const &a ) { + pitch += a.x; + yaw += a.y; + roll += a.z; + + return *this; +} + +inline angles_t operator-( angles_t &a, angles_t &b ) { + return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll ); +} + +inline angles_t& angles_t::operator-=( angles_t &a ) { + pitch -= a.pitch; + yaw -= a.yaw; + roll -= a.roll; + + return *this; +} + +inline angles_t operator*( const angles_t &a, float b ) { + return angles_t( a.pitch * b, a.yaw * b, a.roll * b ); +} + +inline angles_t operator*( float a, const angles_t &b ) { + return angles_t( a * b.pitch, a * b.yaw, a * b.roll ); +} + +inline angles_t& angles_t::operator*=( float a ) { + pitch *= a; + yaw *= a; + roll *= a; + + return *this; +} + +inline int operator==( angles_t &a, angles_t &b ) { + return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) ); +} + +inline int operator!=( angles_t &a, angles_t &b ) { + return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) ); +} + +inline angles_t& angles_t::Zero( void ) { + pitch = 0.0f; + yaw = 0.0f; + roll = 0.0f; + + return *this; +} + +#endif /* !__MATH_ANGLES_H__ */ diff --git a/code/splines/math_matrix.cpp b/code/splines/math_matrix.cpp index c7ae6db..5f8181a 100755 --- a/code/splines/math_matrix.cpp +++ b/code/splines/math_matrix.cpp @@ -1,134 +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 );
-}
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "q_shared.h" + +mat3_t mat3_default( idVec3_t( 1, 0, 0 ), idVec3_t( 0, 1, 0 ), idVec3_t( 0, 0, 1 ) ); + +void toMatrix( quat_t const &src, mat3_t &dst ) { + float wx, wy, wz; + float xx, yy, yz; + float xy, xz, zz; + float x2, y2, z2; + + x2 = src.x + src.x; + y2 = src.y + src.y; + z2 = src.z + src.z; + + xx = src.x * x2; + xy = src.x * y2; + xz = src.x * z2; + + yy = src.y * y2; + yz = src.y * z2; + zz = src.z * z2; + + wx = src.w * x2; + wy = src.w * y2; + wz = src.w * z2; + + dst[ 0 ][ 0 ] = 1.0f - ( yy + zz ); + dst[ 0 ][ 1 ] = xy - wz; + dst[ 0 ][ 2 ] = xz + wy; + + dst[ 1 ][ 0 ] = xy + wz; + dst[ 1 ][ 1 ] = 1.0f - ( xx + zz ); + dst[ 1 ][ 2 ] = yz - wx; + + dst[ 2 ][ 0 ] = xz - wy; + dst[ 2 ][ 1 ] = yz + wx; + dst[ 2 ][ 2 ] = 1.0f - ( xx + yy ); +} + +void toMatrix( angles_t const &src, mat3_t &dst ) { + float angle; + static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs + + angle = src.yaw * ( M_PI * 2.0f / 360.0f ); + sy = sin( angle ); + cy = cos( angle ); + + angle = src.pitch * ( M_PI * 2.0f / 360.0f ); + sp = sin( angle ); + cp = cos( angle ); + + angle = src.roll * ( M_PI * 2.0f / 360.0f ); + sr = sin( angle ); + cr = cos( angle ); + + dst[ 0 ].set( cp * cy, cp * sy, -sp ); + dst[ 1 ].set( sr * sp * cy + cr * -sy, sr * sp * sy + cr * cy, sr * cp ); + dst[ 2 ].set( cr * sp * cy + -sr * -sy, cr * sp * sy + -sr * cy, cr * cp ); +} + +void toMatrix( idVec3_t const &src, mat3_t &dst ) { + angles_t sup = src; + toMatrix(sup, dst); +} + +void mat3_t::ProjectVector( const idVec3_t &src, idVec3_t &dst ) const { + dst.x = src * mat[ 0 ]; + dst.y = src * mat[ 1 ]; + dst.z = src * mat[ 2 ]; +} + +void mat3_t::UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const { + dst = mat[ 0 ] * src.x + mat[ 1 ] * src.y + mat[ 2 ] * src.z; +} + +void mat3_t::Transpose( mat3_t &matrix ) { + int i; + int j; + + for( i = 0; i < 3; i++ ) { + for( j = 0; j < 3; j++ ) { + matrix[ i ][ j ] = mat[ j ][ i ]; + } + } +} + +void mat3_t::Transpose( void ) { + float temp; + int i; + int j; + + for( i = 0; i < 3; i++ ) { + for( j = i + 1; j < 3; j++ ) { + temp = mat[ i ][ j ]; + mat[ i ][ j ] = mat[ j ][ i ]; + mat[ j ][ i ] = temp; + } + } +} + +mat3_t mat3_t::Inverse( void ) const { + mat3_t inv( *this ); + + inv.Transpose(); + + return inv; +} + +void mat3_t::Clear( void ) { + mat[0].set( 1, 0, 0 ); + mat[1].set( 0, 1, 0 ); + mat[2].set( 0, 0, 1 ); +} diff --git a/code/splines/math_matrix.h b/code/splines/math_matrix.h index e15a001..91f146e 100755 --- a/code/splines/math_matrix.h +++ b/code/splines/math_matrix.h @@ -1,223 +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__ */
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#ifndef __MATH_MATRIX_H__ +#define __MATH_MATRIX_H__ + +#include <string.h> +#include "math_vector.h" + +#ifndef ID_INLINE +#ifdef _WIN32 +#define ID_INLINE __inline +#else +#define ID_INLINE inline +#endif +#endif + +class quat_t; +class angles_t; + +class mat3_t { +public: + idVec3_t mat[ 3 ]; + + mat3_t(); + mat3_t( float src[ 3 ][ 3 ] ); + mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z ); + mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ); + + friend void toMatrix( quat_t const &src, mat3_t &dst ); + friend void toMatrix( angles_t const &src, mat3_t &dst ); + friend void toMatrix( idVec3_t const &src, mat3_t &dst ); + + idVec3_t operator[]( int index ) const; + idVec3_t &operator[]( int index ); + + idVec3_t operator*( const idVec3_t &vec ) const; + mat3_t operator*( const mat3_t &a ) const; + mat3_t operator*( float a ) const; + mat3_t operator+( mat3_t const &a ) const; + mat3_t operator-( mat3_t const &a ) const; + + friend idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat ); + friend mat3_t operator*( float a, mat3_t const &b ); + + mat3_t &operator*=( float a ); + mat3_t &operator+=( mat3_t const &a ); + mat3_t &operator-=( mat3_t const &a ); + + void Clear( void ); + + void ProjectVector( const idVec3_t &src, idVec3_t &dst ) const; + void UnprojectVector( const idVec3_t &src, idVec3_t &dst ) const; + + void OrthoNormalize( void ); + void Transpose( mat3_t &matrix ); + void Transpose( void ); + mat3_t Inverse( void ) const; + void Identity( void ); + + friend void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ); + friend mat3_t SkewSymmetric( idVec3_t const &src ); +}; + +ID_INLINE mat3_t::mat3_t() { +} + +ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) { + memcpy( mat, src, sizeof( src ) ); +} + +ID_INLINE mat3_t::mat3_t( idVec3_t const &x, idVec3_t const &y, idVec3_t const &z ) { + mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z; + mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z; + mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z; +} + +ID_INLINE mat3_t::mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) { + mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz; + mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz; + mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz; +} + +ID_INLINE idVec3_t mat3_t::operator[]( int index ) const { + assert( ( index >= 0 ) && ( index < 3 ) ); + return mat[ index ]; +} + +ID_INLINE idVec3_t& mat3_t::operator[]( int index ) { + assert( ( index >= 0 ) && ( index < 3 ) ); + return mat[ index ]; +} + +ID_INLINE idVec3_t mat3_t::operator*( const idVec3_t &vec ) const { + return idVec3_t( + mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z, + mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z, + mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z ); +} + +ID_INLINE mat3_t mat3_t::operator*( const mat3_t &a ) const { + return mat3_t( + mat[0].x * a[0].x + mat[0].y * a[1].x + mat[0].z * a[2].x, + mat[0].x * a[0].y + mat[0].y * a[1].y + mat[0].z * a[2].y, + mat[0].x * a[0].z + mat[0].y * a[1].z + mat[0].z * a[2].z, + mat[1].x * a[0].x + mat[1].y * a[1].x + mat[1].z * a[2].x, + mat[1].x * a[0].y + mat[1].y * a[1].y + mat[1].z * a[2].y, + mat[1].x * a[0].z + mat[1].y * a[1].z + mat[1].z * a[2].z, + mat[2].x * a[0].x + mat[2].y * a[1].x + mat[2].z * a[2].x, + mat[2].x * a[0].y + mat[2].y * a[1].y + mat[2].z * a[2].y, + mat[2].x * a[0].z + mat[2].y * a[1].z + mat[2].z * a[2].z ); +} + +ID_INLINE mat3_t mat3_t::operator*( float a ) const { + return mat3_t( + mat[0].x * a, mat[0].y * a, mat[0].z * a, + mat[1].x * a, mat[1].y * a, mat[1].z * a, + mat[2].x * a, mat[2].y * a, mat[2].z * a ); +} + +ID_INLINE mat3_t mat3_t::operator+( mat3_t const &a ) const { + return mat3_t( + mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, + mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, + mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z ); +} + +ID_INLINE mat3_t mat3_t::operator-( mat3_t const &a ) const { + return mat3_t( + mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, + mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, + mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z ); +} + +ID_INLINE idVec3_t operator*( const idVec3_t &vec, const mat3_t &mat ) { + return idVec3_t( + mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z, + mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z, + mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z ); +} + +ID_INLINE mat3_t operator*( float a, mat3_t const &b ) { + return mat3_t( + b[0].x * a, b[0].y * a, b[0].z * a, + b[1].x * a, b[1].y * a, b[1].z * a, + b[2].x * a, b[2].y * a, b[2].z * a ); +} + +ID_INLINE mat3_t &mat3_t::operator*=( float a ) { + mat[0].x *= a; mat[0].y *= a; mat[0].z *= a; + mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; + mat[2].x *= a; mat[2].y *= a; mat[2].z *= a; + + return *this; +} + +ID_INLINE mat3_t &mat3_t::operator+=( mat3_t const &a ) { + mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z; + mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z; + mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z; + + return *this; +} + +ID_INLINE mat3_t &mat3_t::operator-=( mat3_t const &a ) { + mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z; + mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z; + mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z; + + return *this; +} + +ID_INLINE void mat3_t::OrthoNormalize( void ) { + mat[ 0 ].Normalize(); + mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] ); + mat[ 2 ].Normalize(); + mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] ); + mat[ 1 ].Normalize(); +} + +ID_INLINE void mat3_t::Identity( void ) { + mat[ 0 ].x = 1.f; mat[ 0 ].y = 0.f; mat[ 0 ].z = 0.f; + mat[ 1 ].x = 0.f; mat[ 1 ].y = 1.f; mat[ 1 ].z = 0.f; + mat[ 2 ].x = 0.f; mat[ 2 ].y = 0.f; mat[ 2 ].z = 1.f; +} + +ID_INLINE void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ) { + dst[0].x = inv[0].x * b[0].x + inv[1].x * b[1].x + inv[2].x * b[2].x; + dst[0].y = inv[0].x * b[0].y + inv[1].x * b[1].y + inv[2].x * b[2].y; + dst[0].z = inv[0].x * b[0].z + inv[1].x * b[1].z + inv[2].x * b[2].z; + dst[1].x = inv[0].y * b[0].x + inv[1].y * b[1].x + inv[2].y * b[2].x; + dst[1].y = inv[0].y * b[0].y + inv[1].y * b[1].y + inv[2].y * b[2].y; + dst[1].z = inv[0].y * b[0].z + inv[1].y * b[1].z + inv[2].y * b[2].z; + dst[2].x = inv[0].z * b[0].x + inv[1].z * b[1].x + inv[2].z * b[2].x; + dst[2].y = inv[0].z * b[0].y + inv[1].z * b[1].y + inv[2].z * b[2].y; + dst[2].z = inv[0].z * b[0].z + inv[1].z * b[1].z + inv[2].z * b[2].z; +} + +ID_INLINE mat3_t SkewSymmetric( idVec3_t const &src ) { + return mat3_t( 0.0f, -src.z, src.y, src.z, 0.0f, -src.x, -src.y, src.x, 0.0f ); +} + +extern mat3_t mat3_default; + +#endif /* !__MATH_MATRIX_H__ */ diff --git a/code/splines/math_quaternion.cpp b/code/splines/math_quaternion.cpp index f37a6b6..d799ce9 100755 --- a/code/splines/math_quaternion.cpp +++ b/code/splines/math_quaternion.cpp @@ -1,78 +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;
- }
-}
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#include "math_quaternion.h" +#include "math_matrix.h" + +void toQuat( idVec3_t &src, quat_t &dst ) { + dst.x = src.x; + dst.y = src.y; + dst.z = src.z; + dst.w = 0.0f; +} + +void toQuat( angles_t &src, quat_t &dst ) { + mat3_t temp; + + toMatrix( src, temp ); + toQuat( temp, dst ); +} + +void toQuat( mat3_t &src, quat_t &dst ) { + float trace; + float s; + int i; + int j; + int k; + + static int next[ 3 ] = { 1, 2, 0 }; + + trace = src[ 0 ][ 0 ] + src[ 1 ][ 1 ] + src[ 2 ][ 2 ]; + if ( trace > 0.0f ) { + s = ( float )sqrt( trace + 1.0f ); + dst.w = s * 0.5f; + s = 0.5f / s; + + dst.x = ( src[ 2 ][ 1 ] - src[ 1 ][ 2 ] ) * s; + dst.y = ( src[ 0 ][ 2 ] - src[ 2 ][ 0 ] ) * s; + dst.z = ( src[ 1 ][ 0 ] - src[ 0 ][ 1 ] ) * s; + } else { + i = 0; + if ( src[ 1 ][ 1 ] > src[ 0 ][ 0 ] ) { + i = 1; + } + if ( src[ 2 ][ 2 ] > src[ i ][ i ] ) { + i = 2; + } + + j = next[ i ]; + k = next[ j ]; + + s = ( float )sqrt( ( src[ i ][ i ] - ( src[ j ][ j ] + src[ k ][ k ] ) ) + 1.0f ); + dst[ i ] = s * 0.5f; + + s = 0.5f / s; + + dst.w = ( src[ k ][ j ] - src[ j ][ k ] ) * s; + dst[ j ] = ( src[ j ][ i ] + src[ i ][ j ] ) * s; + dst[ k ] = ( src[ k ][ i ] + src[ i ][ k ] ) * s; + } +} diff --git a/code/splines/math_quaternion.h b/code/splines/math_quaternion.h index f960aea..c899b27 100755 --- a/code/splines/math_quaternion.h +++ b/code/splines/math_quaternion.h @@ -1,190 +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__ */
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#ifndef __MATH_QUATERNION_H__ +#define __MATH_QUATERNION_H__ + +#include <assert.h> +#include <math.h> + +class idVec3_t; +class angles_t; +class mat3_t; + +class quat_t { +public: + float x; + float y; + float z; + float w; + + quat_t(); + quat_t( float x, float y, float z, float w ); + + friend void toQuat( idVec3_t &src, quat_t &dst ); + friend void toQuat( angles_t &src, quat_t &dst ); + friend void toQuat( mat3_t &src, quat_t &dst ); + + float *vec4( void ); + + float operator[]( int index ) const; + float &operator[]( int index ); + + void set( float x, float y, float z, float w ); + + void operator=( quat_t a ); + + friend quat_t operator+( quat_t a, quat_t b ); + quat_t &operator+=( quat_t a ); + + friend quat_t operator-( quat_t a, quat_t b ); + quat_t &operator-=( quat_t a ); + + friend quat_t operator*( quat_t a, float b ); + friend quat_t operator*( float a, quat_t b ); + quat_t &operator*=( float a ); + + friend int operator==( quat_t a, quat_t b ); + friend int operator!=( quat_t a, quat_t b ); + + float Length( void ); + quat_t &Normalize( void ); + + quat_t operator-(); +}; + +inline quat_t::quat_t() { +} + +inline quat_t::quat_t( float x, float y, float z, float w ) { + this->x = x; + this->y = y; + this->z = z; + this->w = w; +} + +inline float *quat_t::vec4( void ) { + return &x; +} + +inline float quat_t::operator[]( int index ) const { + assert( ( index >= 0 ) && ( index < 4 ) ); + return ( &x )[ index ]; +} + +inline float& quat_t::operator[]( int index ) { + assert( ( index >= 0 ) && ( index < 4 ) ); + return ( &x )[ index ]; +} + +inline void quat_t::set( float x, float y, float z, float w ) { + this->x = x; + this->y = y; + this->z = z; + this->w = w; +} + +inline void quat_t::operator=( quat_t a ) { + x = a.x; + y = a.y; + z = a.z; + w = a.w; +} + +inline quat_t operator+( quat_t a, quat_t b ) { + return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w ); +} + +inline quat_t& quat_t::operator+=( quat_t a ) { + x += a.x; + y += a.y; + z += a.z; + w += a.w; + + return *this; +} + +inline quat_t operator-( quat_t a, quat_t b ) { + return quat_t( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w ); +} + +inline quat_t& quat_t::operator-=( quat_t a ) { + x -= a.x; + y -= a.y; + z -= a.z; + w -= a.w; + + return *this; +} + +inline quat_t operator*( quat_t a, float b ) { + return quat_t( a.x * b, a.y * b, a.z * b, a.w * b ); +} + +inline quat_t operator*( float a, quat_t b ) { + return b * a; +} + +inline quat_t& quat_t::operator*=( float a ) { + x *= a; + y *= a; + z *= a; + w *= a; + + return *this; +} + +inline int operator==( quat_t a, quat_t b ) { + return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) ); +} + +inline int operator!=( quat_t a, quat_t b ) { + return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) ); +} + +inline float quat_t::Length( void ) { + float length; + + length = x * x + y * y + z * z + w * w; + return ( float )sqrt( length ); +} + +inline quat_t& quat_t::Normalize( void ) { + float length; + float ilength; + + length = this->Length(); + if ( length ) { + ilength = 1 / length; + x *= ilength; + y *= ilength; + z *= ilength; + w *= ilength; + } + + return *this; +} + +inline quat_t quat_t::operator-() { + return quat_t( -x, -y, -z, -w ); +} + +#endif /* !__MATH_QUATERNION_H__ */ diff --git a/code/splines/math_vector.cpp b/code/splines/math_vector.cpp index a39d859..baa93d3 100755 --- a/code/splines/math_vector.cpp +++ b/code/splines/math_vector.cpp @@ -1,144 +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;
-}
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +//#include "../game/q_shared.h" +#include "math_vector.h" +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <stdlib.h> +#include <time.h> +#include <ctype.h> + +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h + +#define LERP_DELTA 1e-6 + +idVec3_t vec_zero( 0.0f, 0.0f, 0.0f ); + +Bounds boundsZero; + +float idVec3_t::toYaw( void ) { + float yaw; + + if ( ( y == 0 ) && ( x == 0 ) ) { + yaw = 0; + } else { + yaw = atan2( y, x ) * 180 / M_PI; + if ( yaw < 0 ) { + yaw += 360; + } + } + + return yaw; +} + +float idVec3_t::toPitch( void ) { + float forward; + float pitch; + + if ( ( x == 0 ) && ( y == 0 ) ) { + if ( z > 0 ) { + pitch = 90; + } else { + pitch = 270; + } + } else { + forward = ( float )idSqrt( x * x + y * y ); + pitch = atan2( z, forward ) * 180 / M_PI; + if ( pitch < 0 ) { + pitch += 360; + } + } + + return pitch; +} + +/* +angles_t idVec3_t::toAngles( void ) { + float forward; + float yaw; + float pitch; + + if ( ( x == 0 ) && ( y == 0 ) ) { + yaw = 0; + if ( z > 0 ) { + pitch = 90; + } else { + pitch = 270; + } + } else { + yaw = atan2( y, x ) * 180 / M_PI; + if ( yaw < 0 ) { + yaw += 360; + } + + forward = ( float )idSqrt( x * x + y * y ); + pitch = atan2( z, forward ) * 180 / M_PI; + if ( pitch < 0 ) { + pitch += 360; + } + } + + return angles_t( -pitch, yaw, 0 ); +} +*/ + +idVec3_t LerpVector( idVec3_t &w1, idVec3_t &w2, const float t ) { + float omega, cosom, sinom, scale0, scale1; + + cosom = w1 * w2; + if ( ( 1.0 - cosom ) > LERP_DELTA ) { + omega = acos( cosom ); + sinom = sin( omega ); + scale0 = sin( ( 1.0 - t ) * omega ) / sinom; + scale1 = sin( t * omega ) / sinom; + } else { + scale0 = 1.0 - t; + scale1 = t; + } + + return ( w1 * scale0 + w2 * scale1 ); +} + +/* +============= +idVec3_t::string + +This is just a convenience function +for printing vectors +============= +*/ +char *idVec3_t::string( void ) { + static int index = 0; + static char str[ 8 ][ 36 ]; + char *s; + + // use an array so that multiple toString's won't collide + s = str[ index ]; + index = (index + 1)&7; + + sprintf( s, "%.2f %.2f %.2f", x, y, z ); + + return s; +} diff --git a/code/splines/math_vector.h b/code/splines/math_vector.h index be4418d..188907f 100755 --- a/code/splines/math_vector.h +++ b/code/splines/math_vector.h @@ -1,574 +1,574 @@ -/*
-===========================================================================
-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__
-
-#if defined(_WIN32)
-#pragma warning(disable : 4244)
-#endif
-
-#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__ */
+/* +=========================================================================== +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__ + +#if defined(_WIN32) +#pragma warning(disable : 4244) +#endif + +#include <math.h> +#include <assert.h> + +//#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]) +//#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2]) +//#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2]) +//#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2]) +//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z]) + +//#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s)) +#define __VectorMA(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s)) +//#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0]) + +#define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3]) +#define VectorSubtract4(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3]) +#define VectorAdd4(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3]) +#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) +#define VectorScale4(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s)) +#define VectorMA4(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s)) + + +//#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) +#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) +//#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) +#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) + +#define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];} + + +//#include "util_heap.h" + +#ifndef EQUAL_EPSILON +#define EQUAL_EPSILON 0.001 +#endif + +float Q_fabs( float f ); + +#ifndef ID_INLINE +#ifdef _WIN32 +#define ID_INLINE __inline +#else +#define ID_INLINE inline +#endif +#endif + +// if this is defined, vec3 will take four elements, which may allow +// easier SIMD optimizations +//#define FAT_VEC3 +//#ifdef __ppc__ +//#pragma align(16) +//#endif + +class angles_t; +#ifdef __ppc__ +// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, +// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson +// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost. +// We'll then multiply 1/sqrt times the original value to get the sqrt. +// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive) +// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments). + +static inline float idSqrt(float x) { + const float half = 0.5; + const float one = 1.0; + float B, y0, y1; + + // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0 + if (fabs(x) == 0.0) + return x; + B = x; + +#ifdef __GNUC__ + asm("frsqrte %0,%1" : "=f" (y0) : "f" (B)); +#else + y0 = __frsqrte(B); +#endif + /* First refinement step */ + + y1 = y0 + half*y0*(one - B*y0*y0); + + /* Second refinement step -- copy the output of the last step to the input of this step */ + + y0 = y1; + y1 = y0 + half*y0*(one - B*y0*y0); + + /* Get sqrt(x) from x * 1/sqrt(x) */ + return x * y1; +} +#else +static inline double idSqrt(double x) { + return sqrt(x); +} +#endif + + +//class idVec3_t : public idHeap<idVec3_t> { +class idVec3_t { +public: +#ifndef FAT_VEC3 + float x,y,z; +#else + float x,y,z,dist; +#endif + +#ifndef FAT_VEC3 + idVec3_t() {}; +#else + idVec3_t() {dist = 0.0f;}; +#endif + idVec3_t( const float x, const float y, const float z ); + + operator float *(); + + float operator[]( const int index ) const; + float &operator[]( const int index ); + + void set( const float x, const float y, const float z ); + + idVec3_t operator-() const; + + idVec3_t &operator=( const idVec3_t &a ); + + float operator*( const idVec3_t &a ) const; + idVec3_t operator*( const float a ) const; + friend idVec3_t operator*( float a, idVec3_t b ); + + idVec3_t operator+( const idVec3_t &a ) const; + idVec3_t operator-( const idVec3_t &a ) const; + + idVec3_t &operator+=( const idVec3_t &a ); + idVec3_t &operator-=( const idVec3_t &a ); + idVec3_t &operator*=( const float a ); + + int operator==( const idVec3_t &a ) const; + int operator!=( const idVec3_t &a ) const; + + idVec3_t Cross( const idVec3_t &a ) const; + idVec3_t &Cross( const idVec3_t &a, const idVec3_t &b ); + + float Length( void ) const; + float Normalize( void ); + + void Zero( void ); + void Snap( void ); + void SnapTowards( const idVec3_t &to ); + + float toYaw( void ); + float toPitch( void ); + angles_t toAngles( void ); + friend idVec3_t LerpVector( const idVec3_t &w1, const idVec3_t &w2, const float t ); + + char *string( void ); +}; + +extern idVec3_t vec_zero; + +ID_INLINE idVec3_t::idVec3_t( const float x, const float y, const float z ) { + this->x = x; + this->y = y; + this->z = z; +#ifdef FAT_VEC3 + this->dist = 0.0f; +#endif +} + +ID_INLINE float idVec3_t::operator[]( const int index ) const { + return ( &x )[ index ]; +} + +ID_INLINE float &idVec3_t::operator[]( const int index ) { + return ( &x )[ index ]; +} + +ID_INLINE idVec3_t::operator float *( void ) { + return &x; +} + +ID_INLINE idVec3_t idVec3_t::operator-() const { + return idVec3_t( -x, -y, -z ); +} + +ID_INLINE idVec3_t &idVec3_t::operator=( const idVec3_t &a ) { + x = a.x; + y = a.y; + z = a.z; + + return *this; +} + +ID_INLINE void idVec3_t::set( const float x, const float y, const float z ) { + this->x = x; + this->y = y; + this->z = z; +} + +ID_INLINE idVec3_t idVec3_t::operator-( const idVec3_t &a ) const { + return idVec3_t( x - a.x, y - a.y, z - a.z ); +} + +ID_INLINE float idVec3_t::operator*( const idVec3_t &a ) const { + return x * a.x + y * a.y + z * a.z; +} + +ID_INLINE idVec3_t idVec3_t::operator*( const float a ) const { + return idVec3_t( x * a, y * a, z * a ); +} + +ID_INLINE idVec3_t operator*( const float a, const idVec3_t b ) { + return idVec3_t( b.x * a, b.y * a, b.z * a ); +} + +ID_INLINE idVec3_t idVec3_t::operator+( const idVec3_t &a ) const { + return idVec3_t( x + a.x, y + a.y, z + a.z ); +} + +ID_INLINE idVec3_t &idVec3_t::operator+=( const idVec3_t &a ) { + x += a.x; + y += a.y; + z += a.z; + + return *this; +} + +ID_INLINE idVec3_t &idVec3_t::operator-=( const idVec3_t &a ) { + x -= a.x; + y -= a.y; + z -= a.z; + + return *this; +} + +ID_INLINE idVec3_t &idVec3_t::operator*=( const float a ) { + x *= a; + y *= a; + z *= a; + + return *this; +} + +ID_INLINE int idVec3_t::operator==( const idVec3_t &a ) const { + if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) { + return false; + } + + if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) { + return false; + } + + if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) { + return false; + } + + return true; +} + +ID_INLINE int idVec3_t::operator!=( const idVec3_t &a ) const { + if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) { + return true; + } + + if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) { + return true; + } + + if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) { + return true; + } + + return false; +} + +ID_INLINE idVec3_t idVec3_t::Cross( const idVec3_t &a ) const { + return idVec3_t( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x ); +} + +ID_INLINE idVec3_t &idVec3_t::Cross( const idVec3_t &a, const idVec3_t &b ) { + x = a.y * b.z - a.z * b.y; + y = a.z * b.x - a.x * b.z; + z = a.x * b.y - a.y * b.x; + + return *this; +} + +ID_INLINE float idVec3_t::Length( void ) const { + float length; + + length = x * x + y * y + z * z; + return ( float )idSqrt( length ); +} + +ID_INLINE float idVec3_t::Normalize( void ) { + float length; + float ilength; + + length = this->Length(); + if ( length ) { + ilength = 1.0f / length; + x *= ilength; + y *= ilength; + z *= ilength; + } + + return length; +} + +ID_INLINE void idVec3_t::Zero( void ) { + x = 0.0f; + y = 0.0f; + z = 0.0f; +} + +ID_INLINE void idVec3_t::Snap( void ) { + x = float( int( x ) ); + y = float( int( y ) ); + z = float( int( z ) ); +} + +/* +====================== +SnapTowards + +Round a vector to integers for more efficient network +transmission, but make sure that it rounds towards a given point +rather than blindly truncating. This prevents it from truncating +into a wall. +====================== +*/ +ID_INLINE void idVec3_t::SnapTowards( const idVec3_t &to ) { + if ( to.x <= x ) { + x = float( int( x ) ); + } else { + x = float( int( x ) + 1 ); + } + + if ( to.y <= y ) { + y = float( int( y ) ); + } else { + y = float( int( y ) + 1 ); + } + + if ( to.z <= z ) { + z = float( int( z ) ); + } else { + z = float( int( z ) + 1 ); + } +} + +//=============================================================== + +class Bounds { +public: + idVec3_t b[2]; + + Bounds(); + Bounds( const idVec3_t &mins, const idVec3_t &maxs ); + + void Clear(); + void Zero(); + float Radius(); // radius from origin, not from center + idVec3_t Center(); + void AddPoint( const idVec3_t &v ); + void AddBounds( const Bounds &bb ); + bool IsCleared(); + bool ContainsPoint( const idVec3_t &p ); + bool IntersectsBounds( const Bounds &b2 ); // touching is NOT intersecting +}; + +extern Bounds boundsZero; + +ID_INLINE Bounds::Bounds(){ +} + +ID_INLINE bool Bounds::IsCleared() { + return b[0][0] > b[1][0]; +} + +ID_INLINE bool Bounds::ContainsPoint( const idVec3_t &p ) { + if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2] + || p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) { + return false; + } + return true; +} + +ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) { + if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2] + || b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) { + return false; + } + return true; +} + +ID_INLINE Bounds::Bounds( const idVec3_t &mins, const idVec3_t &maxs ) { + b[0] = mins; + b[1] = maxs; +} + +ID_INLINE idVec3_t Bounds::Center() { + return idVec3_t( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f ); +} + +ID_INLINE void Bounds::Clear() { + b[0][0] = b[0][1] = b[0][2] = 99999; + b[1][0] = b[1][1] = b[1][2] = -99999; +} + +ID_INLINE void Bounds::Zero() { + b[0][0] = b[0][1] = b[0][2] = + b[1][0] = b[1][1] = b[1][2] = 0; +} + +ID_INLINE void Bounds::AddPoint( const idVec3_t &v ) { + if ( v[0] < b[0][0]) { + b[0][0] = v[0]; + } + if ( v[0] > b[1][0]) { + b[1][0] = v[0]; + } + if ( v[1] < b[0][1] ) { + b[0][1] = v[1]; + } + if ( v[1] > b[1][1]) { + b[1][1] = v[1]; + } + if ( v[2] < b[0][2] ) { + b[0][2] = v[2]; + } + if ( v[2] > b[1][2]) { + b[1][2] = v[2]; + } +} + + +ID_INLINE void Bounds::AddBounds( const Bounds &bb ) { + if ( bb.b[0][0] < b[0][0]) { + b[0][0] = bb.b[0][0]; + } + if ( bb.b[0][1] < b[0][1]) { + b[0][1] = bb.b[0][1]; + } + if ( bb.b[0][2] < b[0][2]) { + b[0][2] = bb.b[0][2]; + } + + if ( bb.b[1][0] > b[1][0]) { + b[1][0] = bb.b[1][0]; + } + if ( bb.b[1][1] > b[1][1]) { + b[1][1] = bb.b[1][1]; + } + if ( bb.b[1][2] > b[1][2]) { + b[1][2] = bb.b[1][2]; + } +} + +ID_INLINE float Bounds::Radius( ) { + int i; + float total; + float a, aa; + + total = 0; + for (i=0 ; i<3 ; i++) { + a = (float)fabs( b[0][i] ); + aa = (float)fabs( b[1][i] ); + if ( aa > a ) { + a = aa; + } + total += a * a; + } + + return (float)idSqrt( total ); +} + +//=============================================================== + + +class idVec2_t { +public: + float x; + float y; + + operator float *(); + float operator[]( int index ) const; + float &operator[]( int index ); +}; + +ID_INLINE float idVec2_t::operator[]( int index ) const { + return ( &x )[ index ]; +} + +ID_INLINE float& idVec2_t::operator[]( int index ) { + return ( &x )[ index ]; +} + +ID_INLINE idVec2_t::operator float *( void ) { + return &x; +} + +class vec4_t : public idVec3_t { +public: +#ifndef FAT_VEC3 + float dist; +#endif + vec4_t(); + ~vec4_t() {}; + + vec4_t( float x, float y, float z, float dist ); + float operator[]( int index ) const; + float &operator[]( int index ); +}; + +ID_INLINE vec4_t::vec4_t() {} +ID_INLINE vec4_t::vec4_t( float x, float y, float z, float dist ) { + this->x = x; + this->y = y; + this->z = z; + this->dist = dist; +} + +ID_INLINE float vec4_t::operator[]( int index ) const { + return ( &x )[ index ]; +} + +ID_INLINE float& vec4_t::operator[]( int index ) { + return ( &x )[ index ]; +} + + +class idVec5_t : public idVec3_t { +public: + float s; + float t; + float operator[]( int index ) const; + float &operator[]( int index ); +}; + + +ID_INLINE float idVec5_t::operator[]( int index ) const { + return ( &x )[ index ]; +} + +ID_INLINE float& idVec5_t::operator[]( int index ) { + return ( &x )[ index ]; +} + +#endif /* !__MATH_VECTOR_H__ */ diff --git a/code/splines/q_parse.cpp b/code/splines/q_parse.cpp index 4b29ea7..33b6b4b 100755 --- a/code/splines/q_parse.cpp +++ b/code/splines/q_parse.cpp @@ -1,535 +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.hpp"
-
-/*
-============================================================================
-
-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 atoi( 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, ")" );
-}
-
+/* +=========================================================================== +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.hpp" + +/* +============================================================================ + +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 atoi( token ); +} + + + +void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ) { + const char *token; + int i; + + Com_MatchToken( buf_p, "(" ); + + for (i = 0 ; i < x ; i++) { + token = Com_Parse(buf_p); + m[i] = atof(token); + } + + Com_MatchToken( buf_p, ")" ); +} + +void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ) { + int i; + + Com_MatchToken( buf_p, "(" ); + + for (i = 0 ; i < y ; i++) { + Com_Parse1DMatrix (buf_p, x, m + i * x); + } + + Com_MatchToken( buf_p, ")" ); +} + +void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ) { + int i; + + Com_MatchToken( buf_p, "(" ); + + for (i = 0 ; i < z ; i++) { + Com_Parse2DMatrix (buf_p, y, x, m + i * x*y); + } + + Com_MatchToken( buf_p, ")" ); +} + diff --git a/code/splines/q_shared.cpp b/code/splines/q_shared.cpp index 00934dd..ecd2342 100755 --- a/code/splines/q_shared.cpp +++ b/code/splines/q_shared.cpp @@ -1,976 +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.hpp"
-
-/*
-============================================================================
-
-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;
-}
+/* +=========================================================================== +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.hpp" + +/* +============================================================================ + +GROWLISTS + +============================================================================ +*/ + +// malloc / free all in one place for debugging +extern "C" void *Com_Allocate( int bytes ); +extern "C" void Com_Dealloc( void *ptr ); + +void Com_InitGrowList( growList_t *list, int maxElements ) { + list->maxElements = maxElements; + list->currentElements = 0; + list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) ); +} + +int Com_AddToGrowList( growList_t *list, void *data ) { + void **old; + + if ( list->currentElements != list->maxElements ) { + list->elements[list->currentElements] = data; + return list->currentElements++; + } + + // grow, reallocate and move + old = list->elements; + + if ( list->maxElements < 0 ) { + Com_Error( ERR_FATAL, "Com_AddToGrowList: maxElements = %i", list->maxElements ); + } + + if ( list->maxElements == 0 ) { + // initialize the list to hold 100 elements + Com_InitGrowList( list, 100 ); + return Com_AddToGrowList( list, data ); + } + + list->maxElements *= 2; + + Com_DPrintf( "Resizing growlist to %i maxElements\n", list->maxElements ); + + list->elements = (void **)Com_Allocate( list->maxElements * sizeof( void * ) ); + + if ( !list->elements ) { + Com_Error( ERR_DROP, "Growlist alloc failed" ); + } + + memcpy( list->elements, old, list->currentElements * sizeof( void * ) ); + + Com_Dealloc( old ); + + return Com_AddToGrowList( list, data ); +} + +void *Com_GrowListElement( const growList_t *list, int index ) { + if ( index < 0 || index >= list->currentElements ) { + Com_Error( ERR_DROP, "Com_GrowListElement: %i out of range of %i", + index, list->currentElements ); + } + return list->elements[index]; +} + +int Com_IndexForGrowListElement( const growList_t *list, const void *element ) { + int i; + + for ( i = 0 ; i < list->currentElements ; i++ ) { + if ( list->elements[i] == element ) { + return i; + } + } + return -1; +} + +//============================================================================ + + +float Com_Clamp( float min, float max, float value ) { + if ( value < min ) { + return min; + } + if ( value > max ) { + return max; + } + return value; +} + +/* +============ +Com_StringContains +============ +*/ +const char *Com_StringContains( const char *str1, const char *str2, int casesensitive) { + int len, i, j; + + len = strlen(str1) - strlen(str2); + for (i = 0; i <= len; i++, str1++) { + for (j = 0; str2[j]; j++) { + if (casesensitive) { + if (str1[j] != str2[j]) { + break; + } + } + else { + if (toupper(str1[j]) != toupper(str2[j])) { + break; + } + } + } + if (!str2[j]) { + return str1; + } + } + return NULL; +} + +/* +============ +Com_Filter +============ +*/ +int Com_Filter( const char *filter, const char *name, int casesensitive) +{ + char buf[MAX_TOKEN_CHARS]; + const char *ptr; + int i, found; + + while(*filter) { + if (*filter == '*') { + filter++; + for (i = 0; *filter; i++) { + if (*filter == '*' || *filter == '?') break; + buf[i] = *filter; + filter++; + } + buf[i] = '\0'; + if (strlen(buf)) { + ptr = Com_StringContains(name, buf, casesensitive); + if (!ptr) return qfalse; + name = ptr + strlen(buf); + } + } + else if (*filter == '?') { + filter++; + name++; + } + else if (*filter == '[' && *(filter+1) == '[') { + filter++; + } + else if (*filter == '[') { + filter++; + found = qfalse; + while(*filter && !found) { + if (*filter == ']' && *(filter+1) != ']') break; + if (*(filter+1) == '-' && *(filter+2) && (*(filter+2) != ']' || *(filter+3) == ']')) { + if (casesensitive) { + if (*name >= *filter && *name <= *(filter+2)) found = qtrue; + } + else { + if (toupper(*name) >= toupper(*filter) && + toupper(*name) <= toupper(*(filter+2))) found = qtrue; + } + filter += 3; + } + else { + if (casesensitive) { + if (*filter == *name) found = qtrue; + } + else { + if (toupper(*filter) == toupper(*name)) found = qtrue; + } + filter++; + } + } + if (!found) return qfalse; + while(*filter) { + if (*filter == ']' && *(filter+1) != ']') break; + filter++; + } + filter++; + name++; + } + else { + if (casesensitive) { + if (*filter != *name) return qfalse; + } + else { + if (toupper(*filter) != toupper(*name)) return qfalse; + } + filter++; + name++; + } + } + return qtrue; +} + + +/* +================ +Com_HashString + +================ +*/ +int Com_HashString( const char *fname ) { + int i; + long hash; + char letter; + + hash = 0; + i = 0; + while (fname[i] != '\0') { + letter = tolower(fname[i]); + if (letter =='.') break; // don't include extension + if (letter =='\\') letter = '/'; // damn path names + hash+=(long)(letter)*(i+119); + i++; + } + hash &= (FILE_HASH_SIZE-1); + return hash; +} + + +/* +============ +Com_SkipPath +============ +*/ +char *Com_SkipPath (char *pathname) +{ + char *last; + + last = pathname; + while (*pathname) + { + if (*pathname=='/') + last = pathname+1; + pathname++; + } + return last; +} + +/* +============ +Com_StripExtension +============ +*/ +void Com_StripExtension( const char *in, char *out ) { + while ( *in && *in != '.' ) { + *out++ = *in++; + } + *out = 0; +} + + +/* +================== +Com_DefaultExtension +================== +*/ +void Com_DefaultExtension (char *path, int maxSize, const char *extension ) { + char oldPath[MAX_QPATH]; + char *src; + +// +// if path doesn't have a .EXT, append extension +// (extension should include the .) +// + src = path + strlen(path) - 1; + + while (*src != '/' && src != path) { + if ( *src == '.' ) { + return; // it has an extension + } + src--; + } + + Q_strncpyz( oldPath, path, sizeof( oldPath ) ); + Com_sprintf( path, maxSize, "%s%s", oldPath, extension ); +} + +/* +============================================================================ + + BYTE ORDER FUNCTIONS + +============================================================================ +*/ + +// can't just use function pointers, or dll linkage can +// mess up when qcommon is included in multiple places +static short (*_BigShort) (short l); +static short (*_LittleShort) (short l); +static int (*_BigLong) (int l); +static int (*_LittleLong) (int l); +static float (*_BigFloat) (float l); +static float (*_LittleFloat) (float l); + +short BigShort(short l){return _BigShort(l);} +short LittleShort(short l) {return _LittleShort(l);} +int BigLong (int l) {return _BigLong(l);} +int LittleLong (int l) {return _LittleLong(l);} +float BigFloat (float l) {return _BigFloat(l);} +float LittleFloat (float l) {return _LittleFloat(l);} + +short ShortSwap (short l) +{ + byte b1,b2; + + b1 = l&255; + b2 = (l>>8)&255; + + return (b1<<8) + b2; +} + +short ShortNoSwap (short l) +{ + return l; +} + +int LongSwap (int l) +{ + byte b1,b2,b3,b4; + + b1 = l&255; + b2 = (l>>8)&255; + b3 = (l>>16)&255; + b4 = (l>>24)&255; + + return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4; +} + +int LongNoSwap (int l) +{ + return l; +} + +float FloatSwap (float f) +{ + union + { + float f; + byte b[4]; + } dat1, dat2; + + + dat1.f = f; + dat2.b[0] = dat1.b[3]; + dat2.b[1] = dat1.b[2]; + dat2.b[2] = dat1.b[1]; + dat2.b[3] = dat1.b[0]; + return dat2.f; +} + +float FloatNoSwap (float f) +{ + return f; +} + +/* +================ +Swap_Init +================ +*/ +void Swap_Init (void) +{ + byte swaptest[2] = {1,0}; + +// set the byte swapping variables in a portable manner + if ( *(short *)swaptest == 1) + { + _BigShort = ShortSwap; + _LittleShort = ShortNoSwap; + _BigLong = LongSwap; + _LittleLong = LongNoSwap; + _BigFloat = FloatSwap; + _LittleFloat = FloatNoSwap; + } + else + { + _BigShort = ShortNoSwap; + _LittleShort = ShortSwap; + _BigLong = LongNoSwap; + _LittleLong = LongSwap; + _BigFloat = FloatNoSwap; + _LittleFloat = FloatSwap; + } + +} + +/* +=============== +Com_ParseInfos +=============== +*/ +int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ) { + const char *token; + int count; + char key[MAX_TOKEN_CHARS]; + + count = 0; + + while ( 1 ) { + token = Com_Parse( &buf ); + if ( !token[0] ) { + break; + } + if ( strcmp( token, "{" ) ) { + Com_Printf( "Missing { in info file\n" ); + break; + } + + if ( count == max ) { + Com_Printf( "Max infos exceeded\n" ); + break; + } + + infos[count][0] = 0; + while ( 1 ) { + token = Com_Parse( &buf ); + if ( !token[0] ) { + Com_Printf( "Unexpected end of info file\n" ); + break; + } + if ( !strcmp( token, "}" ) ) { + break; + } + Q_strncpyz( key, token, sizeof( key ) ); + + token = Com_ParseOnLine( &buf ); + if ( !token[0] ) { + token = "<NULL>"; + } + Info_SetValueForKey( infos[count], key, token ); + } + count++; + } + + return count; +} + + + +/* +============================================================================ + + LIBRARY REPLACEMENT FUNCTIONS + +============================================================================ +*/ + +int Q_isprint( int c ) +{ + if ( c >= 0x20 && c <= 0x7E ) + return ( 1 ); + return ( 0 ); +} + +int Q_islower( int c ) +{ + if (c >= 'a' && c <= 'z') + return ( 1 ); + return ( 0 ); +} + +int Q_isupper( int c ) +{ + if (c >= 'A' && c <= 'Z') + return ( 1 ); + return ( 0 ); +} + +int Q_isalpha( int c ) +{ + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + return ( 1 ); + return ( 0 ); +} + +char* Q_strrchr( const char* string, int c ) +{ + char cc = c; + char *s; + char *sp=(char *)0; + + s = (char*)string; + + while (*s) + { + if (*s == cc) + sp = s; + s++; + } + if (cc == 0) + sp = s; + + return sp; +} + +/* +============= +Q_strncpyz + +Safe strncpy that ensures a trailing zero +============= +*/ +void Q_strncpyz( char *dest, const char *src, int destsize ) { + if ( !src ) { + Com_Error( ERR_FATAL, "Q_strncpyz: NULL src" ); + } + if ( destsize < 1 ) { + Com_Error(ERR_FATAL,"Q_strncpyz: destsize < 1" ); + } + + strncpy( dest, src, destsize-1 ); + dest[destsize-1] = 0; +} + +int Q_stricmpn (const char *s1, const char *s2, int n) { + int c1, c2; + + do { + c1 = *s1++; + c2 = *s2++; + + if (!n--) { + return 0; // strings are equal until end point + } + + if (c1 != c2) { + if (c1 >= 'a' && c1 <= 'z') { + c1 -= ('a' - 'A'); + } + if (c2 >= 'a' && c2 <= 'z') { + c2 -= ('a' - 'A'); + } + if (c1 != c2) { + return c1 < c2 ? -1 : 1; + } + } + } while (c1); + + return 0; // strings are equal +} + +int Q_strncmp (const char *s1, const char *s2, int n) { + int c1, c2; + + do { + c1 = *s1++; + c2 = *s2++; + + if (!n--) { + return 0; // strings are equal until end point + } + + if (c1 != c2) { + return c1 < c2 ? -1 : 1; + } + } while (c1); + + return 0; // strings are equal +} + +int Q_stricmp (const char *s1, const char *s2) { + return Q_stricmpn (s1, s2, 99999); +} + + +char *Q_strlwr( char *s1 ) { + char *s; + + s = s1; + while ( *s ) { + *s = tolower(*s); + s++; + } + return s1; +} + +char *Q_strupr( char *s1 ) { + char *s; + + s = s1; + while ( *s ) { + *s = toupper(*s); + s++; + } + return s1; +} + + +// never goes past bounds or leaves without a terminating 0 +void Q_strcat( char *dest, int size, const char *src ) { + int l1; + + l1 = strlen( dest ); + if ( l1 >= size ) { + Com_Error( ERR_FATAL, "Q_strcat: already overflowed" ); + } + Q_strncpyz( dest + l1, src, size - l1 ); +} + + +int Q_PrintStrlen( const char *string ) { + int len; + const char *p; + + if( !string ) { + return 0; + } + + len = 0; + p = string; + while( *p ) { + if( Q_IsColorString( p ) ) { + p += 2; + continue; + } + p++; + len++; + } + + return len; +} + + +char *Q_CleanStr( char *string ) { + char* d; + char* s; + int c; + + s = string; + d = string; + while ((c = *s) != 0 ) { + if ( Q_IsColorString( s ) ) { + s++; + } + else if ( c >= 0x20 && c <= 0x7E ) { + *d++ = c; + } + s++; + } + *d = '\0'; + + return string; +} + + +void QDECL Com_sprintf( char *dest, int size, const char *fmt, ...) { + int len; + va_list argptr; + char bigbuffer[32000]; // big, but small enough to fit in PPC stack + + va_start (argptr,fmt); + len = vsprintf (bigbuffer,fmt,argptr); + va_end (argptr); + if ( len >= sizeof( bigbuffer ) ) { + Com_Error( ERR_FATAL, "Com_sprintf: overflowed bigbuffer" ); + } + if (len >= size) { + Com_Printf ("Com_sprintf: overflow of %i in %i\n", len, size); + } + Q_strncpyz (dest, bigbuffer, size ); +} + + +/* +============ +va + +does a varargs printf into a temp buffer, so I don't need to have +varargs versions of all text functions. +FIXME: make this buffer size safe someday +============ +*/ +char * QDECL va( char *format, ... ) { + va_list argptr; + static char string[2][32000]; // in case va is called by nested functions + static int index = 0; + char *buf; + + buf = string[index & 1]; + index++; + + va_start (argptr, format); + vsprintf (buf, format,argptr); + va_end (argptr); + + return buf; +} + + +/* +===================================================================== + + INFO STRINGS + +===================================================================== +*/ + +/* +=============== +Info_ValueForKey + +Searches the string for the given +key and returns the associated value, or an empty string. +FIXME: overflow check? +=============== +*/ +char *Info_ValueForKey( const char *s, const char *key ) { + char pkey[MAX_INFO_KEY]; + static char value[2][MAX_INFO_VALUE]; // use two buffers so compares + // work without stomping on each other + static int valueindex = 0; + char *o; + + if ( !s || !key ) { + return ""; + } + + if ( strlen( s ) >= MAX_INFO_STRING ) { + Com_Error( ERR_DROP, "Info_ValueForKey: oversize infostring" ); + } + + valueindex ^= 1; + if (*s == '\\') + s++; + while (1) + { + o = pkey; + while (*s != '\\') + { + if (!*s) + return ""; + *o++ = *s++; + } + *o = 0; + s++; + + o = value[valueindex]; + + while (*s != '\\' && *s) + { + *o++ = *s++; + } + *o = 0; + + if (!Q_stricmp (key, pkey) ) + return value[valueindex]; + + if (!*s) + break; + s++; + } + + return ""; +} + + +/* +=================== +Info_NextPair + +Used to itterate through all the key/value pairs in an info string +=================== +*/ +void Info_NextPair( const char *(*head), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ) { + char *o; + const char *s; + + s = *head; + + if ( *s == '\\' ) { + s++; + } + key[0] = 0; + value[0] = 0; + + o = key; + while ( *s != '\\' ) { + if ( !*s ) { + *o = 0; + *head = s; + return; + } + *o++ = *s++; + } + *o = 0; + s++; + + o = value; + while ( *s != '\\' && *s ) { + *o++ = *s++; + } + *o = 0; + + *head = s; +} + + +/* +=================== +Info_RemoveKey +=================== +*/ +void Info_RemoveKey( char *s, const char *key ) { + char *start; + char pkey[MAX_INFO_KEY]; + char value[MAX_INFO_VALUE]; + char *o; + + if ( strlen( s ) >= MAX_INFO_STRING ) { + Com_Error( ERR_DROP, "Info_RemoveKey: oversize infostring" ); + } + + if (strchr (key, '\\')) { + return; + } + + while (1) + { + start = s; + if (*s == '\\') + s++; + o = pkey; + while (*s != '\\') + { + if (!*s) + return; + *o++ = *s++; + } + *o = 0; + s++; + + o = value; + while (*s != '\\' && *s) + { + if (!*s) + return; + *o++ = *s++; + } + *o = 0; + + if (!strcmp (key, pkey) ) + { + strcpy (start, s); // remove this part + return; + } + + if (!*s) + return; + } + +} + + +/* +================== +Info_Validate + +Some characters are illegal in info strings because they +can mess up the server's parsing +================== +*/ +qboolean Info_Validate( const char *s ) { + if ( strchr( s, '\"' ) ) { + return qfalse; + } + if ( strchr( s, ';' ) ) { + return qfalse; + } + return qtrue; +} + +/* +================== +Info_SetValueForKey + +Changes or adds a key/value pair +================== +*/ +void Info_SetValueForKey( char *s, const char *key, const char *value ) { + char newi[MAX_INFO_STRING]; + + if ( strlen( s ) >= MAX_INFO_STRING ) { + Com_Error( ERR_DROP, "Info_SetValueForKey: oversize infostring" ); + } + + if (strchr (key, '\\') || strchr (value, '\\')) + { + Com_Printf ("Can't use keys or values with a \\\n"); + return; + } + + if (strchr (key, ';') || strchr (value, ';')) + { + Com_Printf ("Can't use keys or values with a semicolon\n"); + return; + } + + if (strchr (key, '\"') || strchr (value, '\"')) + { + Com_Printf ("Can't use keys or values with a \"\n"); + return; + } + + Info_RemoveKey (s, key); + if (!value || !strlen(value)) + return; + + Com_sprintf (newi, sizeof(newi), "\\%s\\%s", key, value); + + if (strlen(newi) + strlen(s) > MAX_INFO_STRING) + { + Com_Printf ("Info string length exceeded\n"); + return; + } + + strcat (s, newi); +} + +//==================================================================== + + +/* +=============== +ParseHex +=============== +*/ +int ParseHex( const char *text ) { + int value; + int c; + + value = 0; + while ( ( c = *text++ ) != 0 ) { + if ( c >= '0' && c <= '9' ) { + value = value * 16 + c - '0'; + continue; + } + if ( c >= 'a' && c <= 'f' ) { + value = value * 16 + 10 + c - 'a'; + continue; + } + if ( c >= 'A' && c <= 'F' ) { + value = value * 16 + 10 + c - 'A'; + continue; + } + } + + return value; +} diff --git a/code/splines/q_shared.h b/code/splines/q_shared.h index bfe0925..faaaa22 100755 --- a/code/splines/q_shared.h +++ b/code/splines/q_shared.h @@ -1,810 +1,810 @@ -/*
-===========================================================================
-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
-
-// incursion of DOOM code into the Q3A codebase
-//#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__
-
-// bk001205 - from Makefile
-#define stricmp strcasecmp
-
-#define MAC_STATIC // bk: FIXME
-
-#ifdef __i386__
-#define CPUSTRING "linux-i386"
-#elif defined __axp__
-#define CPUSTRING "linux-alpha"
-#else
-#define CPUSTRING "linux-other"
-#endif
-
-#define PATH_SEP '/'
-
-// bk001205 - try
-#ifdef Q3_STATIC
-#define GAME_HARD_LINKED
-#define CGAME_HARD_LINKED
-#define UI_HARD_LINKED
-#define BOTLIB_HARD_LINKED
-#endif
-
-#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
-
+/* +=========================================================================== +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 + +// incursion of DOOM code into the Q3A codebase +//#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__ + +// bk001205 - from Makefile +#define stricmp strcasecmp + +#define MAC_STATIC // bk: FIXME + +#ifdef __i386__ +#define CPUSTRING "linux-i386" +#elif defined __axp__ +#define CPUSTRING "linux-alpha" +#else +#define CPUSTRING "linux-other" +#endif + +#define PATH_SEP '/' + +// bk001205 - try +#ifdef Q3_STATIC +#define GAME_HARD_LINKED +#define CGAME_HARD_LINKED +#define UI_HARD_LINKED +#define BOTLIB_HARD_LINKED +#endif + +#endif + +//============================================================= + + + +typedef enum {qfalse, qtrue} qboolean; + +typedef unsigned char byte; + +#define EQUAL_EPSILON 0.001 + +typedef int qhandle_t; +typedef int sfxHandle_t; +typedef int fileHandle_t; +typedef int clipHandle_t; + +typedef enum { + INVALID_JOINT = -1 +} jointHandle_t; + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define MAX_QINT 0x7fffffff +#define MIN_QINT (-MAX_QINT-1) + +#ifndef max +#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) ) +#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) ) +#endif + +#ifndef sign +#define sign( f ) ( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) ) +#endif + +// angle indexes +#define PITCH 0 // up / down +#define YAW 1 // left / right +#define ROLL 2 // fall over + +// the game guarantees that no string from the network will ever +// exceed MAX_STRING_CHARS +#define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString +#define MAX_STRING_TOKENS 256 // max tokens resulting from Cmd_TokenizeString +#define MAX_TOKEN_CHARS 1024 // max length of an individual token + +#define MAX_INFO_STRING 1024 +#define MAX_INFO_KEY 1024 +#define MAX_INFO_VALUE 1024 + + +#define MAX_QPATH 64 // max length of a quake game pathname +#define MAX_OSPATH 128 // max length of a filesystem pathname + +#define MAX_NAME_LENGTH 32 // max length of a client name + +// paramters for command buffer stuffing +typedef enum { + EXEC_NOW, // don't return until completed, a VM should NEVER use this, + // because some commands might cause the VM to be unloaded... + EXEC_INSERT, // insert at current position, but don't run yet + EXEC_APPEND // add to end of the command buffer (normal case) +} cbufExec_t; + + +// +// these aren't needed by any of the VMs. put in another header? +// +#define MAX_MAP_AREA_BYTES 32 // bit vector of area visibility + +#undef ERR_FATAL // malloc.h on unix + +// parameters to the main Error routine +typedef enum { + ERR_NONE, + ERR_FATAL, // exit the entire game with a popup window + ERR_DROP, // print to console and disconnect from game + ERR_DISCONNECT, // don't kill server + ERR_NEED_CD // pop up the need-cd dialog +} errorParm_t; + + +// font rendering values used by ui and cgame + +#define PROP_GAP_WIDTH 3 +#define PROP_SPACE_WIDTH 8 +#define PROP_HEIGHT 27 +#define PROP_SMALL_SIZE_SCALE 0.75 + +#define BLINK_DIVISOR 200 +#define PULSE_DIVISOR 75 + +#define UI_LEFT 0x00000000 // default +#define UI_CENTER 0x00000001 +#define UI_RIGHT 0x00000002 +#define UI_FORMATMASK 0x00000007 +#define UI_SMALLFONT 0x00000010 +#define UI_BIGFONT 0x00000020 // default +#define UI_GIANTFONT 0x00000040 +#define UI_DROPSHADOW 0x00000800 +#define UI_BLINK 0x00001000 +#define UI_INVERSE 0x00002000 +#define UI_PULSE 0x00004000 + + +/* +============================================================== + +MATHLIB + +============================================================== +*/ +#ifdef __cplusplus // so we can include this in C code +#define SIDE_FRONT 0 +#define SIDE_BACK 1 +#define SIDE_ON 2 +#define SIDE_CROSS 3 + +#define Q_PI 3.14159265358979323846 +#ifndef M_PI +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif + +#include "math_vector.h" +#include "math_angles.h" +#include "math_matrix.h" +#include "math_quaternion.h" + +class idVec3_t; // for defining vectors +typedef idVec3_t &vec3_p; // for passing vectors as function arguments +typedef const idVec3_t &vec3_c; // for passing vectors as const function arguments + +class angles_t; // for defining angle vectors +typedef angles_t &angles_p; // for passing angles as function arguments +typedef const angles_t &angles_c; // for passing angles as const function arguments + +class mat3_t; // for defining matrices +typedef mat3_t &mat3_p; // for passing matrices as function arguments +typedef const mat3_t &mat3_c; // for passing matrices as const function arguments + + + +#define NUMVERTEXNORMALS 162 +extern idVec3_t bytedirs[NUMVERTEXNORMALS]; + +// all drawing is done to a 640*480 virtual screen size +// and will be automatically scaled to the real resolution +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define TINYCHAR_WIDTH (SMALLCHAR_WIDTH) +#define TINYCHAR_HEIGHT (SMALLCHAR_HEIGHT/2) + +#define SMALLCHAR_WIDTH 8 +#define SMALLCHAR_HEIGHT 16 + +#define BIGCHAR_WIDTH 16 +#define BIGCHAR_HEIGHT 16 + +#define GIANTCHAR_WIDTH 32 +#define GIANTCHAR_HEIGHT 48 + +extern vec4_t colorBlack; +extern vec4_t colorRed; +extern vec4_t colorGreen; +extern vec4_t colorBlue; +extern vec4_t colorYellow; +extern vec4_t colorMagenta; +extern vec4_t colorCyan; +extern vec4_t colorWhite; +extern vec4_t colorLtGrey; +extern vec4_t colorMdGrey; +extern vec4_t colorDkGrey; + +#define Q_COLOR_ESCAPE '^' +#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE ) + +#define COLOR_BLACK '0' +#define COLOR_RED '1' +#define COLOR_GREEN '2' +#define COLOR_YELLOW '3' +#define COLOR_BLUE '4' +#define COLOR_CYAN '5' +#define COLOR_MAGENTA '6' +#define COLOR_WHITE '7' +#define ColorIndex(c) ( ( (c) - '0' ) & 7 ) + +#define S_COLOR_BLACK "^0" +#define S_COLOR_RED "^1" +#define S_COLOR_GREEN "^2" +#define S_COLOR_YELLOW "^3" +#define S_COLOR_BLUE "^4" +#define S_COLOR_CYAN "^5" +#define S_COLOR_MAGENTA "^6" +#define S_COLOR_WHITE "^7" + +extern vec4_t g_color_table[8]; + +#define MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b +#define MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a + +#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F ) +#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI ) + +struct cplane_s; + +extern idVec3_t vec3_origin; +extern vec4_t vec4_origin; +extern mat3_t axisDefault; + +#define nanmask (255<<23) + +#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) + +float Q_fabs( float f ); +float Q_rsqrt( float f ); // reciprocal square root + +#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) ) + +signed char ClampChar( int i ); +signed short ClampShort( int i ); + +// this isn't a real cheap function to call! +int DirToByte( const idVec3_t &dir ); +void ByteToDir( int b, vec3_p dir ); + +#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]) +#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2]) +#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2]) +#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2]) +//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z]) + +#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s)) +#define VectorMA(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s)) +#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0]) + +#define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3]) +#define VectorSubtract4(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3]) +#define VectorAdd4(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3]) +#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) +#define VectorScale4(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s)) +#define VectorMA4(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s)) + + +#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) +#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) +#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) +#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) + +#define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];} + +float NormalizeColor( vec3_c in, vec3_p out ); + +int VectorCompare( vec3_c v1, vec3_c v2 ); +float VectorLength( vec3_c v ); +float Distance( vec3_c p1, vec3_c p2 ); +float DistanceSquared( vec3_c p1, vec3_c p2 ); +float VectorNormalize (vec3_p v); // returns vector length +void VectorNormalizeFast(vec3_p v); // does NOT return vector length, uses rsqrt approximation +float VectorNormalize2( vec3_c v, vec3_p out ); +void VectorInverse (vec3_p v); +void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out ); +void VectorPolar(vec3_p v, float radius, float theta, float phi); +void VectorSnap(vec3_p v); +void Vector53Copy( const idVec5_t &in, vec3_p out); +void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out); +void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out); +void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out); +void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out); + + +int Q_log2(int val); + +int Q_rand( int *seed ); +float Q_random( int *seed ); +float Q_crandom( int *seed ); + +#define random() ((rand () & 0x7fff) / ((float)0x7fff)) +#define crandom() (2.0 * (random() - 0.5)) + +float Q_rint( float in ); + +void vectoangles( vec3_c value1, angles_p angles); +void AnglesToAxis( angles_c angles, mat3_p axis ); + +void AxisCopy( mat3_c in, mat3_p out ); +qboolean AxisRotated( mat3_c in ); // assumes a non-degenerate axis + +int SignbitsForNormal( vec3_c normal ); +int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p ); + +float AngleMod(float a); +float LerpAngle (float from, float to, float frac); +float AngleSubtract( float a1, float a2 ); +void AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 ); + +float AngleNormalize360 ( float angle ); +float AngleNormalize180 ( float angle ); +float AngleDelta ( float angle1, float angle2 ); + +qboolean PlaneFromPoints( vec4_t &plane, vec3_c a, vec3_c b, vec3_c c ); +void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal ); +void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees ); +void RotateAroundDirection( mat3_p axis, float yaw ); +void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up ); +// perpendicular vector could be replaced by this + +int PlaneTypeForNormal( vec3_c normal ); + +void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out ); +void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out ); // in2 is transposed during multiply +void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out ); +void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system. +void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up); +void PerpendicularVector( vec3_p dst, vec3_c src ); + +float TriangleArea( vec3_c a, vec3_c b, vec3_c c ); +#endif // __cplusplus + +//============================================= + +float Com_Clamp( float min, float max, float value ); + +#define FILE_HASH_SIZE 1024 +int Com_HashString( const char *fname ); + +char *Com_SkipPath( char *pathname ); + +// it is ok for out == in +void Com_StripExtension( const char *in, char *out ); + +// "extension" should include the dot: ".map" +void Com_DefaultExtension( char *path, int maxSize, const char *extension ); + +int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ); + +/* +===================================================================================== + +SCRIPT PARSING + +===================================================================================== +*/ + +// this just controls the comment printing, it doesn't actually load a file +void Com_BeginParseSession( const char *filename ); +void Com_EndParseSession( void ); + +int Com_GetCurrentParseLine( void ); + +// Will never return NULL, just empty strings. +// An empty string will only be returned at end of file. +// ParseOnLine will return empty if there isn't another token on this line + +// this funny typedef just means a moving pointer into a const char * buffer +const char *Com_Parse( const char *(*data_p) ); +const char *Com_ParseOnLine( const char *(*data_p) ); +const char *Com_ParseRestOfLine( const char *(*data_p) ); + +void Com_UngetToken( void ); + +#ifdef __cplusplus +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse ); +#else +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ); +#endif + +void Com_ScriptError( const char *msg, ... ); +void Com_ScriptWarning( const char *msg, ... ); + +void Com_SkipBracedSection( const char *(*program) ); +void Com_SkipRestOfLine( const char *(*data) ); + +float Com_ParseFloat( const char *(*buf_p) ); +int Com_ParseInt( const char *(*buf_p) ); + +void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ); +void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ); +void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ); + +//===================================================================================== +#ifdef __cplusplus + extern "C" { +#endif + +void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...); + + +// mode parm for FS_FOpenFile +typedef enum { + FS_READ, + FS_WRITE, + FS_APPEND, + FS_APPEND_SYNC +} fsMode_t; + +typedef enum { + FS_SEEK_CUR, + FS_SEEK_END, + FS_SEEK_SET +} fsOrigin_t; + +//============================================= + +int Q_isprint( int c ); +int Q_islower( int c ); +int Q_isupper( int c ); +int Q_isalpha( int c ); + +// portable case insensitive compare +int Q_stricmp (const char *s1, const char *s2); +int Q_strncmp (const char *s1, const char *s2, int n); +int Q_stricmpn (const char *s1, const char *s2, int n); +char *Q_strlwr( char *s1 ); +char *Q_strupr( char *s1 ); +char *Q_strrchr( const char* string, int c ); + +// buffer size safe library replacements +void Q_strncpyz( char *dest, const char *src, int destsize ); +void Q_strcat( char *dest, int size, const char *src ); + +// strlen that discounts Quake color sequences +int Q_PrintStrlen( const char *string ); +// removes color sequences from string +char *Q_CleanStr( char *string ); + +int Com_Filter( const char *filter, const char *name, int casesensitive ); +const char *Com_StringContains( const char *str1, const char *str2, int casesensitive ); + + +//============================================= + +short BigShort(short l); +short LittleShort(short l); +int BigLong (int l); +int LittleLong (int l); +float BigFloat (float l); +float LittleFloat (float l); + +void Swap_Init (void); +char * QDECL va(char *format, ...); + +#ifdef __cplusplus + } +#endif + + +//============================================= +#ifdef __cplusplus +// +// mapfile parsing +// +typedef struct ePair_s { + char *key; + char *value; +} ePair_t; + +typedef struct mapSide_s { + char material[MAX_QPATH]; + vec4_t plane; + vec4_t textureVectors[2]; +} mapSide_t; + +typedef struct { + int numSides; + mapSide_t **sides; +} mapBrush_t; + +typedef struct { + idVec3_t xyz; + float st[2]; +} patchVertex_t; + +typedef struct { + char material[MAX_QPATH]; + int width, height; + patchVertex_t *patchVerts; +} mapPatch_t; + +typedef struct { + char modelName[MAX_QPATH]; + float matrix[16]; +} mapModel_t; + +typedef struct mapPrimitive_s { + int numEpairs; + ePair_t **ePairs; + + // only one of these will be non-NULL + mapBrush_t *brush; + mapPatch_t *patch; + mapModel_t *model; +} mapPrimitive_t; + +typedef struct mapEntity_s { + int numPrimitives; + mapPrimitive_t **primitives; + + int numEpairs; + ePair_t **ePairs; +} mapEntity_t; + +typedef struct { + int numEntities; + mapEntity_t **entities; +} mapFile_t; + + +// the order of entities, brushes, and sides will be maintained, the +// lists won't be swapped on each load or save +mapFile_t *ParseMapFile( const char *text ); +void FreeMapFile( mapFile_t *mapFile ); +void WriteMapFile( const mapFile_t *mapFile, FILE *f ); + +// key names are case-insensitive +const char *ValueForMapEntityKey( const mapEntity_t *ent, const char *key ); +float FloatForMapEntityKey( const mapEntity_t *ent, const char *key ); +qboolean GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3_t &vec ); + +typedef struct { + idVec3_t xyz; + idVec2_t st; + idVec3_t normal; + idVec3_t tangents[2]; + byte smoothing[4]; // colors for silhouette smoothing +} drawVert_t; + +typedef struct { + int width, height; + drawVert_t *verts; +} drawVertMesh_t; + +// Tesselate a map patch into smoothed, drawable vertexes +// MaxError of around 4 is reasonable +drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError ); +#endif // __cplusplus + +//========================================= + +#ifdef __cplusplus + extern "C" { +#endif + +void QDECL Com_Error( int level, const char *error, ... ); +void QDECL Com_Printf( const char *msg, ... ); +void QDECL Com_DPrintf( const char *msg, ... ); + +#ifdef __cplusplus + } +#endif + + +typedef struct { + qboolean frameMemory; + int currentElements; + int maxElements; // will reallocate and move when exceeded + void **elements; +} growList_t; + +// you don't need to init the growlist if you don't mind it growing and moving +// the list as it expands +void Com_InitGrowList( growList_t *list, int maxElements ); +int Com_AddToGrowList( growList_t *list, void *data ); +void *Com_GrowListElement( const growList_t *list, int index ); +int Com_IndexForGrowListElement( const growList_t *list, const void *element ); + + +// +// key / value info strings +// +char *Info_ValueForKey( const char *s, const char *key ); +void Info_RemoveKey( char *s, const char *key ); +void Info_SetValueForKey( char *s, const char *key, const char *value ); +qboolean Info_Validate( const char *s ); +void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ); + +// get cvar defs, collision defs, etc +//#include "../shared/interface.h" + +// get key code numbers for events +//#include "../shared/keycodes.h" + +#ifdef __cplusplus +// get the polygon winding functions +//#include "../shared/windings.h" + +// get the flags class +//#include "../shared/idflags.h" +#endif // __cplusplus + +#endif // __Q_SHARED_H + diff --git a/code/splines/q_shared.hpp b/code/splines/q_shared.hpp index bfe0925..faaaa22 100755 --- a/code/splines/q_shared.hpp +++ b/code/splines/q_shared.hpp @@ -1,810 +1,810 @@ -/*
-===========================================================================
-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
-
-// incursion of DOOM code into the Q3A codebase
-//#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__
-
-// bk001205 - from Makefile
-#define stricmp strcasecmp
-
-#define MAC_STATIC // bk: FIXME
-
-#ifdef __i386__
-#define CPUSTRING "linux-i386"
-#elif defined __axp__
-#define CPUSTRING "linux-alpha"
-#else
-#define CPUSTRING "linux-other"
-#endif
-
-#define PATH_SEP '/'
-
-// bk001205 - try
-#ifdef Q3_STATIC
-#define GAME_HARD_LINKED
-#define CGAME_HARD_LINKED
-#define UI_HARD_LINKED
-#define BOTLIB_HARD_LINKED
-#endif
-
-#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
-
+/* +=========================================================================== +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 + +// incursion of DOOM code into the Q3A codebase +//#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__ + +// bk001205 - from Makefile +#define stricmp strcasecmp + +#define MAC_STATIC // bk: FIXME + +#ifdef __i386__ +#define CPUSTRING "linux-i386" +#elif defined __axp__ +#define CPUSTRING "linux-alpha" +#else +#define CPUSTRING "linux-other" +#endif + +#define PATH_SEP '/' + +// bk001205 - try +#ifdef Q3_STATIC +#define GAME_HARD_LINKED +#define CGAME_HARD_LINKED +#define UI_HARD_LINKED +#define BOTLIB_HARD_LINKED +#endif + +#endif + +//============================================================= + + + +typedef enum {qfalse, qtrue} qboolean; + +typedef unsigned char byte; + +#define EQUAL_EPSILON 0.001 + +typedef int qhandle_t; +typedef int sfxHandle_t; +typedef int fileHandle_t; +typedef int clipHandle_t; + +typedef enum { + INVALID_JOINT = -1 +} jointHandle_t; + +#ifndef NULL +#define NULL ((void *)0) +#endif + +#define MAX_QINT 0x7fffffff +#define MIN_QINT (-MAX_QINT-1) + +#ifndef max +#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) ) +#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) ) +#endif + +#ifndef sign +#define sign( f ) ( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) ) +#endif + +// angle indexes +#define PITCH 0 // up / down +#define YAW 1 // left / right +#define ROLL 2 // fall over + +// the game guarantees that no string from the network will ever +// exceed MAX_STRING_CHARS +#define MAX_STRING_CHARS 1024 // max length of a string passed to Cmd_TokenizeString +#define MAX_STRING_TOKENS 256 // max tokens resulting from Cmd_TokenizeString +#define MAX_TOKEN_CHARS 1024 // max length of an individual token + +#define MAX_INFO_STRING 1024 +#define MAX_INFO_KEY 1024 +#define MAX_INFO_VALUE 1024 + + +#define MAX_QPATH 64 // max length of a quake game pathname +#define MAX_OSPATH 128 // max length of a filesystem pathname + +#define MAX_NAME_LENGTH 32 // max length of a client name + +// paramters for command buffer stuffing +typedef enum { + EXEC_NOW, // don't return until completed, a VM should NEVER use this, + // because some commands might cause the VM to be unloaded... + EXEC_INSERT, // insert at current position, but don't run yet + EXEC_APPEND // add to end of the command buffer (normal case) +} cbufExec_t; + + +// +// these aren't needed by any of the VMs. put in another header? +// +#define MAX_MAP_AREA_BYTES 32 // bit vector of area visibility + +#undef ERR_FATAL // malloc.h on unix + +// parameters to the main Error routine +typedef enum { + ERR_NONE, + ERR_FATAL, // exit the entire game with a popup window + ERR_DROP, // print to console and disconnect from game + ERR_DISCONNECT, // don't kill server + ERR_NEED_CD // pop up the need-cd dialog +} errorParm_t; + + +// font rendering values used by ui and cgame + +#define PROP_GAP_WIDTH 3 +#define PROP_SPACE_WIDTH 8 +#define PROP_HEIGHT 27 +#define PROP_SMALL_SIZE_SCALE 0.75 + +#define BLINK_DIVISOR 200 +#define PULSE_DIVISOR 75 + +#define UI_LEFT 0x00000000 // default +#define UI_CENTER 0x00000001 +#define UI_RIGHT 0x00000002 +#define UI_FORMATMASK 0x00000007 +#define UI_SMALLFONT 0x00000010 +#define UI_BIGFONT 0x00000020 // default +#define UI_GIANTFONT 0x00000040 +#define UI_DROPSHADOW 0x00000800 +#define UI_BLINK 0x00001000 +#define UI_INVERSE 0x00002000 +#define UI_PULSE 0x00004000 + + +/* +============================================================== + +MATHLIB + +============================================================== +*/ +#ifdef __cplusplus // so we can include this in C code +#define SIDE_FRONT 0 +#define SIDE_BACK 1 +#define SIDE_ON 2 +#define SIDE_CROSS 3 + +#define Q_PI 3.14159265358979323846 +#ifndef M_PI +#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +#endif + +#include "math_vector.h" +#include "math_angles.h" +#include "math_matrix.h" +#include "math_quaternion.h" + +class idVec3_t; // for defining vectors +typedef idVec3_t &vec3_p; // for passing vectors as function arguments +typedef const idVec3_t &vec3_c; // for passing vectors as const function arguments + +class angles_t; // for defining angle vectors +typedef angles_t &angles_p; // for passing angles as function arguments +typedef const angles_t &angles_c; // for passing angles as const function arguments + +class mat3_t; // for defining matrices +typedef mat3_t &mat3_p; // for passing matrices as function arguments +typedef const mat3_t &mat3_c; // for passing matrices as const function arguments + + + +#define NUMVERTEXNORMALS 162 +extern idVec3_t bytedirs[NUMVERTEXNORMALS]; + +// all drawing is done to a 640*480 virtual screen size +// and will be automatically scaled to the real resolution +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 + +#define TINYCHAR_WIDTH (SMALLCHAR_WIDTH) +#define TINYCHAR_HEIGHT (SMALLCHAR_HEIGHT/2) + +#define SMALLCHAR_WIDTH 8 +#define SMALLCHAR_HEIGHT 16 + +#define BIGCHAR_WIDTH 16 +#define BIGCHAR_HEIGHT 16 + +#define GIANTCHAR_WIDTH 32 +#define GIANTCHAR_HEIGHT 48 + +extern vec4_t colorBlack; +extern vec4_t colorRed; +extern vec4_t colorGreen; +extern vec4_t colorBlue; +extern vec4_t colorYellow; +extern vec4_t colorMagenta; +extern vec4_t colorCyan; +extern vec4_t colorWhite; +extern vec4_t colorLtGrey; +extern vec4_t colorMdGrey; +extern vec4_t colorDkGrey; + +#define Q_COLOR_ESCAPE '^' +#define Q_IsColorString(p) ( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE ) + +#define COLOR_BLACK '0' +#define COLOR_RED '1' +#define COLOR_GREEN '2' +#define COLOR_YELLOW '3' +#define COLOR_BLUE '4' +#define COLOR_CYAN '5' +#define COLOR_MAGENTA '6' +#define COLOR_WHITE '7' +#define ColorIndex(c) ( ( (c) - '0' ) & 7 ) + +#define S_COLOR_BLACK "^0" +#define S_COLOR_RED "^1" +#define S_COLOR_GREEN "^2" +#define S_COLOR_YELLOW "^3" +#define S_COLOR_BLUE "^4" +#define S_COLOR_CYAN "^5" +#define S_COLOR_MAGENTA "^6" +#define S_COLOR_WHITE "^7" + +extern vec4_t g_color_table[8]; + +#define MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b +#define MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a + +#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F ) +#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI ) + +struct cplane_s; + +extern idVec3_t vec3_origin; +extern vec4_t vec4_origin; +extern mat3_t axisDefault; + +#define nanmask (255<<23) + +#define IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask) + +float Q_fabs( float f ); +float Q_rsqrt( float f ); // reciprocal square root + +#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) ) + +signed char ClampChar( int i ); +signed short ClampShort( int i ); + +// this isn't a real cheap function to call! +int DirToByte( const idVec3_t &dir ); +void ByteToDir( int b, vec3_p dir ); + +#define DotProduct(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]) +#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2]) +#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2]) +#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2]) +//#define VectorCopy(a,b) ((b).x=(a).x,(b).y=(a).y,(b).z=(a).z]) + +#define VectorScale(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s)) +#define VectorMA(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s)) +#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0]) + +#define DotProduct4(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3]) +#define VectorSubtract4(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3]) +#define VectorAdd4(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3]) +#define VectorCopy4(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) +#define VectorScale4(v, s, o) ((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s)) +#define VectorMA4(v, s, b, o) ((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s)) + + +#define VectorClear(a) ((a)[0]=(a)[1]=(a)[2]=0) +#define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) +#define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) +#define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) + +#define SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];} + +float NormalizeColor( vec3_c in, vec3_p out ); + +int VectorCompare( vec3_c v1, vec3_c v2 ); +float VectorLength( vec3_c v ); +float Distance( vec3_c p1, vec3_c p2 ); +float DistanceSquared( vec3_c p1, vec3_c p2 ); +float VectorNormalize (vec3_p v); // returns vector length +void VectorNormalizeFast(vec3_p v); // does NOT return vector length, uses rsqrt approximation +float VectorNormalize2( vec3_c v, vec3_p out ); +void VectorInverse (vec3_p v); +void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out ); +void VectorPolar(vec3_p v, float radius, float theta, float phi); +void VectorSnap(vec3_p v); +void Vector53Copy( const idVec5_t &in, vec3_p out); +void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out); +void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out); +void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out); +void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out); + + +int Q_log2(int val); + +int Q_rand( int *seed ); +float Q_random( int *seed ); +float Q_crandom( int *seed ); + +#define random() ((rand () & 0x7fff) / ((float)0x7fff)) +#define crandom() (2.0 * (random() - 0.5)) + +float Q_rint( float in ); + +void vectoangles( vec3_c value1, angles_p angles); +void AnglesToAxis( angles_c angles, mat3_p axis ); + +void AxisCopy( mat3_c in, mat3_p out ); +qboolean AxisRotated( mat3_c in ); // assumes a non-degenerate axis + +int SignbitsForNormal( vec3_c normal ); +int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p ); + +float AngleMod(float a); +float LerpAngle (float from, float to, float frac); +float AngleSubtract( float a1, float a2 ); +void AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 ); + +float AngleNormalize360 ( float angle ); +float AngleNormalize180 ( float angle ); +float AngleDelta ( float angle1, float angle2 ); + +qboolean PlaneFromPoints( vec4_t &plane, vec3_c a, vec3_c b, vec3_c c ); +void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal ); +void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees ); +void RotateAroundDirection( mat3_p axis, float yaw ); +void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up ); +// perpendicular vector could be replaced by this + +int PlaneTypeForNormal( vec3_c normal ); + +void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out ); +void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out ); // in2 is transposed during multiply +void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out ); +void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system. +void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up); +void PerpendicularVector( vec3_p dst, vec3_c src ); + +float TriangleArea( vec3_c a, vec3_c b, vec3_c c ); +#endif // __cplusplus + +//============================================= + +float Com_Clamp( float min, float max, float value ); + +#define FILE_HASH_SIZE 1024 +int Com_HashString( const char *fname ); + +char *Com_SkipPath( char *pathname ); + +// it is ok for out == in +void Com_StripExtension( const char *in, char *out ); + +// "extension" should include the dot: ".map" +void Com_DefaultExtension( char *path, int maxSize, const char *extension ); + +int Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] ); + +/* +===================================================================================== + +SCRIPT PARSING + +===================================================================================== +*/ + +// this just controls the comment printing, it doesn't actually load a file +void Com_BeginParseSession( const char *filename ); +void Com_EndParseSession( void ); + +int Com_GetCurrentParseLine( void ); + +// Will never return NULL, just empty strings. +// An empty string will only be returned at end of file. +// ParseOnLine will return empty if there isn't another token on this line + +// this funny typedef just means a moving pointer into a const char * buffer +const char *Com_Parse( const char *(*data_p) ); +const char *Com_ParseOnLine( const char *(*data_p) ); +const char *Com_ParseRestOfLine( const char *(*data_p) ); + +void Com_UngetToken( void ); + +#ifdef __cplusplus +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse ); +#else +void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning ); +#endif + +void Com_ScriptError( const char *msg, ... ); +void Com_ScriptWarning( const char *msg, ... ); + +void Com_SkipBracedSection( const char *(*program) ); +void Com_SkipRestOfLine( const char *(*data) ); + +float Com_ParseFloat( const char *(*buf_p) ); +int Com_ParseInt( const char *(*buf_p) ); + +void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m ); +void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m ); +void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m ); + +//===================================================================================== +#ifdef __cplusplus + extern "C" { +#endif + +void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...); + + +// mode parm for FS_FOpenFile +typedef enum { + FS_READ, + FS_WRITE, + FS_APPEND, + FS_APPEND_SYNC +} fsMode_t; + +typedef enum { + FS_SEEK_CUR, + FS_SEEK_END, + FS_SEEK_SET +} fsOrigin_t; + +//============================================= + +int Q_isprint( int c ); +int Q_islower( int c ); +int Q_isupper( int c ); +int Q_isalpha( int c ); + +// portable case insensitive compare +int Q_stricmp (const char *s1, const char *s2); +int Q_strncmp (const char *s1, const char *s2, int n); +int Q_stricmpn (const char *s1, const char *s2, int n); +char *Q_strlwr( char *s1 ); +char *Q_strupr( char *s1 ); +char *Q_strrchr( const char* string, int c ); + +// buffer size safe library replacements +void Q_strncpyz( char *dest, const char *src, int destsize ); +void Q_strcat( char *dest, int size, const char *src ); + +// strlen that discounts Quake color sequences +int Q_PrintStrlen( const char *string ); +// removes color sequences from string +char *Q_CleanStr( char *string ); + +int Com_Filter( const char *filter, const char *name, int casesensitive ); +const char *Com_StringContains( const char *str1, const char *str2, int casesensitive ); + + +//============================================= + +short BigShort(short l); +short LittleShort(short l); +int BigLong (int l); +int LittleLong (int l); +float BigFloat (float l); +float LittleFloat (float l); + +void Swap_Init (void); +char * QDECL va(char *format, ...); + +#ifdef __cplusplus + } +#endif + + +//============================================= +#ifdef __cplusplus +// +// mapfile parsing +// +typedef struct ePair_s { + char *key; + char *value; +} ePair_t; + +typedef struct mapSide_s { + char material[MAX_QPATH]; + vec4_t plane; + vec4_t textureVectors[2]; +} mapSide_t; + +typedef struct { + int numSides; + mapSide_t **sides; +} mapBrush_t; + +typedef struct { + idVec3_t xyz; + float st[2]; +} patchVertex_t; + +typedef struct { + char material[MAX_QPATH]; + int width, height; + patchVertex_t *patchVerts; +} mapPatch_t; + +typedef struct { + char modelName[MAX_QPATH]; + float matrix[16]; +} mapModel_t; + +typedef struct mapPrimitive_s { + int numEpairs; + ePair_t **ePairs; + + // only one of these will be non-NULL + mapBrush_t *brush; + mapPatch_t *patch; + mapModel_t *model; +} mapPrimitive_t; + +typedef struct mapEntity_s { + int numPrimitives; + mapPrimitive_t **primitives; + + int numEpairs; + ePair_t **ePairs; +} mapEntity_t; + +typedef struct { + int numEntities; + mapEntity_t **entities; +} mapFile_t; + + +// the order of entities, brushes, and sides will be maintained, the +// lists won't be swapped on each load or save +mapFile_t *ParseMapFile( const char *text ); +void FreeMapFile( mapFile_t *mapFile ); +void WriteMapFile( const mapFile_t *mapFile, FILE *f ); + +// key names are case-insensitive +const char *ValueForMapEntityKey( const mapEntity_t *ent, const char *key ); +float FloatForMapEntityKey( const mapEntity_t *ent, const char *key ); +qboolean GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3_t &vec ); + +typedef struct { + idVec3_t xyz; + idVec2_t st; + idVec3_t normal; + idVec3_t tangents[2]; + byte smoothing[4]; // colors for silhouette smoothing +} drawVert_t; + +typedef struct { + int width, height; + drawVert_t *verts; +} drawVertMesh_t; + +// Tesselate a map patch into smoothed, drawable vertexes +// MaxError of around 4 is reasonable +drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError ); +#endif // __cplusplus + +//========================================= + +#ifdef __cplusplus + extern "C" { +#endif + +void QDECL Com_Error( int level, const char *error, ... ); +void QDECL Com_Printf( const char *msg, ... ); +void QDECL Com_DPrintf( const char *msg, ... ); + +#ifdef __cplusplus + } +#endif + + +typedef struct { + qboolean frameMemory; + int currentElements; + int maxElements; // will reallocate and move when exceeded + void **elements; +} growList_t; + +// you don't need to init the growlist if you don't mind it growing and moving +// the list as it expands +void Com_InitGrowList( growList_t *list, int maxElements ); +int Com_AddToGrowList( growList_t *list, void *data ); +void *Com_GrowListElement( const growList_t *list, int index ); +int Com_IndexForGrowListElement( const growList_t *list, const void *element ); + + +// +// key / value info strings +// +char *Info_ValueForKey( const char *s, const char *key ); +void Info_RemoveKey( char *s, const char *key ); +void Info_SetValueForKey( char *s, const char *key, const char *value ); +qboolean Info_Validate( const char *s ); +void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] ); + +// get cvar defs, collision defs, etc +//#include "../shared/interface.h" + +// get key code numbers for events +//#include "../shared/keycodes.h" + +#ifdef __cplusplus +// get the polygon winding functions +//#include "../shared/windings.h" + +// get the flags class +//#include "../shared/idflags.h" +#endif // __cplusplus + +#endif // __Q_SHARED_H + diff --git a/code/splines/splines.cpp b/code/splines/splines.cpp index 61830fe..9bcef08 100755 --- a/code/splines/splines.cpp +++ b/code/splines/splines.cpp @@ -1,1250 +1,1250 @@ -/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-
-//#include "stdafx.h"
-//#include "qe3.h"
-
-#include "q_shared.hpp"
-#include "splines.h"
-
-extern "C" {
-int FS_Write( const void *buffer, int len, fileHandle_t h );
-int FS_ReadFile( const char *qpath, void **buffer );
-void FS_FreeFile( void *buffer );
-fileHandle_t FS_FOpenFileWrite( const char *filename );
-void FS_FCloseFile( fileHandle_t f );
-}
-
-float Q_fabs( float f ) {
- int tmp = * ( int * ) &f;
- tmp &= 0x7FFFFFFF;
- return * ( float * ) &tmp;
-}
-
-
-//#include "../shared/windings.h"
-//#include "../qcommon/qcommon.h"
-//#include "../sys/sys_public.h"
-//#include "../game/game_entity.h"
-
-idCameraDef splineList;
-idCameraDef *g_splineList = &splineList;
-
-idVec3_t idSplineList::zero(0,0,0);
-/*
-void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label) {
- qglColor3fv(color);
- qglPointSize(size);
- qglBegin(GL_POINTS);
- qglVertex3fv(point);
- qglEnd();
- idVec3_t v = point;
- v.x += 1;
- v.y += 1;
- v.z += 1;
- qglRasterPos3fv (v);
- qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label);
-}
-
-
-void glBox(idVec3_t &color, idVec3_t &point, float size) {
- idVec3_t mins(point);
- idVec3_t maxs(point);
- mins[0] -= size;
- mins[1] += size;
- mins[2] -= size;
- maxs[0] += size;
- maxs[1] -= size;
- maxs[2] += size;
- qglColor3fv(color);
- qglBegin(GL_LINE_LOOP);
- qglVertex3f(mins[0],mins[1],mins[2]);
- qglVertex3f(maxs[0],mins[1],mins[2]);
- qglVertex3f(maxs[0],maxs[1],mins[2]);
- qglVertex3f(mins[0],maxs[1],mins[2]);
- qglEnd();
- qglBegin(GL_LINE_LOOP);
- qglVertex3f(mins[0],mins[1],maxs[2]);
- qglVertex3f(maxs[0],mins[1],maxs[2]);
- qglVertex3f(maxs[0],maxs[1],maxs[2]);
- qglVertex3f(mins[0],maxs[1],maxs[2]);
- qglEnd();
-
- qglBegin(GL_LINES);
- qglVertex3f(mins[0],mins[1],mins[2]);
- qglVertex3f(mins[0],mins[1],maxs[2]);
- qglVertex3f(mins[0],maxs[1],maxs[2]);
- qglVertex3f(mins[0],maxs[1],mins[2]);
- qglVertex3f(maxs[0],mins[1],mins[2]);
- qglVertex3f(maxs[0],mins[1],maxs[2]);
- qglVertex3f(maxs[0],maxs[1],maxs[2]);
- qglVertex3f(maxs[0],maxs[1],mins[2]);
- qglEnd();
-
-}
-
-void splineTest() {
- //g_splineList->load("p:/doom/base/maps/test_base1.camera");
-}
-
-void splineDraw() {
- //g_splineList->addToRenderer();
-}
-
-
-//extern void D_DebugLine( const idVec3_t &color, const idVec3_t &start, const idVec3_t &end );
-
-void debugLine(idVec3_t &color, float x, float y, float z, float x2, float y2, float z2) {
- //idVec3_t from(x, y, z);
- //idVec3_t to(x2, y2, z2);
- //D_DebugLine(color, from, to);
-}
-
-
-void idSplineList::addToRenderer() {
-
- if (controlPoints.Num() == 0) {
- return;
- }
-
- idVec3_t mins, maxs;
- idVec3_t yellow(1.0, 1.0, 0);
- idVec3_t white(1.0, 1.0, 1.0);
- int i;
-
- for(i = 0; i < controlPoints.Num(); i++) {
- VectorCopy(*controlPoints[i], mins);
- VectorCopy(mins, maxs);
- mins[0] -= 8;
- mins[1] += 8;
- mins[2] -= 8;
- maxs[0] += 8;
- maxs[1] -= 8;
- maxs[2] += 8;
- debugLine( yellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]);
- debugLine( yellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]);
- debugLine( yellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]);
- debugLine( yellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]);
-
- debugLine( yellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]);
- debugLine( yellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]);
- debugLine( yellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]);
- debugLine( yellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]);
-
- }
-
- int step = 0;
- idVec3_t step1;
- for(i = 3; i < controlPoints.Num(); i++) {
- for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) {
- float x = 0;
- float y = 0;
- float z = 0;
- for (int j = 0; j < 4; j++) {
- x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
- y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
- z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
- }
- if (step == 0) {
- step1[0] = x;
- step1[1] = y;
- step1[2] = z;
- step = 1;
- } else {
- debugLine( white, step1[0], step1[1], step1[2], x, y, z);
- step = 0;
- }
-
- }
- }
-}
-*/
-
-void idSplineList::buildSpline() {
- //int start = Sys_Milliseconds();
- clearSpline();
- for(int i = 3; i < controlPoints.Num(); i++) {
- for (float tension = 0.0f; tension < 1.001f; tension += granularity) {
- float x = 0;
- float y = 0;
- float z = 0;
- for (int j = 0; j < 4; j++) {
- x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension);
- y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension);
- z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension);
- }
- splinePoints.Append(new idVec3_t(x, y, z));
- }
- }
- dirty = false;
- //Com_Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000);
-}
-
-/*
-void idSplineList::draw(bool editMode) {
- int i;
- vec4_t yellow(1, 1, 0, 1);
-
- if (controlPoints.Num() == 0) {
- return;
- }
-
- if (dirty) {
- buildSpline();
- }
-
-
- qglColor3fv(controlColor);
- qglPointSize(5);
-
- qglBegin(GL_POINTS);
- for (i = 0; i < controlPoints.Num(); i++) {
- qglVertex3fv(*controlPoints[i]);
- }
- qglEnd();
-
- if (editMode) {
- for(i = 0; i < controlPoints.Num(); i++) {
- glBox(activeColor, *controlPoints[i], 4);
- }
- }
-
- //Draw the curve
- qglColor3fv(pathColor);
- qglBegin(GL_LINE_STRIP);
- int count = splinePoints.Num();
- for (i = 0; i < count; i++) {
- qglVertex3fv(*splinePoints[i]);
- }
- qglEnd();
-
- if (editMode) {
- qglColor3fv(segmentColor);
- qglPointSize(3);
- qglBegin(GL_POINTS);
- for (i = 0; i < count; i++) {
- qglVertex3fv(*splinePoints[i]);
- }
- qglEnd();
- }
- if (count > 0) {
- //assert(activeSegment >=0 && activeSegment < count);
- if (activeSegment >=0 && activeSegment < count) {
- glBox(activeColor, *splinePoints[activeSegment], 6);
- glBox(yellow, *splinePoints[activeSegment], 8);
- }
- }
-
-}
-*/
-
-float idSplineList::totalDistance() {
-
- if (controlPoints.Num() == 0) {
- return 0.0;
- }
-
- if (dirty) {
- buildSpline();
- }
-
- float dist = 0.0;
- idVec3_t temp;
- int count = splinePoints.Num();
- for(int i = 1; i < count; i++) {
- temp = *splinePoints[i-1];
- temp -= *splinePoints[i];
- dist += temp.Length();
- }
- return dist;
-}
-
-void idSplineList::initPosition(long bt, long totalTime) {
-
- if (dirty) {
- buildSpline();
- }
-
- if (splinePoints.Num() == 0) {
- return;
- }
-
- baseTime = bt;
- time = totalTime;
-
- // calc distance to travel ( this will soon be broken into time segments )
- splineTime.Clear();
- splineTime.Append(bt);
- double dist = totalDistance();
- double distSoFar = 0.0;
- idVec3_t temp;
- int count = splinePoints.Num();
- //for(int i = 2; i < count - 1; i++) {
- for(int i = 1; i < count; i++) {
- temp = *splinePoints[i-1];
- temp -= *splinePoints[i];
- distSoFar += temp.Length();
- double percent = distSoFar / dist;
- percent *= totalTime;
- splineTime.Append(percent + bt);
- }
- assert(splineTime.Num() == splinePoints.Num());
- activeSegment = 0;
-}
-
-
-
-float idSplineList::calcSpline(int step, float tension) {
- switch(step) {
- case 0: return (pow(1 - tension, 3)) / 6;
- case 1: return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6;
- case 2: return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6;
- case 3: return pow(tension, 3) / 6;
- }
- return 0.0;
-}
-
-
-
-void idSplineList::updateSelection(const idVec3_t &move) {
- if (selected) {
- dirty = true;
- VectorAdd(*selected, move, *selected);
- }
-}
-
-
-void idSplineList::setSelectedPoint(idVec3_t *p) {
- if (p) {
- p->Snap();
- for(int i = 0; i < controlPoints.Num(); i++) {
- if (*p == *controlPoints[i]) {
- selected = controlPoints[i];
- }
- }
- } else {
- selected = NULL;
- }
-}
-
-const idVec3_t *idSplineList::getPosition(long t) {
- static idVec3_t interpolatedPos;
- //static long lastTime = -1;
-
- int count = splineTime.Num();
- if (count == 0) {
- return &zero;
- }
-
- Com_Printf("Time: %d\n", t);
- assert(splineTime.Num() == splinePoints.Num());
-
- while (activeSegment < count) {
- if (splineTime[activeSegment] >= t) {
- if (activeSegment > 0 && activeSegment < count - 1) {
- double timeHi = splineTime[activeSegment + 1];
- double timeLo = splineTime[activeSegment - 1];
- double percent = (timeHi - t) / (timeHi - timeLo);
- // pick two bounding points
- idVec3_t v1 = *splinePoints[activeSegment-1];
- idVec3_t v2 = *splinePoints[activeSegment+1];
- v2 *= (1.0 - percent);
- v1 *= percent;
- v2 += v1;
- interpolatedPos = v2;
- return &interpolatedPos;
- }
- return splinePoints[activeSegment];
- } else {
- activeSegment++;
- }
- }
- return splinePoints[count-1];
-}
-
-void idSplineList::parse(const char *(*text) ) {
- const char *token;
- //Com_MatchToken( text, "{" );
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !Q_stricmp (token, "}") ) {
- break;
- }
-
- do {
- // if token is not a brace, it is a key for a key/value pair
- if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) {
- break;
- }
-
- Com_UngetToken();
- idStr key = Com_ParseOnLine(text);
- const char *token = Com_Parse(text);
- if (Q_stricmp(key.c_str(), "granularity") == 0) {
- granularity = atof(token);
- } else if (Q_stricmp(key.c_str(), "name") == 0) {
- name = token;
- }
- token = Com_Parse(text);
-
- } while (1);
-
- if ( !Q_stricmp (token, "}") ) {
- break;
- }
-
- Com_UngetToken();
- // read the control point
- idVec3_t point;
- Com_Parse1DMatrix( text, 3, point );
- addPoint(point.x, point.y, point.z);
- } while (1);
-
- //Com_UngetToken();
- //Com_MatchToken( text, "}" );
- dirty = true;
-}
-
-void idSplineList::write(fileHandle_t file, const char *p) {
- idStr s = va("\t\t%s {\n", p);
- FS_Write(s.c_str(), s.length(), file);
- //s = va("\t\tname %s\n", name.c_str());
- //FS_Write(s.c_str(), s.length(), file);
- s = va("\t\t\tgranularity %f\n", granularity);
- FS_Write(s.c_str(), s.length(), file);
- int count = controlPoints.Num();
- for (int i = 0; i < count; i++) {
- s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z);
- FS_Write(s.c_str(), s.length(), file);
- }
- s = "\t\t}\n";
- FS_Write(s.c_str(), s.length(), file);
-}
-
-
-void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) {
-#if 0
- if (!cameraSpline.validTime()) {
- buildCamera();
- }
- double d = (double)segment / numSegments();
- getCameraInfo(d * totalTime * 1000, origin, direction, fov);
-#endif
-/*
- if (!cameraSpline.validTime()) {
- buildCamera();
- }
- origin = *cameraSpline.getSegmentPoint(segment);
-
-
- idVec3_t temp;
-
- int numTargets = getTargetSpline()->controlPoints.Num();
- int count = cameraSpline.splineTime.Num();
- if (numTargets == 0) {
- // follow the path
- if (cameraSpline.getActiveSegment() < count - 1) {
- temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
- }
- } else if (numTargets == 1) {
- temp = *getTargetSpline()->controlPoints[0];
- } else {
- temp = *getTargetSpline()->getSegmentPoint(segment);
- }
-
- temp -= origin;
- temp.Normalize();
- direction = temp;
-*/
-}
-
-bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) {
-
-
- if ((time - startTime) / 1000 > totalTime) {
- return false;
- }
-
-
- for (int i = 0; i < events.Num(); i++) {
- if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) {
- events[i]->setTriggered(true);
- if (events[i]->getType() == idCameraEvent::EVENT_TARGET) {
- setActiveTargetByName(events[i]->getParam());
- getActiveTarget()->start(startTime + events[i]->getTime());
- //Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam());
- } else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) {
- //idEntity *ent = NULL;
- //ent = level.FindTarget( ent, events[i]->getParam());
- //if (ent) {
- // ent->signal( SIG_TRIGGER );
- // ent->ProcessEvent( &EV_Activate, world );
- //}
- } else if (events[i]->getType() == idCameraEvent::EVENT_FOV) {
- //*fv = fov = atof(events[i]->getParam());
- } else if (events[i]->getType() == idCameraEvent::EVENT_STOP) {
- return false;
- }
- }
- }
-
- origin = *cameraPosition->getPosition(time);
-
- *fv = fov.getFOV(time);
-
- idVec3_t temp = origin;
-
- int numTargets = targetPositions.Num();
- if (numTargets == 0) {
-/*
- // follow the path
- if (cameraSpline.getActiveSegment() < count - 1) {
- temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1];
- if (temp == origin) {
- int index = cameraSpline.getActiveSegment() + 2;
- while (temp == origin && index < count - 1) {
- temp = *cameraSpline.splinePoints[index++];
- }
- }
- }
-*/
- } else {
- temp = *getActiveTarget()->getPosition(time);
- }
-
- temp -= origin;
- temp.Normalize();
- direction = temp;
-
- return true;
-}
-
-bool idCameraDef::waitEvent(int index) {
- //for (int i = 0; i < events.Num(); i++) {
- // if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) {
- // return true;
- // }
- //}
- return false;
-}
-
-
-#define NUM_CCELERATION_SEGS 10
-#define CELL_AMT 5
-
-void idCameraDef::buildCamera() {
- int i;
- //int lastSwitch = 0;
- idList<float> waits;
- idList<int> targets;
-
- totalTime = baseTime;
- cameraPosition->setTime(totalTime * 1000);
- // we have a base time layout for the path and the target path
- // now we need to layer on any wait or speed changes
- for (i = 0; i < events.Num(); i++) {
- //idCameraEvent *ev = events[i];
- events[i]->setTriggered(false);
- switch (events[i]->getType()) {
- case idCameraEvent::EVENT_TARGET : {
- targets.Append(i);
- break;
- }
- case idCameraEvent::EVENT_WAIT : {
- waits.Append(atof(events[i]->getParam()));
- cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0);
- break;
- }
- case idCameraEvent::EVENT_TARGETWAIT : {
- //targetWaits.Append(i);
- break;
- }
- case idCameraEvent::EVENT_SPEED : {
-/*
- // take the average delay between up to the next five segments
- float adjust = atof(events[i]->getParam());
- int index = events[i]->getSegment();
- total = 0;
- count = 0;
-
- // get total amount of time over the remainder of the segment
- for (j = index; j < cameraSpline.numSegments() - 1; j++) {
- total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j);
- count++;
- }
-
- // multiply that by the adjustment
- double newTotal = total * adjust;
- // what is the difference..
- newTotal -= total;
- totalTime += newTotal / 1000;
-
- // per segment difference
- newTotal /= count;
- int additive = newTotal;
-
- // now propogate that difference out to each segment
- for (j = index; j < cameraSpline.numSegments(); j++) {
- cameraSpline.addSegmentTime(j, additive);
- additive += newTotal;
- }
- break;
-*/
- }
- default: break; // FIXME: what about other idCameraEvent?
- }
- }
-
-
- for (i = 0; i < waits.Num(); i++) {
- totalTime += waits[i];
- }
-
- // on a new target switch, we need to take time to this point ( since last target switch )
- // and allocate it across the active target, then reset time to this point
- long timeSoFar = 0;
- long total = (int)(totalTime * 1000);
- for (i = 0; i < targets.Num(); i++) {
- long t;
- if (i < targets.Num() - 1) {
- t = events[targets[i+1]]->getTime();
- } else {
- t = total - timeSoFar;
- }
- // t is how much time to use for this target
- setActiveTargetByName(events[targets[i]]->getParam());
- getActiveTarget()->setTime(t);
- timeSoFar += t;
- }
-
-
-}
-
-void idCameraDef::startCamera(long t) {
- buildCamera();
- cameraPosition->start(t);
- //for (int i = 0; i < targetPositions.Num(); i++) {
- // targetPositions[i]->
- //}
- startTime = t;
- cameraRunning = true;
-}
-
-
-void idCameraDef::parse(const char *(*text) ) {
-
- const char *token;
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !Q_stricmp (token, "}") ) {
- break;
- }
-
- if (Q_stricmp(token, "time") == 0) {
- baseTime = Com_ParseFloat(text);
- }
-
- if (Q_stricmp(token, "camera_fixed") == 0) {
- cameraPosition = new idFixedPosition();
- cameraPosition->parse(text);
- }
-
- if (Q_stricmp(token, "camera_interpolated") == 0) {
- cameraPosition = new idInterpolatedPosition();
- cameraPosition->parse(text);
- }
-
- if (Q_stricmp(token, "camera_spline") == 0) {
- cameraPosition = new idSplinePosition();
- cameraPosition->parse(text);
- }
-
- if (Q_stricmp(token, "target_fixed") == 0) {
- idFixedPosition *pos = new idFixedPosition();
- pos->parse(text);
- targetPositions.Append(pos);
- }
-
- if (Q_stricmp(token, "target_interpolated") == 0) {
- idInterpolatedPosition *pos = new idInterpolatedPosition();
- pos->parse(text);
- targetPositions.Append(pos);
- }
-
- if (Q_stricmp(token, "target_spline") == 0) {
- idSplinePosition *pos = new idSplinePosition();
- pos->parse(text);
- targetPositions.Append(pos);
- }
-
- if (Q_stricmp(token, "fov") == 0) {
- fov.parse(text);
- }
-
- if (Q_stricmp(token, "event") == 0) {
- idCameraEvent *event = new idCameraEvent();
- event->parse(text);
- addEvent(event);
- }
-
-
- } while (1);
-
- Com_UngetToken();
- Com_MatchToken( text, "}" );
-
-}
-
-qboolean idCameraDef::load(const char *filename) {
- char *buf;
- const char *buf_p;
- //int length =
- FS_ReadFile( filename, (void **)&buf );
- if ( !buf ) {
- return qfalse;
- }
-
- clear();
- Com_BeginParseSession( filename );
- buf_p = buf;
- parse(&buf_p);
- Com_EndParseSession();
- FS_FreeFile( buf );
-
- return qtrue;
-}
-
-void idCameraDef::save(const char *filename) {
- fileHandle_t file = FS_FOpenFileWrite(filename);
- if (file) {
- int i;
- idStr s = "cameraPathDef { \n";
- FS_Write(s.c_str(), s.length(), file);
- s = va("\ttime %f\n", baseTime);
- FS_Write(s.c_str(), s.length(), file);
-
- cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr()));
-
- for (i = 0; i < numTargets(); i++) {
- targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr()));
- }
-
- for (i = 0; i < events.Num(); i++) {
- events[i]->write(file, "event");
- }
-
- fov.write(file, "fov");
-
- s = "}\n";
- FS_Write(s.c_str(), s.length(), file);
- }
- FS_FCloseFile(file);
-}
-
-int idCameraDef::sortEvents(const void *p1, const void *p2) {
- idCameraEvent *ev1 = (idCameraEvent*)(p1);
- idCameraEvent *ev2 = (idCameraEvent*)(p2);
-
- if (ev1->getTime() > ev2->getTime()) {
- return -1;
- }
- if (ev1->getTime() < ev2->getTime()) {
- return 1;
- }
- return 0;
-}
-
-void idCameraDef::addEvent(idCameraEvent *event) {
- events.Append(event);
- //events.Sort(&sortEvents);
-
-}
-void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) {
- addEvent(new idCameraEvent(t, param, time));
- buildCamera();
-}
-
-
-const char *idCameraEvent::eventStr[] = {
- "NA",
- "WAIT",
- "TARGETWAIT",
- "SPEED",
- "TARGET",
- "SNAPTARGET",
- "FOV",
- "SCRIPT",
- "TRIGGER",
- "STOP"
-};
-
-void idCameraEvent::parse(const char *(*text) ) {
- const char *token;
- Com_MatchToken( text, "{" );
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- // here we may have to jump over brush epairs ( only used in editor )
- do {
- // if token is not a brace, it is a key for a key/value pair
- if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
- break;
- }
-
- Com_UngetToken();
- idStr key = Com_ParseOnLine(text);
- const char *token = Com_Parse(text);
- if (Q_stricmp(key.c_str(), "type") == 0) {
- type = static_cast<idCameraEvent::eventType>(atoi(token));
- } else if (Q_stricmp(key.c_str(), "param") == 0) {
- paramStr = token;
- } else if (Q_stricmp(key.c_str(), "time") == 0) {
- time = atoi(token);
- }
- token = Com_Parse(text);
-
- } while (1);
-
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- } while (1);
-
- Com_UngetToken();
- Com_MatchToken( text, "}" );
-}
-
-void idCameraEvent::write(fileHandle_t file, const char *name) {
- idStr s = va("\t%s {\n", name);
- FS_Write(s.c_str(), s.length(), file);
- s = va("\t\ttype %d\n", static_cast<int>(type));
- FS_Write(s.c_str(), s.length(), file);
- s = va("\t\tparam %s\n", paramStr.c_str());
- FS_Write(s.c_str(), s.length(), file);
- s = va("\t\ttime %d\n", time);
- FS_Write(s.c_str(), s.length(), file);
- s = "\t}\n";
- FS_Write(s.c_str(), s.length(), file);
-}
-
-
-const char *idCameraPosition::positionStr[] = {
- "Fixed",
- "Interpolated",
- "Spline",
-};
-
-
-
-const idVec3_t *idInterpolatedPosition::getPosition(long t) {
- static idVec3_t interpolatedPos;
-
- float velocity = getVelocity(t);
- float timePassed = t - lastTime;
- lastTime = t;
-
- // convert to seconds
- timePassed /= 1000;
-
- float distToTravel = timePassed *= velocity;
-
- idVec3_t temp = startPos;
- temp -= endPos;
- float distance = temp.Length();
-
- distSoFar += distToTravel;
- float percent = (float)(distSoFar) / distance;
-
- if (percent > 1.0) {
- percent = 1.0;
- } else if (percent < 0.0) {
- percent = 0.0;
- }
-
- // the following line does a straigt calc on percentage of time
- // float percent = (float)(startTime + time - t) / time;
-
- idVec3_t v1 = startPos;
- idVec3_t v2 = endPos;
- v1 *= (1.0 - percent);
- v2 *= percent;
- v1 += v2;
- interpolatedPos = v1;
- return &interpolatedPos;
-}
-
-
-void idCameraFOV::parse(const char *(*text) ) {
- const char *token;
- Com_MatchToken( text, "{" );
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- // here we may have to jump over brush epairs ( only used in editor )
- do {
- // if token is not a brace, it is a key for a key/value pair
- if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
- break;
- }
-
- Com_UngetToken();
- idStr key = Com_ParseOnLine(text);
- const char *token = Com_Parse(text);
- if (Q_stricmp(key.c_str(), "fov") == 0) {
- fov = atof(token);
- } else if (Q_stricmp(key.c_str(), "startFOV") == 0) {
- startFOV = atof(token);
- } else if (Q_stricmp(key.c_str(), "endFOV") == 0) {
- endFOV = atof(token);
- } else if (Q_stricmp(key.c_str(), "time") == 0) {
- time = atoi(token);
- }
- token = Com_Parse(text);
-
- } while (1);
-
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- } while (1);
-
- Com_UngetToken();
- Com_MatchToken( text, "}" );
-}
-
-bool idCameraPosition::parseToken(const char *key, const char *(*text)) {
- const char *token = Com_Parse(text);
- if (Q_stricmp(key, "time") == 0) {
- time = atol(token);
- return true;
- } else if (Q_stricmp(key, "type") == 0) {
- type = static_cast<idCameraPosition::positionType>(atoi(token));
- return true;
- } else if (Q_stricmp(key, "velocity") == 0) {
- long t = atol(token);
- token = Com_Parse(text);
- long d = atol(token);
- token = Com_Parse(text);
- float s = atof(token);
- addVelocity(t, d, s);
- return true;
- } else if (Q_stricmp(key, "baseVelocity") == 0) {
- baseVelocity = atof(token);
- return true;
- } else if (Q_stricmp(key, "name") == 0) {
- name = token;
- return true;
- } else if (Q_stricmp(key, "time") == 0) {
- time = atoi(token);
- return true;
- }
- Com_UngetToken();
- return false;
-}
-
-
-
-void idFixedPosition::parse(const char *(*text) ) {
- const char *token;
- Com_MatchToken( text, "{" );
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- // here we may have to jump over brush epairs ( only used in editor )
- do {
- // if token is not a brace, it is a key for a key/value pair
- if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
- break;
- }
-
- Com_UngetToken();
- idStr key = Com_ParseOnLine(text);
-
- const char *token = Com_Parse(text);
- if (Q_stricmp(key.c_str(), "pos") == 0) {
- Com_UngetToken();
- Com_Parse1DMatrix( text, 3, pos );
- } else {
- Com_UngetToken();
- idCameraPosition::parseToken(key.c_str(), text);
- }
- token = Com_Parse(text);
-
- } while (1);
-
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- } while (1);
-
- Com_UngetToken();
- Com_MatchToken( text, "}" );
-}
-
-void idInterpolatedPosition::parse(const char *(*text) ) {
- const char *token;
- Com_MatchToken( text, "{" );
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- // here we may have to jump over brush epairs ( only used in editor )
- do {
- // if token is not a brace, it is a key for a key/value pair
- if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
- break;
- }
-
- Com_UngetToken();
- idStr key = Com_ParseOnLine(text);
-
- const char *token = Com_Parse(text);
- if (Q_stricmp(key.c_str(), "startPos") == 0) {
- Com_UngetToken();
- Com_Parse1DMatrix( text, 3, startPos );
- } else if (Q_stricmp(key.c_str(), "endPos") == 0) {
- Com_UngetToken();
- Com_Parse1DMatrix( text, 3, endPos );
- } else {
- Com_UngetToken();
- idCameraPosition::parseToken(key.c_str(), text);
- }
- token = Com_Parse(text);
-
- } while (1);
-
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- } while (1);
-
- Com_UngetToken();
- Com_MatchToken( text, "}" );
-}
-
-
-void idSplinePosition::parse(const char *(*text) ) {
- const char *token;
- Com_MatchToken( text, "{" );
- do {
- token = Com_Parse( text );
-
- if ( !token[0] ) {
- break;
- }
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- // here we may have to jump over brush epairs ( only used in editor )
- do {
- // if token is not a brace, it is a key for a key/value pair
- if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) {
- break;
- }
-
- Com_UngetToken();
- idStr key = Com_ParseOnLine(text);
-
- const char *token = Com_Parse(text);
- if (Q_stricmp(key.c_str(), "target") == 0) {
- target.parse(text);
- } else {
- Com_UngetToken();
- idCameraPosition::parseToken(key.c_str(), text);
- }
- token = Com_Parse(text);
-
- } while (1);
-
- if ( !strcmp (token, "}") ) {
- break;
- }
-
- } while (1);
-
- Com_UngetToken();
- Com_MatchToken( text, "}" );
-}
-
-
-
-void idCameraFOV::write(fileHandle_t file, const char *p) {
- idStr s = va("\t%s {\n", p);
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\tfov %f\n", fov);
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\tstartFOV %f\n", startFOV);
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\tendFOV %f\n", endFOV);
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\ttime %i\n", time);
- FS_Write(s.c_str(), s.length(), file);
-
- s = "\t}\n";
- FS_Write(s.c_str(), s.length(), file);
-}
-
-
-void idCameraPosition::write(fileHandle_t file, const char *p) {
-
- idStr s = va("\t\ttime %i\n", time);
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\ttype %i\n", static_cast<int>(type));
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\tname %s\n", name.c_str());
- FS_Write(s.c_str(), s.length(), file);
-
- s = va("\t\tbaseVelocity %f\n", baseVelocity);
- FS_Write(s.c_str(), s.length(), file);
-
- for (int i = 0; i < velocities.Num(); i++) {
- s = va("\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed);
- FS_Write(s.c_str(), s.length(), file);
- }
-
-}
-
-void idFixedPosition::write(fileHandle_t file, const char *p) {
- idStr s = va("\t%s {\n", p);
- FS_Write(s.c_str(), s.length(), file);
- idCameraPosition::write(file, p);
- s = va("\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z);
- FS_Write(s.c_str(), s.length(), file);
- s = "\t}\n";
- FS_Write(s.c_str(), s.length(), file);
-}
-
-void idInterpolatedPosition::write(fileHandle_t file, const char *p) {
- idStr s = va("\t%s {\n", p);
- FS_Write(s.c_str(), s.length(), file);
- idCameraPosition::write(file, p);
- s = va("\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z);
- FS_Write(s.c_str(), s.length(), file);
- s = va("\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z);
- FS_Write(s.c_str(), s.length(), file);
- s = "\t}\n";
- FS_Write(s.c_str(), s.length(), file);
-}
-
-void idSplinePosition::write(fileHandle_t file, const char *p) {
- idStr s = va("\t%s {\n", p);
- FS_Write(s.c_str(), s.length(), file);
- idCameraPosition::write(file, p);
- target.write(file, "target");
- s = "\t}\n";
- FS_Write(s.c_str(), s.length(), file);
-}
-
-void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) {
- //const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name; // TTimo: unused
- idCameraPosition *pos = newFromType(type);
- if (pos) {
- pos->setName(name);
- targetPositions.Append(pos);
- activeTarget = numTargets()-1;
- if (activeTarget == 0) {
- // first one
- addEvent(idCameraEvent::EVENT_TARGET, name, 0);
- }
- }
-}
-
-
-
-idCameraDef camera;
-
-extern "C" {
-qboolean loadCamera(const char *name) {
- camera.clear();
- return static_cast<qboolean>(camera.load(name));
-}
-
-qboolean getCameraInfo(int time, float *origin, float*angles) {
- idVec3_t dir, org;
- org[0] = origin[0];
- org[1] = origin[1];
- org[2] = origin[2];
- float fov = 90;
- if (camera.getCameraInfo(time, org, dir, &fov)) {
- origin[0] = org[0];
- origin[1] = org[1];
- origin[2] = org[2];
- angles[1] = atan2 (dir[1], dir[0])*180/3.14159;
- angles[0] = asin (dir[2])*180/3.14159;
- return qtrue;
- }
- return qfalse;
-}
-
-void startCamera(int time) {
- camera.startCamera(time);
-}
-
-}
-
-
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +//#include "stdafx.h" +//#include "qe3.h" + +#include "q_shared.hpp" +#include "splines.h" + +extern "C" { +int FS_Write( const void *buffer, int len, fileHandle_t h ); +int FS_ReadFile( const char *qpath, void **buffer ); +void FS_FreeFile( void *buffer ); +fileHandle_t FS_FOpenFileWrite( const char *filename ); +void FS_FCloseFile( fileHandle_t f ); +} + +float Q_fabs( float f ) { + int tmp = * ( int * ) &f; + tmp &= 0x7FFFFFFF; + return * ( float * ) &tmp; +} + + +//#include "../shared/windings.h" +//#include "../qcommon/qcommon.h" +//#include "../sys/sys_public.h" +//#include "../game/game_entity.h" + +idCameraDef splineList; +idCameraDef *g_splineList = &splineList; + +idVec3_t idSplineList::zero(0,0,0); +/* +void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label) { + qglColor3fv(color); + qglPointSize(size); + qglBegin(GL_POINTS); + qglVertex3fv(point); + qglEnd(); + idVec3_t v = point; + v.x += 1; + v.y += 1; + v.z += 1; + qglRasterPos3fv (v); + qglCallLists (strlen(label), GL_UNSIGNED_BYTE, label); +} + + +void glBox(idVec3_t &color, idVec3_t &point, float size) { + idVec3_t mins(point); + idVec3_t maxs(point); + mins[0] -= size; + mins[1] += size; + mins[2] -= size; + maxs[0] += size; + maxs[1] -= size; + maxs[2] += size; + qglColor3fv(color); + qglBegin(GL_LINE_LOOP); + qglVertex3f(mins[0],mins[1],mins[2]); + qglVertex3f(maxs[0],mins[1],mins[2]); + qglVertex3f(maxs[0],maxs[1],mins[2]); + qglVertex3f(mins[0],maxs[1],mins[2]); + qglEnd(); + qglBegin(GL_LINE_LOOP); + qglVertex3f(mins[0],mins[1],maxs[2]); + qglVertex3f(maxs[0],mins[1],maxs[2]); + qglVertex3f(maxs[0],maxs[1],maxs[2]); + qglVertex3f(mins[0],maxs[1],maxs[2]); + qglEnd(); + + qglBegin(GL_LINES); + qglVertex3f(mins[0],mins[1],mins[2]); + qglVertex3f(mins[0],mins[1],maxs[2]); + qglVertex3f(mins[0],maxs[1],maxs[2]); + qglVertex3f(mins[0],maxs[1],mins[2]); + qglVertex3f(maxs[0],mins[1],mins[2]); + qglVertex3f(maxs[0],mins[1],maxs[2]); + qglVertex3f(maxs[0],maxs[1],maxs[2]); + qglVertex3f(maxs[0],maxs[1],mins[2]); + qglEnd(); + +} + +void splineTest() { + //g_splineList->load("p:/doom/base/maps/test_base1.camera"); +} + +void splineDraw() { + //g_splineList->addToRenderer(); +} + + +//extern void D_DebugLine( const idVec3_t &color, const idVec3_t &start, const idVec3_t &end ); + +void debugLine(idVec3_t &color, float x, float y, float z, float x2, float y2, float z2) { + //idVec3_t from(x, y, z); + //idVec3_t to(x2, y2, z2); + //D_DebugLine(color, from, to); +} + + +void idSplineList::addToRenderer() { + + if (controlPoints.Num() == 0) { + return; + } + + idVec3_t mins, maxs; + idVec3_t yellow(1.0, 1.0, 0); + idVec3_t white(1.0, 1.0, 1.0); + int i; + + for(i = 0; i < controlPoints.Num(); i++) { + VectorCopy(*controlPoints[i], mins); + VectorCopy(mins, maxs); + mins[0] -= 8; + mins[1] += 8; + mins[2] -= 8; + maxs[0] += 8; + maxs[1] -= 8; + maxs[2] += 8; + debugLine( yellow, mins[0], mins[1], mins[2], maxs[0], mins[1], mins[2]); + debugLine( yellow, maxs[0], mins[1], mins[2], maxs[0], maxs[1], mins[2]); + debugLine( yellow, maxs[0], maxs[1], mins[2], mins[0], maxs[1], mins[2]); + debugLine( yellow, mins[0], maxs[1], mins[2], mins[0], mins[1], mins[2]); + + debugLine( yellow, mins[0], mins[1], maxs[2], maxs[0], mins[1], maxs[2]); + debugLine( yellow, maxs[0], mins[1], maxs[2], maxs[0], maxs[1], maxs[2]); + debugLine( yellow, maxs[0], maxs[1], maxs[2], mins[0], maxs[1], maxs[2]); + debugLine( yellow, mins[0], maxs[1], maxs[2], mins[0], mins[1], maxs[2]); + + } + + int step = 0; + idVec3_t step1; + for(i = 3; i < controlPoints.Num(); i++) { + for (float tension = 0.0f; tension < 1.001f; tension += 0.1f) { + float x = 0; + float y = 0; + float z = 0; + for (int j = 0; j < 4; j++) { + x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension); + y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension); + z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension); + } + if (step == 0) { + step1[0] = x; + step1[1] = y; + step1[2] = z; + step = 1; + } else { + debugLine( white, step1[0], step1[1], step1[2], x, y, z); + step = 0; + } + + } + } +} +*/ + +void idSplineList::buildSpline() { + //int start = Sys_Milliseconds(); + clearSpline(); + for(int i = 3; i < controlPoints.Num(); i++) { + for (float tension = 0.0f; tension < 1.001f; tension += granularity) { + float x = 0; + float y = 0; + float z = 0; + for (int j = 0; j < 4; j++) { + x += controlPoints[i - (3 - j)]->x * calcSpline(j, tension); + y += controlPoints[i - (3 - j)]->y * calcSpline(j, tension); + z += controlPoints[i - (3 - j)]->z * calcSpline(j, tension); + } + splinePoints.Append(new idVec3_t(x, y, z)); + } + } + dirty = false; + //Com_Printf("Spline build took %f seconds\n", (float)(Sys_Milliseconds() - start) / 1000); +} + +/* +void idSplineList::draw(bool editMode) { + int i; + vec4_t yellow(1, 1, 0, 1); + + if (controlPoints.Num() == 0) { + return; + } + + if (dirty) { + buildSpline(); + } + + + qglColor3fv(controlColor); + qglPointSize(5); + + qglBegin(GL_POINTS); + for (i = 0; i < controlPoints.Num(); i++) { + qglVertex3fv(*controlPoints[i]); + } + qglEnd(); + + if (editMode) { + for(i = 0; i < controlPoints.Num(); i++) { + glBox(activeColor, *controlPoints[i], 4); + } + } + + //Draw the curve + qglColor3fv(pathColor); + qglBegin(GL_LINE_STRIP); + int count = splinePoints.Num(); + for (i = 0; i < count; i++) { + qglVertex3fv(*splinePoints[i]); + } + qglEnd(); + + if (editMode) { + qglColor3fv(segmentColor); + qglPointSize(3); + qglBegin(GL_POINTS); + for (i = 0; i < count; i++) { + qglVertex3fv(*splinePoints[i]); + } + qglEnd(); + } + if (count > 0) { + //assert(activeSegment >=0 && activeSegment < count); + if (activeSegment >=0 && activeSegment < count) { + glBox(activeColor, *splinePoints[activeSegment], 6); + glBox(yellow, *splinePoints[activeSegment], 8); + } + } + +} +*/ + +float idSplineList::totalDistance() { + + if (controlPoints.Num() == 0) { + return 0.0; + } + + if (dirty) { + buildSpline(); + } + + float dist = 0.0; + idVec3_t temp; + int count = splinePoints.Num(); + for(int i = 1; i < count; i++) { + temp = *splinePoints[i-1]; + temp -= *splinePoints[i]; + dist += temp.Length(); + } + return dist; +} + +void idSplineList::initPosition(long bt, long totalTime) { + + if (dirty) { + buildSpline(); + } + + if (splinePoints.Num() == 0) { + return; + } + + baseTime = bt; + time = totalTime; + + // calc distance to travel ( this will soon be broken into time segments ) + splineTime.Clear(); + splineTime.Append(bt); + double dist = totalDistance(); + double distSoFar = 0.0; + idVec3_t temp; + int count = splinePoints.Num(); + //for(int i = 2; i < count - 1; i++) { + for(int i = 1; i < count; i++) { + temp = *splinePoints[i-1]; + temp -= *splinePoints[i]; + distSoFar += temp.Length(); + double percent = distSoFar / dist; + percent *= totalTime; + splineTime.Append(percent + bt); + } + assert(splineTime.Num() == splinePoints.Num()); + activeSegment = 0; +} + + + +float idSplineList::calcSpline(int step, float tension) { + switch(step) { + case 0: return (pow(1 - tension, 3)) / 6; + case 1: return (3 * pow(tension, 3) - 6 * pow(tension, 2) + 4) / 6; + case 2: return (-3 * pow(tension, 3) + 3 * pow(tension, 2) + 3 * tension + 1) / 6; + case 3: return pow(tension, 3) / 6; + } + return 0.0; +} + + + +void idSplineList::updateSelection(const idVec3_t &move) { + if (selected) { + dirty = true; + VectorAdd(*selected, move, *selected); + } +} + + +void idSplineList::setSelectedPoint(idVec3_t *p) { + if (p) { + p->Snap(); + for(int i = 0; i < controlPoints.Num(); i++) { + if (*p == *controlPoints[i]) { + selected = controlPoints[i]; + } + } + } else { + selected = NULL; + } +} + +const idVec3_t *idSplineList::getPosition(long t) { + static idVec3_t interpolatedPos; + //static long lastTime = -1; + + int count = splineTime.Num(); + if (count == 0) { + return &zero; + } + + Com_Printf("Time: %d\n", t); + assert(splineTime.Num() == splinePoints.Num()); + + while (activeSegment < count) { + if (splineTime[activeSegment] >= t) { + if (activeSegment > 0 && activeSegment < count - 1) { + double timeHi = splineTime[activeSegment + 1]; + double timeLo = splineTime[activeSegment - 1]; + double percent = (timeHi - t) / (timeHi - timeLo); + // pick two bounding points + idVec3_t v1 = *splinePoints[activeSegment-1]; + idVec3_t v2 = *splinePoints[activeSegment+1]; + v2 *= (1.0 - percent); + v1 *= percent; + v2 += v1; + interpolatedPos = v2; + return &interpolatedPos; + } + return splinePoints[activeSegment]; + } else { + activeSegment++; + } + } + return splinePoints[count-1]; +} + +void idSplineList::parse(const char *(*text) ) { + const char *token; + //Com_MatchToken( text, "{" ); + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !Q_stricmp (token, "}") ) { + break; + } + + do { + // if token is not a brace, it is a key for a key/value pair + if ( !token[0] || !Q_stricmp (token, "(") || !Q_stricmp(token, "}")) { + break; + } + + Com_UngetToken(); + idStr key = Com_ParseOnLine(text); + const char *token = Com_Parse(text); + if (Q_stricmp(key.c_str(), "granularity") == 0) { + granularity = atof(token); + } else if (Q_stricmp(key.c_str(), "name") == 0) { + name = token; + } + token = Com_Parse(text); + + } while (1); + + if ( !Q_stricmp (token, "}") ) { + break; + } + + Com_UngetToken(); + // read the control point + idVec3_t point; + Com_Parse1DMatrix( text, 3, point ); + addPoint(point.x, point.y, point.z); + } while (1); + + //Com_UngetToken(); + //Com_MatchToken( text, "}" ); + dirty = true; +} + +void idSplineList::write(fileHandle_t file, const char *p) { + idStr s = va("\t\t%s {\n", p); + FS_Write(s.c_str(), s.length(), file); + //s = va("\t\tname %s\n", name.c_str()); + //FS_Write(s.c_str(), s.length(), file); + s = va("\t\t\tgranularity %f\n", granularity); + FS_Write(s.c_str(), s.length(), file); + int count = controlPoints.Num(); + for (int i = 0; i < count; i++) { + s = va("\t\t\t( %f %f %f )\n", controlPoints[i]->x, controlPoints[i]->y, controlPoints[i]->z); + FS_Write(s.c_str(), s.length(), file); + } + s = "\t\t}\n"; + FS_Write(s.c_str(), s.length(), file); +} + + +void idCameraDef::getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fov) { +#if 0 + if (!cameraSpline.validTime()) { + buildCamera(); + } + double d = (double)segment / numSegments(); + getCameraInfo(d * totalTime * 1000, origin, direction, fov); +#endif +/* + if (!cameraSpline.validTime()) { + buildCamera(); + } + origin = *cameraSpline.getSegmentPoint(segment); + + + idVec3_t temp; + + int numTargets = getTargetSpline()->controlPoints.Num(); + int count = cameraSpline.splineTime.Num(); + if (numTargets == 0) { + // follow the path + if (cameraSpline.getActiveSegment() < count - 1) { + temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1]; + } + } else if (numTargets == 1) { + temp = *getTargetSpline()->controlPoints[0]; + } else { + temp = *getTargetSpline()->getSegmentPoint(segment); + } + + temp -= origin; + temp.Normalize(); + direction = temp; +*/ +} + +bool idCameraDef::getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv) { + + + if ((time - startTime) / 1000 > totalTime) { + return false; + } + + + for (int i = 0; i < events.Num(); i++) { + if (time >= startTime + events[i]->getTime() && !events[i]->getTriggered()) { + events[i]->setTriggered(true); + if (events[i]->getType() == idCameraEvent::EVENT_TARGET) { + setActiveTargetByName(events[i]->getParam()); + getActiveTarget()->start(startTime + events[i]->getTime()); + //Com_Printf("Triggered event switch to target: %s\n",events[i]->getParam()); + } else if (events[i]->getType() == idCameraEvent::EVENT_TRIGGER) { + //idEntity *ent = NULL; + //ent = level.FindTarget( ent, events[i]->getParam()); + //if (ent) { + // ent->signal( SIG_TRIGGER ); + // ent->ProcessEvent( &EV_Activate, world ); + //} + } else if (events[i]->getType() == idCameraEvent::EVENT_FOV) { + //*fv = fov = atof(events[i]->getParam()); + } else if (events[i]->getType() == idCameraEvent::EVENT_STOP) { + return false; + } + } + } + + origin = *cameraPosition->getPosition(time); + + *fv = fov.getFOV(time); + + idVec3_t temp = origin; + + int numTargets = targetPositions.Num(); + if (numTargets == 0) { +/* + // follow the path + if (cameraSpline.getActiveSegment() < count - 1) { + temp = *cameraSpline.splinePoints[cameraSpline.getActiveSegment()+1]; + if (temp == origin) { + int index = cameraSpline.getActiveSegment() + 2; + while (temp == origin && index < count - 1) { + temp = *cameraSpline.splinePoints[index++]; + } + } + } +*/ + } else { + temp = *getActiveTarget()->getPosition(time); + } + + temp -= origin; + temp.Normalize(); + direction = temp; + + return true; +} + +bool idCameraDef::waitEvent(int index) { + //for (int i = 0; i < events.Num(); i++) { + // if (events[i]->getSegment() == index && events[i]->getType() == idCameraEvent::EVENT_WAIT) { + // return true; + // } + //} + return false; +} + + +#define NUM_CCELERATION_SEGS 10 +#define CELL_AMT 5 + +void idCameraDef::buildCamera() { + int i; + //int lastSwitch = 0; + idList<float> waits; + idList<int> targets; + + totalTime = baseTime; + cameraPosition->setTime(totalTime * 1000); + // we have a base time layout for the path and the target path + // now we need to layer on any wait or speed changes + for (i = 0; i < events.Num(); i++) { + //idCameraEvent *ev = events[i]; + events[i]->setTriggered(false); + switch (events[i]->getType()) { + case idCameraEvent::EVENT_TARGET : { + targets.Append(i); + break; + } + case idCameraEvent::EVENT_WAIT : { + waits.Append(atof(events[i]->getParam())); + cameraPosition->addVelocity(events[i]->getTime(), atof(events[i]->getParam()) * 1000, 0); + break; + } + case idCameraEvent::EVENT_TARGETWAIT : { + //targetWaits.Append(i); + break; + } + case idCameraEvent::EVENT_SPEED : { +/* + // take the average delay between up to the next five segments + float adjust = atof(events[i]->getParam()); + int index = events[i]->getSegment(); + total = 0; + count = 0; + + // get total amount of time over the remainder of the segment + for (j = index; j < cameraSpline.numSegments() - 1; j++) { + total += cameraSpline.getSegmentTime(j + 1) - cameraSpline.getSegmentTime(j); + count++; + } + + // multiply that by the adjustment + double newTotal = total * adjust; + // what is the difference.. + newTotal -= total; + totalTime += newTotal / 1000; + + // per segment difference + newTotal /= count; + int additive = newTotal; + + // now propogate that difference out to each segment + for (j = index; j < cameraSpline.numSegments(); j++) { + cameraSpline.addSegmentTime(j, additive); + additive += newTotal; + } + break; +*/ + } + default: break; // FIXME: what about other idCameraEvent? + } + } + + + for (i = 0; i < waits.Num(); i++) { + totalTime += waits[i]; + } + + // on a new target switch, we need to take time to this point ( since last target switch ) + // and allocate it across the active target, then reset time to this point + long timeSoFar = 0; + long total = (int)(totalTime * 1000); + for (i = 0; i < targets.Num(); i++) { + long t; + if (i < targets.Num() - 1) { + t = events[targets[i+1]]->getTime(); + } else { + t = total - timeSoFar; + } + // t is how much time to use for this target + setActiveTargetByName(events[targets[i]]->getParam()); + getActiveTarget()->setTime(t); + timeSoFar += t; + } + + +} + +void idCameraDef::startCamera(long t) { + buildCamera(); + cameraPosition->start(t); + //for (int i = 0; i < targetPositions.Num(); i++) { + // targetPositions[i]-> + //} + startTime = t; + cameraRunning = true; +} + + +void idCameraDef::parse(const char *(*text) ) { + + const char *token; + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !Q_stricmp (token, "}") ) { + break; + } + + if (Q_stricmp(token, "time") == 0) { + baseTime = Com_ParseFloat(text); + } + + if (Q_stricmp(token, "camera_fixed") == 0) { + cameraPosition = new idFixedPosition(); + cameraPosition->parse(text); + } + + if (Q_stricmp(token, "camera_interpolated") == 0) { + cameraPosition = new idInterpolatedPosition(); + cameraPosition->parse(text); + } + + if (Q_stricmp(token, "camera_spline") == 0) { + cameraPosition = new idSplinePosition(); + cameraPosition->parse(text); + } + + if (Q_stricmp(token, "target_fixed") == 0) { + idFixedPosition *pos = new idFixedPosition(); + pos->parse(text); + targetPositions.Append(pos); + } + + if (Q_stricmp(token, "target_interpolated") == 0) { + idInterpolatedPosition *pos = new idInterpolatedPosition(); + pos->parse(text); + targetPositions.Append(pos); + } + + if (Q_stricmp(token, "target_spline") == 0) { + idSplinePosition *pos = new idSplinePosition(); + pos->parse(text); + targetPositions.Append(pos); + } + + if (Q_stricmp(token, "fov") == 0) { + fov.parse(text); + } + + if (Q_stricmp(token, "event") == 0) { + idCameraEvent *event = new idCameraEvent(); + event->parse(text); + addEvent(event); + } + + + } while (1); + + Com_UngetToken(); + Com_MatchToken( text, "}" ); + +} + +qboolean idCameraDef::load(const char *filename) { + char *buf; + const char *buf_p; + //int length = + FS_ReadFile( filename, (void **)&buf ); + if ( !buf ) { + return qfalse; + } + + clear(); + Com_BeginParseSession( filename ); + buf_p = buf; + parse(&buf_p); + Com_EndParseSession(); + FS_FreeFile( buf ); + + return qtrue; +} + +void idCameraDef::save(const char *filename) { + fileHandle_t file = FS_FOpenFileWrite(filename); + if (file) { + int i; + idStr s = "cameraPathDef { \n"; + FS_Write(s.c_str(), s.length(), file); + s = va("\ttime %f\n", baseTime); + FS_Write(s.c_str(), s.length(), file); + + cameraPosition->write(file, va("camera_%s",cameraPosition->typeStr())); + + for (i = 0; i < numTargets(); i++) { + targetPositions[i]->write(file, va("target_%s", targetPositions[i]->typeStr())); + } + + for (i = 0; i < events.Num(); i++) { + events[i]->write(file, "event"); + } + + fov.write(file, "fov"); + + s = "}\n"; + FS_Write(s.c_str(), s.length(), file); + } + FS_FCloseFile(file); +} + +int idCameraDef::sortEvents(const void *p1, const void *p2) { + idCameraEvent *ev1 = (idCameraEvent*)(p1); + idCameraEvent *ev2 = (idCameraEvent*)(p2); + + if (ev1->getTime() > ev2->getTime()) { + return -1; + } + if (ev1->getTime() < ev2->getTime()) { + return 1; + } + return 0; +} + +void idCameraDef::addEvent(idCameraEvent *event) { + events.Append(event); + //events.Sort(&sortEvents); + +} +void idCameraDef::addEvent(idCameraEvent::eventType t, const char *param, long time) { + addEvent(new idCameraEvent(t, param, time)); + buildCamera(); +} + + +const char *idCameraEvent::eventStr[] = { + "NA", + "WAIT", + "TARGETWAIT", + "SPEED", + "TARGET", + "SNAPTARGET", + "FOV", + "SCRIPT", + "TRIGGER", + "STOP" +}; + +void idCameraEvent::parse(const char *(*text) ) { + const char *token; + Com_MatchToken( text, "{" ); + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !strcmp (token, "}") ) { + break; + } + + // here we may have to jump over brush epairs ( only used in editor ) + do { + // if token is not a brace, it is a key for a key/value pair + if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) { + break; + } + + Com_UngetToken(); + idStr key = Com_ParseOnLine(text); + const char *token = Com_Parse(text); + if (Q_stricmp(key.c_str(), "type") == 0) { + type = static_cast<idCameraEvent::eventType>(atoi(token)); + } else if (Q_stricmp(key.c_str(), "param") == 0) { + paramStr = token; + } else if (Q_stricmp(key.c_str(), "time") == 0) { + time = atoi(token); + } + token = Com_Parse(text); + + } while (1); + + if ( !strcmp (token, "}") ) { + break; + } + + } while (1); + + Com_UngetToken(); + Com_MatchToken( text, "}" ); +} + +void idCameraEvent::write(fileHandle_t file, const char *name) { + idStr s = va("\t%s {\n", name); + FS_Write(s.c_str(), s.length(), file); + s = va("\t\ttype %d\n", static_cast<int>(type)); + FS_Write(s.c_str(), s.length(), file); + s = va("\t\tparam %s\n", paramStr.c_str()); + FS_Write(s.c_str(), s.length(), file); + s = va("\t\ttime %d\n", time); + FS_Write(s.c_str(), s.length(), file); + s = "\t}\n"; + FS_Write(s.c_str(), s.length(), file); +} + + +const char *idCameraPosition::positionStr[] = { + "Fixed", + "Interpolated", + "Spline", +}; + + + +const idVec3_t *idInterpolatedPosition::getPosition(long t) { + static idVec3_t interpolatedPos; + + float velocity = getVelocity(t); + float timePassed = t - lastTime; + lastTime = t; + + // convert to seconds + timePassed /= 1000; + + float distToTravel = timePassed *= velocity; + + idVec3_t temp = startPos; + temp -= endPos; + float distance = temp.Length(); + + distSoFar += distToTravel; + float percent = (float)(distSoFar) / distance; + + if (percent > 1.0) { + percent = 1.0; + } else if (percent < 0.0) { + percent = 0.0; + } + + // the following line does a straigt calc on percentage of time + // float percent = (float)(startTime + time - t) / time; + + idVec3_t v1 = startPos; + idVec3_t v2 = endPos; + v1 *= (1.0 - percent); + v2 *= percent; + v1 += v2; + interpolatedPos = v1; + return &interpolatedPos; +} + + +void idCameraFOV::parse(const char *(*text) ) { + const char *token; + Com_MatchToken( text, "{" ); + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !strcmp (token, "}") ) { + break; + } + + // here we may have to jump over brush epairs ( only used in editor ) + do { + // if token is not a brace, it is a key for a key/value pair + if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) { + break; + } + + Com_UngetToken(); + idStr key = Com_ParseOnLine(text); + const char *token = Com_Parse(text); + if (Q_stricmp(key.c_str(), "fov") == 0) { + fov = atof(token); + } else if (Q_stricmp(key.c_str(), "startFOV") == 0) { + startFOV = atof(token); + } else if (Q_stricmp(key.c_str(), "endFOV") == 0) { + endFOV = atof(token); + } else if (Q_stricmp(key.c_str(), "time") == 0) { + time = atoi(token); + } + token = Com_Parse(text); + + } while (1); + + if ( !strcmp (token, "}") ) { + break; + } + + } while (1); + + Com_UngetToken(); + Com_MatchToken( text, "}" ); +} + +bool idCameraPosition::parseToken(const char *key, const char *(*text)) { + const char *token = Com_Parse(text); + if (Q_stricmp(key, "time") == 0) { + time = atol(token); + return true; + } else if (Q_stricmp(key, "type") == 0) { + type = static_cast<idCameraPosition::positionType>(atoi(token)); + return true; + } else if (Q_stricmp(key, "velocity") == 0) { + long t = atol(token); + token = Com_Parse(text); + long d = atol(token); + token = Com_Parse(text); + float s = atof(token); + addVelocity(t, d, s); + return true; + } else if (Q_stricmp(key, "baseVelocity") == 0) { + baseVelocity = atof(token); + return true; + } else if (Q_stricmp(key, "name") == 0) { + name = token; + return true; + } else if (Q_stricmp(key, "time") == 0) { + time = atoi(token); + return true; + } + Com_UngetToken(); + return false; +} + + + +void idFixedPosition::parse(const char *(*text) ) { + const char *token; + Com_MatchToken( text, "{" ); + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !strcmp (token, "}") ) { + break; + } + + // here we may have to jump over brush epairs ( only used in editor ) + do { + // if token is not a brace, it is a key for a key/value pair + if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) { + break; + } + + Com_UngetToken(); + idStr key = Com_ParseOnLine(text); + + const char *token = Com_Parse(text); + if (Q_stricmp(key.c_str(), "pos") == 0) { + Com_UngetToken(); + Com_Parse1DMatrix( text, 3, pos ); + } else { + Com_UngetToken(); + idCameraPosition::parseToken(key.c_str(), text); + } + token = Com_Parse(text); + + } while (1); + + if ( !strcmp (token, "}") ) { + break; + } + + } while (1); + + Com_UngetToken(); + Com_MatchToken( text, "}" ); +} + +void idInterpolatedPosition::parse(const char *(*text) ) { + const char *token; + Com_MatchToken( text, "{" ); + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !strcmp (token, "}") ) { + break; + } + + // here we may have to jump over brush epairs ( only used in editor ) + do { + // if token is not a brace, it is a key for a key/value pair + if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) { + break; + } + + Com_UngetToken(); + idStr key = Com_ParseOnLine(text); + + const char *token = Com_Parse(text); + if (Q_stricmp(key.c_str(), "startPos") == 0) { + Com_UngetToken(); + Com_Parse1DMatrix( text, 3, startPos ); + } else if (Q_stricmp(key.c_str(), "endPos") == 0) { + Com_UngetToken(); + Com_Parse1DMatrix( text, 3, endPos ); + } else { + Com_UngetToken(); + idCameraPosition::parseToken(key.c_str(), text); + } + token = Com_Parse(text); + + } while (1); + + if ( !strcmp (token, "}") ) { + break; + } + + } while (1); + + Com_UngetToken(); + Com_MatchToken( text, "}" ); +} + + +void idSplinePosition::parse(const char *(*text) ) { + const char *token; + Com_MatchToken( text, "{" ); + do { + token = Com_Parse( text ); + + if ( !token[0] ) { + break; + } + if ( !strcmp (token, "}") ) { + break; + } + + // here we may have to jump over brush epairs ( only used in editor ) + do { + // if token is not a brace, it is a key for a key/value pair + if ( !token[0] || !strcmp (token, "(") || !strcmp(token, "}")) { + break; + } + + Com_UngetToken(); + idStr key = Com_ParseOnLine(text); + + const char *token = Com_Parse(text); + if (Q_stricmp(key.c_str(), "target") == 0) { + target.parse(text); + } else { + Com_UngetToken(); + idCameraPosition::parseToken(key.c_str(), text); + } + token = Com_Parse(text); + + } while (1); + + if ( !strcmp (token, "}") ) { + break; + } + + } while (1); + + Com_UngetToken(); + Com_MatchToken( text, "}" ); +} + + + +void idCameraFOV::write(fileHandle_t file, const char *p) { + idStr s = va("\t%s {\n", p); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\tfov %f\n", fov); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\tstartFOV %f\n", startFOV); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\tendFOV %f\n", endFOV); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\ttime %i\n", time); + FS_Write(s.c_str(), s.length(), file); + + s = "\t}\n"; + FS_Write(s.c_str(), s.length(), file); +} + + +void idCameraPosition::write(fileHandle_t file, const char *p) { + + idStr s = va("\t\ttime %i\n", time); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\ttype %i\n", static_cast<int>(type)); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\tname %s\n", name.c_str()); + FS_Write(s.c_str(), s.length(), file); + + s = va("\t\tbaseVelocity %f\n", baseVelocity); + FS_Write(s.c_str(), s.length(), file); + + for (int i = 0; i < velocities.Num(); i++) { + s = va("\t\tvelocity %i %i %f\n", velocities[i]->startTime, velocities[i]->time, velocities[i]->speed); + FS_Write(s.c_str(), s.length(), file); + } + +} + +void idFixedPosition::write(fileHandle_t file, const char *p) { + idStr s = va("\t%s {\n", p); + FS_Write(s.c_str(), s.length(), file); + idCameraPosition::write(file, p); + s = va("\t\tpos ( %f %f %f )\n", pos.x, pos.y, pos.z); + FS_Write(s.c_str(), s.length(), file); + s = "\t}\n"; + FS_Write(s.c_str(), s.length(), file); +} + +void idInterpolatedPosition::write(fileHandle_t file, const char *p) { + idStr s = va("\t%s {\n", p); + FS_Write(s.c_str(), s.length(), file); + idCameraPosition::write(file, p); + s = va("\t\tstartPos ( %f %f %f )\n", startPos.x, startPos.y, startPos.z); + FS_Write(s.c_str(), s.length(), file); + s = va("\t\tendPos ( %f %f %f )\n", endPos.x, endPos.y, endPos.z); + FS_Write(s.c_str(), s.length(), file); + s = "\t}\n"; + FS_Write(s.c_str(), s.length(), file); +} + +void idSplinePosition::write(fileHandle_t file, const char *p) { + idStr s = va("\t%s {\n", p); + FS_Write(s.c_str(), s.length(), file); + idCameraPosition::write(file, p); + target.write(file, "target"); + s = "\t}\n"; + FS_Write(s.c_str(), s.length(), file); +} + +void idCameraDef::addTarget(const char *name, idCameraPosition::positionType type) { + //const char *text = (name == NULL) ? va("target0%d", numTargets()+1) : name; // TTimo: unused + idCameraPosition *pos = newFromType(type); + if (pos) { + pos->setName(name); + targetPositions.Append(pos); + activeTarget = numTargets()-1; + if (activeTarget == 0) { + // first one + addEvent(idCameraEvent::EVENT_TARGET, name, 0); + } + } +} + + + +idCameraDef camera; + +extern "C" { +qboolean loadCamera(const char *name) { + camera.clear(); + return static_cast<qboolean>(camera.load(name)); +} + +qboolean getCameraInfo(int time, float *origin, float*angles) { + idVec3_t dir, org; + org[0] = origin[0]; + org[1] = origin[1]; + org[2] = origin[2]; + float fov = 90; + if (camera.getCameraInfo(time, org, dir, &fov)) { + origin[0] = org[0]; + origin[1] = org[1]; + origin[2] = org[2]; + angles[1] = atan2 (dir[1], dir[0])*180/3.14159; + angles[0] = asin (dir[2])*180/3.14159; + return qtrue; + } + return qfalse; +} + +void startCamera(int time) { + camera.startCamera(time); +} + +} + + diff --git a/code/splines/splines.h b/code/splines/splines.h index bb41dda..0a60123 100755 --- a/code/splines/splines.h +++ b/code/splines/splines.h @@ -1,1075 +1,1075 @@ -/*
-===========================================================================
-Copyright (C) 1999-2005 Id Software, Inc.
-
-This file is part of Quake III Arena source code.
-
-Quake III Arena source code is free software; you can redistribute it
-and/or modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2 of the License,
-or (at your option) any later version.
-
-Quake III Arena source code is distributed in the hope that it will be
-useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Foobar; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-===========================================================================
-*/
-#ifndef __SPLINES_H
-#define __SPLINES_H
-
-extern "C" {
-#ifdef Q3RADIANT
-#include "../qgl.h"
-#else
-//#include "../renderer/qgl.h"
-#endif
-}
-#include "util_list.h"
-#include "util_str.h"
-#include "math_vector.h"
-
-typedef int fileHandle_t;
-
-//extern void glBox(idVec3_t &color, idVec3_t &point, float size);
-//extern void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label);
-
-static vec4_t blue(0, 0, 1, 1);
-static vec4_t red(1, 0, 0, 1);
-
-class idPointListInterface {
-public:
- idPointListInterface() {
- selectedPoints.Clear();
- }
- virtual ~idPointListInterface() {}
-
- virtual int numPoints() {
- return 0;
- }
-
- virtual void addPoint(const float x, const float y, const float z) {}
- virtual void addPoint(const idVec3_t &v) {}
- virtual void removePoint(int index) {}
- virtual idVec3_t *getPoint(int index) { return NULL; }
-
- int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
- idVec3_t origin(ox, oy, oz);
- idVec3_t dir(dx, dy, dz);
- return selectPointByRay(origin, dir, single);
- }
-
- int selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) {
- int i, besti, count;
- float d, bestd;
- idVec3_t temp, temp2;
-
- // find the point closest to the ray
- besti = -1;
- bestd = 8;
- count = numPoints();
-
- for (i=0; i < count; i++) {
- temp = *getPoint(i);
- temp2 = temp;
- temp -= origin;
- d = DotProduct(temp, direction);
- __VectorMA (origin, d, direction, temp);
- temp2 -= temp;
- d = temp2.Length();
- if (d <= bestd) {
- bestd = d;
- besti = i;
- }
- }
-
- if (besti >= 0) {
- selectPoint(besti, single);
- }
-
- return besti;
- }
-
- int isPointSelected(int index) {
- int count = selectedPoints.Num();
- for (int i = 0; i < count; i++) {
- if (selectedPoints[i] == index) {
- return i;
- }
- }
- return -1;
- }
-
- int selectPoint(int index, bool single) {
- if (index >= 0 && index < numPoints()) {
- if (single) {
- deselectAll();
- } else {
- if (isPointSelected(index) >= 0) {
- selectedPoints.Remove(index);
- }
- }
- return selectedPoints.Append(index);
- }
- return -1;
- }
-
- void selectAll() {
- selectedPoints.Clear();
- for (int i = 0; i < numPoints(); i++) {
- selectedPoints.Append(i);
- }
- }
-
- void deselectAll() {
- selectedPoints.Clear();
- }
-
- virtual void updateSelection(float x, float y, float z) {
- idVec3_t move(x, y, z);
- updateSelection(move);
- }
-
- virtual void updateSelection(const idVec3_t &move) {
- int count = selectedPoints.Num();
- for (int i = 0; i < count; i++) {
- *getPoint(selectedPoints[i]) += move;
- }
- }
-/*
- void drawSelection() {
- int count = selectedPoints.Num();
- for (int i = 0; i < count; i++) {
- glBox(red, *getPoint(selectedPoints[i]), 4);
- }
- }
-*/
-protected:
- idList<int> selectedPoints;
-
-};
-
-
-class idSplineList {
-
-public:
-
- idSplineList() {
- clear();
- }
-
- idSplineList(const char *p) {
- clear();
- name = p;
- };
-
- ~idSplineList() {
- clear();
- };
-
- void clearControl() {
- for (int i = 0; i < controlPoints.Num(); i++) {
- delete controlPoints[i];
- }
- controlPoints.Clear();
- }
-
- void clearSpline() {
- for (int i = 0; i < splinePoints.Num(); i++) {
- delete splinePoints[i];
- }
- splinePoints.Clear();
- }
-
- void parse(const char *(*text));
- void write(fileHandle_t file, const char *name);
-
- void clear() {
- clearControl();
- clearSpline();
- splineTime.Clear();
- selected = NULL;
- dirty = true;
- activeSegment = 0;
- granularity = 0.025;
- pathColor.set(1.0, 0.5, 0.0);
- controlColor.set(0.7, 0.0, 1.0);
- segmentColor.set(0.0, 0.0, 1.0);
- activeColor.set(1.0, 0.0, 0.0);
- }
-
- void initPosition(long startTime, long totalTime);
- const idVec3_t *getPosition(long time);
-
-
-// void draw(bool editMode);
- void addToRenderer();
-
- void setSelectedPoint(idVec3_t *p);
- idVec3_t *getSelectedPoint() {
- return selected;
- }
-
- void addPoint(const idVec3_t &v) {
- controlPoints.Append(new idVec3_t(v));
- dirty = true;
- }
-
- void addPoint(float x, float y, float z) {
- controlPoints.Append(new idVec3_t(x, y, z));
- dirty = true;
- }
-
- void updateSelection(const idVec3_t &move);
-
- void startEdit() {
- editMode = true;
- }
-
- void stopEdit() {
- editMode = false;
- }
-
- void buildSpline();
-
- void setGranularity(float f) {
- granularity = f;
- }
-
- float getGranularity() {
- return granularity;
- }
-
- int numPoints() {
- return controlPoints.Num();
- }
-
- idVec3_t *getPoint(int index) {
- assert(index >= 0 && index < controlPoints.Num());
- return controlPoints[index];
- }
-
- idVec3_t *getSegmentPoint(int index) {
- assert(index >= 0 && index < splinePoints.Num());
- return splinePoints[index];
- }
-
-
- void setSegmentTime(int index, int time) {
- assert(index >= 0 && index < splinePoints.Num());
- splineTime[index] = time;
- }
-
- double getSegmentTime(int index) {
- assert(index >= 0 && index < splinePoints.Num());
- return splineTime[index];
- }
- void addSegmentTime(int index, int time) {
- assert(index >= 0 && index < splinePoints.Num());
- splineTime[index] += time;
- }
-
- float totalDistance();
-
- static idVec3_t zero;
-
- int getActiveSegment() {
- return activeSegment;
- }
-
- void setActiveSegment(int i) {
- //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
- activeSegment = i;
- }
-
- int numSegments() {
- return splinePoints.Num();
- }
-
- void setColors(idVec3_t &path, idVec3_t &segment, idVec3_t &control, idVec3_t &active) {
- pathColor = path;
- segmentColor = segment;
- controlColor = control;
- activeColor = active;
- }
-
- const char *getName() {
- return name.c_str();
- }
-
- void setName(const char *p) {
- name = p;
- }
-
- bool validTime() {
- if (dirty) {
- buildSpline();
- }
- // gcc doesn't allow static casting away from bools
- // why? I've no idea...
- return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
- }
-
- void setTime(long t) {
- time = t;
- }
-
- void setBaseTime(long t) {
- baseTime = t;
- }
-
-protected:
- idStr name;
- float calcSpline(int step, float tension);
- idList<idVec3_t*> controlPoints;
- idList<idVec3_t*> splinePoints;
- idList<double> splineTime;
- idVec3_t *selected;
- idVec3_t pathColor, segmentColor, controlColor, activeColor;
- float granularity;
- bool editMode;
- bool dirty;
- int activeSegment;
- long baseTime;
- long time;
- friend class idCamera;
-};
-
-// time in milliseconds
-// velocity where 1.0 equal rough walking speed
-struct idVelocity {
- idVelocity(long start, long duration, float s) {
- startTime = start;
- time = duration;
- speed = s;
- }
- long startTime;
- long time;
- float speed;
-};
-
-// can either be a look at or origin position for a camera
-//
-class idCameraPosition : public idPointListInterface {
-public:
-
- virtual void clear() {
- editMode = false;
- for (int i = 0; i < velocities.Num(); i++) {
- delete velocities[i];
- velocities[i] = NULL;
- }
- velocities.Clear();
- }
-
- idCameraPosition(const char *p) {
- name = p;
- }
-
- idCameraPosition() {
- time = 0;
- name = "position";
- }
-
- idCameraPosition(long t) {
- time = t;
- }
-
- virtual ~idCameraPosition() {
- clear();
- }
-
-
- // this can be done with RTTI syntax but i like the derived classes setting a type
- // makes serialization a bit easier to see
- //
- enum positionType {
- FIXED = 0x00,
- INTERPOLATED,
- SPLINE,
- POSITION_COUNT
- };
-
-
- virtual void start(long t) {
- startTime = t;
- }
-
- long getTime() {
- return time;
- }
-
- virtual void setTime(long t) {
- time = t;
- }
-
- float getVelocity(long t) {
- long check = t - startTime;
- for (int i = 0; i < velocities.Num(); i++) {
- if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
- return velocities[i]->speed;
- }
- }
- return baseVelocity;
- }
-
- void addVelocity(long start, long duration, float speed) {
- velocities.Append(new idVelocity(start, duration, speed));
- }
-
- virtual const idVec3_t *getPosition(long t) {
- assert(true);
- return NULL;
- }
-
-// virtual void draw(bool editMode) {};
-
- virtual void parse(const char *(*text)) {};
- virtual void write(fileHandle_t file, const char *name);
- virtual bool parseToken(const char *key, const char *(*text));
-
- const char *getName() {
- return name.c_str();
- }
-
- void setName(const char *p) {
- name = p;
- }
-
- virtual void startEdit() {
- editMode = true;
- }
-
- virtual void stopEdit() {
- editMode = false;
- }
-
-// virtual void draw() {};
-
- const char *typeStr() {
- return positionStr[static_cast<int>(type)];
- }
-
- void calcVelocity(float distance) {
- float secs = (float)time / 1000;
- baseVelocity = distance / secs;
- }
-
-protected:
- static const char* positionStr[POSITION_COUNT];
- long startTime;
- long time;
- idCameraPosition::positionType type;
- idStr name;
- bool editMode;
- idList<idVelocity*> velocities;
- float baseVelocity;
-};
-
-class idFixedPosition : public idCameraPosition {
-public:
-
- void init() {
- pos.Zero();
- type = idCameraPosition::FIXED;
- }
-
- idFixedPosition() : idCameraPosition() {
- init();
- }
-
- idFixedPosition(idVec3_t p) : idCameraPosition() {
- init();
- pos = p;
- }
-
- virtual void addPoint(const idVec3_t &v) {
- pos = v;
- }
-
- virtual void addPoint(const float x, const float y, const float z) {
- pos.set(x, y, z);
- }
-
-
- ~idFixedPosition() {
- }
-
- virtual const idVec3_t *getPosition(long t) {
- return &pos;
- }
-
- void parse(const char *(*text));
- void write(fileHandle_t file, const char *name);
-
- virtual int numPoints() {
- return 1;
- }
-
- virtual idVec3_t *getPoint(int index) {
- if (index != 0) {
- assert(true);
- };
- return &pos;
- }
-/*
- virtual void draw(bool editMode) {
- glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
- }
-*/
-protected:
- idVec3_t pos;
-};
-
-class idInterpolatedPosition : public idCameraPosition {
-public:
-
- void init() {
- type = idCameraPosition::INTERPOLATED;
- first = true;
- startPos.Zero();
- endPos.Zero();
- }
-
- idInterpolatedPosition() : idCameraPosition() {
- init();
- }
-
- idInterpolatedPosition(idVec3_t start, idVec3_t end, long time) : idCameraPosition(time) {
- init();
- startPos = start;
- endPos = end;
- }
-
- ~idInterpolatedPosition() {
- }
-
- virtual const idVec3_t *getPosition(long t);
-
- void parse(const char *(*text));
- void write(fileHandle_t file, const char *name);
-
- virtual int numPoints() {
- return 2;
- }
-
- virtual idVec3_t *getPoint(int index) {
- assert(index >= 0 && index < 2);
- if (index == 0) {
- return &startPos;
- }
- return &endPos;
- }
-
- virtual void addPoint(const float x, const float y, const float z) {
- if (first) {
- startPos.set(x, y, z);
- first = false;
- } else {
- endPos.set(x, y, z);
- first = true;
- }
- }
-
- virtual void addPoint(const idVec3_t &v) {
- if (first) {
- startPos = v;
- first = false;
- } else {
- endPos = v;
- first = true;
- }
- }
-/*
- virtual void draw(bool editMode) {
- glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
- glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
- qglBegin(GL_LINES);
- qglVertex3fv(startPos);
- qglVertex3fv(endPos);
- qglEnd();
- }
-*/
- virtual void start(long t) {
- idCameraPosition::start(t);
- lastTime = startTime;
- distSoFar = 0.0;
- idVec3_t temp = startPos;
- temp -= endPos;
- calcVelocity(temp.Length());
- }
-
-protected:
- bool first;
- idVec3_t startPos;
- idVec3_t endPos;
- long lastTime;
- float distSoFar;
-};
-
-class idSplinePosition : public idCameraPosition {
-public:
-
- void init() {
- type = idCameraPosition::SPLINE;
- }
-
- idSplinePosition() : idCameraPosition() {
- init();
- }
-
- idSplinePosition(long time) : idCameraPosition(time) {
- init();
- }
-
- ~idSplinePosition() {
- }
-
- virtual void start(long t) {
- idCameraPosition::start(t);
- target.initPosition(t, time);
- calcVelocity(target.totalDistance());
- }
-
- virtual const idVec3_t *getPosition(long t) {
- return target.getPosition(t);
- }
-
- //virtual const idVec3_t *getPosition(long t) const {
-
- void addControlPoint(idVec3_t &v) {
- target.addPoint(v);
- }
-
- void parse(const char *(*text));
- void write(fileHandle_t file, const char *name);
-
- virtual int numPoints() {
- return target.numPoints();
- }
-
- virtual idVec3_t *getPoint(int index) {
- return target.getPoint(index);
- }
-
- virtual void addPoint(const idVec3_t &v) {
- target.addPoint(v);
- }
-
- virtual void addPoint(const float x, const float y, const float z) {
- target.addPoint(x, y, z);
- }
-
-/* virtual void draw(bool editMode) {
- target.draw(editMode);
- }
-*/
- virtual void updateSelection(const idVec3_t &move) {
- idCameraPosition::updateSelection(move);
- target.buildSpline();
- }
-
-protected:
- idSplineList target;
-};
-
-class idCameraFOV {
-public:
-
- idCameraFOV() {
- time = 0;
- fov = 90;
- }
-
- idCameraFOV(int v) {
- time = 0;
- fov = v;
- }
-
- idCameraFOV(int s, int e, long t) {
- startFOV = s;
- endFOV = e;
- time = t;
- }
-
-
- ~idCameraFOV(){}
-
- void setFOV(float f) {
- fov = f;
- }
-
- float getFOV(long t) {
- if (time) {
- assert(startTime);
- float percent = t / startTime;
- float temp = startFOV - endFOV;
- temp *= percent;
- fov = startFOV + temp;
- }
- return fov;
- }
-
- void start(long t) {
- startTime = t;
- }
-
- void parse(const char *(*text));
- void write(fileHandle_t file, const char *name);
-
-protected:
- float fov;
- float startFOV;
- float endFOV;
- int startTime;
- int time;
-};
-
-
-
-
-class idCameraEvent {
-public:
- enum eventType {
- EVENT_NA = 0x00,
- EVENT_WAIT,
- EVENT_TARGETWAIT,
- EVENT_SPEED,
- EVENT_TARGET,
- EVENT_SNAPTARGET,
- EVENT_FOV,
- EVENT_SCRIPT,
- EVENT_TRIGGER,
- EVENT_STOP,
- EVENT_COUNT
- };
-
- static const char* eventStr[EVENT_COUNT];
-
- idCameraEvent() {
- paramStr = "";
- type = EVENT_NA;
- time = 0;
- }
-
- idCameraEvent(eventType t, const char *param, long n) {
- type = t;
- paramStr = param;
- time = n;
- }
-
- ~idCameraEvent() {};
-
- eventType getType() {
- return type;
- }
-
- const char *typeStr() {
- return eventStr[static_cast<int>(type)];
- }
-
- const char *getParam() {
- return paramStr.c_str();
- }
-
- long getTime() {
- return time;
- }
-
- void setTime(long n) {
- time = n;
- }
-
- void parse(const char *(*text));
- void write(fileHandle_t file, const char *name);
-
- void setTriggered(bool b) {
- triggered = b;
- }
-
- bool getTriggered() {
- return triggered;
- }
-
-protected:
- eventType type;
- idStr paramStr;
- long time;
- bool triggered;
-
-};
-
-class idCameraDef {
-public:
-
- void clear() {
- currentCameraPosition = 0;
- cameraRunning = false;
- lastDirection.Zero();
- baseTime = 30;
- activeTarget = 0;
- name = "camera01";
- fov.setFOV(90);
- int i;
- for (i = 0; i < targetPositions.Num(); i++) {
- delete targetPositions[i];
- }
- for (i = 0; i < events.Num(); i++) {
- delete events[i];
- }
- delete cameraPosition;
- cameraPosition = NULL;
- events.Clear();
- targetPositions.Clear();
- }
-
- idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
- clear();
- if (type == idCameraPosition::SPLINE) {
- cameraPosition = new idSplinePosition();
- } else if (type == idCameraPosition::INTERPOLATED) {
- cameraPosition = new idInterpolatedPosition();
- } else {
- cameraPosition = new idFixedPosition();
- }
- return cameraPosition;
- }
-
- idCameraDef() {
- clear();
- }
-
- ~idCameraDef() {
- clear();
- }
-
- void addEvent(idCameraEvent::eventType t, const char *param, long time);
-
- void addEvent(idCameraEvent *event);
-
- static int sortEvents(const void *p1, const void *p2);
-
- int numEvents() {
- return events.Num();
- }
-
- idCameraEvent *getEvent(int index) {
- assert(index >= 0 && index < events.Num());
- return events[index];
- }
-
- void parse(const char *(*text));
- qboolean load(const char *filename);
- void save(const char *filename);
-
- void buildCamera();
-
- //idSplineList *getcameraPosition() {
- // return &cameraPosition;
- //}
-
- static idCameraPosition *newFromType(idCameraPosition::positionType t) {
- switch (t) {
- case idCameraPosition::FIXED : return new idFixedPosition();
- case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
- case idCameraPosition::SPLINE : return new idSplinePosition();
- default:
- break;
- };
- return NULL;
- }
-
- void addTarget(const char *name, idCameraPosition::positionType type);
-
- idCameraPosition *getActiveTarget() {
- if (targetPositions.Num() == 0) {
- addTarget(NULL, idCameraPosition::FIXED);
- }
- return targetPositions[activeTarget];
- }
-
- idCameraPosition *getActiveTarget(int index) {
- if (targetPositions.Num() == 0) {
- addTarget(NULL, idCameraPosition::FIXED);
- return targetPositions[0];
- }
- return targetPositions[index];
- }
-
- int numTargets() {
- return targetPositions.Num();
- }
-
-
- void setActiveTargetByName(const char *name) {
- for (int i = 0; i < targetPositions.Num(); i++) {
- if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
- setActiveTarget(i);
- return;
- }
- }
- }
-
- void setActiveTarget(int index) {
- assert(index >= 0 && index < targetPositions.Num());
- activeTarget = index;
- }
-
- void setRunning(bool b) {
- cameraRunning = b;
- }
-
- void setBaseTime(float f) {
- baseTime = f;
- }
-
- float getBaseTime() {
- return baseTime;
- }
-
- float getTotalTime() {
- return totalTime;
- }
-
- void startCamera(long t);
- void stopCamera() {
- cameraRunning = true;
- }
- void getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fv);
-
- bool getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv);
- bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
- idVec3_t org, dir;
- org[0] = origin[0];
- org[1] = origin[1];
- org[2] = origin[2];
- dir[0] = direction[0];
- dir[1] = direction[1];
- dir[2] = direction[2];
- bool b = getCameraInfo(time, org, dir, fv);
- origin[0] = org[0];
- origin[1] = org[1];
- origin[2] = org[2];
- direction[0] = dir[0];
- direction[1] = dir[1];
- direction[2] = dir[2];
- return b;
- }
-/*
- void draw(bool editMode) {
- // gcc doesn't allow casting away from bools
- // why? I've no idea...
- if (cameraPosition) {
- cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
- int count = targetPositions.Num();
- for (int i = 0; i < count; i++) {
- targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
- }
- }
- }
-*/
-/*
- int numSegments() {
- if (cameraEdit) {
- return cameraPosition.numSegments();
- }
- return getTargetSpline()->numSegments();
- }
-
- int getActiveSegment() {
- if (cameraEdit) {
- return cameraPosition.getActiveSegment();
- }
- return getTargetSpline()->getActiveSegment();
- }
-
- void setActiveSegment(int i) {
- if (cameraEdit) {
- cameraPosition.setActiveSegment(i);
- } else {
- getTargetSpline()->setActiveSegment(i);
- }
- }
-*/
- int numPoints() {
- if (cameraEdit) {
- return cameraPosition->numPoints();
- }
- return getActiveTarget()->numPoints();
- }
-
- const idVec3_t *getPoint(int index) {
- if (cameraEdit) {
- return cameraPosition->getPoint(index);
- }
- return getActiveTarget()->getPoint(index);
- }
-
- void stopEdit() {
- editMode = false;
- if (cameraEdit) {
- cameraPosition->stopEdit();
- } else {
- getActiveTarget()->stopEdit();
- }
- }
-
- void startEdit(bool camera) {
- cameraEdit = camera;
- if (camera) {
- cameraPosition->startEdit();
- for (int i = 0; i < targetPositions.Num(); i++) {
- targetPositions[i]->stopEdit();
- }
- } else {
- getActiveTarget()->startEdit();
- cameraPosition->stopEdit();
- }
- editMode = true;
- }
-
- bool waitEvent(int index);
-
- const char *getName() {
- return name.c_str();
- }
-
- void setName(const char *p) {
- name = p;
- }
-
- idCameraPosition *getPositionObj() {
- if (cameraPosition == NULL) {
- cameraPosition = new idFixedPosition();
- }
- return cameraPosition;
- }
-
-protected:
- idStr name;
- int currentCameraPosition;
- idVec3_t lastDirection;
- bool cameraRunning;
- idCameraPosition *cameraPosition;
- idList<idCameraPosition*> targetPositions;
- idList<idCameraEvent*> events;
- idCameraFOV fov;
- int activeTarget;
- float totalTime;
- float baseTime;
- long startTime;
-
- bool cameraEdit;
- bool editMode;
-};
-
-extern bool g_splineMode;
-
-extern idCameraDef *g_splineList;
-
-
-#endif
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#ifndef __SPLINES_H +#define __SPLINES_H + +extern "C" { +#ifdef Q3RADIANT +#include "../qgl.h" +#else +//#include "../renderer/qgl.h" +#endif +} +#include "util_list.h" +#include "util_str.h" +#include "math_vector.h" + +typedef int fileHandle_t; + +//extern void glBox(idVec3_t &color, idVec3_t &point, float size); +//extern void glLabeledPoint(idVec3_t &color, idVec3_t &point, float size, const char *label); + +static vec4_t blue(0, 0, 1, 1); +static vec4_t red(1, 0, 0, 1); + +class idPointListInterface { +public: + idPointListInterface() { + selectedPoints.Clear(); + } + virtual ~idPointListInterface() {} + + virtual int numPoints() { + return 0; + } + + virtual void addPoint(const float x, const float y, const float z) {} + virtual void addPoint(const idVec3_t &v) {} + virtual void removePoint(int index) {} + virtual idVec3_t *getPoint(int index) { return NULL; } + + int selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) { + idVec3_t origin(ox, oy, oz); + idVec3_t dir(dx, dy, dz); + return selectPointByRay(origin, dir, single); + } + + int selectPointByRay(const idVec3_t origin, const idVec3_t direction, bool single) { + int i, besti, count; + float d, bestd; + idVec3_t temp, temp2; + + // find the point closest to the ray + besti = -1; + bestd = 8; + count = numPoints(); + + for (i=0; i < count; i++) { + temp = *getPoint(i); + temp2 = temp; + temp -= origin; + d = DotProduct(temp, direction); + __VectorMA (origin, d, direction, temp); + temp2 -= temp; + d = temp2.Length(); + if (d <= bestd) { + bestd = d; + besti = i; + } + } + + if (besti >= 0) { + selectPoint(besti, single); + } + + return besti; + } + + int isPointSelected(int index) { + int count = selectedPoints.Num(); + for (int i = 0; i < count; i++) { + if (selectedPoints[i] == index) { + return i; + } + } + return -1; + } + + int selectPoint(int index, bool single) { + if (index >= 0 && index < numPoints()) { + if (single) { + deselectAll(); + } else { + if (isPointSelected(index) >= 0) { + selectedPoints.Remove(index); + } + } + return selectedPoints.Append(index); + } + return -1; + } + + void selectAll() { + selectedPoints.Clear(); + for (int i = 0; i < numPoints(); i++) { + selectedPoints.Append(i); + } + } + + void deselectAll() { + selectedPoints.Clear(); + } + + virtual void updateSelection(float x, float y, float z) { + idVec3_t move(x, y, z); + updateSelection(move); + } + + virtual void updateSelection(const idVec3_t &move) { + int count = selectedPoints.Num(); + for (int i = 0; i < count; i++) { + *getPoint(selectedPoints[i]) += move; + } + } +/* + void drawSelection() { + int count = selectedPoints.Num(); + for (int i = 0; i < count; i++) { + glBox(red, *getPoint(selectedPoints[i]), 4); + } + } +*/ +protected: + idList<int> selectedPoints; + +}; + + +class idSplineList { + +public: + + idSplineList() { + clear(); + } + + idSplineList(const char *p) { + clear(); + name = p; + }; + + ~idSplineList() { + clear(); + }; + + void clearControl() { + for (int i = 0; i < controlPoints.Num(); i++) { + delete controlPoints[i]; + } + controlPoints.Clear(); + } + + void clearSpline() { + for (int i = 0; i < splinePoints.Num(); i++) { + delete splinePoints[i]; + } + splinePoints.Clear(); + } + + void parse(const char *(*text)); + void write(fileHandle_t file, const char *name); + + void clear() { + clearControl(); + clearSpline(); + splineTime.Clear(); + selected = NULL; + dirty = true; + activeSegment = 0; + granularity = 0.025; + pathColor.set(1.0, 0.5, 0.0); + controlColor.set(0.7, 0.0, 1.0); + segmentColor.set(0.0, 0.0, 1.0); + activeColor.set(1.0, 0.0, 0.0); + } + + void initPosition(long startTime, long totalTime); + const idVec3_t *getPosition(long time); + + +// void draw(bool editMode); + void addToRenderer(); + + void setSelectedPoint(idVec3_t *p); + idVec3_t *getSelectedPoint() { + return selected; + } + + void addPoint(const idVec3_t &v) { + controlPoints.Append(new idVec3_t(v)); + dirty = true; + } + + void addPoint(float x, float y, float z) { + controlPoints.Append(new idVec3_t(x, y, z)); + dirty = true; + } + + void updateSelection(const idVec3_t &move); + + void startEdit() { + editMode = true; + } + + void stopEdit() { + editMode = false; + } + + void buildSpline(); + + void setGranularity(float f) { + granularity = f; + } + + float getGranularity() { + return granularity; + } + + int numPoints() { + return controlPoints.Num(); + } + + idVec3_t *getPoint(int index) { + assert(index >= 0 && index < controlPoints.Num()); + return controlPoints[index]; + } + + idVec3_t *getSegmentPoint(int index) { + assert(index >= 0 && index < splinePoints.Num()); + return splinePoints[index]; + } + + + void setSegmentTime(int index, int time) { + assert(index >= 0 && index < splinePoints.Num()); + splineTime[index] = time; + } + + double getSegmentTime(int index) { + assert(index >= 0 && index < splinePoints.Num()); + return splineTime[index]; + } + void addSegmentTime(int index, int time) { + assert(index >= 0 && index < splinePoints.Num()); + splineTime[index] += time; + } + + float totalDistance(); + + static idVec3_t zero; + + int getActiveSegment() { + return activeSegment; + } + + void setActiveSegment(int i) { + //assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num())); + activeSegment = i; + } + + int numSegments() { + return splinePoints.Num(); + } + + void setColors(idVec3_t &path, idVec3_t &segment, idVec3_t &control, idVec3_t &active) { + pathColor = path; + segmentColor = segment; + controlColor = control; + activeColor = active; + } + + const char *getName() { + return name.c_str(); + } + + void setName(const char *p) { + name = p; + } + + bool validTime() { + if (dirty) { + buildSpline(); + } + // gcc doesn't allow static casting away from bools + // why? I've no idea... + return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num()); + } + + void setTime(long t) { + time = t; + } + + void setBaseTime(long t) { + baseTime = t; + } + +protected: + idStr name; + float calcSpline(int step, float tension); + idList<idVec3_t*> controlPoints; + idList<idVec3_t*> splinePoints; + idList<double> splineTime; + idVec3_t *selected; + idVec3_t pathColor, segmentColor, controlColor, activeColor; + float granularity; + bool editMode; + bool dirty; + int activeSegment; + long baseTime; + long time; + friend class idCamera; +}; + +// time in milliseconds +// velocity where 1.0 equal rough walking speed +struct idVelocity { + idVelocity(long start, long duration, float s) { + startTime = start; + time = duration; + speed = s; + } + long startTime; + long time; + float speed; +}; + +// can either be a look at or origin position for a camera +// +class idCameraPosition : public idPointListInterface { +public: + + virtual void clear() { + editMode = false; + for (int i = 0; i < velocities.Num(); i++) { + delete velocities[i]; + velocities[i] = NULL; + } + velocities.Clear(); + } + + idCameraPosition(const char *p) { + name = p; + } + + idCameraPosition() { + time = 0; + name = "position"; + } + + idCameraPosition(long t) { + time = t; + } + + virtual ~idCameraPosition() { + clear(); + } + + + // this can be done with RTTI syntax but i like the derived classes setting a type + // makes serialization a bit easier to see + // + enum positionType { + FIXED = 0x00, + INTERPOLATED, + SPLINE, + POSITION_COUNT + }; + + + virtual void start(long t) { + startTime = t; + } + + long getTime() { + return time; + } + + virtual void setTime(long t) { + time = t; + } + + float getVelocity(long t) { + long check = t - startTime; + for (int i = 0; i < velocities.Num(); i++) { + if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) { + return velocities[i]->speed; + } + } + return baseVelocity; + } + + void addVelocity(long start, long duration, float speed) { + velocities.Append(new idVelocity(start, duration, speed)); + } + + virtual const idVec3_t *getPosition(long t) { + assert(true); + return NULL; + } + +// virtual void draw(bool editMode) {}; + + virtual void parse(const char *(*text)) {}; + virtual void write(fileHandle_t file, const char *name); + virtual bool parseToken(const char *key, const char *(*text)); + + const char *getName() { + return name.c_str(); + } + + void setName(const char *p) { + name = p; + } + + virtual void startEdit() { + editMode = true; + } + + virtual void stopEdit() { + editMode = false; + } + +// virtual void draw() {}; + + const char *typeStr() { + return positionStr[static_cast<int>(type)]; + } + + void calcVelocity(float distance) { + float secs = (float)time / 1000; + baseVelocity = distance / secs; + } + +protected: + static const char* positionStr[POSITION_COUNT]; + long startTime; + long time; + idCameraPosition::positionType type; + idStr name; + bool editMode; + idList<idVelocity*> velocities; + float baseVelocity; +}; + +class idFixedPosition : public idCameraPosition { +public: + + void init() { + pos.Zero(); + type = idCameraPosition::FIXED; + } + + idFixedPosition() : idCameraPosition() { + init(); + } + + idFixedPosition(idVec3_t p) : idCameraPosition() { + init(); + pos = p; + } + + virtual void addPoint(const idVec3_t &v) { + pos = v; + } + + virtual void addPoint(const float x, const float y, const float z) { + pos.set(x, y, z); + } + + + ~idFixedPosition() { + } + + virtual const idVec3_t *getPosition(long t) { + return &pos; + } + + void parse(const char *(*text)); + void write(fileHandle_t file, const char *name); + + virtual int numPoints() { + return 1; + } + + virtual idVec3_t *getPoint(int index) { + if (index != 0) { + assert(true); + }; + return &pos; + } +/* + virtual void draw(bool editMode) { + glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point"); + } +*/ +protected: + idVec3_t pos; +}; + +class idInterpolatedPosition : public idCameraPosition { +public: + + void init() { + type = idCameraPosition::INTERPOLATED; + first = true; + startPos.Zero(); + endPos.Zero(); + } + + idInterpolatedPosition() : idCameraPosition() { + init(); + } + + idInterpolatedPosition(idVec3_t start, idVec3_t end, long time) : idCameraPosition(time) { + init(); + startPos = start; + endPos = end; + } + + ~idInterpolatedPosition() { + } + + virtual const idVec3_t *getPosition(long t); + + void parse(const char *(*text)); + void write(fileHandle_t file, const char *name); + + virtual int numPoints() { + return 2; + } + + virtual idVec3_t *getPoint(int index) { + assert(index >= 0 && index < 2); + if (index == 0) { + return &startPos; + } + return &endPos; + } + + virtual void addPoint(const float x, const float y, const float z) { + if (first) { + startPos.set(x, y, z); + first = false; + } else { + endPos.set(x, y, z); + first = true; + } + } + + virtual void addPoint(const idVec3_t &v) { + if (first) { + startPos = v; + first = false; + } else { + endPos = v; + first = true; + } + } +/* + virtual void draw(bool editMode) { + glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated"); + glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated"); + qglBegin(GL_LINES); + qglVertex3fv(startPos); + qglVertex3fv(endPos); + qglEnd(); + } +*/ + virtual void start(long t) { + idCameraPosition::start(t); + lastTime = startTime; + distSoFar = 0.0; + idVec3_t temp = startPos; + temp -= endPos; + calcVelocity(temp.Length()); + } + +protected: + bool first; + idVec3_t startPos; + idVec3_t endPos; + long lastTime; + float distSoFar; +}; + +class idSplinePosition : public idCameraPosition { +public: + + void init() { + type = idCameraPosition::SPLINE; + } + + idSplinePosition() : idCameraPosition() { + init(); + } + + idSplinePosition(long time) : idCameraPosition(time) { + init(); + } + + ~idSplinePosition() { + } + + virtual void start(long t) { + idCameraPosition::start(t); + target.initPosition(t, time); + calcVelocity(target.totalDistance()); + } + + virtual const idVec3_t *getPosition(long t) { + return target.getPosition(t); + } + + //virtual const idVec3_t *getPosition(long t) const { + + void addControlPoint(idVec3_t &v) { + target.addPoint(v); + } + + void parse(const char *(*text)); + void write(fileHandle_t file, const char *name); + + virtual int numPoints() { + return target.numPoints(); + } + + virtual idVec3_t *getPoint(int index) { + return target.getPoint(index); + } + + virtual void addPoint(const idVec3_t &v) { + target.addPoint(v); + } + + virtual void addPoint(const float x, const float y, const float z) { + target.addPoint(x, y, z); + } + +/* virtual void draw(bool editMode) { + target.draw(editMode); + } +*/ + virtual void updateSelection(const idVec3_t &move) { + idCameraPosition::updateSelection(move); + target.buildSpline(); + } + +protected: + idSplineList target; +}; + +class idCameraFOV { +public: + + idCameraFOV() { + time = 0; + fov = 90; + } + + idCameraFOV(int v) { + time = 0; + fov = v; + } + + idCameraFOV(int s, int e, long t) { + startFOV = s; + endFOV = e; + time = t; + } + + + ~idCameraFOV(){} + + void setFOV(float f) { + fov = f; + } + + float getFOV(long t) { + if (time) { + assert(startTime); + float percent = t / startTime; + float temp = startFOV - endFOV; + temp *= percent; + fov = startFOV + temp; + } + return fov; + } + + void start(long t) { + startTime = t; + } + + void parse(const char *(*text)); + void write(fileHandle_t file, const char *name); + +protected: + float fov; + float startFOV; + float endFOV; + int startTime; + int time; +}; + + + + +class idCameraEvent { +public: + enum eventType { + EVENT_NA = 0x00, + EVENT_WAIT, + EVENT_TARGETWAIT, + EVENT_SPEED, + EVENT_TARGET, + EVENT_SNAPTARGET, + EVENT_FOV, + EVENT_SCRIPT, + EVENT_TRIGGER, + EVENT_STOP, + EVENT_COUNT + }; + + static const char* eventStr[EVENT_COUNT]; + + idCameraEvent() { + paramStr = ""; + type = EVENT_NA; + time = 0; + } + + idCameraEvent(eventType t, const char *param, long n) { + type = t; + paramStr = param; + time = n; + } + + ~idCameraEvent() {}; + + eventType getType() { + return type; + } + + const char *typeStr() { + return eventStr[static_cast<int>(type)]; + } + + const char *getParam() { + return paramStr.c_str(); + } + + long getTime() { + return time; + } + + void setTime(long n) { + time = n; + } + + void parse(const char *(*text)); + void write(fileHandle_t file, const char *name); + + void setTriggered(bool b) { + triggered = b; + } + + bool getTriggered() { + return triggered; + } + +protected: + eventType type; + idStr paramStr; + long time; + bool triggered; + +}; + +class idCameraDef { +public: + + void clear() { + currentCameraPosition = 0; + cameraRunning = false; + lastDirection.Zero(); + baseTime = 30; + activeTarget = 0; + name = "camera01"; + fov.setFOV(90); + int i; + for (i = 0; i < targetPositions.Num(); i++) { + delete targetPositions[i]; + } + for (i = 0; i < events.Num(); i++) { + delete events[i]; + } + delete cameraPosition; + cameraPosition = NULL; + events.Clear(); + targetPositions.Clear(); + } + + idCameraPosition *startNewCamera(idCameraPosition::positionType type) { + clear(); + if (type == idCameraPosition::SPLINE) { + cameraPosition = new idSplinePosition(); + } else if (type == idCameraPosition::INTERPOLATED) { + cameraPosition = new idInterpolatedPosition(); + } else { + cameraPosition = new idFixedPosition(); + } + return cameraPosition; + } + + idCameraDef() { + clear(); + } + + ~idCameraDef() { + clear(); + } + + void addEvent(idCameraEvent::eventType t, const char *param, long time); + + void addEvent(idCameraEvent *event); + + static int sortEvents(const void *p1, const void *p2); + + int numEvents() { + return events.Num(); + } + + idCameraEvent *getEvent(int index) { + assert(index >= 0 && index < events.Num()); + return events[index]; + } + + void parse(const char *(*text)); + qboolean load(const char *filename); + void save(const char *filename); + + void buildCamera(); + + //idSplineList *getcameraPosition() { + // return &cameraPosition; + //} + + static idCameraPosition *newFromType(idCameraPosition::positionType t) { + switch (t) { + case idCameraPosition::FIXED : return new idFixedPosition(); + case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition(); + case idCameraPosition::SPLINE : return new idSplinePosition(); + default: + break; + }; + return NULL; + } + + void addTarget(const char *name, idCameraPosition::positionType type); + + idCameraPosition *getActiveTarget() { + if (targetPositions.Num() == 0) { + addTarget(NULL, idCameraPosition::FIXED); + } + return targetPositions[activeTarget]; + } + + idCameraPosition *getActiveTarget(int index) { + if (targetPositions.Num() == 0) { + addTarget(NULL, idCameraPosition::FIXED); + return targetPositions[0]; + } + return targetPositions[index]; + } + + int numTargets() { + return targetPositions.Num(); + } + + + void setActiveTargetByName(const char *name) { + for (int i = 0; i < targetPositions.Num(); i++) { + if (Q_stricmp(name, targetPositions[i]->getName()) == 0) { + setActiveTarget(i); + return; + } + } + } + + void setActiveTarget(int index) { + assert(index >= 0 && index < targetPositions.Num()); + activeTarget = index; + } + + void setRunning(bool b) { + cameraRunning = b; + } + + void setBaseTime(float f) { + baseTime = f; + } + + float getBaseTime() { + return baseTime; + } + + float getTotalTime() { + return totalTime; + } + + void startCamera(long t); + void stopCamera() { + cameraRunning = true; + } + void getActiveSegmentInfo(int segment, idVec3_t &origin, idVec3_t &direction, float *fv); + + bool getCameraInfo(long time, idVec3_t &origin, idVec3_t &direction, float *fv); + bool getCameraInfo(long time, float *origin, float *direction, float *fv) { + idVec3_t org, dir; + org[0] = origin[0]; + org[1] = origin[1]; + org[2] = origin[2]; + dir[0] = direction[0]; + dir[1] = direction[1]; + dir[2] = direction[2]; + bool b = getCameraInfo(time, org, dir, fv); + origin[0] = org[0]; + origin[1] = org[1]; + origin[2] = org[2]; + direction[0] = dir[0]; + direction[1] = dir[1]; + direction[2] = dir[2]; + return b; + } +/* + void draw(bool editMode) { + // gcc doesn't allow casting away from bools + // why? I've no idea... + if (cameraPosition) { + cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit)); + int count = targetPositions.Num(); + for (int i = 0; i < count; i++) { + targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit)); + } + } + } +*/ +/* + int numSegments() { + if (cameraEdit) { + return cameraPosition.numSegments(); + } + return getTargetSpline()->numSegments(); + } + + int getActiveSegment() { + if (cameraEdit) { + return cameraPosition.getActiveSegment(); + } + return getTargetSpline()->getActiveSegment(); + } + + void setActiveSegment(int i) { + if (cameraEdit) { + cameraPosition.setActiveSegment(i); + } else { + getTargetSpline()->setActiveSegment(i); + } + } +*/ + int numPoints() { + if (cameraEdit) { + return cameraPosition->numPoints(); + } + return getActiveTarget()->numPoints(); + } + + const idVec3_t *getPoint(int index) { + if (cameraEdit) { + return cameraPosition->getPoint(index); + } + return getActiveTarget()->getPoint(index); + } + + void stopEdit() { + editMode = false; + if (cameraEdit) { + cameraPosition->stopEdit(); + } else { + getActiveTarget()->stopEdit(); + } + } + + void startEdit(bool camera) { + cameraEdit = camera; + if (camera) { + cameraPosition->startEdit(); + for (int i = 0; i < targetPositions.Num(); i++) { + targetPositions[i]->stopEdit(); + } + } else { + getActiveTarget()->startEdit(); + cameraPosition->stopEdit(); + } + editMode = true; + } + + bool waitEvent(int index); + + const char *getName() { + return name.c_str(); + } + + void setName(const char *p) { + name = p; + } + + idCameraPosition *getPositionObj() { + if (cameraPosition == NULL) { + cameraPosition = new idFixedPosition(); + } + return cameraPosition; + } + +protected: + idStr name; + int currentCameraPosition; + idVec3_t lastDirection; + bool cameraRunning; + idCameraPosition *cameraPosition; + idList<idCameraPosition*> targetPositions; + idList<idCameraEvent*> events; + idCameraFOV fov; + int activeTarget; + float totalTime; + float baseTime; + long startTime; + + bool cameraEdit; + bool editMode; +}; + +extern bool g_splineMode; + +extern idCameraDef *g_splineList; + + +#endif diff --git a/code/splines/util_list.h b/code/splines/util_list.h index 6ee8f6a..6fcc472 100755 --- a/code/splines/util_list.h +++ b/code/splines/util_list.h @@ -1,346 +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__ */
+/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Foobar; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +#ifndef __UTIL_LIST_H__ +#define __UTIL_LIST_H__ + +#include <stdlib.h> +#include <assert.h> + +template< class type > +class idList { +private: + int m_num; + int m_size; + int m_granularity; + type *m_list; + +public: + idList( int granularity = 16 ); + ~idList<type>(); + void Clear( void ); + int Num( void ); + void SetNum( int num ); + void SetGranularity( int granularity ); + void Condense( void ); + int Size( void ); + void Resize( int size ); + type operator[]( int index ) const; + type &operator[]( int index ); + int Append( type const & obj ); + int AddUnique( type const & obj ); + type *Find( type const & obj, int *index = NULL ); + bool RemoveIndex( int index ); + bool Remove( type const & obj ); + typedef int cmp_t(const void *, const void *); + void Sort( cmp_t *compare ); +}; + +/* +================ +idList<type>::idList( int ) +================ +*/ +template< class type > +inline idList<type>::idList( int granularity ) { + assert( granularity > 0 ); + + m_list = NULL; + m_granularity = granularity; + Clear(); +} + +/* +================ +idList<type>::~idList<type> +================ +*/ +template< class type > +inline idList<type>::~idList() { + Clear(); +} + +/* +================ +idList<type>::Clear +================ +*/ +template< class type > +inline void idList<type>::Clear( void ) { + if ( m_list ) { + delete[] m_list; + } + + m_list = NULL; + m_num = 0; + m_size = 0; +} + +/* +================ +idList<type>::Num +================ +*/ +template< class type > +inline int idList<type>::Num( void ) { + return m_num; +} + +/* +================ +idList<type>::SetNum +================ +*/ +template< class type > +inline void idList<type>::SetNum( int num ) { + assert( num >= 0 ); + if ( num > m_size ) { + // resize it up to the closest level of granularity + Resize( ( ( num + m_granularity - 1 ) / m_granularity ) * m_granularity ); + } + m_num = num; +} + +/* +================ +idList<type>::SetGranularity +================ +*/ +template< class type > +inline void idList<type>::SetGranularity( int granularity ) { + int newsize; + + assert( granularity > 0 ); + m_granularity = granularity; + + if ( m_list ) { + // resize it to the closest level of granularity + newsize = ( ( m_num + m_granularity - 1 ) / m_granularity ) * m_granularity; + if ( newsize != m_size ) { + Resize( newsize ); + } + } +} + +/* +================ +idList<type>::Condense + +Resizes the array to exactly the number of elements it contains +================ +*/ +template< class type > +inline void idList<type>::Condense( void ) { + if ( m_list ) { + if ( m_num ) { + Resize( m_num ); + } else { + Clear(); + } + } +} + +/* +================ +idList<type>::Size +================ +*/ +template< class type > +inline int idList<type>::Size( void ) { + return m_size; +} + +/* +================ +idList<type>::Resize +================ +*/ +template< class type > +inline void idList<type>::Resize( int size ) { + type *temp; + int i; + + assert( size > 0 ); + + if ( size <= 0 ) { + Clear(); + return; + } + + temp = m_list; + m_size = size; + if ( m_size < m_num ) { + m_num = m_size; + } + + m_list = new type[ m_size ]; + for( i = 0; i < m_num; i++ ) { + m_list[ i ] = temp[ i ]; + } + + if ( temp ) { + delete[] temp; + } +} + +/* +================ +idList<type>::operator[] const +================ +*/ +template< class type > +inline type idList<type>::operator[]( int index ) const { + assert( index >= 0 ); + assert( index < m_num ); + + return m_list[ index ]; +} + +/* +================ +idList<type>::operator[] +================ +*/ +template< class type > +inline type &idList<type>::operator[]( int index ) { + assert( index >= 0 ); + assert( index < m_num ); + + return m_list[ index ]; +} + +/* +================ +idList<type>::Append +================ +*/ +template< class type > +inline int idList<type>::Append( type const & obj ) { + if ( !m_list ) { + Resize( m_granularity ); + } + + if ( m_num == m_size ) { + Resize( m_size + m_granularity ); + } + + m_list[ m_num ] = obj; + m_num++; + + return m_num - 1; +} + +/* +================ +idList<type>::AddUnique +================ +*/ +template< class type > +inline int idList<type>::AddUnique( type const & obj ) { + int index; + + if ( !Find( obj, &index ) ) { + index = Append( obj ); + } + + return index; +} + +/* +================ +idList<type>::Find +================ +*/ +template< class type > +inline type *idList<type>::Find( type const & obj, int *index ) { + int i; + + for( i = 0; i < m_num; i++ ) { + if ( m_list[ i ] == obj ) { + if ( index ) { + *index = i; + } + return &m_list[ i ]; + } + } + + return NULL; +} + +/* +================ +idList<type>::RemoveIndex +================ +*/ +template< class type > +inline bool idList<type>::RemoveIndex( int index ) { + int i; + + if ( !m_list || !m_num ) { + return false; + } + + assert( index >= 0 ); + assert( index < m_num ); + + if ( ( index < 0 ) || ( index >= m_num ) ) { + return false; + } + + m_num--; + for( i = index; i < m_num; i++ ) { + m_list[ i ] = m_list[ i + 1 ]; + } + + return true; +} + +/* +================ +idList<type>::Remove +================ +*/ +template< class type > +inline bool idList<type>::Remove( type const & obj ) { + int index; + + if ( Find( obj, &index ) ) { + return RemoveIndex( index ); + } + + return false; +} + +/* +================ +idList<type>::Sort +================ +*/ +template< class type > +inline void idList<type>::Sort( cmp_t *compare ) { + if ( !m_list ) { + return; + } + + qsort( ( void * )m_list, ( size_t )m_num, sizeof( type ), compare ); +} + +#endif /* !__UTIL_LIST_H__ */ diff --git a/code/splines/util_str.cpp b/code/splines/util_str.cpp index 0ae7362..395f62b 100755 --- a/code/splines/util_str.cpp +++ b/code/splines/util_str.cpp @@ -1,620 +1,620 @@ -/*
-===========================================================================
-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
-
- // TTimo: not used
-// 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
+/* +=========================================================================== +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 + + // TTimo: not used +// const char *s1 = a.c_str(); // s1 == "\0" +// const char *s2 = c.c_str(); // s2 == "test\0" + + t = new idStr(); // t->len == 0, t->data == "\0" + delete t; // t == ? + + b = "test"; // b.len == 4, b.data == "test\0" + t = new idStr( "test" ); // t->len == 4, t->data == "test\0" + delete t; // t == ? + + a = c; // a.len == 4, a.data == "test\0" +// a = ""; + a = NULL; // a.len == 0, a.data == "\0" ASSERT! + a = c + d; // a.len == 8, a.data == "testtest\0" + a = c + "wow"; // a.len == 7, a.data == "testwow\0" + a = c + reinterpret_cast<const char *>(NULL); + // a.len == 4, a.data == "test\0" ASSERT! + a = "this" + d; // a.len == 8, a.data == "thistest\0" + a = reinterpret_cast<const char *>(NULL) + d; + // a.len == 4, a.data == "test\0" ASSERT! + a += c; // a.len == 8, a.data == "testtest\0" + a += "wow"; // a.len == 11, a.data == "testtestwow\0" + a += reinterpret_cast<const char *>(NULL); + // a.len == 11, a.data == "testtestwow\0" ASSERT! + + a = "test"; // a.len == 4, a.data == "test\0" + ch = a[ 0 ]; // ch == 't' + ch = a[ -1 ]; // ch == 0 ASSERT! + ch = a[ 1000 ]; // ch == 0 ASSERT! + ch = a[ 0 ]; // ch == 't' + ch = a[ 1 ]; // ch == 'e' + ch = a[ 2 ]; // ch == 's' + ch = a[ 3 ]; // ch == 't' + ch = a[ 4 ]; // ch == '\0' ASSERT! + ch = a[ 5 ]; // ch == '\0' ASSERT! + + a[ 1 ] = 'b'; // a.len == 4, a.data == "tbst\0" + a[ -1 ] = 'b'; // a.len == 4, a.data == "tbst\0" ASSERT! + a[ 0 ] = '0'; // a.len == 4, a.data == "0bst\0" + a[ 1 ] = '1'; // a.len == 4, a.data == "01st\0" + a[ 2 ] = '2'; // a.len == 4, a.data == "012t\0" + a[ 3 ] = '3'; // a.len == 4, a.data == "0123\0" + a[ 4 ] = '4'; // a.len == 4, a.data == "0123\0" ASSERT! + a[ 5 ] = '5'; // a.len == 4, a.data == "0123\0" ASSERT! + a[ 7 ] = '7'; // a.len == 4, a.data == "0123\0" ASSERT! + + a = "test"; // a.len == 4, a.data == "test\0" + b = "no"; // b.len == 2, b.data == "no\0" + + i = ( a == b ); // i == 0 + i = ( a == c ); // i == 1 + + i = ( a == "blow" ); // i == 0 + i = ( a == "test" ); // i == 1 + i = ( a == NULL ); // i == 0 ASSERT! + + i = ( "test" == b ); // i == 0 + i = ( "test" == a ); // i == 1 + i = ( NULL == a ); // i == 0 ASSERT! + + i = ( a != b ); // i == 1 + i = ( a != c ); // i == 0 + + i = ( a != "blow" ); // i == 1 + i = ( a != "test" ); // i == 0 + i = ( a != NULL ); // i == 1 ASSERT! + + i = ( "test" != b ); // i == 1 + i = ( "test" != a ); // i == 0 + i = ( NULL != a ); // i == 1 ASSERT! + + a = "test"; // a.data == "test" + b = a; // b.data == "test" + + a = "not"; // a.data == "not", b.data == "test" + + a = b; // a.data == b.data == "test" + + a += b; // a.data == "testtest", b.data = "test" + + a = b; + + a[1] = '1'; // a.data = "t1st", b.data = "test" + } + +#ifdef _WIN32 +#pragma warning(default : 4189) // local variable is initialized but not referenced +#pragma warning(disable : 4514) // unreferenced inline function has been removed +#endif diff --git a/code/splines/util_str.h b/code/splines/util_str.h index 514464b..2ef3fc2 100755 --- a/code/splines/util_str.h +++ b/code/splines/util_str.h @@ -1,817 +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 );
-
- static char *toLower( char *s1 );
- static char *toUpper( char *s1 );
-
- 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 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
+/* +=========================================================================== +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 ); + + static char *toLower( char *s1 ); + static char *toUpper( char *s1 ); + + 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 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 |