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
4 changes: 4 additions & 0 deletions Core/GameEngine/Include/Common/GameDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
#define RETAIL_COMPATIBLE_PATHFINDING_ALLOCATION (1)
#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
#endif

// This is essentially synonymous for RETAIL_COMPATIBLE_CRC. There is a lot wrong with AIGroup, such as use-after-free, double-free, leaks,
// but we cannot touch it much without breaking retail compatibility. Do not shy away from using massive hacks when fixing issues with AIGroup,
// but put them behind this macro.
Expand Down
5 changes: 5 additions & 0 deletions Generals/Code/GameEngine/Include/GameLogic/PartitionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,11 @@ class PartitionData : public MemoryPoolObject
Real radius
);

/**
A more advanced implementation of doCircleFill that is 100% accurate.
*/
void doCircleFillPrecise(Real centerX, Real centerY, Real radius);

/**
fill in the pixels covered by the given rectangular shape with the given
center, dimensions, and rotation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1878,6 +1878,43 @@ void PartitionData::doCircleFill(
}
}

static Bool doesCircleOverlapCell(Real centerX, Real centerY, Real radius, Real cellX, Real cellY, Real cellSize)
{
Real closestX = maxReal(cellX, minReal(centerX, cellX + cellSize));
Real closestY = maxReal(cellY, minReal(centerY, cellY + cellSize));
Real distX = centerX - closestX;
Real distY = centerY - closestY;

return (distX * distX + distY * distY) < radius * radius;
}

void PartitionData::doCircleFillPrecise(Real centerX, Real centerY, Real radius)
{
Int minCellX, minCellY, maxCellX, maxCellY;
ThePartitionManager->worldToCell(centerX - radius, centerY - radius, &minCellX, &minCellY);
ThePartitionManager->worldToCell(centerX + radius, centerY + radius, &maxCellX, &maxCellY);

Real cellSize = ThePartitionManager->getCellSize();

for (Int x = minCellX; x <= maxCellX; ++x)
{
for (Int y = minCellY; y <= maxCellY; ++y)
{
Real cellWorldX = x * cellSize;
Real cellWorldY = y * cellSize;

if (doesCircleOverlapCell(centerX, centerY, radius, cellWorldX, cellWorldY, cellSize))
{
PartitionCell* cell = ThePartitionManager->getCellAt(x, y);
if (cell)
{
addSubPixToCoverage(cell);
}
}
}
}
}

// -----------------------------------------------------------------------------
void PartitionData::doSmallFill(
Real centerX,
Expand Down Expand Up @@ -2079,7 +2116,13 @@ void PartitionData::updateCellsTouched()
case GEOMETRY_SPHERE:
case GEOMETRY_CYLINDER:
{
#if RETAIL_COMPATIBLE_CRC || RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM
doCircleFill(pos.x, pos.y, majorRadius);
#else
// TheSuperHackers @bugfix Stubbjax 29/01/2026 Use precise circle fill to improve
// collision accuracy, most notably for objects with geometry radii >= 20 and < 40.
Comment on lines +2122 to +2123
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

date in comment shows 29/01/2026 but PR was created on 2026-01-28

Prompt To Fix With AI
This is a comment left during a code review.
Path: Generals/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp
Line: 2122:2123

Comment:
date in comment shows 29/01/2026 but PR was created on 2026-01-28

How can I resolve this? If you propose a fix, please make it concise.

doCircleFillPrecise(pos.x, pos.y, majorRadius);
#endif
break;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,11 @@ class PartitionData : public MemoryPoolObject
Real radius
);

/**
A more advanced implementation of doCircleFill that is 100% accurate.
*/
void doCircleFillPrecise(Real centerX, Real centerY, Real radius);

/**
fill in the pixels covered by the given rectangular shape with the given
center, dimensions, and rotation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,43 @@ void PartitionData::doCircleFill(
}
}

static Bool doesCircleOverlapCell(Real centerX, Real centerY, Real radius, Real cellX, Real cellY, Real cellSize)
{
Real closestX = maxReal(cellX, minReal(centerX, cellX + cellSize));
Real closestY = maxReal(cellY, minReal(centerY, cellY + cellSize));
Real distX = centerX - closestX;
Real distY = centerY - closestY;

return (distX * distX + distY * distY) < radius * radius;
}

void PartitionData::doCircleFillPrecise(Real centerX, Real centerY, Real radius)
{
Int minCellX, minCellY, maxCellX, maxCellY;
ThePartitionManager->worldToCell(centerX - radius, centerY - radius, &minCellX, &minCellY);
ThePartitionManager->worldToCell(centerX + radius, centerY + radius, &maxCellX, &maxCellY);

Real cellSize = ThePartitionManager->getCellSize();

for (Int x = minCellX; x <= maxCellX; ++x)
{
for (Int y = minCellY; y <= maxCellY; ++y)
{
Real cellWorldX = x * cellSize;
Real cellWorldY = y * cellSize;

if (doesCircleOverlapCell(centerX, centerY, radius, cellWorldX, cellWorldY, cellSize))
{
PartitionCell* cell = ThePartitionManager->getCellAt(x, y);
if (cell)
{
addSubPixToCoverage(cell);
}
}
}
}
}

// -----------------------------------------------------------------------------
void PartitionData::doSmallFill(
Real centerX,
Expand Down Expand Up @@ -2083,7 +2120,13 @@ void PartitionData::updateCellsTouched()
case GEOMETRY_SPHERE:
case GEOMETRY_CYLINDER:
{
#if RETAIL_COMPATIBLE_CRC || RETAIL_COMPATIBLE_CIRCLE_FILL_ALGORITHM
doCircleFill(pos.x, pos.y, majorRadius);
#else
// TheSuperHackers @bugfix Stubbjax 29/01/2026 Use precise circle fill to improve
// collision accuracy, most notably for objects with geometry radii >= 20 and < 40.
Comment on lines +2126 to +2127
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

date in comment shows 29/01/2026 but PR was created on 2026-01-28

Prompt To Fix With AI
This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/Object/PartitionManager.cpp
Line: 2126:2127

Comment:
date in comment shows 29/01/2026 but PR was created on 2026-01-28

How can I resolve this? If you propose a fix, please make it concise.

doCircleFillPrecise(pos.x, pos.y, majorRadius);
#endif
break;
}

Expand Down
Loading