Changeset View
Changeset View
Standalone View
Standalone View
0ad/source/simulation2/components/CCmpRallyPointRenderer.cpp
Show First 20 Lines • Show All 238 Lines • ▼ Show 20 Lines | for (size_t i = 0; i < m_RallyPoints.size(); ++i) | ||||
if (m_MarkerEntityIds[i] == INVALID_ENTITY) | if (m_MarkerEntityIds[i] == INVALID_ENTITY) | ||||
LOGERROR("Failed to create rally point marker entity"); | LOGERROR("Failed to create rally point marker entity"); | ||||
CmpPtr<ICmpPosition> markerCmpPosition(GetSimContext(), m_MarkerEntityIds[i]); | CmpPtr<ICmpPosition> markerCmpPosition(GetSimContext(), m_MarkerEntityIds[i]); | ||||
if (markerCmpPosition) | if (markerCmpPosition) | ||||
{ | { | ||||
if (m_Displayed && IsSet()) | if (m_Displayed && IsSet()) | ||||
{ | { | ||||
markerCmpPosition->MoveTo(m_RallyPoints[i].X, m_RallyPoints[i].Y); | markerCmpPosition->MoveTo(m_RallyPoints[i].getX(), m_RallyPoints[i].getY()); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
markerCmpPosition->MoveOutOfWorld(); | markerCmpPosition->MoveOutOfWorld(); | ||||
} | } | ||||
} | } | ||||
// Set rally point flag selection based on player civilization | // Set rally point flag selection based on player civilization | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | void CCmpRallyPointRenderer::RecomputeRallyPointPath(size_t index, CmpPtr<ICmpPosition>& cmpPosition, CmpPtr<ICmpFootprint>& cmpFootprint, CmpPtr<ICmpPathfinder> cmpPathfinder) | ||||
// Find a long path to the goal point -- this uses the tile-based pathfinder, which will return a | // Find a long path to the goal point -- this uses the tile-based pathfinder, which will return a | ||||
// list of waypoints (i.e. a Path) from the goal to the foundation/previous rally point, where each | // list of waypoints (i.e. a Path) from the goal to the foundation/previous rally point, where each | ||||
// waypoint is centered at a tile. We'll have to do some post-processing on the path to get it smooth. | // waypoint is centered at a tile. We'll have to do some post-processing on the path to get it smooth. | ||||
WaypointPath path; | WaypointPath path; | ||||
std::vector<Waypoint>& waypoints = path.m_Waypoints; | std::vector<Waypoint>& waypoints = path.m_Waypoints; | ||||
CFixedVector2D start(cmpPosition->GetPosition2D()); | CFixedVector2D start(cmpPosition->GetPosition2D()); | ||||
PathGoal goal = { PathGoal::POINT, m_RallyPoints[index].X, m_RallyPoints[index].Y }; | PathGoal goal = { PathGoal::POINT, m_RallyPoints[index].getX(), m_RallyPoints[index].getY() }; | ||||
if (index == 0) | if (index == 0) | ||||
GetClosestsEdgePointFrom(start,m_RallyPoints[index], cmpPosition, cmpFootprint); | GetClosestsEdgePointFrom(start,m_RallyPoints[index], cmpPosition, cmpFootprint); | ||||
else | else | ||||
{ | { | ||||
start.X = m_RallyPoints[index-1].X; | start.Xref() = m_RallyPoints[index-1].getX(); | ||||
start.Y = m_RallyPoints[index-1].Y; | start.Yref() = m_RallyPoints[index-1].getY(); | ||||
} | } | ||||
cmpPathfinder->ComputePathImmediate(start.X, start.Y, goal, cmpPathfinder->GetPassabilityClass(m_LinePassabilityClass), path); | cmpPathfinder->ComputePathImmediate(start.getX(), start.getY(), goal, cmpPathfinder->GetPassabilityClass(m_LinePassabilityClass), path); | ||||
// Check if we got a path back; if not we probably have two markers less than one tile apart. | // Check if we got a path back; if not we probably have two markers less than one tile apart. | ||||
if (path.m_Waypoints.size() < 2) | if (path.m_Waypoints.size() < 2) | ||||
{ | { | ||||
m_Path[index].emplace_back(start.X.ToFloat(), start.Y.ToFloat()); | m_Path[index].emplace_back(start.getX().ToFloat(), start.getY().ToFloat()); | ||||
m_Path[index].emplace_back(m_RallyPoints[index].X.ToFloat(), m_RallyPoints[index].Y.ToFloat()); | m_Path[index].emplace_back(m_RallyPoints[index].getX().ToFloat(), m_RallyPoints[index].getY().ToFloat()); | ||||
return; | return; | ||||
} | } | ||||
else if (index == 0) | else if (index == 0) | ||||
{ | { | ||||
// Sometimes this ends up not being optimal if you asked for a long path, so improve. | // Sometimes this ends up not being optimal if you asked for a long path, so improve. | ||||
CFixedVector2D newend(waypoints[waypoints.size()-2].x,waypoints[waypoints.size()-2].z); | CFixedVector2D newend(waypoints[waypoints.size()-2].x,waypoints[waypoints.size()-2].z); | ||||
GetClosestsEdgePointFrom(newend,newend, cmpPosition, cmpFootprint); | GetClosestsEdgePointFrom(newend,newend, cmpPosition, cmpFootprint); | ||||
waypoints.back().x = newend.X; | waypoints.back().x = newend.getX(); | ||||
waypoints.back().z = newend.Y; | waypoints.back().z = newend.getY(); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Make sure we actually start at the rallypoint because the pathfinder moves us to a usable tile. | // Make sure we actually start at the rallypoint because the pathfinder moves us to a usable tile. | ||||
waypoints.back().x = m_RallyPoints[index-1].X; | waypoints.back().x = m_RallyPoints[index-1].getX(); | ||||
waypoints.back().z = m_RallyPoints[index-1].Y; | waypoints.back().z = m_RallyPoints[index-1].getY(); | ||||
} | } | ||||
// Pathfinder makes us go to the nearest passable cell which isn't always what we want | // Pathfinder makes us go to the nearest passable cell which isn't always what we want | ||||
waypoints[0].x = m_RallyPoints[index].X; | waypoints[0].x = m_RallyPoints[index].getX(); | ||||
waypoints[0].z = m_RallyPoints[index].Y; | waypoints[0].z = m_RallyPoints[index].getY(); | ||||
// From here on, we choose to represent the waypoints as CVector2D floats to avoid to have to convert back and forth | // From here on, we choose to represent the waypoints as CVector2D floats to avoid to have to convert back and forth | ||||
// between fixed-point Waypoint/CFixedVector2D and various other float-based formats used by interpolation and whatnot. | // between fixed-point Waypoint/CFixedVector2D and various other float-based formats used by interpolation and whatnot. | ||||
// Since we'll only be further using these points for rendering purposes, using floats should be fine. | // Since we'll only be further using these points for rendering purposes, using floats should be fine. | ||||
for (Waypoint& waypoint : waypoints) | for (Waypoint& waypoint : waypoints) | ||||
m_Path[index].emplace_back(waypoint.x.ToFloat(), waypoint.z.ToFloat()); | m_Path[index].emplace_back(waypoint.x.ToFloat(), waypoint.z.ToFloat()); | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | switch (footprintShape) | ||||
{ | { | ||||
// In this case, footprintSize0 and 1 indicate the size along the X and Z axes, respectively. | // In this case, footprintSize0 and 1 indicate the size along the X and Z axes, respectively. | ||||
// The building's footprint could be rotated any which way, so let's get the rotation around the Y axis | // The building's footprint could be rotated any which way, so let's get the rotation around the Y axis | ||||
// and the rotated unit vectors in the X/Z plane of the shape's footprint | // and the rotated unit vectors in the X/Z plane of the shape's footprint | ||||
// (the Footprint itself holds only the outline, the Position holds the orientation) | // (the Footprint itself holds only the outline, the Position holds the orientation) | ||||
// Sinus and cosinus of the Y axis rotation angle (aka the yaw) | // Sinus and cosinus of the Y axis rotation angle (aka the yaw) | ||||
fixed s, c; | fixed s, c; | ||||
fixed a = cmpPosition->GetRotation().Y; | fixed a = cmpPosition->GetRotation().getY(); | ||||
sincos_approx(a, s, c); | sincos_approx(a, s, c); | ||||
// Unit vector along the rotated X axis | // Unit vector along the rotated X axis | ||||
CFixedVector2D u(c, -s); | CFixedVector2D u(c, -s); | ||||
// Unit vector along the rotated Z axis | // Unit vector along the rotated Z axis | ||||
CFixedVector2D v(s, c); | CFixedVector2D v(s, c); | ||||
CFixedVector2D halfSize(footprintSize0 / 2, footprintSize1 / 2); | CFixedVector2D halfSize(footprintSize0 / 2, footprintSize1 / 2); | ||||
CFixedVector2D footprintEdgePoint = Geometry::NearestPointOnSquare(start - center, u, v, halfSize); | CFixedVector2D footprintEdgePoint = Geometry::NearestPointOnSquare(start - center, u, v, halfSize); | ||||
result = center + footprintEdgePoint; | result = center + footprintEdgePoint; | ||||
break; | break; | ||||
} | } | ||||
case ICmpFootprint::CIRCLE: | case ICmpFootprint::CIRCLE: | ||||
{ | { | ||||
// In this case, both footprintSize0 and 1 indicate the circle's radius | // In this case, both footprintSize0 and 1 indicate the circle's radius | ||||
// Transform target to the point nearest on the edge. | // Transform target to the point nearest on the edge. | ||||
CFixedVector2D centerVec2D(center.X, center.Y); | CFixedVector2D centerVec2D(center.getX(), center.getY()); | ||||
CFixedVector2D centerToLast(start - centerVec2D); | CFixedVector2D centerToLast(start - centerVec2D); | ||||
centerToLast.Normalize(); | centerToLast.Normalize(); | ||||
result = centerVec2D + (centerToLast.Multiply(footprintSize0)); | result = centerVec2D + (centerToLast.Multiply(footprintSize0)); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 332 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator