Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ endif()

include(cmake/config.cmake)
include(cmake/gamespy.cmake)
if (NOT IS_VS6_BUILD)
include(cmake/gamemath.cmake)
endif()
include(cmake/lzhl.cmake)
include(cmake/stb.cmake)

Expand Down
1 change: 1 addition & 0 deletions Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ target_include_directories(corei_libraries_source_wwvegas INTERFACE "Libraries/S
target_include_directories(corei_main INTERFACE "Main")

target_sources(corei_libraries_include PRIVATE
Libraries/Include/Lib/BaseDefines.h
Libraries/Include/Lib/BaseType.h
Libraries/Include/Lib/BaseTypeCore.h
Libraries/Include/Lib/trig.h
Expand Down
27 changes: 27 additions & 0 deletions Core/GameEngine/Include/Common/BezierSegment.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,36 @@

#include <d3dx8math.h>
#include "Common/STLTypedefs.h"
#include "Lib/BaseDefines.h"

#define USUAL_TOLERANCE 1.0f

class BezierMath
{
public:
static void D3DXVec4Transform(D3DXVECTOR4* out, const D3DXVECTOR4* v, const D3DXMATRIX* m)
{
#if USE_DETERMINISTIC_MATH
const float x = v->x, y = v->y, z = v->z, w = v->w;
out->x = ((x * m->m[0][0] + y * m->m[1][0]) + z * m->m[2][0]) + w * m->m[3][0];
out->y = ((x * m->m[0][1] + y * m->m[1][1]) + z * m->m[2][1]) + w * m->m[3][1];
out->z = ((x * m->m[0][2] + y * m->m[1][2]) + z * m->m[2][2]) + w * m->m[3][2];
out->w = ((x * m->m[0][3] + y * m->m[1][3]) + z * m->m[2][3]) + w * m->m[3][3];
#else
::D3DXVec4Transform(out, v, m);
#endif
}

static float D3DXVec4Dot(const D3DXVECTOR4* a, const D3DXVECTOR4* b)
{
#if USE_DETERMINISTIC_MATH
return ((a->x * b->x + a->y * b->y) + a->z * b->z) + a->w * b->w;
#else
return ::D3DXVec4Dot(a, b);
#endif
}
};

class BezierSegment
{
protected:
Expand Down
4 changes: 4 additions & 0 deletions Core/GameEngine/Include/Common/Diagnostic/SimulationMathCrc.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@

#pragma once

// Flags for diagnostic math benchmarks
#define RUN_MATH_BENCHMARK_REPLAY400_FLAG (0)

class SimulationMathCrc
{
public:
static UnsignedInt calculate();
static void runBenchmark(int iterations = 10000);
};
4 changes: 1 addition & 3 deletions Core/GameEngine/Include/Common/GameDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,7 @@
#define PRESERVE_RETAIL_PARTICLES (1) // Preserve original look of particles 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
#endif
// RETAIL_COMPATIBLE_CRC is default defined in BaseDefines.h

#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
Expand Down
6 changes: 3 additions & 3 deletions Core/GameEngine/Source/Common/Bezier/BezFwdIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ void BezFwdIterator::start()
D3DXVECTOR4 pz(mBezSeg.m_controlPoints[0].z, mBezSeg.m_controlPoints[1].z, mBezSeg.m_controlPoints[2].z, mBezSeg.m_controlPoints[3].z);

D3DXVECTOR4 cVec[3];
D3DXVec4Transform(&cVec[0], &px, &BezierSegment::s_bezBasisMatrix);
D3DXVec4Transform(&cVec[1], &py, &BezierSegment::s_bezBasisMatrix);
D3DXVec4Transform(&cVec[2], &pz, &BezierSegment::s_bezBasisMatrix);
BezierMath::D3DXVec4Transform(&cVec[0], &px, &BezierSegment::s_bezBasisMatrix);
BezierMath::D3DXVec4Transform(&cVec[1], &py, &BezierSegment::s_bezBasisMatrix);
BezierMath::D3DXVec4Transform(&cVec[2], &pz, &BezierSegment::s_bezBasisMatrix);

mCurrPoint = mBezSeg.m_controlPoints[0];

Expand Down
8 changes: 4 additions & 4 deletions Core/GameEngine/Source/Common/Bezier/BezierSegment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ void BezierSegment::evaluateBezSegmentAtT(Real tValue, Coord3D *outResult) const
D3DXVECTOR4 zCoords(m_controlPoints[0].z, m_controlPoints[1].z, m_controlPoints[2].z, m_controlPoints[3].z);

D3DXVECTOR4 tResult;
D3DXVec4Transform(&tResult, &tVec, &BezierSegment::s_bezBasisMatrix);
BezierMath::D3DXVec4Transform(&tResult, &tVec, &BezierSegment::s_bezBasisMatrix);

outResult->x = D3DXVec4Dot(&xCoords, &tResult);
outResult->y = D3DXVec4Dot(&yCoords, &tResult);
outResult->z = D3DXVec4Dot(&zCoords, &tResult);
outResult->x = BezierMath::D3DXVec4Dot(&xCoords, &tResult);
outResult->y = BezierMath::D3DXVec4Dot(&yCoords, &tResult);
outResult->z = BezierMath::D3DXVec4Dot(&zCoords, &tResult);
}

//-------------------------------------------------------------------------------------------------
Expand Down
105 changes: 91 additions & 14 deletions Core/GameEngine/Source/Common/Diagnostic/SimulationMathCrc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
#include "GameLogic/FPUControl.h"

#include <math.h>
#include <stdio.h>
#include <time.h>

static void appendSimulationMathCrc(XferCRC &xfer)
static void appendSimulationMathCrc_Deterministic(XferCRC &xfer)
{
Matrix3D matrix;
Matrix3D factorsMatrix;
Expand All @@ -37,18 +39,48 @@ static void appendSimulationMathCrc(XferCRC &xfer)
0.9f, 1.0f, 2.1f, 1.2f);

factorsMatrix.Set(
WWMath::Sin(0.7f) * log10f(2.3f),
WWMath::Cos(1.1f) * powf(1.1f, 2.0f),
tanf(0.3f),
asinf(0.967302263f),
acosf(0.967302263f),
atanf(0.967302263f) * powf(1.1f, 2.0f),
atan2f(0.4f, 1.3f),
sinhf(0.2f),
coshf(0.4f) * tanhf(0.5f),
sqrtf(55788.84375f),
expf(0.1f) * log10f(2.3f),
logf(1.4f));
WWMath::Sinf(0.7f) * WWMath::Log10f(2.3f),
WWMath::Cosf(1.1f) * WWMath::Powf(1.1f, 2.0f),
WWMath::Tanf(0.3f),
WWMath::Asinf(0.967302263f),
WWMath::Acosf(0.967302263f),
WWMath::Atanf(0.967302263f) * WWMath::Powf(1.1f, 2.0f),
WWMath::Atan2f(0.4f, 1.3f),
WWMath::Sinhf(0.2f),
WWMath::Coshf(0.4f) * WWMath::Tanhf(0.5f),
WWMath::Sqrtf(55788.84375f),
WWMath::Expf(0.1f) * WWMath::Log10f(2.3f),
WWMath::Logf(1.4f));

Matrix3D::Multiply(matrix, factorsMatrix, &matrix);
matrix.Get_Inverse(matrix);

xfer.xferMatrix3D(&matrix);
}

