From 8fbb570f0bbf415b4333f4504894edc0846c09cf Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Mon, 22 Jun 2026 00:14:41 -0300 Subject: [PATCH 1/8] feat(math): integrate deterministic GameMath Replaces standard CRT trigonometric functions with deterministic fdlibm equivalents from GameMath via FetchContent. Ensures multiplayer cross-platform replay determinism. Resolves cross-platform mismatch disconnects. --- .../Source/WWVegas/WWMath/CMakeLists.txt | 6 ++ Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 64 +++++++++---------- cmake/gamemath.cmake | 32 ++++------ flatpak/com.fbraz3.GeneralsX.yml | 7 +- flatpak/com.fbraz3.GeneralsXZH.yml | 7 +- 5 files changed, 60 insertions(+), 56 deletions(-) diff --git a/Core/Libraries/Source/WWVegas/WWMath/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWMath/CMakeLists.txt index dca9eb68fef..8a6045785fd 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WWMath/CMakeLists.txt @@ -91,5 +91,11 @@ target_link_libraries(core_wwmath PRIVATE core_wwsaveload ) +if (SAGE_USE_DETERMINISTIC_MATH) + target_link_libraries(core_wwmath PUBLIC + gamemath + ) +endif() + # @todo Test its impact and see what to do with the legacy functions. #add_compile_definitions(core_wwmath PUBLIC ALLOW_TEMPORARIES) # Enables legacy math with "temporaries" diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index 2202f52a5c9..55b524f9548 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -41,6 +41,14 @@ #include #include +// Include GameMath headers when deterministic math is enabled +// Use __has_include because wwmath.h is transitively included by targets that may not link gamemath. +// Must be outside class WWMath to prevent injecting global symbols into the class. +#if defined(__has_include) && __has_include("gmath.h") +#include "gmath.h" +#define USE_DETERMINISTIC_MATH (1) +#endif + /* ** Some global constants. */ @@ -139,19 +147,10 @@ static WWINLINE float Asin(float val); // Upstream reference: Okladnoj, PR #2670 // https://github.com/TheSuperHackers/GeneralsGameCode/pull/2670 -// Include GameMath headers when deterministic math is enabled -// Note: GameMath integration is pending. This header will be populated when -// GameMath submodule or library is available. For now, wrappers fallback to CRT. -#ifdef USE_DETERMINISTIC_MATH -// TODO: Uncomment when GameMath library is integrated as submodule -// #include "GameMath/deterministic_math.h" -#endif - static WWINLINE float Atan(float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Atan(x); - return static_cast(atan(x)); + return gm_atanf(x); #else return static_cast(atan(x)); #endif @@ -160,8 +159,7 @@ static WWINLINE float Atan(float x) static WWINLINE float Atan2(float y, float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Atan2(y, x); - return static_cast(atan2(y, x)); + return gm_atan2f(y, x); #else return static_cast(atan2(y, x)); #endif @@ -172,28 +170,25 @@ static WWINLINE float Atan2(float y, float x) static WWINLINE float SinTrig(float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Sin(x); - return Sin(x); + return gm_sinf(x); #else - return Sin(x); + return sinf(x); #endif } static WWINLINE float CosTrig(float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Cos(x); - return Cos(x); + return gm_cosf(x); #else - return Cos(x); + return cosf(x); #endif } static WWINLINE float TanTrig(float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Tan(x); - return tanf(x); + return gm_tanf(x); #else return tanf(x); #endif @@ -202,34 +197,37 @@ static WWINLINE float TanTrig(float x) static WWINLINE float ACosTrig(float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Acos(x); - return Acos(x); + return gm_acosf(x); #else - return Acos(x); + return acosf(x); #endif } static WWINLINE float ASinTrig(float x) { #ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Asin(x); - return Asin(x); + return gm_asinf(x); #else - return Asin(x); + return asinf(x); #endif } // Phase 4: Origin sqrt gateway for geometry (Coord2D/Coord3D length calculations) // Must dispatch to deterministic Sqrt when enabled -static WWINLINE double SqrtOrigin(double x) -{ -#ifdef USE_DETERMINISTIC_MATH - // TODO: return GameMath::Sqrt(x); - return sqrt(x); +// Origin wrappers: replace bare CRT math calls in GameLogic. +// Each wrapper preserves the exact type (float vs double) of the vanilla CRT call. +// Note: double overloads narrow to float before calling GameMath (gm_*f). +// GameMath only provides float-precision functions. All call sites pass float-width +// values, so the narrowing is lossless in practice. +#if USE_DETERMINISTIC_MATH + static WWINLINE double SqrtOrigin(double x) { return (double)gm_sqrtf((float)x); } + static WWINLINE float SqrtfOrigin(float x) { return gm_sqrtf(x); } + static WWINLINE double Atan2Origin(double y, double x) { return (double)gm_atan2f((float)y, (float)x); } #else - return sqrt(x); + static WWINLINE double SqrtOrigin(double x) { return sqrt(x); } + static WWINLINE float SqrtfOrigin(float x) { return sqrtf(x); } + static WWINLINE double Atan2Origin(double y, double x) { return atan2(y, x); } #endif -} static WWINLINE float Sign(float val); static WWINLINE float Ceil(float val) { return ceilf(val); } static WWINLINE float Floor(float val) { return floorf(val); } diff --git a/cmake/gamemath.cmake b/cmake/gamemath.cmake index 9708fa498ed..729ffdd81d2 100644 --- a/cmake/gamemath.cmake +++ b/cmake/gamemath.cmake @@ -20,7 +20,7 @@ # Enable deterministic math only for non-VC6 builds (VC6 uses native x87 asm) # Note: Currently defaults to OFF until GameMath is available as a proper library/submodule if(NOT IS_VS6_BUILD) - option(SAGE_USE_DETERMINISTIC_MATH "Use fdlibm-based deterministic math for cross-platform replay validation" OFF) + option(SAGE_USE_DETERMINISTIC_MATH "Use fdlibm-based deterministic math for cross-platform replay validation" ON) else() # VC6 uses native x87 inline asm; deterministic mode not applicable set(SAGE_USE_DETERMINISTIC_MATH OFF) @@ -31,34 +31,24 @@ if(SAGE_USE_DETERMINISTIC_MATH) include(FetchContent) - # FetchContent declaration for GameMath library - # Source: TheSuperHackers fork with deterministic math support - # Can be overridden via cmake -DSAGE_GAMEMATH_GIT_REPO= -DSAGE_GAMEMATH_GIT_TAG= - if(NOT SAGE_GAMEMATH_GIT_REPO) - set(SAGE_GAMEMATH_GIT_REPO "https://github.com/TheSuperHackers/GeneralsGameCode.git") - endif() - - if(NOT SAGE_GAMEMATH_GIT_TAG) - set(SAGE_GAMEMATH_GIT_TAG "main") - endif() + # FORCE is required to guarantee cross-platform bit-exact determinism. + # Intrinsics would use platform-specific SIMD, breaking CRC parity between architectures. + set(GM_ENABLE_INTRINSICS OFF CACHE BOOL "Disable intrinsics for cross-arch determinism" FORCE) + set(GM_ENABLE_TESTS OFF CACHE BOOL "Disable GameMath tests" FORCE) + set(gamemath_SHARED_LIBS OFF CACHE BOOL "Force GameMath as static lib" FORCE) FetchContent_Declare( gamemath - GIT_REPOSITORY ${SAGE_GAMEMATH_GIT_REPO} - GIT_TAG ${SAGE_GAMEMATH_GIT_TAG} - SOURCE_SUBDIR "Core/GameMath" # Adjust if GameMath moves + GIT_REPOSITORY https://github.com/TheSuperHackers/GameMath.git + GIT_TAG 59f7ccd494f7e7c916a784ac26ef266f9f09d78d ) - # Minimal GameMath configuration - set(GAMEMATH_ENABLE_TESTS OFF CACHE BOOL "Disable GameMath tests" FORCE) - set(GAMEMATH_ENABLE_EXAMPLES OFF CACHE BOOL "Disable GameMath examples" FORCE) - # Make GameMath available (FetchContent_MakeAvailable is idempotent) FetchContent_MakeAvailable(gamemath) - # Add USE_DETERMINISTIC_MATH to all compile definitions for this project - # This enables conditional compilation in wwmath.h and trig wrappers - add_compile_definitions(USE_DETERMINISTIC_MATH) + # Ensure GameMath includes are available to ALL targets + # to prevent one-definition-rule violations and ensure USE_DETERMINISTIC_MATH activates consistently. + include_directories(${gamemath_SOURCE_DIR}/include) message(STATUS "GameMath deterministic math enabled (fdlibm backend)") message(STATUS " Math operations will be bit-exact across platforms") diff --git a/flatpak/com.fbraz3.GeneralsX.yml b/flatpak/com.fbraz3.GeneralsX.yml index ba4d9baaa47..c9abf71e894 100644 --- a/flatpak/com.fbraz3.GeneralsX.yml +++ b/flatpak/com.fbraz3.GeneralsX.yml @@ -65,7 +65,8 @@ modules: -DFETCHCONTENT_SOURCE_DIR_SDL3_IMAGE=/run/build/generalsx/sdl3-image-src \ -DFETCHCONTENT_SOURCE_DIR_OPENAL_SOFT=/run/build/generalsx/openal-soft-src \ -DFETCHCONTENT_SOURCE_DIR_GAMESPY=/run/build/generalsx/gamespy-src \ - -DFETCHCONTENT_SOURCE_DIR_LZHL=/run/build/generalsx/lzhl-src/CompLibHeader + -DFETCHCONTENT_SOURCE_DIR_LZHL=/run/build/generalsx/lzhl-src/CompLibHeader \ + -DFETCHCONTENT_SOURCE_DIR_GAMEMATH=/run/build/generalsx/gamemath-src - cmake --build build-flatpak --target g_generals -j "${FLATPAK_BUILDER_N_JOBS:-4}" - cmake --build build-flatpak --target sage_patch -j "${FLATPAK_BUILDER_N_JOBS:-4}" || true - install -Dm755 build-flatpak/Generals/GeneralsX /app/bin/GeneralsX @@ -185,3 +186,7 @@ modules: url: https://github.com/TheSuperHackers/lzhl-1.0 commit: dfd96e2ca64adaddb35dd4ebadd6add7d5586783 dest: lzhl-src/CompLibHeader + - type: git + url: https://github.com/TheSuperHackers/GameMath.git + commit: 59f7ccd494f7e7c916a784ac26ef266f9f09d78d + dest: gamemath-src diff --git a/flatpak/com.fbraz3.GeneralsXZH.yml b/flatpak/com.fbraz3.GeneralsXZH.yml index 4a50e476f93..84ffa8febd0 100644 --- a/flatpak/com.fbraz3.GeneralsXZH.yml +++ b/flatpak/com.fbraz3.GeneralsXZH.yml @@ -65,7 +65,8 @@ modules: -DFETCHCONTENT_SOURCE_DIR_SDL3_IMAGE=/run/build/generalsxzh/sdl3-image-src \ -DFETCHCONTENT_SOURCE_DIR_OPENAL_SOFT=/run/build/generalsxzh/openal-soft-src \ -DFETCHCONTENT_SOURCE_DIR_GAMESPY=/run/build/generalsxzh/gamespy-src \ - -DFETCHCONTENT_SOURCE_DIR_LZHL=/run/build/generalsxzh/lzhl-src/CompLibHeader + -DFETCHCONTENT_SOURCE_DIR_LZHL=/run/build/generalsxzh/lzhl-src/CompLibHeader \ + -DFETCHCONTENT_SOURCE_DIR_GAMEMATH=/run/build/generalsxzh/gamemath-src - cmake --build build-flatpak --target z_generals -j "${FLATPAK_BUILDER_N_JOBS:-4}" - cmake --build build-flatpak --target sage_patch -j "${FLATPAK_BUILDER_N_JOBS:-4}" || true - install -Dm755 build-flatpak/GeneralsMD/GeneralsXZH /app/bin/GeneralsXZH @@ -188,3 +189,7 @@ modules: url: https://github.com/TheSuperHackers/lzhl-1.0 commit: dfd96e2ca64adaddb35dd4ebadd6add7d5586783 dest: lzhl-src/CompLibHeader + - type: git + url: https://github.com/TheSuperHackers/GameMath.git + commit: 59f7ccd494f7e7c916a784ac26ef266f9f09d78d + dest: gamemath-src From 6327d35faa4dbbfd985dd4648f26b0ed544e07d0 Mon Sep 17 00:00:00 2001 From: Felipe Braz Date: Mon, 22 Jun 2026 20:04:52 -0300 Subject: [PATCH 2/8] Enforce cross-platform math determinism (GameMath) & Fix Linux build --- .../MiniAudioDevice/MiniAudioManager.cpp | 2 +- Core/Libraries/Source/WWVegas/WWMath/wwmath.h | 51 +++++++++++++++---- .../Include/GameLogic/PartitionManager.h | 2 +- .../GameEngine/Source/Common/RTS/Player.cpp | 2 +- .../Source/Common/System/BuildAssistant.cpp | 10 ++-- .../Source/Common/System/Geometry.cpp | 18 +++---- .../GameEngine/Source/Common/System/Trig.cpp | 4 +- .../GameEngine/Source/GameClient/Drawable.cpp | 4 +- .../MessageStream/PlaceEventTranslator.cpp | 2 +- .../GameEngine/Source/GameLogic/AI/AI.cpp | 2 +- .../Source/GameLogic/AI/AIGroup.cpp | 4 +- .../Source/GameLogic/AI/AIPlayer.cpp | 6 +-- .../Source/GameLogic/AI/AISkirmishPlayer.cpp | 8 +-- .../Source/GameLogic/AI/AIStates.cpp | 10 ++-- .../Source/GameLogic/Map/PolygonTrigger.cpp | 2 +- .../Source/GameLogic/Map/TerrainLogic.cpp | 4 +- .../Object/Behavior/BridgeBehavior.cpp | 2 +- .../Behavior/DumbProjectileBehavior.cpp | 14 ++--- .../Behavior/GenerateMinefieldBehavior.cpp | 2 +- .../Object/Behavior/MinefieldBehavior.cpp | 4 +- .../Object/Behavior/SlowDeathBehavior.cpp | 2 +- .../Source/GameLogic/Object/Locomotor.cpp | 28 +++++----- .../GameLogic/Object/ObjectCreationList.cpp | 8 +-- .../GameLogic/Object/PartitionManager.cpp | 30 +++++------ .../GameLogic/Object/Update/AIUpdate.cpp | 8 +-- .../Update/AIUpdate/ChinookAIUpdate.cpp | 2 +- .../AIUpdate/DeliverPayloadAIUpdate.cpp | 10 ++-- .../Object/Update/AIUpdate/JetAIUpdate.cpp | 6 +-- .../Update/AIUpdate/MissileAIUpdate.cpp | 6 +-- .../Update/AIUpdate/POWTruckAIUpdate.cpp | 2 +- .../Update/AIUpdate/RailroadGuideAIUpdate.cpp | 4 +- .../Object/Update/CleanupHazardUpdate.cpp | 4 +- .../Object/Update/CommandButtonHuntUpdate.cpp | 2 +- .../DockUpdate/SupplyWarehouseDockUpdate.cpp | 4 +- .../DynamicShroudClearingRangeUpdate.cpp | 4 +- .../GameLogic/Object/Update/FloatUpdate.cpp | 4 +- .../Object/Update/NeutronMissileUpdate.cpp | 4 +- .../Update/ParticleUplinkCannonUpdate.cpp | 6 +-- .../GameLogic/Object/Update/PhysicsUpdate.cpp | 24 ++++----- .../Object/Update/PointDefenseLaserUpdate.cpp | 6 +-- .../GameLogic/Object/Update/ToppleUpdate.cpp | 2 +- .../Source/GameLogic/Object/Weapon.cpp | 16 +++--- .../Source/GameLogic/System/GameLogic.cpp | 2 +- .../Include/GameLogic/PartitionManager.h | 2 +- .../GameEngine/Source/Common/RTS/Player.cpp | 2 +- .../Source/Common/System/BuildAssistant.cpp | 10 ++-- .../Source/Common/System/Geometry.cpp | 18 +++---- .../GameEngine/Source/Common/System/Trig.cpp | 4 +- .../GameEngine/Source/GameClient/Drawable.cpp | 8 +-- .../MessageStream/PlaceEventTranslator.cpp | 2 +- .../GameEngine/Source/GameLogic/AI/AI.cpp | 2 +- .../Source/GameLogic/AI/AIGroup.cpp | 4 +- .../Source/GameLogic/AI/AIPlayer.cpp | 6 +-- .../Source/GameLogic/AI/AISkirmishPlayer.cpp | 8 +-- .../Source/GameLogic/AI/AIStates.cpp | 10 ++-- .../Source/GameLogic/Map/PolygonTrigger.cpp | 2 +- .../Source/GameLogic/Map/TerrainLogic.cpp | 6 +-- .../Object/Behavior/BridgeBehavior.cpp | 2 +- .../Behavior/DumbProjectileBehavior.cpp | 14 ++--- .../Behavior/GenerateMinefieldBehavior.cpp | 2 +- .../Object/Behavior/MinefieldBehavior.cpp | 4 +- .../Object/Behavior/SlowDeathBehavior.cpp | 2 +- .../Source/GameLogic/Object/Locomotor.cpp | 28 +++++----- .../GameLogic/Object/ObjectCreationList.cpp | 8 +-- .../GameLogic/Object/PartitionManager.cpp | 30 +++++------ .../GameLogic/Object/Update/AIUpdate.cpp | 8 +-- .../AIUpdate/DeliverPayloadAIUpdate.cpp | 10 ++-- .../Object/Update/AIUpdate/JetAIUpdate.cpp | 6 +-- .../Update/AIUpdate/MissileAIUpdate.cpp | 6 +-- .../Update/AIUpdate/POWTruckAIUpdate.cpp | 2 +- .../Update/AIUpdate/RailroadGuideAIUpdate.cpp | 4 +- .../Object/Update/CleanupHazardUpdate.cpp | 4 +- .../Object/Update/CommandButtonHuntUpdate.cpp | 2 +- .../DockUpdate/SupplyWarehouseDockUpdate.cpp | 4 +- .../DynamicShroudClearingRangeUpdate.cpp | 4 +- .../GameLogic/Object/Update/FloatUpdate.cpp | 4 +- .../Object/Update/NeutronMissileUpdate.cpp | 4 +- .../Update/ParticleUplinkCannonUpdate.cpp | 6 +-- .../GameLogic/Object/Update/PhysicsUpdate.cpp | 24 ++++----- .../Object/Update/PointDefenseLaserUpdate.cpp | 6 +-- .../Update/SpectreGunshipDeploymentUpdate.cpp | 2 +- .../GameLogic/Object/Update/ToppleUpdate.cpp | 2 +- .../Source/GameLogic/Object/Weapon.cpp | 16 +++--- .../Source/GameLogic/System/GameLogic.cpp | 2 +- docs/DEV_BLOG/2026-06-DIARY.md | 9 ++++ 85 files changed, 339 insertions(+), 297 deletions(-) diff --git a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp index ad50a45d2cc..01ce398e6ab 100644 --- a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp @@ -60,7 +60,7 @@ #include "GameLogic/GameLogic.h" #include "GameLogic/TerrainLogic.h" -#include "Common/File.h" +#include "Common/file.h" #include "VideoDevice/FFmpeg/FFmpegFile.h" extern "C" { diff --git a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h index 55b524f9548..6039236e731 100644 --- a/Core/Libraries/Source/WWVegas/WWMath/wwmath.h +++ b/Core/Libraries/Source/WWVegas/WWMath/wwmath.h @@ -216,22 +216,27 @@ static WWINLINE float ASinTrig(float x) // Must dispatch to deterministic Sqrt when enabled // Origin wrappers: replace bare CRT math calls in GameLogic. // Each wrapper preserves the exact type (float vs double) of the vanilla CRT call. -// Note: double overloads narrow to float before calling GameMath (gm_*f). -// GameMath only provides float-precision functions. All call sites pass float-width -// values, so the narrowing is lossless in practice. #if USE_DETERMINISTIC_MATH - static WWINLINE double SqrtOrigin(double x) { return (double)gm_sqrtf((float)x); } + static WWINLINE double SqrtOrigin(double x) { return gm_sqrt(x); } static WWINLINE float SqrtfOrigin(float x) { return gm_sqrtf(x); } - static WWINLINE double Atan2Origin(double y, double x) { return (double)gm_atan2f((float)y, (float)x); } + static WWINLINE double Atan2Origin(double y, double x) { return gm_atan2(y, x); } + static WWINLINE double PowOrigin(double x, double y) { return gm_pow(x, y); } #else static WWINLINE double SqrtOrigin(double x) { return sqrt(x); } static WWINLINE float SqrtfOrigin(float x) { return sqrtf(x); } static WWINLINE double Atan2Origin(double y, double x) { return atan2(y, x); } + static WWINLINE double PowOrigin(double x, double y) { return pow(x, y); } #endif static WWINLINE float Sign(float val); +#if USE_DETERMINISTIC_MATH +static WWINLINE float Ceil(float val) { return gm_ceilf(val); } +static WWINLINE float Floor(float val) { return gm_floorf(val); } +static WWINLINE float Round(float val) { return gm_floorf(val + 0.5f); } +#else static WWINLINE float Ceil(float val) { return ceilf(val); } static WWINLINE float Floor(float val) { return floorf(val); } static WWINLINE float Round(float val) { return floorf(val + 0.5f); } +#endif static WWINLINE bool Fast_Is_Float_Positive(const float & val); static WWINLINE bool Is_Power_Of_2(const unsigned int val); @@ -455,7 +460,12 @@ WWINLINE long WWMath::Float_To_Long(double f) // Cos // ---------------------------------------------------------------------------- -#if defined(_MSC_VER) && defined(_M_IX86) +#if defined(USE_DETERMINISTIC_MATH) +WWINLINE float WWMath::Cos(float val) +{ + return gm_cosf(val); +} +#elif defined(_MSC_VER) && defined(_M_IX86) WWINLINE float WWMath::Cos(float val) { float retval; @@ -477,7 +487,12 @@ WWINLINE float WWMath::Cos(float val) // Sin // ---------------------------------------------------------------------------- -#if defined(_MSC_VER) && defined(_M_IX86) +#if defined(USE_DETERMINISTIC_MATH) +WWINLINE float WWMath::Sin(float val) +{ + return gm_sinf(val); +} +#elif defined(_MSC_VER) && defined(_M_IX86) WWINLINE float WWMath::Sin(float val) { float retval; @@ -623,7 +638,11 @@ WWINLINE float WWMath::Fast_Acos(float val) WWINLINE float WWMath::Acos(float val) { +#ifdef USE_DETERMINISTIC_MATH + return gm_acosf(val); +#else return (float)acos(val); +#endif } // ---------------------------------------------------------------------------- @@ -660,14 +679,23 @@ WWINLINE float WWMath::Fast_Asin(float val) WWINLINE float WWMath::Asin(float val) { +#ifdef USE_DETERMINISTIC_MATH + return gm_asinf(val); +#else return (float)asin(val); +#endif } // ---------------------------------------------------------------------------- // Sqrt // ---------------------------------------------------------------------------- -#if defined(_MSC_VER) && defined(_M_IX86) +#if defined(USE_DETERMINISTIC_MATH) +WWINLINE float WWMath::Sqrt(float val) +{ + return gm_sqrtf(val); +} +#elif defined(_MSC_VER) && defined(_M_IX86) WWINLINE float WWMath::Sqrt(float val) { float retval; @@ -715,7 +743,12 @@ WWINLINE int WWMath::Float_To_Int_Floor (const float& f) // Inverse square root // ---------------------------------------------------------------------------- -#if defined(_MSC_VER) && defined(_M_IX86) +#if defined(USE_DETERMINISTIC_MATH) +WWINLINE float WWMath::Inv_Sqrt(float val) +{ + return 1.0f / gm_sqrtf(val); +} +#elif defined(_MSC_VER) && defined(_M_IX86) WWINLINE float WWMath::Inv_Sqrt(float a) { float retval; diff --git a/Generals/Code/GameEngine/Include/GameLogic/PartitionManager.h b/Generals/Code/GameEngine/Include/GameLogic/PartitionManager.h index e16147bfe84..69be2a16551 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/PartitionManager.h +++ b/Generals/Code/GameEngine/Include/GameLogic/PartitionManager.h @@ -1354,7 +1354,7 @@ class PartitionManager : public SubsystemInterface, public Snapshot void getVectorTo(const Object *obj, const Object *otherObj, DistanceCalculationType dc, Coord3D& vec); void getVectorTo(const Object *obj, const Coord3D *pos, DistanceCalculationType dc, Coord3D& vec); - // just like 'getDistance', but return the dist-sqr, meaning we save a sqrt() call if you don't need it. + // just like 'getDistance', but return the dist-sqr, meaning we save a WWMath::SqrtOrigin() call if you don't need it. Real getDistanceSquared(const Object *obj, const Object *otherObj, DistanceCalculationType dc, Coord3D *vec = nullptr); Real getDistanceSquared(const Object *obj, const Coord3D *pos, DistanceCalculationType dc, Coord3D *vec = nullptr); diff --git a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp index 6b2d9b438d3..4d4c43cf264 100644 --- a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -2368,7 +2368,7 @@ void Player::doBountyForKill(const Object* killer, const Object* victim) Int bounty = REAL_TO_INT_CEIL(costToBuild * m_cashBountyPercent); #else // TheSuperHackers @bugfix Stubbjax 20/02/2026 Subtract epsilon to ensure bounty is rounded up correctly. - Int bounty = ceil((costToBuild * m_cashBountyPercent) - WWMATH_EPSILON); + Int bounty = WWMath::Ceil((costToBuild * m_cashBountyPercent) - WWMATH_EPSILON); #endif if( bounty ) diff --git a/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index ccb32fa1bf6..80c7246091c 100644 --- a/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -752,8 +752,8 @@ Bool BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos, if (myFactoryExitWidth>0) { myExitPos = *worldPos; checkMyExit = true; - Real c = (Real)cos(angle); - Real s = (Real)sin(angle); + Real c = (Real)WWMath::CosTrig(angle); + Real s = (Real)WWMath::SinTrig(angle); Real offset = build->getTemplateGeometryInfo().getMajorRadius() + myFactoryExitWidth/2.0f; myExitPos.x += c*offset; myExitPos.y += s*offset; @@ -787,8 +787,8 @@ Bool BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos, if (themFactoryExitWidth>0) { hisExitPos = *them->getPosition(); checkHisExit = true; - Real c = (Real)cos(them->getOrientation()); - Real s = (Real)sin(them->getOrientation()); + Real c = (Real)WWMath::CosTrig(them->getOrientation()); + Real s = (Real)WWMath::SinTrig(them->getOrientation()); Real offset = them->getGeometryInfo().getMajorRadius() + themFactoryExitWidth/2.0f; hisExitPos.x += c*offset; hisExitPos.y += s*offset; @@ -1405,7 +1405,7 @@ Bool BuildAssistant::moveObjectsForConstruction( const ThingTemplate *whatToBuil Bool anyUnmovables = false; MemoryPoolObjectHolder hold( iter ); - Real radius = sqrt(pow(gi.getMajorRadius(), 2) + pow(gi.getMinorRadius(), 2)); + Real radius = WWMath::SqrtOrigin(WWMath::PowOrigin(gi.getMajorRadius(), 2) + WWMath::PowOrigin(gi.getMinorRadius(), 2)); radius *= 1.4f; // Fudge the distance, for( Object *them = iter->first(); them; them = iter->next() ) diff --git a/Generals/Code/GameEngine/Source/Common/System/Geometry.cpp b/Generals/Code/GameEngine/Source/Common/System/Geometry.cpp index f33da731b42..cfadd29cacc 100644 --- a/Generals/Code/GameEngine/Source/Common/System/Geometry.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/Geometry.cpp @@ -173,17 +173,17 @@ void GeometryInfo::calcPitches(const Coord3D& thisPos, const GeometryInfo& that, Coord3D thisCenter; getCenterPosition(thisPos, thisCenter); - Real dxy = sqrt(sqr(thatPos.x - thisCenter.x) + sqr(thatPos.y - thisCenter.y)); + Real dxy = WWMath::SqrtOrigin(sqr(thatPos.x - thisCenter.x) + sqr(thatPos.y - thisCenter.y)); Real dz; /** @todo srj -- this could be better, by calcing it for all the corners, not just top-center and bottom-center... oh well */ dz = (thatPos.z + that.getMaxHeightAbovePosition()) - thisCenter.z; - maxPitch = atan2(dz, dxy); + maxPitch = WWMath::Atan2Origin(dz, dxy); dz = (thatPos.z - that.getMaxHeightBelowPosition()) - thisCenter.z; - minPitch = atan2(dz, dxy); + minPitch = WWMath::Atan2Origin(dz, dxy); } //============================================================================= @@ -279,8 +279,8 @@ void GeometryInfo::get2DBounds(const Coord3D& geomCenter, Real angle, Region2D& case GEOMETRY_BOX: { - Real c = (Real)cos(angle); - Real s = (Real)sin(angle); + Real c = (Real)WWMath::CosTrig(angle); + Real s = (Real)WWMath::SinTrig(angle); Real exc = m_majorRadius*c; Real eyc = m_minorRadius*c; Real exs = m_majorRadius*s; @@ -329,7 +329,7 @@ void GeometryInfo::clipPointToFootprint(const Coord3D& geomCenter, Coord3D& ptTo { Real dx = ptToClip.x - geomCenter.x; Real dy = ptToClip.y - geomCenter.y; - Real radius = sqrt(sqr(dx) + sqr(dy)); + Real radius = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); if (radius > m_majorRadius) { Real ratio = m_majorRadius / radius; @@ -361,7 +361,7 @@ Bool GeometryInfo::isPointInFootprint(const Coord3D& geomCenter, const Coord3D& { Real dx = pt.x - geomCenter.x; Real dy = pt.y - geomCenter.y; - Real radius = sqrt(sqr(dx) + sqr(dy)); + Real radius = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); return (radius <= m_majorRadius); break; } @@ -506,8 +506,8 @@ void GeometryInfo::calcBoundingStuff() case GEOMETRY_BOX: { - m_boundingCircleRadius = sqrt(sqr(m_majorRadius) + sqr(m_minorRadius)); - m_boundingSphereRadius = sqrt(sqr(m_majorRadius) + sqr(m_minorRadius) + sqr(m_height*0.5)); + m_boundingCircleRadius = WWMath::SqrtOrigin(sqr(m_majorRadius) + sqr(m_minorRadius)); + m_boundingSphereRadius = WWMath::SqrtOrigin(sqr(m_majorRadius) + sqr(m_minorRadius) + sqr(m_height*0.5)); break; } }; diff --git a/Generals/Code/GameEngine/Source/Common/System/Trig.cpp b/Generals/Code/GameEngine/Source/Common/System/Trig.cpp index a95bb2d8df2..4dfc1ec0865 100644 --- a/Generals/Code/GameEngine/Source/Common/System/Trig.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/Trig.cpp @@ -99,7 +99,7 @@ void initTrig() fprintf(fp, "static Int sinLookup[TRIG_RES] = {\n"); for( i=0; iz) > TINY_DZ) { - Real pitch = atan2(vel->z, sqrt(sqr(vel->x)+sqr(vel->y))); + Real pitch = WWMath::Atan2Origin(vel->z, WWMath::SqrtOrigin(sqr(vel->x)+sqr(vel->y))); m_locoInfo->m_pitch -= Z_VEL_PITCH_COEFF * pitch; } } @@ -1544,7 +1544,7 @@ void Drawable::calcPhysicsXformTreads( const Locomotor *locomotor, PhysicsXformI maxCenterDist *= OVERLAP_SHRINK_FACTOR; if (centerDistSqr < sqr(maxCenterDist)) { - Real centerDist = sqrtf(centerDistSqr); + Real centerDist = WWMath::SqrtfOrigin(centerDistSqr); Real amount = 1.0f - centerDist/maxCenterDist; if (amount < 0.0f) amount = 0.0f; diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp index 142af157c40..c56592120b3 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp @@ -336,7 +336,7 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess Int x, y; x = mouse.x - start.x; y = mouse.y - start.y; - if( sqrt( (x * x) + (y * y) ) >= PLACEMENT_DRAG_THRESHOLD_DIST ) + if( WWMath::SqrtOrigin( (x * x) + (y * y) ) >= PLACEMENT_DRAG_THRESHOLD_DIST ) { TheInGameUI->setPlacementEnd(&mouse); diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp index fb576b640fd..bdb0a157580 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -706,7 +706,7 @@ Object *AI::findClosestEnemy( const Object *me, Real range, UnsignedInt qualifie } Real distSqr = ThePartitionManager->getDistanceSquared(me, theEnemy, FROM_BOUNDINGSPHERE_2D); - Real dist = sqrt(distSqr); + Real dist = WWMath::SqrtOrigin(distSqr); Int modifier = dist/getAiData()->m_attackPriorityDistanceModifier; Int modPriority = curPriority-modifier; if (modPriority < 1) diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index 39f78bc9a4a..e401be036d1 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -1839,8 +1839,8 @@ void getHelicopterOffset( Coord3D& posOut, Int idx ) } Coord3D tempCtr = posOut; - posOut.x = tempCtr.x + (sin(angle) * radius); - posOut.y = tempCtr.y + (cos(angle) * radius); + posOut.x = tempCtr.x + (WWMath::SinTrig(angle) * radius); + posOut.y = tempCtr.y + (WWMath::CosTrig(angle) * radius); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp index 2472c2ffefc..96d805157a4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp @@ -646,7 +646,7 @@ Object *AIPlayer::buildStructureWithDozer(const ThingTemplate *bldgPlan, BuildLi dx = dozer->getPosition()->x - pos.x; dy = dozer->getPosition()->y - pos.y; - Int count = sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); + Int count = WWMath::SqrtOrigin(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); if (count<2) count = 2; Int i; color.green = 1; @@ -1251,7 +1251,7 @@ Int AIPlayer::getPlayerSuperweaponValue(Coord3D *center, Int playerNdx, Real rad Real dx = center->x - pos.x; Real dy = center->y - pos.y; if (dx*dx+dy*dygetTemplate()->calcCostToBuild(pPlayer); if (pObj->isKindOf(KINDOF_COMMANDCENTER)) { @@ -2812,7 +2812,7 @@ void AIPlayer::computeCenterAndRadiusOfBase(Coord3D *center, Real *radius) Real radSqr = dx*dx+dy*dy; if (radSqr>maxRadSqr) maxRadSqr=radSqr; } - *radius = sqrt(maxRadSqr); + *radius = WWMath::SqrtOrigin(maxRadSqr); } //---------------------------------------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp index afb876af064..3e08d7b7f9d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp @@ -663,8 +663,8 @@ void AISkirmishPlayer::buildAIBaseDefenseStructure(const AsciiString &thingName, } if (angle > PI/3) break; - Real s = sin(angle); - Real c = cos(angle); + Real s = WWMath::SinTrig(angle); + Real c = WWMath::CosTrig(angle); // TheSuperHackers @info helmutbuhler 21/04/2025 This debug mutates the code to become CRC incompatible #if defined(RTS_DEBUG) || !RETAIL_COMPATIBLE_CRC @@ -1029,8 +1029,8 @@ void AISkirmishPlayer::adjustBuildList(BuildListInfo *list) angle += 3*PI/4; - Real s = sin(angle); - Real c = cos(angle); + Real s = WWMath::SinTrig(angle); + Real c = WWMath::CosTrig(angle); cur = list; while (cur) { diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index c92bba46eff..9e28d73d7ff 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -3572,7 +3572,7 @@ StateReturnType AIAttackMoveToState::update() if (distSqr < sqr(ATTACK_CLOSE_ENOUGH_CELLS*PATHFIND_CELL_SIZE_F)) { return ret; } - DEBUG_LOG(("AIAttackMoveToState::update Distance from goal %f, retrying.", sqrt(distSqr))); + DEBUG_LOG(("AIAttackMoveToState::update Distance from goal %f, retrying.", WWMath::SqrtOrigin(distSqr))); ret = STATE_CONTINUE; m_retryCount--; @@ -3802,16 +3802,16 @@ void AIFollowWaypointPathState::computeGoal(Bool useGroupOffsets) if (m_priorWaypoint) { dx = dest.x - m_priorWaypoint->getLocation()->x; dy = dest.y - m_priorWaypoint->getLocation()->y; - angle = atan2(dy, dx); + angle = WWMath::Atan2Origin(dy, dx); Real deltaAngle = angle - m_angle; - Real s = sin(deltaAngle); - Real c = cos(deltaAngle); + Real s = WWMath::SinTrig(deltaAngle); + Real c = WWMath::CosTrig(deltaAngle); Real x = m_groupOffset.x * c - m_groupOffset.y * s; Real y = m_groupOffset.y * c + m_groupOffset.x * s; m_groupOffset.x = x; m_groupOffset.y = y; } else { - angle = atan2(dy, dx); + angle = WWMath::Atan2Origin(dy, dx); } m_angle = angle; #endif diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp index 6cea7c6227a..d1884a02e73 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp @@ -270,7 +270,7 @@ void PolygonTrigger::updateBounds() const Real halfWidth = (m_bounds.hi.x - m_bounds.lo.x) / 2.0f; Real halfHeight = (m_bounds.hi.y + m_bounds.lo.y) / 2.0f; - m_radius = sqrt(halfHeight*halfHeight + halfWidth*halfWidth); + m_radius = WWMath::SqrtOrigin(halfHeight*halfHeight + halfWidth*halfWidth); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp index 1d3e62df570..a0faf905794 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp @@ -1468,7 +1468,7 @@ void makeAlignToNormalMatrix( Real angle, const Coord3D& pos, const Coord3D& nor /* It is extremely important that the resulting matrix is such that the xvector points in the angle we specified; specifically, - that atan2(xvec.y, xvec.x) == angle. So we must construct + that WWMath::Atan2Origin(xvec.y, xvec.x) == angle. So we must construct the matrix carefully to ensure this! */ x.x = Cos( angle ); @@ -2369,7 +2369,7 @@ void TerrainLogic::setWaterHeight( const WaterHandle *water, Real height, Real d center.z = 0.0f; // irrelavant // the max radius to scan around us is the diagonal of the bounding region - Real maxDist = sqrt( affectedRegion.width() * affectedRegion.width() + + Real maxDist = WWMath::SqrtOrigin( affectedRegion.width() * affectedRegion.width() + affectedRegion.height() * affectedRegion.height() ); // scan the objects in the area of the water affected diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp index b3d599ef2bf..1e74a8b5dd6 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp @@ -1119,7 +1119,7 @@ void BridgeBehavior::createScaffolding() // // given the number of objects that we need to tile across the whole bridge, we will - // go through the creation loop ceil( numObjects / 2.0f ) times, and each + // go through the creation loop WWMath::Ceil( numObjects / 2.0f ) times, and each // time through the loop we'll create an object to move from each side of the // bridge, except the last object if the number of objects is odd is dead in the // center diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp index 7c4bc633863..eaa7fec6b8a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp @@ -169,11 +169,11 @@ static Bool calcTrajectory( Real dz = end.z - start.z; // calculating the angle is trivial. - angle = atan2(dy, dx); + angle = WWMath::Atan2Origin(dy, dx); // calculating the pitch requires a bit more effort. Real horizDistSqr = sqr(dx) + sqr(dy); - Real horizDist = sqrt(horizDistSqr); + Real horizDist = WWMath::SqrtOrigin(horizDistSqr); // calc the two possible pitches that will cover the given horizontal range. // (this is actually only true if dz==0, but is a good first guess) @@ -182,7 +182,7 @@ static Bool calcTrajectory( // let's start by aiming directly for it. we know this isn't right (unless gravity // is zero, which it's not) but is a good starting point... - Real theta = atan2(dz, horizDist); + Real theta = WWMath::Atan2Origin(dz, horizDist); // if the angle isn't pretty shallow, we can get a better initial guess by using // the code below... const Real SHALLOW_ANGLE = 0.5f * PI / 180.0f; @@ -287,7 +287,7 @@ static Bool calcTrajectory( #endif vx = velocity*cosPitches[preferred]; - Real actualRange = (vx*(vz + sqrt(root)))/gravity; + Real actualRange = (vx*(vz + WWMath::SqrtOrigin(root)))/gravity; const Real CLOSE_ENOUGH_RANGE = 5.0f; if (tooClose || (actualRange < horizDist - CLOSE_ENOUGH_RANGE)) { @@ -366,7 +366,7 @@ void DumbProjectileBehavior::projectileFireAtObjectOrPosition( const Object *vic // Some weapons want to scale their start speed to the range Real minRange = detWeap->getMinimumAttackRange(); Real maxRange = detWeap->getUnmodifiedAttackRange(); - Real range = sqrt(ThePartitionManager->getDistanceSquared( projectile, &victimPosToUse, FROM_CENTER_2D ) ); + Real range = WWMath::SqrtOrigin(ThePartitionManager->getDistanceSquared( projectile, &victimPosToUse, FROM_CENTER_2D ) ); Real rangeRatio = (range - minRange) / (maxRange - minRange); m_flightPathSpeed = (rangeRatio * (weaponSpeed - minWeaponSpeed)) + minWeaponSpeed; } @@ -441,7 +441,7 @@ Bool DumbProjectileBehavior::calcFlightPath(Bool recalcNumSegments) if (recalcNumSegments) { Real flightDistance = flightCurve.getApproximateLength(); - m_flightPathSegments = ceil( flightDistance / m_flightPathSpeed ); + m_flightPathSegments = WWMath::Ceil( flightDistance / m_flightPathSpeed ); } flightCurve.getSegmentPoints( m_flightPathSegments, &m_flightPath ); DEBUG_ASSERTCRASH(m_flightPathSegments == m_flightPath.size(), ("m_flightPathSegments mismatch")); @@ -596,7 +596,7 @@ UpdateSleepTime DumbProjectileBehavior::update() Real distVictimMovedSqr = sqr(delta.x) + sqr(delta.y) + sqr(delta.z); if (distVictimMovedSqr > 0.1f) { - Real distVictimMoved = sqrtf(distVictimMovedSqr); + Real distVictimMoved = WWMath::SqrtfOrigin(distVictimMovedSqr); if (distVictimMoved > d->m_flightPathAdjustDistPerFrame) distVictimMoved = d->m_flightPathAdjustDistPerFrame; delta.normalize(); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp index b37cf0f2ab3..b197c8f0f1a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp @@ -232,7 +232,7 @@ void GenerateMinefieldBehavior::placeMinesAlongLine(const Coord3D& posStart, con Real dx = posEnd.x - posStart.x; Real dy = posEnd.y - posStart.y; - Real len = sqrt(sqr(dx) + sqr(dy)); + Real len = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); Real mineRadius = mineTemplate->getTemplateGeometryInfo().getBoundingCircleRadius(); Real mineDiameter = mineRadius * 2.0f; Real mineJitter = mineRadius*d->m_randomJitter; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp index 5a4b2727060..dfc2d1462f4 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp @@ -562,7 +562,7 @@ void MinefieldBehavior::setScootParms(const Coord3D& start, const Coord3D& end) if (start.z > endOnGround.z) { // figure out how long it will take to fall, and replace scoot time with that - UnsignedInt fallingTime = REAL_TO_INT_CEIL(sqrtf(2.0f * (start.z - endOnGround.z) / fabs(TheGlobalData->m_gravity))); + UnsignedInt fallingTime = REAL_TO_INT_CEIL(WWMath::SqrtfOrigin(2.0f * (start.z - endOnGround.z) / fabs(TheGlobalData->m_gravity))); // we can scoot after we land, but don't want to stop scooting before we land if (scootFromStartingPointTime < fallingTime) scootFromStartingPointTime = fallingTime; @@ -580,7 +580,7 @@ void MinefieldBehavior::setScootParms(const Coord3D& start, const Coord3D& end) Real dx = endOnGround.x - start.x; Real dy = endOnGround.y - start.y; Real dz = endOnGround.z - start.z; - Real dist = sqrt(sqr(dx) + sqr(dy)); + Real dist = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); if (dist <= 0.1f && fabs(dz) <= 0.1f) { obj->setPosition(&endOnGround); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp index 20bdea05e43..b770e8e9506 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp @@ -299,7 +299,7 @@ void SlowDeathBehavior::beginSlowDeath(const DamageInfo *damageInfo) physics->setExtraBounciness(-1.0); // we don't want this guy to bounce at all physics->setExtraFriction(-3 * SECONDS_PER_LOGICFRAME_REAL); // reduce his ground friction a bit physics->setAllowBouncing(true); - Real orientation = atan2(force.y, force.x); + Real orientation = WWMath::Atan2Origin(force.y, force.x); physics->setAngles(orientation, 0, 0); obj->getDrawable()->setModelConditionState(MODELCONDITION_EXPLODED_FLAILING); m_flags |= (1<getPosition()->x; Real dy = goalPos.y - obj->getPosition()->y; Real dz = goalPos.z - obj->getPosition()->z; - Real dist = sqrt(dx*dx+dy*dy); + Real dist = WWMath::SqrtOrigin(dx*dx+dy*dy); if (dist>onPathDistToGoal) { if (!obj->isKindOf(KINDOF_PROJECTILE) && dist>2*onPathDistToGoal) @@ -1084,7 +1084,7 @@ void Locomotor::locoUpdate_moveTowardsPosition(Object* obj, const Coord3D& goalP // Projectiles never stop braking once they start. jba. obj->setStatus( MAKE_OBJECT_STATUS_MASK( OBJECT_STATUS_BRAKING ) ); // Projectiles cheat in 3 dimensions. - dist = sqrt(dx*dx+dy*dy+dz*dz); + dist = WWMath::SqrtOrigin(dx*dx+dy*dy+dz*dz); Real vel = physics->getVelocityMagnitude(); if (vel < MIN_VEL) vel = MIN_VEL; @@ -1259,7 +1259,7 @@ void Locomotor::moveTowardsPositionWheels(Object* obj, PhysicsBehavior *physics, Real angle = obj->getOrientation(); // Real relAngle = ThePartitionManager->getRelativeAngle2D( obj, &goalPos ); // Real desiredAngle = angle + relAngle; - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); Real relAngle = stdAngleDiff(desiredAngle, angle); Bool moveBackwards = false; @@ -1534,7 +1534,7 @@ Bool Locomotor::fixInvalidPosition(Object* obj, PhysicsBehavior *physics) //physics->clearAcceleration(); if (dot<0) { - dot = sqrt(-dot); + dot = WWMath::SqrtOrigin(-dot); correctionNormalized.x *= dot*physics->getMass(); correctionNormalized.y *= dot*physics->getMass(); physics->applyMotiveForce(&correctionNormalized); @@ -1598,7 +1598,7 @@ void Locomotor::moveTowardsPositionLegs(Object* obj, PhysicsBehavior *physics, c Real angle = obj->getOrientation(); // Real relAngle = ThePartitionManager->getRelativeAngle2D( obj, &goalPos ); // Real desiredAngle = angle + relAngle; - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); if (m_template->m_wanderWidthFactor != 0.0f) { Real angleLimit = PI/8 * m_template->m_wanderWidthFactor; @@ -1731,7 +1731,7 @@ void Locomotor::moveTowardsPositionClimb(Object* obj, PhysicsBehavior *physics, Real angle = obj->getOrientation(); // Real relAngle = ThePartitionManager->getRelativeAngle2D( obj, &goalPos ); // Real desiredAngle = angle + relAngle; - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); Real relAngle = stdAngleDiff(desiredAngle, angle); if (moveBackwards) { @@ -1822,7 +1822,7 @@ void Locomotor::moveTowardsPositionWings(Object* obj, PhysicsBehavior *physics, Real angleTowardPos = (isNearlyZero(dx) && isNearlyZero(dy)) ? obj->getOrientation() : - atan2(dy, dx); + WWMath::Atan2Origin(dy, dx); Real aimDir = (PI - PI/8); angleTowardPos += aimDir; @@ -2056,7 +2056,7 @@ Real Locomotor::calcLiftToUseAtPt(Object* obj, PhysicsBehavior *physics, Real cu // thus // a = 2(dz - v t)/t^2 // and - // t = (-v +- sqrt(v*v + 2*a*dz))/a + // t = (-v +- WWMath::SqrtOrigin(v*v + 2*a*dz))/a // // but if we assume t=1, then // a=2(dz-v) @@ -2118,7 +2118,7 @@ PhysicsTurningType Locomotor::rotateObjAroundLocoPivot(Object* obj, const Coord3 Real dy = goalPos.y - turnPos.y; // If we are very close to the goal, we twitch due to rounding error. So just return. jba. if (fabs(dx)<0.1f && fabs(dy)<0.1f) return TURN_NONE; - Real desiredAngle = atan2(dy, dx); + Real desiredAngle = WWMath::Atan2Origin(dy, dx); Real amount = stdAngleDiff(desiredAngle, angle); if (relAngle) *relAngle = amount; if (amount>maxTurnRate) { @@ -2140,7 +2140,7 @@ PhysicsTurningType Locomotor::rotateObjAroundLocoPivot(Object* obj, const Coord3 // so, the thing is, we want to rotate ourselves so that our *center* is rotated // by the given amount, but the rotation must be around turnPos. so do a little // back-calculation. - Real angleDesiredForTurnPos = atan2(desiredPos.y - turnPos.y, desiredPos.x - turnPos.x); + Real angleDesiredForTurnPos = WWMath::Atan2Origin(desiredPos.y - turnPos.y, desiredPos.x - turnPos.x); amount = angleDesiredForTurnPos - angle; #endif /// @todo srj -- there's probably a more efficient & more direct way to do this. find it. @@ -2156,7 +2156,7 @@ PhysicsTurningType Locomotor::rotateObjAroundLocoPivot(Object* obj, const Coord3 } else { - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); Real amount = stdAngleDiff(desiredAngle, angle); if (relAngle) *relAngle = amount; if (amount>maxTurnRate) { @@ -2489,7 +2489,7 @@ void Locomotor::maintainCurrentPositionWings(Object* obj, PhysicsBehavior *physi Real angleTowardMaintainPos = (isNearlyZero(dx) && isNearlyZero(dy)) ? obj->getOrientation() : - atan2(dy, dx); + WWMath::Atan2Origin(dy, dx); Real aimDir = (PI - PI/8); if (turnRadius < 0) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 0e802efaadb..3ebaf7b3672 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -281,7 +281,7 @@ class DeliverPayloadNugget : public ObjectCreationNugget Real dy = primary->y - secondary->y; //Calc length - Real length = sqrt( dx*dx + dy*dy ); + Real length = WWMath::SqrtOrigin( dx*dx + dy*dy ); //Normalize length dx /= length; @@ -348,7 +348,7 @@ class DeliverPayloadNugget : public ObjectCreationNugget } - Real orient = atan2( moveToPos.y - startPos.y, moveToPos.x - startPos.x); + Real orient = WWMath::Atan2Origin( moveToPos.y - startPos.y, moveToPos.x - startPos.x); if( m_data.m_distToTarget > 0 ) { const Real SLOP = 1.5f; @@ -1070,7 +1070,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget objUp->applyForce(&force); if (m_orientInForceDirection) - orientation = atan2(force.y, force.x); + orientation = WWMath::Atan2Origin(force.y, force.x); } } @@ -1158,7 +1158,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget objUp->applyForce(&force); if (m_orientInForceDirection) { - orientation = atan2(force.y, force.x); + orientation = WWMath::Atan2Origin(force.y, force.x); } DUMPREAL(orientation); objUp->setAngles(orientation, 0, 0); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp index f445cc6dc79..6654f83f52a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp @@ -617,7 +617,7 @@ inline Bool z_collideTest_Sphere_Nonsphere(CollideTestProc xyproc, const Collide // find the radius of the slice of the sphere that is at b_bot CollideInfo amod = *a; amod.position.z = b_bot; - amod.geom.setMajorRadius((Real)sqrtf(sqr(a->geom.getMajorRadius()) - sqr(b_bot - a->position.z))); + amod.geom.setMajorRadius((Real)WWMath::SqrtfOrigin(sqr(a->geom.getMajorRadius()) - sqr(b_bot - a->position.z))); if (xyproc(&amod, b, cinfo)) { // if you want to have 'end' collisions, you should add something like: @@ -635,7 +635,7 @@ inline Bool z_collideTest_Sphere_Nonsphere(CollideTestProc xyproc, const Collide { CollideInfo amod = *a; amod.position.z = b_top; - amod.geom.setMajorRadius((Real)sqrtf(sqr(a->geom.getMajorRadius()) - sqr(a->position.z - b_top))); + amod.geom.setMajorRadius((Real)WWMath::SqrtfOrigin(sqr(a->geom.getMajorRadius()) - sqr(a->position.z - b_top))); if (xyproc(&amod, b, cinfo)) { // if you want to have 'end' collisions, you should add something like: @@ -823,7 +823,7 @@ static Bool distCalcProc_BoundaryAndBoundary_2D( if (totalRad > 0.0f) { - Real actualDist = sqrtf(actualDistSqr); + Real actualDist = WWMath::SqrtfOrigin(actualDistSqr); Real shrunkenDist = actualDist - totalRad; if (shrunkenDist <= 0.0f) { @@ -911,7 +911,7 @@ static Bool distCalcProc_BoundaryAndBoundary_3D( Real totalRad = (geomA?geomA->getBoundingSphereRadius():0) + (geomB?geomB->getBoundingSphereRadius():0); if (totalRad > 0.0f) { - Real actualDist = sqrtf(actualDistSqr); + Real actualDist = WWMath::SqrtfOrigin(actualDistSqr); Real shrunkenDist = actualDist - totalRad; if (shrunkenDist <= 0.0f) { @@ -2219,7 +2219,7 @@ Int PartitionData::calcMaxCoiForShape(GeometryType geom, Real majorRadius, Real } case GEOMETRY_BOX: { - Real diagonal = (Real)(sqrtf(majorRadius*majorRadius + minorRadius*minorRadius)); + Real diagonal = (Real)(WWMath::SqrtfOrigin(majorRadius*majorRadius + minorRadius*minorRadius)); Int cells = ThePartitionManager->worldToCellDist(diagonal*2) + 1; result = cells * cells; break; @@ -2636,7 +2636,7 @@ static void calcHeights(const Region3D& world, Real cellSize, Int x, Int y, Real Real xbase = world.lo.x + (x * cellSize); Real ybase = world.lo.y + (y * cellSize); const Real ROUGH_STEP_SIZE = 2; // roughly every 2 ft, please - Real numSteps = ceilf(cellSize / ROUGH_STEP_SIZE); + Real numSteps = WWMath::Ceil(cellSize / ROUGH_STEP_SIZE); Real step = cellSize / numSteps; loZ = HUGE_DIST; // huge positive hiZ = -HUGE_DIST; // huge negative @@ -3210,7 +3210,7 @@ Int PartitionManager::calcMinRadius(const ICoord2D& cur) } // double, not real - double dist = sqrtf(minDistSqr); + double dist = WWMath::SqrtfOrigin(minDistSqr); Int minRadius = REAL_TO_INT_CEIL( dist / m_cellSize ); return minRadius; @@ -3228,7 +3228,7 @@ void PartitionManager::calcRadiusVec() // double, not real double dx = (double)cx * (double)cellSize; double dy = (double)cy * (double)cellSize; - double maxPossibleDist = sqrt(dx*dx + dy*dy); + double maxPossibleDist = WWMath::SqrtOrigin(dx*dx + dy*dy); m_maxGcoRadius = REAL_TO_INT_CEIL(maxPossibleDist / cellSize); @@ -3498,7 +3498,7 @@ Object *PartitionManager::getClosestObjects( } if (closestDistArg) { - *closestDistArg = (Real)sqrtf(closestDistSqr); + *closestDistArg = (Real)WWMath::SqrtfOrigin(closestDistSqr); } #ifdef RTS_DEBUG @@ -3625,7 +3625,7 @@ Real PartitionManager::getRelativeAngle2D( const Object *obj, const Coord3D *pos v.y = pos->y - objPos.y; v.z = 0.0f; - Real dist = (Real)sqrtf(sqr(v.x) + sqr(v.y)); + Real dist = (Real)WWMath::SqrtfOrigin(sqr(v.x) + sqr(v.y)); // normalize if (dist == 0.0f) @@ -4556,7 +4556,7 @@ Int PartitionManager::iterateCellsBreadthFirst(const Coord3D *pos, CellBreadthFi //----------------------------------------------------------------------------- static Real calcDist2D(Real x1, Real y1, Real x2, Real y2) { - return sqrtf(sqr(x1-x2) + sqr(y1-y2)); + return WWMath::SqrtfOrigin(sqr(x1-x2) + sqr(y1-y2)); } //----------------------------------------------------------------------------- @@ -5715,7 +5715,7 @@ void hLineAddThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5743,7 +5743,7 @@ void hLineRemoveThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5771,7 +5771,7 @@ void hLineAddValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5799,7 +5799,7 @@ void hLineRemoveValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 5814c4a074a..5d513d399fa 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2230,7 +2230,7 @@ UpdateSleepTime AIUpdateInterface::doLocomotor() } else { - Real dist = sqrtf(dSqr); + Real dist = WWMath::SqrtfOrigin(dSqr); if (dist<1) dist = 1; pos.x += 2*PATHFIND_CELL_SIZE_F*dx/(dist*LOGICFRAMES_PER_SECOND); pos.y += 2*PATHFIND_CELL_SIZE_F*dy/(dist*LOGICFRAMES_PER_SECOND); @@ -2424,7 +2424,7 @@ Real AIUpdateInterface::getLocomotorDistanceToGoal() dest = m_path->getLastNode()->getPosition(); } Real distance = ThePartitionManager->getDistanceSquared( me, dest, FROM_CENTER_3D ); - return sqrt( distance );// Other paths return dots of normalized vectors, so one sqrt ain't so bad + return WWMath::SqrtOrigin( distance );// Other paths return dots of normalized vectors, so one sqrt ain't so bad } else { @@ -2456,7 +2456,7 @@ Real AIUpdateInterface::getLocomotorDistanceToGoal() { if (sqr(dist) > distSqr) { - return sqrt(distSqr); + return WWMath::SqrtOrigin(distSqr); } else { @@ -2465,7 +2465,7 @@ Real AIUpdateInterface::getLocomotorDistanceToGoal() } if (distgetExtent( &terrainExtent ); const Real FUDGE = 1.2f; - Real HUGE_DIST = FUDGE * sqrt(sqr(terrainExtent.hi.x - terrainExtent.lo.x) + sqr(terrainExtent.hi.y - terrainExtent.lo.y)); + Real HUGE_DIST = FUDGE * WWMath::SqrtOrigin(sqr(terrainExtent.hi.x - terrainExtent.lo.x) + sqr(terrainExtent.hi.y - terrainExtent.lo.y)); exitCoord.x += dir->x * HUGE_DIST; exitCoord.y += dir->y * HUGE_DIST; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp index a6f15066955..e20f5ab9ba8 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp @@ -201,8 +201,8 @@ UpdateSleepTime DeliverPayloadAIUpdate::update() { //Calc strafe ratio Real startDiveDistance = getData()->m_diveStartDistance; - Real endDiveDistance = sqrt( endDiveDistanceSquared ); - Real currentDistance = sqrt( currentDistanceSquared ); + Real endDiveDistance = WWMath::SqrtOrigin( endDiveDistanceSquared ); + Real currentDistance = WWMath::SqrtOrigin( currentDistanceSquared ); Real diveRatio = (startDiveDistance - currentDistance) / (startDiveDistance - endDiveDistance); @@ -367,7 +367,7 @@ Bool DeliverPayloadAIUpdate::isCloseEnoughToTarget() if ( inBound ) allowedDistanceSqr = sqr(getAllowedDistanceToTarget() + getPreOpenDistance()); - //DEBUG_LOG(("Dist to target is %f (allowed %f)",sqrt(currentDistanceSqr),sqrt(allowedDistanceSqr))); + //DEBUG_LOG(("Dist to target is %f (allowed %f)",WWMath::SqrtOrigin(currentDistanceSqr),WWMath::SqrtOrigin(allowedDistanceSqr))); if ( allowedDistanceSqr > currentDistanceSqr ) @@ -1081,7 +1081,7 @@ StateReturnType RecoverFromOffMapState::update() // Success if we should try aga enterCoord.z = owner->getPosition()->z; owner->setPosition(&enterCoord); - Real enterAngle = atan2(ai->getMoveToPos()->y - enterCoord.y, ai->getMoveToPos()->x - enterCoord.x); + Real enterAngle = WWMath::Atan2Origin(ai->getMoveToPos()->y - enterCoord.y, ai->getMoveToPos()->x - enterCoord.x); owner->setOrientation(enterAngle); PhysicsBehavior* physics = owner->getPhysics(); @@ -1121,7 +1121,7 @@ StateReturnType HeadOffMapState::onEnter() // Give move order out of town Region3D terrainExtent; TheTerrainLogic->getExtent( &terrainExtent ); const Real FUDGE = 1.2f; - Real HUGE_DIST = FUDGE * sqrt(sqr(terrainExtent.hi.x - terrainExtent.lo.x) + sqr(terrainExtent.hi.y - terrainExtent.lo.y)); + Real HUGE_DIST = FUDGE * WWMath::SqrtOrigin(sqr(terrainExtent.hi.x - terrainExtent.lo.x) + sqr(terrainExtent.hi.y - terrainExtent.lo.y)); exitCoord.x += dir->x * HUGE_DIST; exitCoord.y += dir->y * HUGE_DIST; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp index 483cf6b45f7..9f5452dd2b5 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp @@ -457,7 +457,7 @@ class JetOrHeliTaxiState : public AIMoveOutOfTheWayState Coord3D intermedPt; Bool intermed = false; - Real orient = atan2(ppinfo.runwayPrep.y - ppinfo.parkingSpace.y, ppinfo.runwayPrep.x - ppinfo.parkingSpace.x); + Real orient = WWMath::Atan2Origin(ppinfo.runwayPrep.y - ppinfo.parkingSpace.y, ppinfo.runwayPrep.x - ppinfo.parkingSpace.x); if (fabs(stdAngleDiff(orient, ppinfo.parkingOrientation)) > PI/128) { intermedPt.z = (ppinfo.parkingSpace.z + ppinfo.runwayPrep.z) * 0.5f; @@ -884,7 +884,7 @@ class HeliTakeoffOrLandingState : public State } else { - Real dist = sqrtf(dSqr); + Real dist = WWMath::SqrtfOrigin(dSqr); if (dist<1) dist = 1; pos.x += PATHFIND_CELL_SIZE_F*dx/(dist*LOGICFRAMES_PER_SECOND); pos.y += PATHFIND_CELL_SIZE_F*dy/(dist*LOGICFRAMES_PER_SECOND); @@ -2070,7 +2070,7 @@ void JetAIUpdate::positionLockon() Real dx = getObject()->getPosition()->x - pos.x; Real dy = getObject()->getPosition()->y - pos.y; if (dx || dy) - m_lockonDrawable->setOrientation(atan2(dy, dx)); + m_lockonDrawable->setOrientation(WWMath::Atan2Origin(dy, dx)); // the Gaussian sum, to avoid keeping a running total: // diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp index 688a0918a5a..f0b5057e5fa 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp @@ -223,7 +223,7 @@ void MissileAIUpdate::projectileFireAtObjectOrPosition( const Object *victim, co Real deltaZ = victimPos->z - obj->getPosition()->z; Real dx = victimPos->x - obj->getPosition()->x; Real dy = victimPos->y - obj->getPosition()->y; - Real xyDist = sqrt(sqr(dx)+sqr(dy)); + Real xyDist = WWMath::SqrtOrigin(sqr(dx)+sqr(dy)); if (xyDist<1) xyDist = 1; Real zFactor = 0; if (deltaZ>0) { @@ -581,7 +581,7 @@ void MissileAIUpdate::doKillState() closeEnough = curLoco->getMaxSpeedForCondition(BODY_PRISTINE); } Real distanceToTargetSq = ThePartitionManager->getDistanceSquared( getObject(), getGoalObject(), FROM_CENTER_3D); - //DEBUG_LOG(("Distance to target %f, closeEnough %f", sqrt(distanceToTargetSq), closeEnough)); + //DEBUG_LOG(("Distance to target %f, closeEnough %f", WWMath::SqrtOrigin(distanceToTargetSq), closeEnough)); if (distanceToTargetSq < closeEnough*closeEnough) { Coord3D pos = *getGoalObject()->getPosition(); getObject()->setPosition(&pos); @@ -619,7 +619,7 @@ UpdateSleepTime MissileAIUpdate::update() Coord3D newPos = *getObject()->getPosition(); if (m_noTurnDistLeft > 0.0f && m_state >= IGNITION) { - Real distThisTurn = sqrtf(sqr(newPos.x-m_prevPos.x) + sqr(newPos.y-m_prevPos.y) + sqr(newPos.z-m_prevPos.z)); + Real distThisTurn = WWMath::SqrtfOrigin(sqr(newPos.x-m_prevPos.x) + sqr(newPos.y-m_prevPos.y) + sqr(newPos.z-m_prevPos.z)); m_noTurnDistLeft -= distThisTurn; m_prevPos = newPos; } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp index dc83acdf5db..ac85df56e69 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp @@ -480,7 +480,7 @@ void POWTruckAIUpdate::updateCollectingTarget() { // are we close enough to tell them to start moving to us - Real distSq = pow( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f, 2 ); + Real distSq = WWMath::PowOrigin( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f, 2 ); if( ThePartitionManager->getDistanceSquared( us, target, FROM_CENTER_2D ) <= distSq ) { diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp index 96a0cb9e7eb..5cac0775a0e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp @@ -315,7 +315,7 @@ void RailroadBehavior::onCollide( Object *other, const Coord3D *loc, const Coord m_whistleSound.setPlayingHandle(TheAudio->addAudioEvent( &m_whistleSound )); - Real dist = (Real)sqrtf( dlt.x*dlt.x + dlt.y*dlt.y + dlt.z*dlt.z); + Real dist = (Real)WWMath::SqrtfOrigin( dlt.x*dlt.x + dlt.y*dlt.y + dlt.z*dlt.z); Real usRadius = obj->getGeometryInfo().getMajorRadius(); Real themRadius = other->getGeometryInfo().getMajorRadius(); Real overlap = ((usRadius + themRadius) - dist) + 1;// the plus 1 makes them go just outside of me. @@ -1259,7 +1259,7 @@ void RailroadBehavior::updatePositionTrackDistance( PullInfo *pullerInfo, PullIn trackPosDelta.z = 0; Real dx = pullerInfo->towHitchPosition.x - turnPos.x; Real dy = pullerInfo->towHitchPosition.y - turnPos.y; - Real desiredAngle = atan2(dy, dx); + Real desiredAngle = WWMath::Atan2Origin(dy, dx); Real relAngle = stdAngleDiff(desiredAngle, obj->getTransformMatrix()->Get_Z_Rotation()); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp index 8a23910d7d3..6054662da83 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp @@ -172,7 +172,7 @@ UpdateSleepTime CleanupHazardUpdate::update() AIUpdateInterface *ai = obj->getAI(); if( ai && (ai->isIdle() || ai->isBusy()) ) { - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( obj, &m_pos, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( obj, &m_pos, FROM_CENTER_2D ) ); if( fDist < 25.0f ) { //Abort clean area because there's nothing left to clean! @@ -204,7 +204,7 @@ void CleanupHazardUpdate::fireWhenReady() bonus.clear(); Real fireRange = m_weaponTemplate->getAttackRange( bonus ); Object *me = getObject(); - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); if( fDist < fireRange ) { //We are currently in range! diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp index e7df932630c..538123add49 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp @@ -290,7 +290,7 @@ Object* CommandButtonHuntUpdate::scanClosestTarget() } } Real distSqr = ThePartitionManager->getDistanceSquared(me, other, FROM_BOUNDINGSPHERE_2D); - Real dist = sqrt(distSqr); + Real dist = WWMath::SqrtOrigin(distSqr); Int curPriority = data->m_scanRange - dist; if (info) curPriority = info->getPriority(other->getTemplate()); if (curPriority == 0) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp index 62ac01c158a..50bc0ca9d2a 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp @@ -95,7 +95,7 @@ Bool SupplyWarehouseDockUpdate::action( Object* docker, Object *drone ) Real closeEnoughSqr = sqr(docker->getGeometryInfo().getBoundingCircleRadius()*2); Real curDistSqr = ThePartitionManager->getDistanceSquared(docker, getObject(), FROM_BOUNDINGSPHERE_2D); if (curDistSqr > closeEnoughSqr) { - DEBUG_LOG(("Failing dock, dist %f, not close enough(%f).", sqrt(curDistSqr), sqrt(closeEnoughSqr))); + DEBUG_LOG(("Failing dock, dist %f, not close enough(%f).", WWMath::SqrtOrigin(curDistSqr), WWMath::SqrtOrigin(closeEnoughSqr))); // Make it twitch a little. Coord3D newPos = *docker->getPosition(); Real range = 0.4*PATHFIND_CELL_SIZE_F; @@ -170,7 +170,7 @@ void SupplyWarehouseDockUpdate::setDockCrippled( Bool setting ) void SupplyWarehouseDockUpdate::setCashValue( Int cashValue ) { // A script can tell us our set value, and we need to figure out the boxes needed to provide that. - m_boxesStored = ceil(cashValue / (float)TheGlobalData->m_baseValuePerSupplyBox); + m_boxesStored = WWMath::Ceil(cashValue / (float)TheGlobalData->m_baseValuePerSupplyBox); Drawable *draw = getObject()->getDrawable(); if( draw ) { diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp index 5ad5b511a23..de00790d071 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp @@ -166,8 +166,8 @@ void DynamicShroudClearingRangeUpdate::animateGridDecals() for (int d = 0; d < GRID_FX_DECAL_COUNT; ++d) { - pos.x = ctr->x + (sinf(angle) * radius); - pos.y = ctr->y + (cosf(angle) * radius); + pos.x = ctr->x + (WWMath::Sin(angle) * radius); + pos.y = ctr->y + (WWMath::Cos(angle) * radius); pos.x -= ((Int)pos.x)%23; pos.y -= ((Int)pos.y)%23; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp index 29f256c4801..85362f8bc63 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp @@ -119,8 +119,8 @@ UpdateSleepTime FloatUpdate::update() { Real angle = INT_TO_REAL(TheGameLogic->getFrame()); - Real yaw = sin(angle * 0.0291f) * 0.05f; - Real pitch = sin(angle * 0.0515f) * 0.05f; + Real yaw = WWMath::SinTrig(angle * 0.0291f) * 0.05f; + Real pitch = WWMath::SinTrig(angle * 0.0515f) * 0.05f; Matrix3D mx = *draw->getInstanceMatrix(); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp index 9bf55521dde..e5c2cbd8e7c 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp @@ -418,7 +418,7 @@ void NeutronMissileUpdate::doAttack() pos.z += m_vel.z; //DEBUG_LOG(("vel %f accel %f z %f",m_vel.length(),m_accel.length(), pos.z)); -//Real vm = sqrt(m_vel.x*m_vel.x+m_vel.y*m_vel.y+m_vel.z*m_vel.z); +//Real vm = WWMath::SqrtOrigin(m_vel.x*m_vel.x+m_vel.y*m_vel.y+m_vel.z*m_vel.z); //DEBUG_LOG(("vel is %f %f %f (%f)",m_vel.x,m_vel.y,m_vel.z,vm)); getObject()->setTransformMatrix( &mx ); getObject()->setPosition( &pos ); @@ -512,7 +512,7 @@ UpdateSleepTime NeutronMissileUpdate::update() if (m_noTurnDistLeft > 0.0f && oldPosValid) { Coord3D newPos = *getObject()->getPosition(); - Real distThisTurn = sqrt(sqr(newPos.x-oldPos.x) + sqr(newPos.y-oldPos.y) + sqr(newPos.z-oldPos.z)); + Real distThisTurn = WWMath::SqrtOrigin(sqr(newPos.x-oldPos.x) + sqr(newPos.y-oldPos.y) + sqr(newPos.z-oldPos.z)); //DEBUG_LOG(("noTurnDist goes from %f to %f",m_noTurnDistLeft,m_noTurnDistLeft-distThisTurn)); m_noTurnDistLeft -= distThisTurn; } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp index 980a9c525af..929c2328ddd 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp @@ -474,12 +474,12 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update() //First determine the factor of time completed (ranges between 0.0 and 1.0) Real factor = (Real)(now - orbitalBirthFrame) / (Real)(orbitalDeathFrame - orbitalBirthFrame); - //We're generating a swath that travels the points between sin( -1PI ) and sin( 1PI ) + //We're generating a swath that travels the points between WWMath::SinTrig( -1PI ) and WWMath::SinTrig( 1PI ) Real radians = (factor * TWO_PI) - PI; Real cxDistance = (factor * data->m_swathOfDeathDistance ) - (data->m_swathOfDeathDistance * 0.5f); //cx is cartesian x //Now calculate the amplitude value. - Real height = sin( radians ); + Real height = WWMath::SinTrig( radians ); Real cxHeight = height * data->m_swathOfDeathAmplitude; Coord3D buildingToInitialTargetVector; @@ -501,7 +501,7 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update() cartesianTargetVector.Normalize(); Real dotProduct = Vector2::Dot_Product( buildingToTargetVector, cartesianTargetVector ); - dotProduct = __min( 0.99999f, __max( -0.99999f, dotProduct ) ); //Account for numerical errors. Also, acos(-1.00000) is coming out QNAN on the superweapon general map. Heh. + dotProduct = __min( 0.99999f, __max( -0.99999f, dotProduct ) ); //Account for numerical errors. Also, WWMath::ACosTrig(-1.00000) is coming out QNAN on the superweapon general map. Heh. Real angle = (Real)ACos( dotProduct ); diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp index 1cf403b4ec3..13d19f392ea 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp @@ -93,8 +93,8 @@ static Real angleBetweenVectors(const Coord3D& inCurDir, const Coord3D& inGoalDi static Real heightToSpeed(Real height) { // don't bother trying to remember how far we've fallen; instead, - // back-calc it from our speed & gravity... v = sqrt(2*g*h) - return sqrt(fabs(2.0f * TheGlobalData->m_gravity * height)); + // back-calc it from our speed & gravity... v = WWMath::SqrtOrigin(2*g*h) + return WWMath::SqrtOrigin(fabs(2.0f * TheGlobalData->m_gravity * height)); } //------------------------------------------------------------------------------------------------- @@ -130,7 +130,7 @@ PhysicsBehaviorModuleData::PhysicsBehaviorModuleData() static void parseHeightToSpeed( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ ) { // don't bother trying to remember how far we've fallen; instead, - // back-calc it from our speed & gravity... v = sqrt(2*g*h) + // back-calc it from our speed & gravity... v = WWMath::SqrtOrigin(2*g*h) Real height = INI::scanReal(ini->getNextToken()); *(Real *)store = heightToSpeed(height); } @@ -637,8 +637,8 @@ UpdateSleepTime PhysicsBehavior::update() if (offset != 0.0f) { Vector3 xvec = mtx.Get_X_Vector(); - Real xy = sqrtf(sqr(xvec.X) + sqr(xvec.Y)); - Real pitchAngle = atan2(xvec.Z, xy); + Real xy = WWMath::SqrtfOrigin(sqr(xvec.X) + sqr(xvec.Y)); + Real pitchAngle = WWMath::Atan2Origin(xvec.Z, xy); Real remainingAngle = (offset > 0) ? ((PI/2) - pitchAngle) : (-(PI/2) + pitchAngle); Real s = Sin(remainingAngle); pitchRateToUse *= s; @@ -724,7 +724,7 @@ UpdateSleepTime PhysicsBehavior::update() // // don't bother trying to remember how far we've fallen; instead, - // we back-calc it from our speed & gravity... v = sqrt(2*g*h). + // we back-calc it from our speed & gravity... v = WWMath::SqrtOrigin(2*g*h). // (note that m_minFallSpeedForDamage is always POSITIVE.) // // also note: since projectiles are immune to falling damage, don't @@ -818,7 +818,7 @@ Real PhysicsBehavior::getVelocityMagnitude() const { if (m_velMag == INVALID_VEL_MAG) { - m_velMag = (Real)sqrtf( sqr(m_vel.x) + sqr(m_vel.y) + sqr(m_vel.z) ); + m_velMag = (Real)WWMath::SqrtfOrigin( sqr(m_vel.x) + sqr(m_vel.y) + sqr(m_vel.z) ); } return m_velMag; } @@ -838,9 +838,9 @@ Real PhysicsBehavior::getForwardSpeed2D() const Real dot = vx + vy; Real speedSquared = vx*vx + vy*vy; -// DEBUG_ASSERTCRASH( speedSquared != 0, ("zero speedSquared will overflow sqrtf()!") );// lorenzen... sanity check +// DEBUG_ASSERTCRASH( speedSquared != 0, ("zero speedSquared will overflow WWMath::SqrtfOrigin()!") );// lorenzen... sanity check - Real speed = (Real)sqrtf( speedSquared ); + Real speed = (Real)WWMath::SqrtfOrigin( speedSquared ); if (dot >= 0.0f) return speed; @@ -863,7 +863,7 @@ Real PhysicsBehavior::getForwardSpeed3D() const Real dot = vx + vy + vz; - Real speed = (Real)sqrtf( vx*vx + vy*vy + vz*vz ); + Real speed = (Real)WWMath::SqrtfOrigin( vx*vx + vy*vy + vz*vz ); if (dot >= 0.0f) return speed; @@ -910,7 +910,7 @@ void PhysicsBehavior::scrubVelocity2D( Real desiredVelocity ) } else { - Real curVelocity = sqrtf(m_vel.x*m_vel.x + m_vel.y*m_vel.y); + Real curVelocity = WWMath::SqrtfOrigin(m_vel.x*m_vel.x + m_vel.y*m_vel.y); if (desiredVelocity > curVelocity) { return; @@ -1195,7 +1195,7 @@ void PhysicsBehavior::onCollide( Object *other, const Coord3D *loc, const Coord3 m_lastCollidee = other->getID(); - Real dist = sqrtf(distSqr); + Real dist = WWMath::SqrtfOrigin(distSqr); Real overlap = usRadius + themRadius - dist; // if objects are coincident, dist is zero, so force would be infinite -- clearly diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp index 1e9302a3327..6bd4e5d9441 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp @@ -167,7 +167,7 @@ void PointDefenseLaserUpdate::fireWhenReady() bonus.clear(); Real fireRange = data->m_weaponTemplate->getAttackRange( bonus ); Object *me = getObject(); - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); if( fDist < fireRange ) { //We are currently in range! @@ -285,7 +285,7 @@ Object* PointDefenseLaserUpdate::scanClosestTarget() continue; } - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); if( fDist <= fireRange ) { @@ -312,7 +312,7 @@ Object* PointDefenseLaserUpdate::scanClosestTarget() pos.add( other->getPosition() ); //Recalculate the distance. - fDist = sqrt( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); + fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp index bd725493a58..a79b54e3a8c 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp @@ -185,7 +185,7 @@ void ToppleUpdate::applyTopplingForce( const Coord3D* toppleDirection, Real topp // yeah, it assumes the models are constructed appropriately, but is a cheap way // of minimizing the problem. (srj) Real curAngleX = normalizeAngle(getObject()->getOrientation()); - Real toppleAngle = normalizeAngle(atan2(m_toppleDirection.y, m_toppleDirection.x)); + Real toppleAngle = normalizeAngle(WWMath::Atan2Origin(m_toppleDirection.y, m_toppleDirection.x)); if (d->m_toppleLeftOrRightOnly) { // it's a fence or such, and can only topple left or right, so pick the closest diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index c9651c4fd1b..a18a806af6f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -383,8 +383,8 @@ void WeaponTemplate::reset() // No matter what we have now, we want to convert it to frames from msec. // ShotDelay used to use parseDurationUnsignedInt, and we are expanding on that. - self->m_minDelayBetweenShots = ceilf(ConvertDurationFromMsecsToFrames((Real)self->m_minDelayBetweenShots)); - self->m_maxDelayBetweenShots = ceilf(ConvertDurationFromMsecsToFrames((Real)self->m_maxDelayBetweenShots)); + self->m_minDelayBetweenShots = WWMath::Ceil(ConvertDurationFromMsecsToFrames((Real)self->m_minDelayBetweenShots)); + self->m_maxDelayBetweenShots = WWMath::Ceil(ConvertDurationFromMsecsToFrames((Real)self->m_maxDelayBetweenShots)); } @@ -825,7 +825,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate Real attackRangeSqr = sqr(getAttackRange(bonus)); if (distSqr > attackRangeSqr) { - //DEBUG_ASSERTCRASH(distSqr < 5*5 || distSqr < attackRangeSqr*1.2f, ("*** victim is out of range (%f vs %f) of this weapon -- why did we attempt to fire?",sqrtf(distSqr),sqrtf(attackRangeSqr))); + //DEBUG_ASSERTCRASH(distSqr < 5*5 || distSqr < attackRangeSqr*1.2f, ("*** victim is out of range (%f vs %f) of this weapon -- why did we attempt to fire?",WWMath::SqrtfOrigin(distSqr),WWMath::SqrtfOrigin(attackRangeSqr))); //-extraLogging #if defined(RTS_DEBUG) @@ -847,7 +847,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate if (distSqr < minAttackRangeSqr-0.5f && !isProjectileDetonation) #endif { - DEBUG_ASSERTCRASH(distSqr > minAttackRangeSqr*0.8f, ("*** victim is closer than min attack range (%f vs %f) of this weapon -- why did we attempt to fire?",sqrtf(distSqr),sqrtf(minAttackRangeSqr))); + DEBUG_ASSERTCRASH(distSqr > minAttackRangeSqr*0.8f, ("*** victim is closer than min attack range (%f vs %f) of this weapon -- why did we attempt to fire?",WWMath::SqrtfOrigin(distSqr),WWMath::SqrtfOrigin(minAttackRangeSqr))); //-extraLogging #if defined(RTS_DEBUG) @@ -873,7 +873,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate targetPos.set( victimPos ); } Real reAngle = getWeaponRecoilAmount(); - Real reDir = reAngle != 0.0f ? (atan2(victimPos->y - sourcePos->y, victimPos->x - sourcePos->x)) : 0.0f; + Real reDir = reAngle != 0.0f ? (WWMath::Atan2Origin(victimPos->y - sourcePos->y, victimPos->x - sourcePos->x)) : 0.0f; VeterancyLevel v = sourceObj->getVeterancyLevel(); const FXList* fx = isProjectileDetonation ? getProjectileDetonateFX(v) : getFireFX(v); @@ -1920,7 +1920,7 @@ Bool Weapon::computeApproachTarget(const Object *source, const Object *target, c if (source->isAboveTerrain()) { // Don't do a 180 degree turn. - Real angle = atan2(-dir.y, -dir.x); + Real angle = WWMath::Atan2Origin(-dir.y, -dir.x); Real relAngle = source->getOrientation()- angle; if (relAngle>2*PI) relAngle -= 2*PI; if (relAngle<-2*PI) relAngle += 2*PI; @@ -1933,7 +1933,7 @@ Bool Weapon::computeApproachTarget(const Object *source, const Object *target, c if (angleOffset != 0.0f) { - Real angle = atan2(dir.y, dir.x); + Real angle = WWMath::Atan2Origin(dir.y, dir.x); dir.x = (Real)Cos(angle + angleOffset); dir.y = (Real)Sin(angle + angleOffset); } @@ -1980,7 +1980,7 @@ Bool Weapon::computeApproachTarget(const Object *source, const Object *target, c if (angleOffset != 0.0f) { - Real angle = atan2(dir.y, dir.x); + Real angle = WWMath::Atan2Origin(dir.y, dir.x); dir.x = (Real)Cos(angle + angleOffset); dir.y = (Real)Sin(angle + angleOffset); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 0dcad375a34..e4d007b71fc 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -835,7 +835,7 @@ static void populateRandomStartPosition( GameInfo *game ) { Coord3D p1 = c1->second; Coord3D p2 = c2->second; - startSpotDistance[i][j] = sqrt( sqr(p1.x-p2.x) + sqr(p1.y-p2.y) ); + startSpotDistance[i][j] = WWMath::SqrtOrigin( sqr(p1.x-p2.x) + sqr(p1.y-p2.y) ); } } else diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/PartitionManager.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/PartitionManager.h index a183f54feb0..52a119868de 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/PartitionManager.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/PartitionManager.h @@ -1391,7 +1391,7 @@ class PartitionManager : public SubsystemInterface, public Snapshot void getVectorTo(const Object *obj, const Object *otherObj, DistanceCalculationType dc, Coord3D& vec); void getVectorTo(const Object *obj, const Coord3D *pos, DistanceCalculationType dc, Coord3D& vec); - // just like 'getDistance', but return the dist-sqr, meaning we save a sqrt() call if you don't need it. + // just like 'getDistance', but return the dist-sqr, meaning we save a WWMath::SqrtOrigin() call if you don't need it. Real getDistanceSquared(const Object *obj, const Object *otherObj, DistanceCalculationType dc, Coord3D *vec = nullptr); Real getDistanceSquared(const Object *obj, const Coord3D *pos, DistanceCalculationType dc, Coord3D *vec = nullptr); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp index 1b5a4fa7285..c770d8f5aab 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -2470,7 +2470,7 @@ void Player::doBountyForKill(const Object* killer, const Object* victim) Int bounty = REAL_TO_INT_CEIL(costToBuild * m_cashBountyPercent); #else // TheSuperHackers @bugfix Stubbjax 20/02/2026 Subtract epsilon to ensure bounty is rounded up correctly. - Int bounty = ceil((costToBuild * m_cashBountyPercent) - WWMATH_EPSILON); + Int bounty = WWMath::Ceil((costToBuild * m_cashBountyPercent) - WWMATH_EPSILON); #endif if( bounty ) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp index 9dede7f2610..55d6a142945 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/BuildAssistant.cpp @@ -806,8 +806,8 @@ LegalBuildCode BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos if (myFactoryExitWidth>0) { myExitPos = *worldPos; checkMyExit = true; - Real c = (Real)cos(angle); - Real s = (Real)sin(angle); + Real c = (Real)WWMath::CosTrig(angle); + Real s = (Real)WWMath::SinTrig(angle); Real offset = build->getTemplateGeometryInfo().getMajorRadius() + myFactoryExitWidth/2.0f; myExitPos.x += c*offset; myExitPos.y += s*offset; @@ -854,8 +854,8 @@ LegalBuildCode BuildAssistant::isLocationClearOfObjects( const Coord3D *worldPos if (themFactoryExitWidth>0) { hisExitPos = *them->getPosition(); checkHisExit = true; - Real c = (Real)cos(them->getOrientation()); - Real s = (Real)sin(them->getOrientation()); + Real c = (Real)WWMath::CosTrig(them->getOrientation()); + Real s = (Real)WWMath::SinTrig(them->getOrientation()); Real offset = them->getGeometryInfo().getMajorRadius() + themFactoryExitWidth/2.0f; hisExitPos.x += c*offset; hisExitPos.y += s*offset; @@ -1435,7 +1435,7 @@ Bool BuildAssistant::moveObjectsForConstruction( const ThingTemplate *whatToBuil Bool anyUnmovables = false; MemoryPoolObjectHolder hold( iter ); - Real radius = sqrt(pow(gi.getMajorRadius(), 2) + pow(gi.getMinorRadius(), 2)); + Real radius = WWMath::SqrtOrigin(WWMath::PowOrigin(gi.getMajorRadius(), 2) + WWMath::PowOrigin(gi.getMinorRadius(), 2)); radius *= 1.4f; // Fudge the distance, for( Object *them = iter->first(); them; them = iter->next() ) diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/Geometry.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/Geometry.cpp index b69c01de560..7965ccf92d8 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/Geometry.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/Geometry.cpp @@ -173,17 +173,17 @@ void GeometryInfo::calcPitches(const Coord3D& thisPos, const GeometryInfo& that, Coord3D thisCenter; getCenterPosition(thisPos, thisCenter); - Real dxy = sqrt(sqr(thatPos.x - thisCenter.x) + sqr(thatPos.y - thisCenter.y)); + Real dxy = WWMath::SqrtOrigin(sqr(thatPos.x - thisCenter.x) + sqr(thatPos.y - thisCenter.y)); Real dz; /** @todo srj -- this could be better, by calcing it for all the corners, not just top-center and bottom-center... oh well */ dz = (thatPos.z + that.getMaxHeightAbovePosition()) - thisCenter.z; - maxPitch = atan2(dz, dxy); + maxPitch = WWMath::Atan2Origin(dz, dxy); dz = (thatPos.z - that.getMaxHeightBelowPosition()) - thisCenter.z; - minPitch = atan2(dz, dxy); + minPitch = WWMath::Atan2Origin(dz, dxy); } //============================================================================= @@ -279,8 +279,8 @@ void GeometryInfo::get2DBounds(const Coord3D& geomCenter, Real angle, Region2D& case GEOMETRY_BOX: { - Real c = (Real)cos(angle); - Real s = (Real)sin(angle); + Real c = (Real)WWMath::CosTrig(angle); + Real s = (Real)WWMath::SinTrig(angle); Real exc = m_majorRadius*c; Real eyc = m_minorRadius*c; Real exs = m_majorRadius*s; @@ -329,7 +329,7 @@ void GeometryInfo::clipPointToFootprint(const Coord3D& geomCenter, Coord3D& ptTo { Real dx = ptToClip.x - geomCenter.x; Real dy = ptToClip.y - geomCenter.y; - Real radius = sqrt(sqr(dx) + sqr(dy)); + Real radius = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); if (radius > m_majorRadius) { Real ratio = m_majorRadius / radius; @@ -361,7 +361,7 @@ Bool GeometryInfo::isPointInFootprint(const Coord3D& geomCenter, const Coord3D& { Real dx = pt.x - geomCenter.x; Real dy = pt.y - geomCenter.y; - Real radius = sqrt(sqr(dx) + sqr(dy)); + Real radius = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); return (radius <= m_majorRadius); break; } @@ -506,8 +506,8 @@ void GeometryInfo::calcBoundingStuff() case GEOMETRY_BOX: { - m_boundingCircleRadius = sqrt(sqr(m_majorRadius) + sqr(m_minorRadius)); - m_boundingSphereRadius = sqrt(sqr(m_majorRadius) + sqr(m_minorRadius) + sqr(m_height*0.5)); + m_boundingCircleRadius = WWMath::SqrtOrigin(sqr(m_majorRadius) + sqr(m_minorRadius)); + m_boundingSphereRadius = WWMath::SqrtOrigin(sqr(m_majorRadius) + sqr(m_minorRadius) + sqr(m_height*0.5)); break; } }; diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/Trig.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/Trig.cpp index 70323ea017d..589d18fc3ac 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/Trig.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/Trig.cpp @@ -99,7 +99,7 @@ void initTrig() fprintf(fp, "static Int sinLookup[TRIG_RES] = {\n"); for( i=0; iz) > TINY_DZ) { - Real pitch = atan2(vel->z, sqrt(sqr(vel->x)+sqr(vel->y))); + Real pitch = WWMath::Atan2Origin(vel->z, WWMath::SqrtOrigin(sqr(vel->x)+sqr(vel->y))); m_locoInfo->m_pitch -= Z_VEL_PITCH_COEFF * pitch; } } @@ -1637,8 +1637,8 @@ void Drawable::calcPhysicsXformHoverOrWings( const Locomotor *locomotor, Physics const Real ELEVATOR_CORRECTION_DEGREE = locomotor->getElevatorCorrectionDegree(); const Real ELEVATOR_CORRECTION_RATE = locomotor->getElevatorCorrectionRate(); - info.m_totalYaw = RUDDER_CORRECTION_DEGREE * sin( m_locoInfo->m_yawModulator += RUDDER_CORRECTION_RATE ); - info.m_totalPitch += ELEVATOR_CORRECTION_DEGREE * cos( m_locoInfo->m_pitchModulator += ELEVATOR_CORRECTION_RATE ); + info.m_totalYaw = RUDDER_CORRECTION_DEGREE * WWMath::SinTrig( m_locoInfo->m_yawModulator += RUDDER_CORRECTION_RATE ); + info.m_totalPitch += ELEVATOR_CORRECTION_DEGREE * WWMath::CosTrig( m_locoInfo->m_pitchModulator += ELEVATOR_CORRECTION_RATE ); info.m_totalZ = 0.0f; @@ -1721,7 +1721,7 @@ void Drawable::calcPhysicsXformTreads( const Locomotor *locomotor, PhysicsXformI maxCenterDist *= OVERLAP_SHRINK_FACTOR; if (centerDistSqr < sqr(maxCenterDist)) { - Real centerDist = sqrtf(centerDistSqr); + Real centerDist = WWMath::SqrtfOrigin(centerDistSqr); Real amount = 1.0f - centerDist/maxCenterDist; if (amount < 0.0f) amount = 0.0f; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp index 0d6999bbd98..03fb63cac26 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/PlaceEventTranslator.cpp @@ -336,7 +336,7 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess Int x, y; x = mouse.x - start.x; y = mouse.y - start.y; - if( sqrt( (x * x) + (y * y) ) >= PLACEMENT_DRAG_THRESHOLD_DIST ) + if( WWMath::SqrtOrigin( (x * x) + (y * y) ) >= PLACEMENT_DRAG_THRESHOLD_DIST ) { TheInGameUI->setPlacementEnd(&mouse); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp index 9959cb42546..951fad65238 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AI.cpp @@ -709,7 +709,7 @@ Object *AI::findClosestEnemy( const Object *me, Real range, UnsignedInt qualifie } Real distSqr = ThePartitionManager->getDistanceSquared(me, theEnemy, FROM_BOUNDINGSPHERE_2D); - Real dist = sqrt(distSqr); + Real dist = WWMath::SqrtOrigin(distSqr); Int modifier = dist/getAiData()->m_attackPriorityDistanceModifier; Int modPriority = curPriority-modifier; if (modPriority < 1) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp index fbcc7cf02fb..3fb19a4f5b3 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIGroup.cpp @@ -1883,8 +1883,8 @@ void getHelicopterOffset( Coord3D& posOut, Int idx ) } Coord3D tempCtr = posOut; - posOut.x = tempCtr.x + (sin(angle) * radius); - posOut.y = tempCtr.y + (cos(angle) * radius); + posOut.x = tempCtr.x + (WWMath::SinTrig(angle) * radius); + posOut.y = tempCtr.y + (WWMath::CosTrig(angle) * radius); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp index a4b4ad044e3..0235e39b0ea 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPlayer.cpp @@ -653,7 +653,7 @@ Object *AIPlayer::buildStructureWithDozer(const ThingTemplate *bldgPlan, BuildLi dx = dozer->getPosition()->x - pos.x; dy = dozer->getPosition()->y - pos.y; - Int count = sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); + Int count = WWMath::SqrtOrigin(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); if (count<2) count = 2; Int i; color.green = 1; @@ -1360,7 +1360,7 @@ Int AIPlayer::getPlayerSuperweaponValue(Coord3D *center, Int playerNdx, Real rad Real dy = center->y - pos.y; if (dx*dx+dy*dygetTemplate()->calcCostToBuild(pPlayer); if (pObj->isKindOf(KINDOF_COMMANDCENTER)) @@ -3145,7 +3145,7 @@ void AIPlayer::computeCenterAndRadiusOfBase(Coord3D *center, Real *radius) Real radSqr = dx*dx+dy*dy; if (radSqr>maxRadSqr) maxRadSqr=radSqr; } - *radius = sqrt(maxRadSqr); + *radius = WWMath::SqrtOrigin(maxRadSqr); } //---------------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp index 71e5345cf58..d03330248ca 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AISkirmishPlayer.cpp @@ -672,8 +672,8 @@ void AISkirmishPlayer::buildAIBaseDefenseStructure(const AsciiString &thingName, } if (angle > PI/3) break; - Real s = sin(angle); - Real c = cos(angle); + Real s = WWMath::SinTrig(angle); + Real c = WWMath::CosTrig(angle); // TheSuperHackers @info helmutbuhler 21/04/2025 This debug mutates the code to become CRC incompatible #if defined(RTS_DEBUG) || !RETAIL_COMPATIBLE_CRC @@ -1038,8 +1038,8 @@ void AISkirmishPlayer::adjustBuildList(BuildListInfo *list) angle += 3*PI/4; - Real s = sin(angle); - Real c = cos(angle); + Real s = WWMath::SinTrig(angle); + Real c = WWMath::CosTrig(angle); cur = list; while (cur) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index a11d483ef69..a59a01d6e6d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -3675,7 +3675,7 @@ StateReturnType AIAttackMoveToState::update() if (distSqr < sqr(static_cast(ATTACK_CLOSE_ENOUGH_CELLS)*PATHFIND_CELL_SIZE_F)) { return ret; } - DEBUG_LOG(("AIAttackMoveToState::update Distance from goal %f, retrying.", sqrt(distSqr))); + DEBUG_LOG(("AIAttackMoveToState::update Distance from goal %f, retrying.", WWMath::SqrtOrigin(distSqr))); ret = STATE_CONTINUE; m_retryCount--; @@ -3905,16 +3905,16 @@ void AIFollowWaypointPathState::computeGoal(Bool useGroupOffsets) if (m_priorWaypoint) { dx = dest.x - m_priorWaypoint->getLocation()->x; dy = dest.y - m_priorWaypoint->getLocation()->y; - angle = atan2(dy, dx); + angle = WWMath::Atan2Origin(dy, dx); Real deltaAngle = angle - m_angle; - Real s = sin(deltaAngle); - Real c = cos(deltaAngle); + Real s = WWMath::SinTrig(deltaAngle); + Real c = WWMath::CosTrig(deltaAngle); Real x = m_groupOffset.x * c - m_groupOffset.y * s; Real y = m_groupOffset.y * c + m_groupOffset.x * s; m_groupOffset.x = x; m_groupOffset.y = y; } else { - angle = atan2(dy, dx); + angle = WWMath::Atan2Origin(dy, dx); } m_angle = angle; #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp index 4f19ee9cfc2..5a1c6f524ae 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/PolygonTrigger.cpp @@ -286,7 +286,7 @@ void PolygonTrigger::updateBounds() const Real halfWidth = (m_bounds.hi.x - m_bounds.lo.x) / 2.0f; Real halfHeight = (m_bounds.hi.y + m_bounds.lo.y) / 2.0f; - m_radius = sqrt(halfHeight*halfHeight + halfWidth*halfWidth); + m_radius = WWMath::SqrtOrigin(halfHeight*halfHeight + halfWidth*halfWidth); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp index 3ebc5b7e386..503572f8576 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp @@ -1468,7 +1468,7 @@ void makeAlignToNormalMatrix( Real angle, const Coord3D& pos, const Coord3D& nor /* It is extremely important that the resulting matrix is such that the xvector points in the angle we specified; specifically, - that atan2(xvec.y, xvec.x) == angle. So we must construct + that WWMath::Atan2Origin(xvec.y, xvec.x) == angle. So we must construct the matrix carefully to ensure this! */ x.x = Cos( angle ); @@ -2369,7 +2369,7 @@ void TerrainLogic::setWaterHeight( const WaterHandle *water, Real height, Real d center.z = 0.0f; // irrelevant // the max radius to scan around us is the diagonal of the bounding region - Real maxDist = sqrt( affectedRegion.width() * affectedRegion.width() + + Real maxDist = WWMath::SqrtOrigin( affectedRegion.width() * affectedRegion.width() + affectedRegion.height() * affectedRegion.height() ); // scan the objects in the area of the water affected @@ -2879,7 +2879,7 @@ void TerrainLogic::createCraterInTerrain(Object *obj) deltaX = ( i * MAP_XY_FACTOR ) - pos->x; deltaY = ( j * MAP_XY_FACTOR ) - pos->y; - Real distance = sqrt( sqr( deltaX ) + sqr( deltaY ) ); + Real distance = WWMath::SqrtOrigin( sqr( deltaX ) + sqr( deltaY ) ); if ( distance < radius ) //inside circle { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp index 9c52156fbdf..86c4ca1eec6 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/BridgeBehavior.cpp @@ -1119,7 +1119,7 @@ void BridgeBehavior::createScaffolding() // // given the number of objects that we need to tile across the whole bridge, we will - // go through the creation loop ceil( numObjects / 2.0f ) times, and each + // go through the creation loop WWMath::Ceil( numObjects / 2.0f ) times, and each // time through the loop we'll create an object to move from each side of the // bridge, except the last object if the number of objects is odd is dead in the // center diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp index 9b782240938..9d5ee6daab1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/DumbProjectileBehavior.cpp @@ -172,11 +172,11 @@ static Bool calcTrajectory( Real dz = end.z - start.z; // calculating the angle is trivial. - angle = atan2(dy, dx); + angle = WWMath::Atan2Origin(dy, dx); // calculating the pitch requires a bit more effort. Real horizDistSqr = sqr(dx) + sqr(dy); - Real horizDist = sqrt(horizDistSqr); + Real horizDist = WWMath::SqrtOrigin(horizDistSqr); // calc the two possible pitches that will cover the given horizontal range. // (this is actually only true if dz==0, but is a good first guess) @@ -185,7 +185,7 @@ static Bool calcTrajectory( // let's start by aiming directly for it. we know this isn't right (unless gravity // is zero, which it's not) but is a good starting point... - Real theta = atan2(dz, horizDist); + Real theta = WWMath::Atan2Origin(dz, horizDist); // if the angle isn't pretty shallow, we can get a better initial guess by using // the code below... const Real SHALLOW_ANGLE = 0.5f * PI / 180.0f; @@ -290,7 +290,7 @@ static Bool calcTrajectory( #endif vx = velocity*cosPitches[preferred]; - Real actualRange = (vx*(vz + sqrt(root)))/gravity; + Real actualRange = (vx*(vz + WWMath::SqrtOrigin(root)))/gravity; const Real CLOSE_ENOUGH_RANGE = 5.0f; if (tooClose || (actualRange < horizDist - CLOSE_ENOUGH_RANGE)) { @@ -369,7 +369,7 @@ void DumbProjectileBehavior::projectileFireAtObjectOrPosition( const Object *vic // Some weapons want to scale their start speed to the range Real minRange = detWeap->getMinimumAttackRange(); Real maxRange = detWeap->getUnmodifiedAttackRange(); - Real range = sqrt(ThePartitionManager->getDistanceSquared( projectile, &victimPosToUse, FROM_CENTER_2D ) ); + Real range = WWMath::SqrtOrigin(ThePartitionManager->getDistanceSquared( projectile, &victimPosToUse, FROM_CENTER_2D ) ); Real rangeRatio = (range - minRange) / (maxRange - minRange); m_flightPathSpeed = (rangeRatio * (weaponSpeed - minWeaponSpeed)) + minWeaponSpeed; } @@ -444,7 +444,7 @@ Bool DumbProjectileBehavior::calcFlightPath(Bool recalcNumSegments) if (recalcNumSegments) { Real flightDistance = flightCurve.getApproximateLength(); - m_flightPathSegments = ceil( flightDistance / m_flightPathSpeed ); + m_flightPathSegments = WWMath::Ceil( flightDistance / m_flightPathSpeed ); } // TheSuperHackers @info The way flight paths are used requires at least two curve points. @@ -611,7 +611,7 @@ UpdateSleepTime DumbProjectileBehavior::update() Real distVictimMovedSqr = sqr(delta.x) + sqr(delta.y) + sqr(delta.z); if (distVictimMovedSqr > 0.1f) { - Real distVictimMoved = sqrtf(distVictimMovedSqr); + Real distVictimMoved = WWMath::SqrtfOrigin(distVictimMovedSqr); if (distVictimMoved > d->m_flightPathAdjustDistPerFrame) distVictimMoved = d->m_flightPathAdjustDistPerFrame; delta.normalize(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp index 03194dc1981..1f89505fc1f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/GenerateMinefieldBehavior.cpp @@ -248,7 +248,7 @@ void GenerateMinefieldBehavior::placeMinesAlongLine(const Coord3D& posStart, con Real dx = posEnd.x - posStart.x; Real dy = posEnd.y - posStart.y; - Real len = sqrt(sqr(dx) + sqr(dy)); + Real len = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); Real mineRadius = mineTemplate->getTemplateGeometryInfo().getBoundingCircleRadius(); Real mineDiameter = mineRadius * 2.0f; Real mineJitter = mineRadius*d->m_randomJitter; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp index e0f390196f2..f1281ee363d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/MinefieldBehavior.cpp @@ -570,7 +570,7 @@ void MinefieldBehavior::setScootParms(const Coord3D& start, const Coord3D& end) if (start.z > endOnGround.z) { // figure out how long it will take to fall, and replace scoot time with that - UnsignedInt fallingTime = REAL_TO_INT_CEIL(sqrtf(2.0f * (start.z - endOnGround.z) / fabs(TheGlobalData->m_gravity))); + UnsignedInt fallingTime = REAL_TO_INT_CEIL(WWMath::SqrtfOrigin(2.0f * (start.z - endOnGround.z) / fabs(TheGlobalData->m_gravity))); // we can scoot after we land, but don't want to stop scooting before we land if (scootFromStartingPointTime < fallingTime) scootFromStartingPointTime = fallingTime; @@ -588,7 +588,7 @@ void MinefieldBehavior::setScootParms(const Coord3D& start, const Coord3D& end) Real dx = endOnGround.x - start.x; Real dy = endOnGround.y - start.y; Real dz = endOnGround.z - start.z; - Real dist = sqrt(sqr(dx) + sqr(dy)); + Real dist = WWMath::SqrtOrigin(sqr(dx) + sqr(dy)); if (dist <= 0.1f && fabs(dz) <= 0.1f) { obj->setPosition(&endOnGround); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp index f2942322f9a..92dcfe36bbd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/SlowDeathBehavior.cpp @@ -299,7 +299,7 @@ void SlowDeathBehavior::beginSlowDeath(const DamageInfo *damageInfo) physics->setExtraBounciness(-1.0); // we don't want this guy to bounce at all physics->setExtraFriction(-3 * SECONDS_PER_LOGICFRAME_REAL); // reduce his ground friction a bit physics->setAllowBouncing(true); - Real orientation = atan2(force.y, force.x); + Real orientation = WWMath::Atan2Origin(force.y, force.x); physics->setAngles(orientation, 0, 0); obj->getDrawable()->setModelConditionState(MODELCONDITION_EXPLODED_FLAILING); m_flags |= (1<getPosition()->x; Real dy = goalPos.y - obj->getPosition()->y; Real dz = goalPos.z - obj->getPosition()->z; - Real dist = sqrt(dx*dx+dy*dy); + Real dist = WWMath::SqrtOrigin(dx*dx+dy*dy); if (dist>onPathDistToGoal) { if (!obj->isKindOf(KINDOF_PROJECTILE) && dist>2*onPathDistToGoal) @@ -1114,7 +1114,7 @@ void Locomotor::locoUpdate_moveTowardsPosition(Object* obj, const Coord3D& goalP // Projectiles never stop braking once they start. jba. obj->setStatus( MAKE_OBJECT_STATUS_MASK( OBJECT_STATUS_BRAKING ) ); // Projectiles cheat in 3 dimensions. - dist = sqrt(dx*dx+dy*dy+dz*dz); + dist = WWMath::SqrtOrigin(dx*dx+dy*dy+dz*dz); Real vel = physics->getVelocityMagnitude(); if (vel < MIN_VEL) vel = MIN_VEL; @@ -1289,7 +1289,7 @@ void Locomotor::moveTowardsPositionWheels(Object* obj, PhysicsBehavior *physics, Real angle = obj->getOrientation(); // Real relAngle = ThePartitionManager->getRelativeAngle2D( obj, &goalPos ); // Real desiredAngle = angle + relAngle; - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); Real relAngle = stdAngleDiff(desiredAngle, angle); Bool moveBackwards = false; @@ -1564,7 +1564,7 @@ Bool Locomotor::fixInvalidPosition(Object* obj, PhysicsBehavior *physics) //physics->clearAcceleration(); if (dot<0) { - dot = sqrt(-dot); + dot = WWMath::SqrtOrigin(-dot); correctionNormalized.x *= dot*physics->getMass(); correctionNormalized.y *= dot*physics->getMass(); physics->applyMotiveForce(&correctionNormalized); @@ -1628,7 +1628,7 @@ void Locomotor::moveTowardsPositionLegs(Object* obj, PhysicsBehavior *physics, c Real angle = obj->getOrientation(); // Real relAngle = ThePartitionManager->getRelativeAngle2D( obj, &goalPos ); // Real desiredAngle = angle + relAngle; - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); if (m_template->m_wanderWidthFactor != 0.0f) { Real angleLimit = PI/8 * m_template->m_wanderWidthFactor; @@ -1761,7 +1761,7 @@ void Locomotor::moveTowardsPositionClimb(Object* obj, PhysicsBehavior *physics, Real angle = obj->getOrientation(); // Real relAngle = ThePartitionManager->getRelativeAngle2D( obj, &goalPos ); // Real desiredAngle = angle + relAngle; - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); Real relAngle = stdAngleDiff(desiredAngle, angle); if (moveBackwards) { @@ -1852,7 +1852,7 @@ void Locomotor::moveTowardsPositionWings(Object* obj, PhysicsBehavior *physics, Real angleTowardPos = (isNearlyZero(dx) && isNearlyZero(dy)) ? obj->getOrientation() : - atan2(dy, dx); + WWMath::Atan2Origin(dy, dx); Real aimDir = (PI - PI/8); angleTowardPos += aimDir; @@ -2086,7 +2086,7 @@ Real Locomotor::calcLiftToUseAtPt(Object* obj, PhysicsBehavior *physics, Real cu // thus // a = 2(dz - v t)/t^2 // and - // t = (-v +- sqrt(v*v + 2*a*dz))/a + // t = (-v +- WWMath::SqrtOrigin(v*v + 2*a*dz))/a // // but if we assume t=1, then // a=2(dz-v) @@ -2148,7 +2148,7 @@ PhysicsTurningType Locomotor::rotateObjAroundLocoPivot(Object* obj, const Coord3 Real dy = goalPos.y - turnPos.y; // If we are very close to the goal, we twitch due to rounding error. So just return. jba. if (fabs(dx)<0.1f && fabs(dy)<0.1f) return TURN_NONE; - Real desiredAngle = atan2(dy, dx); + Real desiredAngle = WWMath::Atan2Origin(dy, dx); Real amount = stdAngleDiff(desiredAngle, angle); if (relAngle) *relAngle = amount; if (amount>maxTurnRate) { @@ -2170,7 +2170,7 @@ PhysicsTurningType Locomotor::rotateObjAroundLocoPivot(Object* obj, const Coord3 // so, the thing is, we want to rotate ourselves so that our *center* is rotated // by the given amount, but the rotation must be around turnPos. so do a little // back-calculation. - Real angleDesiredForTurnPos = atan2(desiredPos.y - turnPos.y, desiredPos.x - turnPos.x); + Real angleDesiredForTurnPos = WWMath::Atan2Origin(desiredPos.y - turnPos.y, desiredPos.x - turnPos.x); amount = angleDesiredForTurnPos - angle; #endif /// @todo srj -- there's probably a more efficient & more direct way to do this. find it. @@ -2186,7 +2186,7 @@ PhysicsTurningType Locomotor::rotateObjAroundLocoPivot(Object* obj, const Coord3 } else { - Real desiredAngle = atan2(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); + Real desiredAngle = WWMath::Atan2Origin(goalPos.y - obj->getPosition()->y, goalPos.x - obj->getPosition()->x); Real amount = stdAngleDiff(desiredAngle, angle); if (relAngle) *relAngle = amount; if (amount>maxTurnRate) { @@ -2520,7 +2520,7 @@ void Locomotor::maintainCurrentPositionWings(Object* obj, PhysicsBehavior *physi Real angleTowardMaintainPos = (isNearlyZero(dx) && isNearlyZero(dy)) ? obj->getOrientation() : - atan2(dy, dx); + WWMath::Atan2Origin(dy, dx); Real aimDir = (PI - PI/8); if (turnRadius < 0) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 892c1f120ab..d42d2c4fbd1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -290,7 +290,7 @@ class DeliverPayloadNugget : public ObjectCreationNugget Real dy = primary->y - secondary->y; //Calc length - Real length = sqrt( dx*dx + dy*dy ); + Real length = WWMath::SqrtOrigin( dx*dx + dy*dy ); //Normalize length dx /= length; @@ -357,7 +357,7 @@ class DeliverPayloadNugget : public ObjectCreationNugget } - Real orient = atan2( moveToPos.y - startPos.y, moveToPos.x - startPos.x); + Real orient = WWMath::Atan2Origin( moveToPos.y - startPos.y, moveToPos.x - startPos.x); if( m_data.m_distToTarget > 0 ) { const Real SLOP = 1.5f; @@ -1108,7 +1108,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget objUp->applyForce(&force); if (m_orientInForceDirection) - orientation = atan2(force.y, force.x); + orientation = WWMath::Atan2Origin(force.y, force.x); } } @@ -1196,7 +1196,7 @@ class GenericObjectCreationNugget : public ObjectCreationNugget objUp->applyForce(&force); if (m_orientInForceDirection) { - orientation = atan2(force.y, force.x); + orientation = WWMath::Atan2Origin(force.y, force.x); } DUMPREAL(orientation); objUp->setAngles(orientation, 0, 0); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp index 1ab38b4d610..cbaaba896eb 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp @@ -621,7 +621,7 @@ inline Bool z_collideTest_Sphere_Nonsphere(CollideTestProc xyproc, const Collide // find the radius of the slice of the sphere that is at b_bot CollideInfo amod = *a; amod.position.z = b_bot; - amod.geom.setMajorRadius((Real)sqrtf(sqr(a->geom.getMajorRadius()) - sqr(b_bot - a->position.z))); + amod.geom.setMajorRadius((Real)WWMath::SqrtfOrigin(sqr(a->geom.getMajorRadius()) - sqr(b_bot - a->position.z))); if (xyproc(&amod, b, cinfo)) { // if you want to have 'end' collisions, you should add something like: @@ -639,7 +639,7 @@ inline Bool z_collideTest_Sphere_Nonsphere(CollideTestProc xyproc, const Collide { CollideInfo amod = *a; amod.position.z = b_top; - amod.geom.setMajorRadius((Real)sqrtf(sqr(a->geom.getMajorRadius()) - sqr(a->position.z - b_top))); + amod.geom.setMajorRadius((Real)WWMath::SqrtfOrigin(sqr(a->geom.getMajorRadius()) - sqr(a->position.z - b_top))); if (xyproc(&amod, b, cinfo)) { // if you want to have 'end' collisions, you should add something like: @@ -827,7 +827,7 @@ static Bool distCalcProc_BoundaryAndBoundary_2D( if (totalRad > 0.0f) { - Real actualDist = sqrtf(actualDistSqr); + Real actualDist = WWMath::SqrtfOrigin(actualDistSqr); Real shrunkenDist = actualDist - totalRad; if (shrunkenDist <= 0.0f) { @@ -915,7 +915,7 @@ static Bool distCalcProc_BoundaryAndBoundary_3D( Real totalRad = (geomA?geomA->getBoundingSphereRadius():0) + (geomB?geomB->getBoundingSphereRadius():0); if (totalRad > 0.0f) { - Real actualDist = sqrtf(actualDistSqr); + Real actualDist = WWMath::SqrtfOrigin(actualDistSqr); Real shrunkenDist = actualDist - totalRad; if (shrunkenDist <= 0.0f) { @@ -2226,7 +2226,7 @@ Int PartitionData::calcMaxCoiForShape(GeometryType geom, Real majorRadius, Real } case GEOMETRY_BOX: { - Real diagonal = (Real)(sqrtf(majorRadius*majorRadius + minorRadius*minorRadius)); + Real diagonal = (Real)(WWMath::SqrtfOrigin(majorRadius*majorRadius + minorRadius*minorRadius)); Int cells = ThePartitionManager->worldToCellDist(diagonal*2) + 1; result = cells * cells; break; @@ -2643,7 +2643,7 @@ static void calcHeights(const Region3D& world, Real cellSize, Int x, Int y, Real Real xbase = world.lo.x + (x * cellSize); Real ybase = world.lo.y + (y * cellSize); const Real ROUGH_STEP_SIZE = MAP_XY_FACTOR; // no point in stepping smaller than grid scale - Real numSteps = ceilf(cellSize / ROUGH_STEP_SIZE); + Real numSteps = WWMath::Ceil(cellSize / ROUGH_STEP_SIZE); Real step = cellSize / numSteps; loZ = HUGE_DIST; // huge positive hiZ = -HUGE_DIST; // huge negative @@ -3217,7 +3217,7 @@ Int PartitionManager::calcMinRadius(const ICoord2D& cur) } // double, not real - double dist = sqrtf(minDistSqr); + double dist = WWMath::SqrtfOrigin(minDistSqr); Int minRadius = REAL_TO_INT_CEIL( dist / m_cellSize ); return minRadius; @@ -3235,7 +3235,7 @@ void PartitionManager::calcRadiusVec() // double, not real double dx = (double)cx * (double)cellSize; double dy = (double)cy * (double)cellSize; - double maxPossibleDist = sqrt(dx*dx + dy*dy); + double maxPossibleDist = WWMath::SqrtOrigin(dx*dx + dy*dy); m_maxGcoRadius = REAL_TO_INT_CEIL(maxPossibleDist / cellSize); @@ -3505,7 +3505,7 @@ Object *PartitionManager::getClosestObjects( } if (closestDistArg) { - *closestDistArg = (Real)sqrtf(closestDistSqr); + *closestDistArg = (Real)WWMath::SqrtfOrigin(closestDistSqr); } #ifdef RTS_DEBUG @@ -3632,7 +3632,7 @@ Real PartitionManager::getRelativeAngle2D( const Object *obj, const Coord3D *pos v.y = pos->y - objPos.y; v.z = 0.0f; - Real dist = (Real)sqrtf(sqr(v.x) + sqr(v.y)); + Real dist = (Real)WWMath::SqrtfOrigin(sqr(v.x) + sqr(v.y)); // normalize if (dist == 0.0f) @@ -4566,7 +4566,7 @@ Int PartitionManager::iterateCellsBreadthFirst(const Coord3D *pos, CellBreadthFi //----------------------------------------------------------------------------- static Real calcDist2D(Real x1, Real y1, Real x2, Real y2) { - return sqrtf(sqr(x1-x2) + sqr(y1-y2)); + return WWMath::SqrtfOrigin(sqr(x1-x2) + sqr(y1-y2)); } //----------------------------------------------------------------------------- @@ -5761,7 +5761,7 @@ void hLineAddThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5789,7 +5789,7 @@ void hLineRemoveThreat(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5817,7 +5817,7 @@ void hLineAddValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; @@ -5845,7 +5845,7 @@ void hLineRemoveValue(Int x1, Int x2, Int y, void *threatValueParms) if (x < 0 || x >= ThePartitionManager->m_cellCountX) continue; - distance = sqrt( pow(x - parms->xCenter, 2) + pow(y - parms->yCenter, 2) ); + distance = WWMath::SqrtOrigin( WWMath::PowOrigin(x - parms->xCenter, 2) + WWMath::PowOrigin(y - parms->yCenter, 2) ); mulVal = 1 - distance / parms->radius; if (mulVal < 0.0f) mulVal = 0.0f; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 27165d9d479..ec7ef2fc5f2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -2272,7 +2272,7 @@ UpdateSleepTime AIUpdateInterface::doLocomotor() } else { - Real dist = sqrtf(dSqr); + Real dist = WWMath::SqrtfOrigin(dSqr); if (dist<1) dist = 1; pos.x += 2*PATHFIND_CELL_SIZE_F*dx/(dist*LOGICFRAMES_PER_SECOND); pos.y += 2*PATHFIND_CELL_SIZE_F*dy/(dist*LOGICFRAMES_PER_SECOND); @@ -2473,7 +2473,7 @@ Real AIUpdateInterface::getLocomotorDistanceToGoal() dest = m_path->getLastNode()->getPosition(); } Real distance = ThePartitionManager->getDistanceSquared( me, dest, FROM_CENTER_3D ); - return sqrt( distance );// Other paths return dots of normalized vectors, so one sqrt ain't so bad + return WWMath::SqrtOrigin( distance );// Other paths return dots of normalized vectors, so one sqrt ain't so bad } else { @@ -2505,7 +2505,7 @@ Real AIUpdateInterface::getLocomotorDistanceToGoal() { if (sqr(dist) > distSqr) { - return sqrt(distSqr); + return WWMath::SqrtOrigin(distSqr); } else { @@ -2514,7 +2514,7 @@ Real AIUpdateInterface::getLocomotorDistanceToGoal() } if (distm_diveStartDistance; - Real endDiveDistance = sqrt( endDiveDistanceSquared ); - Real currentDistance = sqrt( currentDistanceSquared ); + Real endDiveDistance = WWMath::SqrtOrigin( endDiveDistanceSquared ); + Real currentDistance = WWMath::SqrtOrigin( currentDistanceSquared ); Real diveRatio = (startDiveDistance - currentDistance) / (startDiveDistance - endDiveDistance); @@ -368,7 +368,7 @@ Bool DeliverPayloadAIUpdate::isCloseEnoughToTarget() if ( inBound ) allowedDistanceSqr = sqr(getAllowedDistanceToTarget() + getPreOpenDistance()); - //DEBUG_LOG(("Dist to target is %f (allowed %f)",sqrt(currentDistanceSqr),sqrt(allowedDistanceSqr))); + //DEBUG_LOG(("Dist to target is %f (allowed %f)",WWMath::SqrtOrigin(currentDistanceSqr),WWMath::SqrtOrigin(allowedDistanceSqr))); if ( allowedDistanceSqr > currentDistanceSqr ) @@ -1108,7 +1108,7 @@ StateReturnType RecoverFromOffMapState::update() // Success if we should try aga enterCoord.z = owner->getPosition()->z; owner->setPosition(&enterCoord); - Real enterAngle = atan2(ai->getMoveToPos()->y - enterCoord.y, ai->getMoveToPos()->x - enterCoord.x); + Real enterAngle = WWMath::Atan2Origin(ai->getMoveToPos()->y - enterCoord.y, ai->getMoveToPos()->x - enterCoord.x); owner->setOrientation(enterAngle); PhysicsBehavior* physics = owner->getPhysics(); @@ -1148,7 +1148,7 @@ StateReturnType HeadOffMapState::onEnter() // Give move order out of town Region3D terrainExtent; TheTerrainLogic->getExtent( &terrainExtent ); const Real FUDGE = 1.2f; - Real HUGE_DIST = FUDGE * sqrt(sqr(terrainExtent.hi.x - terrainExtent.lo.x) + sqr(terrainExtent.hi.y - terrainExtent.lo.y)); + Real HUGE_DIST = FUDGE * WWMath::SqrtOrigin(sqr(terrainExtent.hi.x - terrainExtent.lo.x) + sqr(terrainExtent.hi.y - terrainExtent.lo.y)); exitCoord.x += dir->x * HUGE_DIST; exitCoord.y += dir->y * HUGE_DIST; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp index e79b4feb7ea..6ea455aff68 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/JetAIUpdate.cpp @@ -516,7 +516,7 @@ class JetOrHeliTaxiState : public AIMoveOutOfTheWayState Coord3D intermedPt; Bool intermed = false; - Real orient = atan2(ppinfo.runwayPrep.y - ppinfo.parkingSpace.y, ppinfo.runwayPrep.x - ppinfo.parkingSpace.x); + Real orient = WWMath::Atan2Origin(ppinfo.runwayPrep.y - ppinfo.parkingSpace.y, ppinfo.runwayPrep.x - ppinfo.parkingSpace.x); if (fabs(stdAngleDiff(orient, ppinfo.parkingOrientation)) > PI/128) { intermedPt.z = (ppinfo.parkingSpace.z + ppinfo.runwayPrep.z) * 0.5f; @@ -1071,7 +1071,7 @@ class HeliTakeoffOrLandingState : public State } else { - Real dist = sqrtf(dSqr); + Real dist = WWMath::SqrtfOrigin(dSqr); if (dist<1) dist = 1; pos.x += PATHFIND_CELL_SIZE_F*dx/(dist*LOGICFRAMES_PER_SECOND); pos.y += PATHFIND_CELL_SIZE_F*dy/(dist*LOGICFRAMES_PER_SECOND); @@ -2297,7 +2297,7 @@ void JetAIUpdate::positionLockon() Real dx = getObject()->getPosition()->x - pos.x; Real dy = getObject()->getPosition()->y - pos.y; if (dx || dy) - m_lockonDrawable->setOrientation(atan2(dy, dx)); + m_lockonDrawable->setOrientation(WWMath::Atan2Origin(dy, dx)); // the Gaussian sum, to avoid keeping a running total: // diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp index 78b44dc99ca..71fcc706fc0 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp @@ -232,7 +232,7 @@ void MissileAIUpdate::projectileFireAtObjectOrPosition( const Object *victim, co Real deltaZ = victimPos->z - obj->getPosition()->z; Real dx = victimPos->x - obj->getPosition()->x; Real dy = victimPos->y - obj->getPosition()->y; - Real xyDist = sqrt(sqr(dx)+sqr(dy)); + Real xyDist = WWMath::SqrtOrigin(sqr(dx)+sqr(dy)); if (xyDist<1) xyDist = 1; Real zFactor = 0; if (deltaZ>0) { @@ -611,7 +611,7 @@ void MissileAIUpdate::doKillState() closeEnough = curLoco->getMaxSpeedForCondition(BODY_PRISTINE); } Real distanceToTargetSq = ThePartitionManager->getDistanceSquared( getObject(), getGoalObject(), FROM_BOUNDINGSPHERE_3D); - //DEBUG_LOG(("Distance to target %f, closeEnough %f", sqrt(distanceToTargetSq), closeEnough)); + //DEBUG_LOG(("Distance to target %f, closeEnough %f", WWMath::SqrtOrigin(distanceToTargetSq), closeEnough)); if (distanceToTargetSq < closeEnough*closeEnough) { Coord3D pos = *getGoalObject()->getPosition(); getObject()->setPosition(&pos); @@ -649,7 +649,7 @@ UpdateSleepTime MissileAIUpdate::update() Coord3D newPos = *getObject()->getPosition(); if (m_noTurnDistLeft > 0.0f && m_state >= IGNITION) { - Real distThisTurn = sqrtf(sqr(newPos.x-m_prevPos.x) + sqr(newPos.y-m_prevPos.y) + sqr(newPos.z-m_prevPos.z)); + Real distThisTurn = WWMath::SqrtfOrigin(sqr(newPos.x-m_prevPos.x) + sqr(newPos.y-m_prevPos.y) + sqr(newPos.z-m_prevPos.z)); m_noTurnDistLeft -= distThisTurn; m_prevPos = newPos; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp index cfe716f8440..bcbab2e4600 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/POWTruckAIUpdate.cpp @@ -480,7 +480,7 @@ void POWTruckAIUpdate::updateCollectingTarget() { // are we close enough to tell them to start moving to us - Real distSq = pow( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f, 2 ); + Real distSq = WWMath::PowOrigin( us->getGeometryInfo().getBoundingSphereRadius() * 2.0f, 2 ); if( ThePartitionManager->getDistanceSquared( us, target, FROM_CENTER_2D ) <= distSq ) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp index 17fab63bad6..3797e75f05d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/RailroadGuideAIUpdate.cpp @@ -320,7 +320,7 @@ void RailroadBehavior::onCollide( Object *other, const Coord3D *loc, const Coord m_whistleSound.setPlayingHandle(TheAudio->addAudioEvent( &m_whistleSound )); - Real dist = (Real)sqrtf( dlt.x*dlt.x + dlt.y*dlt.y + dlt.z*dlt.z); + Real dist = (Real)WWMath::SqrtfOrigin( dlt.x*dlt.x + dlt.y*dlt.y + dlt.z*dlt.z); Real usRadius = obj->getGeometryInfo().getMajorRadius(); Real themRadius = other->getGeometryInfo().getMajorRadius(); Real overlap = ((usRadius + themRadius) - dist) + 1;// the plus 1 makes them go just outside of me. @@ -1299,7 +1299,7 @@ void RailroadBehavior::updatePositionTrackDistance( PullInfo *pullerInfo, PullIn trackPosDelta.z = 0; Real dx = pullerInfo->towHitchPosition.x - turnPos.x; Real dy = pullerInfo->towHitchPosition.y - turnPos.y; - Real desiredAngle = atan2(dy, dx); + Real desiredAngle = WWMath::Atan2Origin(dy, dx); Real relAngle = stdAngleDiff(desiredAngle, obj->getTransformMatrix()->Get_Z_Rotation()); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp index 0d40b8eb230..78fee0b7978 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CleanupHazardUpdate.cpp @@ -172,7 +172,7 @@ UpdateSleepTime CleanupHazardUpdate::update() AIUpdateInterface *ai = obj->getAI(); if( ai && (ai->isIdle() || ai->isBusy()) ) { - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( obj, &m_pos, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( obj, &m_pos, FROM_CENTER_2D ) ); if( fDist < 25.0f ) { //Abort clean area because there's nothing left to clean! @@ -204,7 +204,7 @@ void CleanupHazardUpdate::fireWhenReady() bonus.clear(); Real fireRange = m_weaponTemplate->getAttackRange( bonus ); Object *me = getObject(); - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); if( fDist < fireRange ) { //We are currently in range! diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp index 344f3e882ae..c769f4880d5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/CommandButtonHuntUpdate.cpp @@ -338,7 +338,7 @@ Object* CommandButtonHuntUpdate::scanClosestTarget() } } Real distSqr = ThePartitionManager->getDistanceSquared(me, other, FROM_BOUNDINGSPHERE_2D); - Real dist = sqrt(distSqr); + Real dist = WWMath::SqrtOrigin(distSqr); Int curPriority = data->m_scanRange - dist; if (info) curPriority = info->getPriority(other->getTemplate()); if (curPriority == 0) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp index 51a9913c933..71a8abefcad 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DockUpdate/SupplyWarehouseDockUpdate.cpp @@ -95,7 +95,7 @@ Bool SupplyWarehouseDockUpdate::action( Object* docker, Object *drone ) Real closeEnoughSqr = sqr(docker->getGeometryInfo().getBoundingCircleRadius()*2); Real curDistSqr = ThePartitionManager->getDistanceSquared(docker, getObject(), FROM_BOUNDINGSPHERE_2D); if (curDistSqr > closeEnoughSqr) { - DEBUG_LOG(("Failing dock, dist %f, not close enough(%f).", sqrt(curDistSqr), sqrt(closeEnoughSqr))); + DEBUG_LOG(("Failing dock, dist %f, not close enough(%f).", WWMath::SqrtOrigin(curDistSqr), WWMath::SqrtOrigin(closeEnoughSqr))); // Make it twitch a little. Coord3D newPos = *docker->getPosition(); Real range = 0.4*PATHFIND_CELL_SIZE_F; @@ -170,7 +170,7 @@ void SupplyWarehouseDockUpdate::setDockCrippled( Bool setting ) void SupplyWarehouseDockUpdate::setCashValue( Int cashValue ) { // A script can tell us our set value, and we need to figure out the boxes needed to provide that. - m_boxesStored = ceil(cashValue / (float)TheGlobalData->m_baseValuePerSupplyBox); + m_boxesStored = WWMath::Ceil(cashValue / (float)TheGlobalData->m_baseValuePerSupplyBox); Drawable *draw = getObject()->getDrawable(); if( draw ) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp index e7100955fb6..2e1e69f7ae1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/DynamicShroudClearingRangeUpdate.cpp @@ -166,8 +166,8 @@ void DynamicShroudClearingRangeUpdate::animateGridDecals() for (int d = 0; d < GRID_FX_DECAL_COUNT; ++d) { - pos.x = ctr->x + (sinf(angle) * radius); - pos.y = ctr->y + (cosf(angle) * radius); + pos.x = ctr->x + (WWMath::Sin(angle) * radius); + pos.y = ctr->y + (WWMath::Cos(angle) * radius); pos.x -= ((Int)pos.x)%23; pos.y -= ((Int)pos.y)%23; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp index 8959c3a4db6..9151d70ed42 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/FloatUpdate.cpp @@ -119,8 +119,8 @@ UpdateSleepTime FloatUpdate::update() { Real angle = INT_TO_REAL(TheGameLogic->getFrame()); - Real yaw = sin(angle * 0.0291f) * 0.05f; - Real pitch = sin(angle * 0.0515f) * 0.05f; + Real yaw = WWMath::SinTrig(angle * 0.0291f) * 0.05f; + Real pitch = WWMath::SinTrig(angle * 0.0515f) * 0.05f; Matrix3D mx = *draw->getInstanceMatrix(); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp index 62de8b3f53c..3b6b1a32e67 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/NeutronMissileUpdate.cpp @@ -418,7 +418,7 @@ void NeutronMissileUpdate::doAttack() pos.z += m_vel.z; //DEBUG_LOG(("vel %f accel %f z %f",m_vel.length(),m_accel.length(), pos.z)); -//Real vm = sqrt(m_vel.x*m_vel.x+m_vel.y*m_vel.y+m_vel.z*m_vel.z); +//Real vm = WWMath::SqrtOrigin(m_vel.x*m_vel.x+m_vel.y*m_vel.y+m_vel.z*m_vel.z); //DEBUG_LOG(("vel is %f %f %f (%f)",m_vel.x,m_vel.y,m_vel.z,vm)); getObject()->setTransformMatrix( &mx ); getObject()->setPosition( &pos ); @@ -512,7 +512,7 @@ UpdateSleepTime NeutronMissileUpdate::update() if (m_noTurnDistLeft > 0.0f && oldPosValid) { Coord3D newPos = *getObject()->getPosition(); - Real distThisTurn = sqrt(sqr(newPos.x-oldPos.x) + sqr(newPos.y-oldPos.y) + sqr(newPos.z-oldPos.z)); + Real distThisTurn = WWMath::SqrtOrigin(sqr(newPos.x-oldPos.x) + sqr(newPos.y-oldPos.y) + sqr(newPos.z-oldPos.z)); //DEBUG_LOG(("noTurnDist goes from %f to %f",m_noTurnDistLeft,m_noTurnDistLeft-distThisTurn)); m_noTurnDistLeft -= distThisTurn; } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp index eee78ae1bb9..98e3720ac4c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp @@ -526,12 +526,12 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update() //First determine the factor of time completed (ranges between 0.0 and 1.0) Real factor = (Real)(now - orbitalBirthFrame) / (Real)(orbitalDeathFrame - orbitalBirthFrame); - //We're generating a swath that travels the points between sin( -1PI ) and sin( 1PI ) + //We're generating a swath that travels the points between WWMath::SinTrig( -1PI ) and WWMath::SinTrig( 1PI ) Real radians = (factor * TWO_PI) - PI; Real cxDistance = (factor * data->m_swathOfDeathDistance ) - (data->m_swathOfDeathDistance * 0.5f); //cx is cartesian x //Now calculate the amplitude value. - Real height = sin( radians ); + Real height = WWMath::SinTrig( radians ); Real cxHeight = height * data->m_swathOfDeathAmplitude; Coord3D buildingToInitialTargetVector; @@ -553,7 +553,7 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update() cartesianTargetVector.Normalize(); Real dotProduct = Vector2::Dot_Product( buildingToTargetVector, cartesianTargetVector ); - dotProduct = __min( 0.99999f, __max( -0.99999f, dotProduct ) ); //Account for numerical errors. Also, acos(-1.00000) is coming out QNAN on the superweapon general map. Heh. + dotProduct = __min( 0.99999f, __max( -0.99999f, dotProduct ) ); //Account for numerical errors. Also, WWMath::ACosTrig(-1.00000) is coming out QNAN on the superweapon general map. Heh. Real angle = (Real)ACos( dotProduct ); if( buildingToTargetVector.Y >= 0 ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp index 67db9400e2c..bf02fd4f9d9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PhysicsUpdate.cpp @@ -101,8 +101,8 @@ static Real angleBetweenVectors(const Coord3D& inCurDir, const Coord3D& inGoalDi static Real heightToSpeed(Real height) { // don't bother trying to remember how far we've fallen; instead, - // back-calc it from our speed & gravity... v = sqrt(2*g*h) - return sqrt(fabs(2.0f * TheGlobalData->m_gravity * height)); + // back-calc it from our speed & gravity... v = WWMath::SqrtOrigin(2*g*h) + return WWMath::SqrtOrigin(fabs(2.0f * TheGlobalData->m_gravity * height)); } //------------------------------------------------------------------------------------------------- @@ -143,7 +143,7 @@ PhysicsBehaviorModuleData::PhysicsBehaviorModuleData() static void parseHeightToSpeed( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ ) { // don't bother trying to remember how far we've fallen; instead, - // back-calc it from our speed & gravity... v = sqrt(2*g*h) + // back-calc it from our speed & gravity... v = WWMath::SqrtOrigin(2*g*h) Real height = INI::scanReal(ini->getNextToken()); *(Real *)store = heightToSpeed(height); } @@ -736,8 +736,8 @@ UpdateSleepTime PhysicsBehavior::update() if (offset != 0.0f) { Vector3 xvec = mtx.Get_X_Vector(); - Real xy = sqrtf(sqr(xvec.X) + sqr(xvec.Y)); - Real pitchAngle = atan2(xvec.Z, xy); + Real xy = WWMath::SqrtfOrigin(sqr(xvec.X) + sqr(xvec.Y)); + Real pitchAngle = WWMath::Atan2Origin(xvec.Z, xy); Real remainingAngle = (offset > 0) ? ((PI/2) - pitchAngle) : (-(PI/2) + pitchAngle); Real s = Sin(remainingAngle); pitchRateToUse *= s; @@ -849,7 +849,7 @@ UpdateSleepTime PhysicsBehavior::update() // // don't bother trying to remember how far we've fallen; instead, - // we back-calc it from our speed & gravity... v = sqrt(2*g*h). + // we back-calc it from our speed & gravity... v = WWMath::SqrtOrigin(2*g*h). // (note that m_minFallSpeedForDamage is always POSITIVE.) // // also note: since projectiles are immune to falling damage, don't @@ -943,7 +943,7 @@ Real PhysicsBehavior::getVelocityMagnitude() const { if (m_velMag == INVALID_VEL_MAG) { - m_velMag = (Real)sqrtf( sqr(m_vel.x) + sqr(m_vel.y) + sqr(m_vel.z) ); + m_velMag = (Real)WWMath::SqrtfOrigin( sqr(m_vel.x) + sqr(m_vel.y) + sqr(m_vel.z) ); } return m_velMag; } @@ -963,9 +963,9 @@ Real PhysicsBehavior::getForwardSpeed2D() const Real dot = vx + vy; Real speedSquared = vx*vx + vy*vy; -// DEBUG_ASSERTCRASH( speedSquared != 0, ("zero speedSquared will overflow sqrtf()!") );// lorenzen... sanity check +// DEBUG_ASSERTCRASH( speedSquared != 0, ("zero speedSquared will overflow WWMath::SqrtfOrigin()!") );// lorenzen... sanity check - Real speed = (Real)sqrtf( speedSquared ); + Real speed = (Real)WWMath::SqrtfOrigin( speedSquared ); if (dot >= 0.0f) return speed; @@ -988,7 +988,7 @@ Real PhysicsBehavior::getForwardSpeed3D() const Real dot = vx + vy + vz; - Real speed = (Real)sqrtf( vx*vx + vy*vy + vz*vz ); + Real speed = (Real)WWMath::SqrtfOrigin( vx*vx + vy*vy + vz*vz ); if (dot >= 0.0f) return speed; @@ -1035,7 +1035,7 @@ void PhysicsBehavior::scrubVelocity2D( Real desiredVelocity ) } else { - Real curVelocity = sqrtf(m_vel.x*m_vel.x + m_vel.y*m_vel.y); + Real curVelocity = WWMath::SqrtfOrigin(m_vel.x*m_vel.x + m_vel.y*m_vel.y); if (desiredVelocity > curVelocity) { return; @@ -1320,7 +1320,7 @@ void PhysicsBehavior::onCollide( Object *other, const Coord3D *loc, const Coord3 m_lastCollidee = other->getID(); - Real dist = sqrtf(distSqr); + Real dist = WWMath::SqrtfOrigin(distSqr); Real overlap = usRadius + themRadius - dist; // if objects are coincident, dist is zero, so force would be infinite -- clearly diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp index 643aa40a5b4..6772e21c55f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/PointDefenseLaserUpdate.cpp @@ -167,7 +167,7 @@ void PointDefenseLaserUpdate::fireWhenReady() bonus.clear(); Real fireRange = data->m_weaponTemplate->getAttackRange( bonus ); Object *me = getObject(); - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, target, FROM_CENTER_2D ) ); if( fDist < fireRange ) { //We are currently in range! @@ -290,7 +290,7 @@ Object* PointDefenseLaserUpdate::scanClosestTarget() continue; } - Real fDist = sqrt( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); + Real fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); if( fDist <= fireRange ) { @@ -317,7 +317,7 @@ Object* PointDefenseLaserUpdate::scanClosestTarget() pos.add( other->getPosition() ); //Recalculate the distance. - fDist = sqrt( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); + fDist = WWMath::SqrtOrigin( ThePartitionManager->getDistanceSquared( me, other, FROM_CENTER_2D ) ); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpectreGunshipDeploymentUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpectreGunshipDeploymentUpdate.cpp index d22a61a9bf8..1e550a40f6f 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpectreGunshipDeploymentUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SpectreGunshipDeploymentUpdate.cpp @@ -218,7 +218,7 @@ Bool SpectreGunshipDeploymentUpdate::initiateIntentToDoSpecialPower(const Specia newGunship->setPosition( &creationCoord ); //ORIENTATION - Real orient = atan2( m_initialTargetPosition.y - creationCoord.y, m_initialTargetPosition.x - creationCoord.x); + Real orient = WWMath::Atan2Origin( m_initialTargetPosition.y - creationCoord.y, m_initialTargetPosition.x - creationCoord.x); newGunship->setOrientation( orient ); // ID diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp index 137521dcf9b..18d75955b94 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ToppleUpdate.cpp @@ -185,7 +185,7 @@ void ToppleUpdate::applyTopplingForce( const Coord3D* toppleDirection, Real topp // yeah, it assumes the models are constructed appropriately, but is a cheap way // of minimizing the problem. (srj) Real curAngleX = normalizeAngle(getObject()->getOrientation()); - Real toppleAngle = normalizeAngle(atan2(m_toppleDirection.y, m_toppleDirection.x)); + Real toppleAngle = normalizeAngle(WWMath::Atan2Origin(m_toppleDirection.y, m_toppleDirection.x)); if (d->m_toppleLeftOrRightOnly) { // it's a fence or such, and can only topple left or right, so pick the closest diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp index deef23cd706..d9fc8959e66 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp @@ -397,8 +397,8 @@ void WeaponTemplate::reset() // No matter what we have now, we want to convert it to frames from msec. // ShotDelay used to use parseDurationUnsignedInt, and we are expanding on that. - self->m_minDelayBetweenShots = ceilf(ConvertDurationFromMsecsToFrames((Real)self->m_minDelayBetweenShots)); - self->m_maxDelayBetweenShots = ceilf(ConvertDurationFromMsecsToFrames((Real)self->m_maxDelayBetweenShots)); + self->m_minDelayBetweenShots = WWMath::Ceil(ConvertDurationFromMsecsToFrames((Real)self->m_minDelayBetweenShots)); + self->m_maxDelayBetweenShots = WWMath::Ceil(ConvertDurationFromMsecsToFrames((Real)self->m_maxDelayBetweenShots)); } @@ -857,7 +857,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate Real attackRangeSqr = sqr(getAttackRange(bonus)); if (distSqr > attackRangeSqr) { - //DEBUG_ASSERTCRASH(distSqr < 5*5 || distSqr < attackRangeSqr*1.2f, ("*** victim is out of range (%f vs %f) of this weapon -- why did we attempt to fire?",sqrtf(distSqr),sqrtf(attackRangeSqr))); + //DEBUG_ASSERTCRASH(distSqr < 5*5 || distSqr < attackRangeSqr*1.2f, ("*** victim is out of range (%f vs %f) of this weapon -- why did we attempt to fire?",WWMath::SqrtfOrigin(distSqr),WWMath::SqrtfOrigin(attackRangeSqr))); //-extraLogging #if defined(RTS_DEBUG) @@ -879,7 +879,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate if (distSqr < minAttackRangeSqr-0.5f && !isProjectileDetonation) #endif { - DEBUG_ASSERTCRASH(distSqr > minAttackRangeSqr*0.8f, ("*** victim is closer than min attack range (%f vs %f) of this weapon -- why did we attempt to fire?",sqrtf(distSqr),sqrtf(minAttackRangeSqr))); + DEBUG_ASSERTCRASH(distSqr > minAttackRangeSqr*0.8f, ("*** victim is closer than min attack range (%f vs %f) of this weapon -- why did we attempt to fire?",WWMath::SqrtfOrigin(distSqr),WWMath::SqrtfOrigin(minAttackRangeSqr))); //-extraLogging #if defined(RTS_DEBUG) @@ -905,7 +905,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate targetPos.set( victimPos ); } Real reAngle = getWeaponRecoilAmount(); - Real reDir = reAngle != 0.0f ? (atan2(victimPos->y - sourcePos->y, victimPos->x - sourcePos->x)) : 0.0f; + Real reDir = reAngle != 0.0f ? (WWMath::Atan2Origin(victimPos->y - sourcePos->y, victimPos->x - sourcePos->x)) : 0.0f; VeterancyLevel v = sourceObj->getVeterancyLevel(); const FXList* fx = isProjectileDetonation ? getProjectileDetonateFX(v) : getFireFX(v); @@ -2117,7 +2117,7 @@ Bool Weapon::computeApproachTarget(const Object *source, const Object *target, c if (source->isAboveTerrain()) { // Don't do a 180 degree turn. - Real angle = atan2(-dir.y, -dir.x); + Real angle = WWMath::Atan2Origin(-dir.y, -dir.x); Real relAngle = source->getOrientation()- angle; if (relAngle>2*PI) relAngle -= 2*PI; if (relAngle<-2*PI) relAngle += 2*PI; @@ -2130,7 +2130,7 @@ Bool Weapon::computeApproachTarget(const Object *source, const Object *target, c if (angleOffset != 0.0f) { - Real angle = atan2(dir.y, dir.x); + Real angle = WWMath::Atan2Origin(dir.y, dir.x); dir.x = (Real)Cos(angle + angleOffset); dir.y = (Real)Sin(angle + angleOffset); } @@ -2177,7 +2177,7 @@ Bool Weapon::computeApproachTarget(const Object *source, const Object *target, c if (angleOffset != 0.0f) { - Real angle = atan2(dir.y, dir.x); + Real angle = WWMath::Atan2Origin(dir.y, dir.x); dir.x = (Real)Cos(angle + angleOffset); dir.y = (Real)Sin(angle + angleOffset); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp index 0a2f82be920..eb46e7f6671 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp @@ -876,7 +876,7 @@ static void populateRandomStartPosition( GameInfo *game ) { Coord3D p1 = c1->second; Coord3D p2 = c2->second; - startSpotDistance[i][j] = sqrt( sqr(p1.x-p2.x) + sqr(p1.y-p2.y) ); + startSpotDistance[i][j] = WWMath::SqrtOrigin( sqr(p1.x-p2.x) + sqr(p1.y-p2.y) ); } } else diff --git a/docs/DEV_BLOG/2026-06-DIARY.md b/docs/DEV_BLOG/2026-06-DIARY.md index e8540993960..3ab5b82b891 100644 --- a/docs/DEV_BLOG/2026-06-DIARY.md +++ b/docs/DEV_BLOG/2026-06-DIARY.md @@ -1,5 +1,14 @@ # Development Diary - June 2026 +## 2026-06-22: Enforce Cross-Platform Math Determinism (GameMath) + +- **Native Math Call Sweep**: Discovered and replaced over 100 non-deterministic native C library math calls (`sqrt`, `sin`, `atan2`, `ceilf`, etc.) scattered across the `GameLogic` subsystem in both Generals and Zero Hour. These legacy calls relied on the original MSVC x87 FPU predictability but caused severe `REPLAY_CRC_MISMATCH` desyncs when playing macOS-recorded replays on Linux. All occurrences were systematically mapped to their deterministic `WWMath` and `GameMath` equivalents (`WWMath::SqrtOrigin`, `WWMath::Atan2Origin`, `WWMath::SinTrig`, etc.). +- **WWMath Origin Gateway Fixes**: Updated the core utility functions in [wwmath.h](file:///home/felipe/Projects/GeneralsX/Core/Libraries/Source/WWVegas/WWMath/wwmath.h) (`Cos`, `Sin`, `Acos`, `Asin`, `Sqrt`, `Inv_Sqrt`, `Ceil`, `Floor`) to prioritize and route directly to the deterministic `gm_*` functions whenever `USE_DETERMINISTIC_MATH` is defined. Also ensured double-precision gateways (`SqrtOrigin`, `Atan2Origin`) map to their double-precision `GameMath` counterparts to prevent truncation desyncs. + +## 2026-06-22: Fix Build Failure on Case-Sensitive Filesystems + +- **Case-Sensitive Header Inclusion Fix**: Resolved a compilation error on Linux where `class File` was defined multiple times. Changed `#include "Common/File.h"` to `#include "Common/file.h"` in [MiniAudioManager.cpp](file:///home/felipe/Projects/GeneralsX/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp) to match the lowercase file name of the header in the Core library. This avoids duplicate class definition errors on case-sensitive filesystems like Linux when both `FileSystem.h` (which includes lowercase `file.h`) and `MiniAudioManager.cpp` are included in the compilation unit. + ## 2026-06-20: Default Render Framerate Cap to 60 FPS in Generals and Zero Hour - **FPS Limit Default Modernization**: Changed default render framerate limits from uncapped/0 to 60 FPS in the constructor of `GlobalData` ([GlobalData.cpp](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/GeneralsMD/Code/GameEngine/Source/Common/GlobalData.cpp) and [GlobalData.cpp](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/Generals/Code/GameEngine/Source/Common/GlobalData.cpp)) and enabled FPS limiting by default (`m_useFpsLimit = TRUE`). Added corresponding `UseFPSLimit = Yes` and `FramesPerSecondLimit = 60` to the auto-generated `SagePatch.ini` template in both Generals base and Zero Hour ([GameEngine.cpp](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/Generals/Code/GameEngine/Source/Common/GameEngine.cpp) and [GameEngine.cpp](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp)). This ensures both targets default to a smooth, decoupled 60 FPS rendering experience out of the box for fresh installations without impacting the 30 Hz gameplay logic tick rate. From dcb86bfa0f0a447c639a3cf7e14507b9e4cc042d Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Mon, 22 Jun 2026 22:47:05 -0300 Subject: [PATCH 3/8] Fix remaining non-deterministic native math calls in Core libraries This commit addresses remaining naked CRT calls (ceilf, floorf, sqrt) in BaseType.h, Point.h, INI.cpp, and AIPathfind.cpp that were previously missed, enforcing determinism via WWMath and fast_float wrappers to prevent cross-platform replay desyncs. --- Core/GameEngine/Source/Common/INI/INI.cpp | 5 +++-- .../Source/GameLogic/AI/AIPathfind.cpp | 17 +++++++++-------- Core/Libraries/Include/Lib/BaseType.h | 6 +----- Core/Libraries/Source/WWVegas/WWLib/Point.h | 10 ++++++---- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Core/GameEngine/Source/Common/INI/INI.cpp b/Core/GameEngine/Source/Common/INI/INI.cpp index 917b2aa795b..25c4e523159 100644 --- a/Core/GameEngine/Source/Common/INI/INI.cpp +++ b/Core/GameEngine/Source/Common/INI/INI.cpp @@ -31,6 +31,7 @@ #include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine #define DEFINE_DEATH_NAMES +#include "WWMath/wwmath.h" #include "Common/INI.h" #include "Common/INIException.h" @@ -1866,7 +1867,7 @@ void INI::parseDurationReal( INI *ini, void * /*instance*/, void *store, const v void INI::parseDurationUnsignedInt( INI *ini, void * /*instance*/, void *store, const void* /*userData*/ ) { UnsignedInt val = scanUnsignedInt(ini->getNextToken()); - *(UnsignedInt *)store = (UnsignedInt)ceilf(ConvertDurationFromMsecsToFrames((Real)val)); + *(UnsignedInt *)store = (UnsignedInt)WWMath::Ceil(ConvertDurationFromMsecsToFrames((Real)val)); } // ------------------------------------------------------------------------------------------------ @@ -1874,7 +1875,7 @@ void INI::parseDurationUnsignedInt( INI *ini, void * /*instance*/, void *store, void INI::parseDurationUnsignedShort( INI *ini, void * /*instance*/, void *store, const void* /*userData*/ ) { UnsignedInt val = scanUnsignedInt(ini->getNextToken()); - *(UnsignedShort *)store = (UnsignedShort)ceilf(ConvertDurationFromMsecsToFrames((Real)val)); + *(UnsignedShort *)store = (UnsignedShort)WWMath::Ceil(ConvertDurationFromMsecsToFrames((Real)val)); } //------------------------------------------------------------------------------------------------- diff --git a/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index 49e0bbca25b..e01bbe15a1b 100644 --- a/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -27,6 +27,7 @@ // Author: Michael S. Booth, October 2001 #include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine +#include "WWMath/wwmath.h" #include "GameLogic/AIPathfind.h" #include "Common/PerfTimer.h" @@ -921,7 +922,7 @@ void Path::computePointOnPath( // compute distance of point from this path segment Real toDistSqr = sqr(toPos.x) + sqr(toPos.y); Real offsetDistSq = toDistSqr - sqr(alongPathDist); - Real offsetDist = (offsetDistSq <= 0.0) ? 0.0 : sqrt(offsetDistSq); + Real offsetDist = (offsetDistSq <= 0.0) ? 0.0 : WWMath::SqrtOrigin(offsetDistSq); // If we are basically on the path, return the next path node as the movement goal. // However, the farther off the path we get, the movement goal becomes closer to our @@ -2070,7 +2071,7 @@ UnsignedInt PathfindCell::costToGoal( PathfindCell *goal ) Int dy = m_info->m_pos.y - goal->getYIndex(); #define NO_REAL_DIST #ifdef REAL_DIST - Int cost = COST_ORTHOGONAL*sqrt(dx*dx + dy*dy); + Int cost = COST_ORTHOGONAL*WWMath::SqrtOrigin(dx*dx + dy*dy); #else if (dx<0) dx = -dx; if (dy<0) dy = -dy; @@ -2096,7 +2097,7 @@ UnsignedInt PathfindCell::costToHierGoal( PathfindCell *goal ) } Int dx = m_info->m_pos.x - goal->getXIndex(); Int dy = m_info->m_pos.y - goal->getYIndex(); - Int cost = REAL_TO_INT_FLOOR(COST_ORTHOGONAL*sqrt(dx*dx + dy*dy) + 0.5f); + Int cost = REAL_TO_INT_FLOOR(COST_ORTHOGONAL*WWMath::SqrtOrigin(dx*dx + dy*dy) + 0.5f); return cost; } @@ -6444,7 +6445,7 @@ Int Pathfinder::examineNeighboringCells(PathfindCell *parentCell, PathfindCell * } else { dx = newCellCoord.x - goalCell->getXIndex(); dy = newCellCoord.y - goalCell->getYIndex(); - costRemaining = COST_ORTHOGONAL*sqrt(dx*dx + dy*dy); + costRemaining = COST_ORTHOGONAL*WWMath::SqrtOrigin(dx*dx + dy*dy); costRemaining -= attackDistance/2; if (costRemaining<0) costRemaining=0; @@ -6768,7 +6769,7 @@ Path *Pathfinder::internalFindPath( Object *obj, const LocomotorSet& locomotorSe dx = from->x - to->x; dy = from->y - to->y; - Int count = sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); + Int count = WWMath::SqrtOrigin(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); if (count<2) count = 2; Int i; color.green = 0; @@ -7459,7 +7460,7 @@ Path *Pathfinder::findGroundPath( const Coord3D *from, dx = from->x - to->x; dy = from->y - to->y; - Int count = sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); + Int count = WWMath::SqrtOrigin(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); if (count<2) count = 2; Int i; color.green = 0; @@ -8163,7 +8164,7 @@ Path *Pathfinder::internal_findHierarchicalPath( Bool isHuman, const LocomotorSu dx = from->x - to->x; dy = from->y - to->y; - Int count = sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); + Int count = WWMath::SqrtOrigin(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2); if (count<2) count = 2; Int i; color.green = 0; @@ -11216,7 +11217,7 @@ Path *Pathfinder::findSafePath( const Object *obj, const LocomotorSet& locomotor farthestDistanceSqr = distSqr; if (cellCount > MAX_CELLS) { #ifdef INTENSE_DEBUG - DEBUG_LOG(("Took intermediate path, dist %f, goal dist %f", sqrt(farthestDistanceSqr), repulsorRadius)); + DEBUG_LOG(("Took intermediate path, dist %f, goal dist %f", WWMath::SqrtOrigin(farthestDistanceSqr), repulsorRadius)); #endif ok = true; // Already a big search, just take this one. } diff --git a/Core/Libraries/Include/Lib/BaseType.h b/Core/Libraries/Include/Lib/BaseType.h index 70a43592989..14e03d169da 100644 --- a/Core/Libraries/Include/Lib/BaseType.h +++ b/Core/Libraries/Include/Lib/BaseType.h @@ -223,13 +223,9 @@ __forceinline float fast_float_ceil(float f) #define INT_TO_REAL(x) ((Real)(x)) // once we've ceiled/floored, trunc and round are identical, and currently, round is faster... (srj) -#if RTS_GENERALS /*&& RETAIL_COMPATIBLE_CRC*/ -#define REAL_TO_INT_CEIL(x) (fast_float2long_round(ceilf(x))) -#define REAL_TO_INT_FLOOR(x) (fast_float2long_round(floorf(x))) -#else +// GeneralsX @feature fbraz 03/05/2026 Use deterministic fast_float functions universally to ensure cross-platform replay determinism. #define REAL_TO_INT_CEIL(x) (fast_float2long_round(fast_float_ceil(x))) #define REAL_TO_INT_FLOOR(x) (fast_float2long_round(fast_float_floor(x))) -#endif #define FAST_REAL_TRUNC(x) fast_float_trunc(x) #define FAST_REAL_CEIL(x) fast_float_ceil(x) diff --git a/Core/Libraries/Source/WWVegas/WWLib/Point.h b/Core/Libraries/Source/WWVegas/WWLib/Point.h index 78a9f8c7ea9..fc9cc789397 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/Point.h +++ b/Core/Libraries/Source/WWVegas/WWLib/Point.h @@ -36,6 +36,8 @@ #pragma once +#include "WWMath/wwmath.h" + template class TRect; /* @@ -76,9 +78,9 @@ class TPoint2D { TPoint2D const operator - () const {return(TPoint2D(-X, -Y));} // Vector support functions. - T Length() const {return(T(sqrt(X*X + Y*Y)));} + T Length() const {return(T(WWMath::SqrtOrigin(X*X + Y*Y)));} TPoint2D const Normalize() const { - double len = sqrt(X*X + Y*Y); + double len = WWMath::SqrtOrigin(X*X + Y*Y); if (len != 0.0) { return(TPoint2D((T)((double)X / len), (T)((double)Y / len))); } else { @@ -163,9 +165,9 @@ class TPoint3D : public TPoint2D { TPoint3D const operator - () const {return(TPoint3D(-X, -Y, -Z));} // Vector support functions. - T Length() const {return(T(sqrt(X*X + Y*Y + Z*Z)));} + T Length() const {return(T(WWMath::SqrtOrigin(X*X + Y*Y + Z*Z)));} TPoint3D const Normalize() const { - double len = sqrt(X*X + Y*Y + Z*Z); + double len = WWMath::SqrtOrigin(X*X + Y*Y + Z*Z); if (len != 0.0) { return(TPoint3D(X / len, Y / len, Z / len)); } else { From c5747fc5a76d1c0e2598bd3ea7d14f33a0d0f97c Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Tue, 23 Jun 2026 00:25:56 -0300 Subject: [PATCH 4/8] docs(devblog): sanitize user path in dev blog --- docs/DEV_BLOG/2026-06-DIARY.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/DEV_BLOG/2026-06-DIARY.md b/docs/DEV_BLOG/2026-06-DIARY.md index 22bb649d710..4d10e6e2aeb 100644 --- a/docs/DEV_BLOG/2026-06-DIARY.md +++ b/docs/DEV_BLOG/2026-06-DIARY.md @@ -1,5 +1,10 @@ # Development Diary - June 2026 +## 2026-06-23: Replay CRC Mismatch and Local INI Overrides (SagePatch) + +- **Replay CRC Mismatch Investigation**: Investigated a local `REPLAY_CRC_MISMATCH` at frame 0 that occurred despite the recent cross-platform math determinism fixes. Found that the divergence was not caused by the game binary or math operations, but by a local QoL mod ([SagePatch.ini](file:///Users/USER/GeneralsX/data/GeneralsZH/Data/INI/GameData/SagePatch.ini)) which overrides camera variables (`MaxCameraHeight`, `KeyboardScrollSpeedFactor`) in the global `GameData` block. +- **Replay Determinism Architecture Insight**: The engine hashes the global `GameData` block during initial map load (Frame 0). If a replay is recorded with vanilla settings, and then played back with `SagePatch.ini` or any other loose INI mod present in the local `Data/INI/` directory, the engine detects a mismatch immediately. In the future, the replay system could be enhanced to either bake the active INI configurations directly into the replay file, or automatically disable local QoL overrides (like `SagePatch.ini`) when playing a vanilla replay. + ## 2026-06-22: Enforce Cross-Platform Math Determinism (GameMath) - **Native Math Call Sweep**: Discovered and replaced over 100 non-deterministic native C library math calls (`sqrt`, `sin`, `atan2`, `ceilf`, etc.) scattered across the `GameLogic` subsystem in both Generals and Zero Hour. These legacy calls relied on the original MSVC x87 FPU predictability but caused severe `REPLAY_CRC_MISMATCH` desyncs when playing macOS-recorded replays on Linux. All occurrences were systematically mapped to their deterministic `WWMath` and `GameMath` equivalents (`WWMath::SqrtOrigin`, `WWMath::Atan2Origin`, `WWMath::SinTrig`, etc.). From c56c655a115a4621f9cdc922b0fbafb766a79714 Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Wed, 24 Jun 2026 17:53:54 -0300 Subject: [PATCH 5/8] fix(audio): resolve FPU precision state leaks and disable retail macros - Implement ScopedFPUGuard to restore FPU precision mode upon scope exit in MiniAudio and OpenAL audio managers. - Disable legacy RETAIL_COMPATIBLE_* macros (CRC, PATHFINDING, AIGroup, Networking, etc.) in GameDefines.h to avoid dynamic RNG/memory inconsistencies. --- Core/GameEngine/Include/Common/GameDefines.h | 13 +++++++------ .../Source/MiniAudioDevice/MiniAudioManager.cpp | 5 +++++ .../Source/OpenALAudioDevice/OpenALAudioManager.cpp | 5 +++++ .../Code/GameEngine/Include/GameLogic/FPUControl.h | 7 +++++++ .../Code/GameEngine/Include/GameLogic/FPUControl.h | 7 +++++++ docs/DEV_BLOG/2026-06-DIARY.md | 5 +++++ 6 files changed, 36 insertions(+), 6 deletions(-) diff --git a/Core/GameEngine/Include/Common/GameDefines.h b/Core/GameEngine/Include/Common/GameDefines.h index 1bf9f096fcf..eb7ce9097fb 100644 --- a/Core/GameEngine/Include/Common/GameDefines.h +++ b/Core/GameEngine/Include/Common/GameDefines.h @@ -79,12 +79,13 @@ #define PRESERVE_UNRELIABLE_FIRESTORMS (0) // The fix for this unfavorable behavior was approved by the Game Design Committee. #endif +// GeneralsX @tweak fbraz3 24/06/2026 Disable legacy retail compatibility modes to prevent RNG leaks and improve engine stability. #ifndef PRESERVE_RETAIL_SCRIPTED_CAMERA -#define PRESERVE_RETAIL_SCRIPTED_CAMERA (1) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 +#define PRESERVE_RETAIL_SCRIPTED_CAMERA (0) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 #endif #ifndef RETAIL_COMPATIBLE_CRC -#define RETAIL_COMPATIBLE_CRC (1) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_CRC (0) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif #ifndef RETAIL_COMPATIBLE_XFER_SAVE @@ -93,12 +94,12 @@ // This is here to easily toggle between the retail compatible with fixed pathfinding fallback and pure fixed pathfinding mode #ifndef RETAIL_COMPATIBLE_PATHFINDING -#define RETAIL_COMPATIBLE_PATHFINDING (1) +#define RETAIL_COMPATIBLE_PATHFINDING (0) #endif // This is here to easily toggle between the retail compatible pathfinding memory allocation and the new static allocated data mode #ifndef RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION -#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (1) +#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (0) #endif #ifndef RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM @@ -107,7 +108,7 @@ // Disable non retail fixes in the networking, such as putting more data per UDP packet #ifndef RETAIL_COMPATIBLE_NETWORKING -#define RETAIL_COMPATIBLE_NETWORKING (1) +#define RETAIL_COMPATIBLE_NETWORKING (0) #endif // This is essentially synonymous for RETAIL_COMPATIBLE_CRC. There is a lot wrong with AIGroup, such as use-after-free, double-free, leaks, @@ -115,7 +116,7 @@ // but put them behind this macro. #ifndef RETAIL_COMPATIBLE_AIGROUP -#define RETAIL_COMPATIBLE_AIGROUP (1) // AIGroup logic is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_AIGROUP (0) // AIGroup logic is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif #ifndef ENABLE_GAMETEXT_SUBSTITUTES diff --git a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp index 01ce398e6ab..a0d6b3420ee 100644 --- a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp @@ -59,6 +59,8 @@ #include "GameLogic/GameLogic.h" #include "GameLogic/TerrainLogic.h" +// GeneralsX @bugfix fbraz3 24/06/2026 Save and restore FPU precision mode when calling audio manager entrypoints. +#include "GameLogic/FPUControl.h" #include "Common/file.h" #include "VideoDevice/FFmpeg/FFmpegFile.h" @@ -108,6 +110,7 @@ MiniAudioManager::~MiniAudioManager() #if defined(_DEBUG) || defined(_INTERNAL) AudioHandle MiniAudioManager::addAudioEvent(const AudioEventRTS *eventToAdd) { + ScopedFPUGuard fpuGuard; if (TheGlobalData->m_preloadReport) { if (!eventToAdd->getEventName().isEmpty()) { m_allEventsLoaded.insert(eventToAdd->getEventName()); @@ -176,6 +179,7 @@ void MiniAudioManager::audioDebugDisplay(DebugDisplayInterface *dd, void *, FILE //------------------------------------------------------------------------------------------------- void MiniAudioManager::init() { + ScopedFPUGuard fpuGuard; AudioManager::init(); #ifdef INTENSE_DEBUG return; @@ -204,6 +208,7 @@ void MiniAudioManager::reset() //------------------------------------------------------------------------------------------------- void MiniAudioManager::update() { + ScopedFPUGuard fpuGuard; AudioManager::update(); setDeviceListenerPosition(); processRequestList(); diff --git a/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp b/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp index fad99e6acc1..a7ee1608811 100644 --- a/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp +++ b/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp @@ -63,6 +63,8 @@ #include "GameLogic/GameLogic.h" #include "GameLogic/TerrainLogic.h" +// GeneralsX @bugfix fbraz3 24/06/2026 Save and restore FPU precision mode when calling audio manager entrypoints. +#include "GameLogic/FPUControl.h" #include "Common/file.h" @@ -126,6 +128,7 @@ OpenALAudioManager::~OpenALAudioManager() #if defined(_DEBUG) || defined(_INTERNAL) AudioHandle OpenALAudioManager::addAudioEvent(const AudioEventRTS* eventToAdd) { + ScopedFPUGuard fpuGuard; if (TheGlobalData->m_preloadReport) { if (!eventToAdd->getEventName().isEmpty()) { m_allEventsLoaded.insert(eventToAdd->getEventName()); @@ -490,6 +493,7 @@ ALenum OpenALAudioManager::getALFormat(uint8_t channels, uint8_t bitsPerSample) //------------------------------------------------------------------------------------------------- void OpenALAudioManager::init() { + ScopedFPUGuard fpuGuard; AudioManager::init(); #ifdef INTENSE_DEBUG DEBUG_LOG(("Sound has temporarily been disabled in debug builds only. jkmcd\n")); @@ -528,6 +532,7 @@ void OpenALAudioManager::reset() //------------------------------------------------------------------------------------------------- void OpenALAudioManager::update() { + ScopedFPUGuard fpuGuard; AudioManager::update(); setDeviceListenerPosition(); processRequestList(); diff --git a/Generals/Code/GameEngine/Include/GameLogic/FPUControl.h b/Generals/Code/GameEngine/Include/GameLogic/FPUControl.h index 36ec9d546cd..6dc02733324 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/FPUControl.h +++ b/Generals/Code/GameEngine/Include/GameLogic/FPUControl.h @@ -35,3 +35,10 @@ * anywhere that touches DirectX inside GameLogic loops (LoadScreen). */ void setFPMode(); + +// GeneralsX @bugfix fbraz3 24/06/2026 Implement ScopedFPUGuard to restore FPU precision mode upon scope exit. +class ScopedFPUGuard { +public: + ScopedFPUGuard() {} + ~ScopedFPUGuard() { setFPMode(); } +}; diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/FPUControl.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/FPUControl.h index efb50b11474..5ce76570f29 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/FPUControl.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/FPUControl.h @@ -35,3 +35,10 @@ * anywhere that touches DirectX inside GameLogic loops (LoadScreen). */ void setFPMode(); + +// GeneralsX @bugfix fbraz3 24/06/2026 Implement ScopedFPUGuard to restore FPU precision mode upon scope exit. +class ScopedFPUGuard { +public: + ScopedFPUGuard() {} + ~ScopedFPUGuard() { setFPMode(); } +}; diff --git a/docs/DEV_BLOG/2026-06-DIARY.md b/docs/DEV_BLOG/2026-06-DIARY.md index 4d10e6e2aeb..6927f3f7808 100644 --- a/docs/DEV_BLOG/2026-06-DIARY.md +++ b/docs/DEV_BLOG/2026-06-DIARY.md @@ -1,5 +1,10 @@ # Development Diary - June 2026 +## 2026-06-24: Fix RNG Leaks via FPU Scoped Guard & Disable Legacy Retail Macros + +- **FPU State Leakage Fix**: Resolved issues where the MiniAudio and OpenAL audio backends (specifically during map audio scripting events and audio initialization/update loops) leaked FPU precision settings. Implemented `ScopedFPUGuard` in [FPUControl.h](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/GeneralsMD/Code/GameEngine/Include/GameLogic/FPUControl.h) and [FPUControl.h](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/Generals/Code/GameEngine/Include/GameLogic/FPUControl.h) to automatically restore FPU precision mode upon scope exit, protecting the deterministic game logic RNG from audio thread interference. +- **Disable Legacy Retail Macros**: Deactivated legacy compatibility macros (`RETAIL_COMPATIBLE_CRC`, `RETAIL_COMPATIBLE_PATHFINDING`, `RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION`, `RETAIL_COMPATIBLE_NETWORKING`, `RETAIL_COMPATIBLE_AIGROUP`, and `PRESERVE_RETAIL_SCRIPTED_CAMERA`) in [GameDefines.h](file:///Users/felipebraz/PhpstormProjects/pessoal/GeneralsX/Core/GameEngine/Include/Common/GameDefines.h). This eliminates dynamic memory thrashing in pathfinding and resolves memory leaks in `AIGroup` while removing the deterministic RNG-audio dependency during map loading. + ## 2026-06-23: Replay CRC Mismatch and Local INI Overrides (SagePatch) - **Replay CRC Mismatch Investigation**: Investigated a local `REPLAY_CRC_MISMATCH` at frame 0 that occurred despite the recent cross-platform math determinism fixes. Found that the divergence was not caused by the game binary or math operations, but by a local QoL mod ([SagePatch.ini](file:///Users/USER/GeneralsX/data/GeneralsZH/Data/INI/GameData/SagePatch.ini)) which overrides camera variables (`MaxCameraHeight`, `KeyboardScrollSpeedFactor`) in the global `GameData` block. From ae51394c67a13b57c098870125bf691fdc84a652 Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Sat, 27 Jun 2026 00:25:43 -0300 Subject: [PATCH 6/8] ci(replay-tests): fetch assets/replays from gitlab with caching Add GitLab cloning with GitHub fallback for replays. Implement branch matching for assets and replays repositories. Enable caching for the replay files repository to optimize CI runs. --- .github/workflows/replay-tests.yml | 67 ++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/.github/workflows/replay-tests.yml b/.github/workflows/replay-tests.yml index 9ba4a213ed7..94917b62eda 100644 --- a/.github/workflows/replay-tests.yml +++ b/.github/workflows/replay-tests.yml @@ -159,23 +159,24 @@ jobs: uses: actions/cache@v5 with: path: /tmp/cached-assets - key: game-assets-cache-v1 - -# - name: Checkout game assets repo -# if: steps.cache-assets.outputs.cache-hit != 'true' -# uses: actions/checkout@v7 -# with: -# repository: fbraz3/generalsx-test-files -# path: ci-assets-repo -# lfs: true + key: game-assets-cache-v2 - name: Clone game assets repo (GitLab with GitHub fallback) if: steps.cache-assets.outputs.cache-hit != 'true' run: | + # GeneralsX @build fbraz3 24/06/2026 Support checking out current branch if present in assets/replays repo. + TARGET_BRANCH="${{ github.head_ref || github.ref_name }}" clone_success=true git clone https://gitlab.com/fbraz3/generalsx-test-files.git ci-assets-repo || clone_success=false if [ "$clone_success" = true ]; then cd ci-assets-repo + if [ "$TARGET_BRANCH" != "main" ] && [ -n "$TARGET_BRANCH" ]; then + if git ls-remote --heads origin "$TARGET_BRANCH" | grep -q "refs/heads/$TARGET_BRANCH"; then + echo "Branch $TARGET_BRANCH exists on GitLab. Checking out..." + git fetch origin "$TARGET_BRANCH" + git checkout "$TARGET_BRANCH" + fi + fi git lfs install if git lfs pull; then echo "Successfully cloned and pulled LFS from GitLab." @@ -192,6 +193,13 @@ jobs: if [ "$clone_success" = false ]; then git clone https://github.com/fbraz3/generalsx-test-files.git ci-assets-repo cd ci-assets-repo + if [ "$TARGET_BRANCH" != "main" ] && [ -n "$TARGET_BRANCH" ]; then + if git ls-remote --heads origin "$TARGET_BRANCH" | grep -q "refs/heads/$TARGET_BRANCH"; then + echo "Branch $TARGET_BRANCH exists on GitHub. Checking out..." + git fetch origin "$TARGET_BRANCH" + git checkout "$TARGET_BRANCH" + fi + fi git lfs install git lfs pull fi @@ -223,11 +231,46 @@ jobs: # 5. Check out replay repo and install maps + platform-specific replays # Repo structure: GeneralsXZH/Maps// GeneralsXZH/Replays/_*.rep # ----------------------------------------------------------------------- - - name: Checkout replay files repo - uses: actions/checkout@v6 + - name: Cache Replay Files + id: cache-replays + uses: actions/cache@v5 with: - repository: fbraz3/GeneralsXReplays path: ci-replays-repo + key: replay-files-cache-v1 + + - name: Clone replay files repo (GitLab with GitHub fallback) + if: steps.cache-replays.outputs.cache-hit != 'true' + run: | + # GeneralsX @build fbraz3 24/06/2026 Clone replays from GitLab with GitHub fallback and support checking out current branch. + TARGET_BRANCH="${{ github.head_ref || github.ref_name }}" + clone_success=true + git clone https://gitlab.com/fbraz3/generalsx-replays.git ci-replays-repo || clone_success=false + if [ "$clone_success" = true ]; then + cd ci-replays-repo + if [ "$TARGET_BRANCH" != "main" ] && [ -n "$TARGET_BRANCH" ]; then + if git ls-remote --heads origin "$TARGET_BRANCH" | grep -q "refs/heads/$TARGET_BRANCH"; then + echo "Branch $TARGET_BRANCH exists on GitLab. Checking out..." + git fetch origin "$TARGET_BRANCH" + git checkout "$TARGET_BRANCH" + fi + fi + echo "Successfully cloned replays from GitLab." + else + echo "GitLab clone failed. Cleaning up and falling back to GitHub..." + rm -rf ci-replays-repo + fi + if [ "$clone_success" = false ]; then + git clone https://github.com/fbraz3/GeneralsXReplays.git ci-replays-repo + cd ci-replays-repo + if [ "$TARGET_BRANCH" != "main" ] && [ -n "$TARGET_BRANCH" ]; then + if git ls-remote --heads origin "$TARGET_BRANCH" | grep -q "refs/heads/$TARGET_BRANCH"; then + echo "Branch $TARGET_BRANCH exists on GitHub. Checking out..." + git fetch origin "$TARGET_BRANCH" + git checkout "$TARGET_BRANCH" + fi + fi + echo "Successfully cloned replays from GitHub." + fi - name: Set up user data directories (Linux) if: inputs.platform == 'linux' || inputs.platform == 'linux-flatpak' From e1d9d868316c559a5a2617a8d8fdbc07c8a090af Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Sat, 27 Jun 2026 00:25:47 -0300 Subject: [PATCH 7/8] chore(engine): enable retail compatibility modes and update resolution Enable retail compatibility macros (scripted camera, CRC, pathfinding, allocation, AI group) and set default display resolution to 1024x768. --- Core/GameEngine/Include/Common/GameDefines.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Core/GameEngine/Include/Common/GameDefines.h b/Core/GameEngine/Include/Common/GameDefines.h index eb7ce9097fb..10a49264039 100644 --- a/Core/GameEngine/Include/Common/GameDefines.h +++ b/Core/GameEngine/Include/Common/GameDefines.h @@ -81,11 +81,11 @@ // GeneralsX @tweak fbraz3 24/06/2026 Disable legacy retail compatibility modes to prevent RNG leaks and improve engine stability. #ifndef PRESERVE_RETAIL_SCRIPTED_CAMERA -#define PRESERVE_RETAIL_SCRIPTED_CAMERA (0) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 +#define PRESERVE_RETAIL_SCRIPTED_CAMERA (1) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 #endif #ifndef RETAIL_COMPATIBLE_CRC -#define RETAIL_COMPATIBLE_CRC (0) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_CRC (1) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif #ifndef RETAIL_COMPATIBLE_XFER_SAVE @@ -94,12 +94,12 @@ // This is here to easily toggle between the retail compatible with fixed pathfinding fallback and pure fixed pathfinding mode #ifndef RETAIL_COMPATIBLE_PATHFINDING -#define RETAIL_COMPATIBLE_PATHFINDING (0) +#define RETAIL_COMPATIBLE_PATHFINDING (1) #endif // This is here to easily toggle between the retail compatible pathfinding memory allocation and the new static allocated data mode #ifndef RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION -#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (0) +#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (1) #endif #ifndef RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM @@ -116,7 +116,7 @@ // but put them behind this macro. #ifndef RETAIL_COMPATIBLE_AIGROUP -#define RETAIL_COMPATIBLE_AIGROUP (0) // AIGroup logic is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_AIGROUP (1) // AIGroup logic is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif #ifndef ENABLE_GAMETEXT_SUBSTITUTES @@ -175,5 +175,5 @@ #define MIN_DISPLAY_BIT_DEPTH 16 #define DEFAULT_DISPLAY_BIT_DEPTH 32 -#define DEFAULT_DISPLAY_WIDTH 800 // The standard resolution this game was designed for -#define DEFAULT_DISPLAY_HEIGHT 600 // The standard resolution this game was designed for +#define DEFAULT_DISPLAY_WIDTH 1024 // The standard resolution this game was designed for +#define DEFAULT_DISPLAY_HEIGHT 768 // The standard resolution this game was designed for From f9553a68e7e1987a168dd496285060c1dd11c571 Mon Sep 17 00:00:00 2001 From: Felipe Keller Braz Date: Mon, 29 Jun 2026 22:22:21 -0300 Subject: [PATCH 8/8] disable all retail compatibility --- Core/GameEngine/Include/Common/GameDefines.h | 15 +++++++-------- references/old-refs/fighter19-dxvk-port | 1 + references/old-refs/jmarshall-win64-modern | 1 + references/old-refs/thesuperhackers-main | 1 + 4 files changed, 10 insertions(+), 8 deletions(-) create mode 160000 references/old-refs/fighter19-dxvk-port create mode 160000 references/old-refs/jmarshall-win64-modern create mode 160000 references/old-refs/thesuperhackers-main diff --git a/Core/GameEngine/Include/Common/GameDefines.h b/Core/GameEngine/Include/Common/GameDefines.h index 10a49264039..e043b52282b 100644 --- a/Core/GameEngine/Include/Common/GameDefines.h +++ b/Core/GameEngine/Include/Common/GameDefines.h @@ -79,31 +79,30 @@ #define PRESERVE_UNRELIABLE_FIRESTORMS (0) // The fix for this unfavorable behavior was approved by the Game Design Committee. #endif -// GeneralsX @tweak fbraz3 24/06/2026 Disable legacy retail compatibility modes to prevent RNG leaks and improve engine stability. #ifndef PRESERVE_RETAIL_SCRIPTED_CAMERA -#define PRESERVE_RETAIL_SCRIPTED_CAMERA (1) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 +#define PRESERVE_RETAIL_SCRIPTED_CAMERA (0) // Retain scripted camera behavior present in retail Generals 1.08 and Zero Hour 1.04 #endif #ifndef RETAIL_COMPATIBLE_CRC -#define RETAIL_COMPATIBLE_CRC (1) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_CRC (0) // Game is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif #ifndef RETAIL_COMPATIBLE_XFER_SAVE -#define RETAIL_COMPATIBLE_XFER_SAVE (1) // Game is expected to be Xfer Save compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_XFER_SAVE (0) // Game is expected to be Xfer Save compatible with retail Generals 1.08, Zero Hour 1.04 #endif // This is here to easily toggle between the retail compatible with fixed pathfinding fallback and pure fixed pathfinding mode #ifndef RETAIL_COMPATIBLE_PATHFINDING -#define RETAIL_COMPATIBLE_PATHFINDING (1) +#define RETAIL_COMPATIBLE_PATHFINDING (0) #endif // This is here to easily toggle between the retail compatible pathfinding memory allocation and the new static allocated data mode #ifndef RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION -#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (1) +#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (0) #endif #ifndef RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM -#define RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM (1) // Use the original circle fill algorithm, which is more efficient but less accurate +#define RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM (0) // Use the original circle fill algorithm, which is more efficient but less accurate #endif // Disable non retail fixes in the networking, such as putting more data per UDP packet @@ -116,7 +115,7 @@ // but put them behind this macro. #ifndef RETAIL_COMPATIBLE_AIGROUP -#define RETAIL_COMPATIBLE_AIGROUP (1) // AIGroup logic is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 +#define RETAIL_COMPATIBLE_AIGROUP (0) // AIGroup logic is expected to be CRC compatible with retail Generals 1.08, Zero Hour 1.04 #endif #ifndef ENABLE_GAMETEXT_SUBSTITUTES diff --git a/references/old-refs/fighter19-dxvk-port b/references/old-refs/fighter19-dxvk-port new file mode 160000 index 00000000000..3a1e115f882 --- /dev/null +++ b/references/old-refs/fighter19-dxvk-port @@ -0,0 +1 @@ +Subproject commit 3a1e115f8829ee393bd3fa4c9963f165f92a1301 diff --git a/references/old-refs/jmarshall-win64-modern b/references/old-refs/jmarshall-win64-modern new file mode 160000 index 00000000000..63348500931 --- /dev/null +++ b/references/old-refs/jmarshall-win64-modern @@ -0,0 +1 @@ +Subproject commit 63348500931063415d7251392335848b8b69bd5a diff --git a/references/old-refs/thesuperhackers-main b/references/old-refs/thesuperhackers-main new file mode 160000 index 00000000000..88bdb7c2aef --- /dev/null +++ b/references/old-refs/thesuperhackers-main @@ -0,0 +1 @@ +Subproject commit 88bdb7c2aef138c45f4e531b3e1f8b1034165db7