static void appendSimulationMathCrc_Native(XferCRC &xfer)
{
Matrix3D matrix;
Matrix3D factorsMatrix;

matrix.Set(
4.1f, 1.2f, 0.3f, 0.4f,
0.5f, 3.6f, 0.7f, 0.8f,
0.9f, 1.0f, 2.1f, 1.2f);

factorsMatrix.Set(
(float)(::sin(0.7) * ::log10(2.3)),
(float)(::cos(1.1) * ::pow(1.1, 2.0)),
(float)::tan(0.3),
(float)::asin(0.967302263),
(float)::acos(0.967302263),
(float)(::atan(0.967302263) * ::pow(1.1, 2.0)),
(float)::atan2(0.4, 1.3),
(float)::sinh(0.2),
(float)(::cosh(0.4) * ::tanh(0.5)),
(float)::sqrt(55788.84375),
(float)(::exp(0.1) * ::log10(2.3)),
(float)::log(1.4));

Matrix3D::Multiply(matrix, factorsMatrix, &matrix);
matrix.Get_Inverse(matrix);
Expand All @@ -63,11 +95,56 @@ UnsignedInt SimulationMathCrc::calculate()

setFPMode();

appendSimulationMathCrc(xfer);
appendSimulationMathCrc_Deterministic(xfer);

_fpreset();

xfer.close();

return xfer.getCRC();
}

void SimulationMathCrc::runBenchmark(int iterations)
{
int i;
clock_t startDet = clock();
UnsignedInt crcDet = 0;

setFPMode();

for (i = 0; i < iterations; ++i)
{
XferCRC xfer;
xfer.open("SimMathDet");
appendSimulationMathCrc_Deterministic(xfer);
xfer.close();
if (i == 0)
crcDet = xfer.getCRC();
}
_fpreset();
clock_t endDet = clock();
double timeDetMs = (double)(endDet - startDet) / CLOCKS_PER_SEC * 1000.0;

clock_t startNat = clock();
UnsignedInt crcNat = 0;

setFPMode();

for (i = 0; i < iterations; ++i)
{
XferCRC xfer;
xfer.open("SimMathNat");
appendSimulationMathCrc_Native(xfer);
xfer.close();
if (i == 0)
crcNat = xfer.getCRC();
}
_fpreset();
clock_t endNat = clock();
double timeNatMs = (double)(endNat - startNat) / CLOCKS_PER_SEC * 1000.0;

printf("\n================ MATH BENCHMARK (%d iterations) ================\n", iterations);
printf("Deterministic (WWMath): CRC = %08X, Time = %.2f ms\n", crcDet, timeDetMs);
printf("Native (system math): CRC = %08X, Time = %.2f ms\n", crcNat, timeNatMs);
printf("===========================================================\n\n");
}
4 changes: 2 additions & 2 deletions Core/GameEngine/Source/Common/INI/INI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1788,15 +1788,15 @@ 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::Ceilf(ConvertDurationFromMsecsToFrames((Real)val));
}

// ------------------------------------------------------------------------------------------------
// parse a duration in msec and convert to duration in integral number of frames, (unsignedshort) rounding UP
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::Ceilf(ConvertDurationFromMsecsToFrames((Real)val));
}

//-------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage
if (TheInGameUI->isInForceAttackMode())
{
const Real snapRadians = DEG_TO_RADF(45);
targetAngle = WWMath::Round(targetAngle / snapRadians) * snapRadians;
targetAngle = WWMath::Roundf(targetAngle / snapRadians) * snapRadians;
}

TheTacticalView->userSetAngle(targetAngle);
Expand Down
34 changes: 17 additions & 17 deletions Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -727,9 +727,9 @@ inline Bool isReallyClose(const Coord3D& a, const Coord3D& b)
{
const Real CLOSE_ENOUGH = 0.1f;
return
fabs(a.x-b.x) <= CLOSE_ENOUGH &&
fabs(a.y-b.y) <= CLOSE_ENOUGH &&
fabs(a.z-b.z) <= CLOSE_ENOUGH;
WWMath::Fabs(a.x-b.x) <= CLOSE_ENOUGH &&
WWMath::Fabs(a.y-b.y) <= CLOSE_ENOUGH &&
WWMath::Fabs(a.z-b.z) <= CLOSE_ENOUGH;
}

/**
Expand Down Expand Up @@ -921,14 +921,14 @@ 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::Sqrt(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
// projected position on the path. If we are very far off the path, we will move
// directly towards the nearest point on the path, and not the next path node.
const Real maxPathError = 3.0f * PATHFIND_CELL_SIZE_F;
const Real maxPathErrorInv = 1.0 / maxPathError;
const Real maxPathErrorInv = 1.0f / maxPathError;
Real k = offsetDist * maxPathErrorInv;
if (k > 1.0f)
k = 1.0f;
Expand Down Expand Up @@ -1011,8 +1011,8 @@ void Path::computePointOnPath(
out.posOnPath.x = closeNodePos->x + alongPathDist * segmentDirNorm.x;
out.posOnPath.y = closeNodePos->y + alongPathDist * segmentDirNorm.y;
out.posOnPath.z = closeNodePos->z;
Real dx = fabs(pos.x - out.posOnPath.x);
Real dy = fabs(pos.y - out.posOnPath.y);
Real dx = WWMath::Fabs(pos.x - out.posOnPath.x);
Real dy = WWMath::Fabs(pos.y - out.posOnPath.y);
if (dx<1 && dy<1 && closeNode->getNextOptimized() && closeNode->getNextOptimized()->getNextOptimized()) {
out.posOnPath = *closeNode->getNextOptimized()->getNextOptimized()->getPosition();
}
Expand Down Expand Up @@ -2091,7 +2091,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::Sqrt((float)(dx*dx + dy*dy));
#else
if (dx<0) dx = -dx;
if (dy<0) dy = -dy;
Expand All @@ -2117,7 +2117,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::Sqrt((float)(dx*dx + dy*dy)) + 0.5f);
return cost;
}

Expand Down Expand Up @@ -3984,8 +3984,8 @@ Bool PathfindLayer::isPointOnWall(ObjectID *wallPieces, Int numPieces, const Coo
Real pty = pt->y - obj->getPosition()->y;

// inverse-rotate it to the right coord system
Real ptx_new = (Real)fabs(ptx*c - pty*s);
Real pty_new = (Real)fabs(ptx*s + pty*c);
Real ptx_new = (Real)WWMath::Fabs(ptx*c - pty*s);
Real pty_new = (Real)WWMath::Fabs(ptx*s + pty*c);

if (ptx_new <= major && pty_new <= minor)
{
Expand Down Expand Up @@ -6440,7 +6440,7 @@ Int Pathfinder::examineNeighboringCells(PathfindCell *parentCell, PathfindCell *
toPos.y = newCellCoord.y * PATHFIND_CELL_SIZE_F ;
toPos.z = TheTerrainLogic->getGroundHeight(toPos.x , toPos.y);

if ( fabs(fromPos.z - toPos.z)<PATHFIND_CELL_SIZE_F) {
if ( WWMath::Fabs(fromPos.z - toPos.z)<PATHFIND_CELL_SIZE_F) {
newCostSoFar += 7*COST_DIAGONAL;
}
} else if (newCell->getPinched()) {
Expand All @@ -6465,7 +6465,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::Sqrt((float)(dx*dx + dy*dy));
costRemaining -= attackDistance/2;
if (costRemaining<0)
costRemaining=0;
Expand Down Expand Up @@ -6789,7 +6789,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::Sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2);
if (count<2) count = 2;
Int i;
color.green = 0;
Expand Down Expand Up @@ -7480,7 +7480,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::Sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2);
if (count<2) count = 2;
Int i;
color.green = 0;
Expand Down Expand Up @@ -8184,7 +8184,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::Sqrt(dx*dx+dy*dy)/(PATHFIND_CELL_SIZE_F/2);
if (count<2) count = 2;
Int i;
color.green = 0;
Expand Down Expand Up @@ -11237,7 +11237,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::Sqrt(farthestDistanceSqr), repulsorRadius));
#endif
ok = true; // Already a big search, just take this one.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1722,7 +1722,7 @@ void BaseHeightMapRenderObjClass::updateViewImpassableAreas(Bool partial, Int mi
}

// save calculating the tangent over and over again.
Real tanImpassableRad = tan(m_curImpassableSlope / 360.f * 2 * PI);
Real tanImpassableRad = WWMath::Tan(m_curImpassableSlope / 360.f * 2 * PI);
for (Int j = minY; j < maxY; ++j) {
for (Int i = minX; i < maxX; ++i) {
m_showAsVisibleCliff[i + j * xSize] = evaluateAsVisibleCliff(i, j, tanImpassableRad);
Expand Down
Loading
Loading