Skip to content

Commit

Permalink
feat: use islands detected by Giants
Browse files Browse the repository at this point in the history
  • Loading branch information
Peter Vaiko committed Jan 1, 2025
1 parent 18f79be commit 943ad7a
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 20 deletions.
21 changes: 16 additions & 5 deletions scripts/courseGenerator/CourseGeneratorInterface.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ CourseGeneratorInterface.generatedCourse = nil
---@param startPosition table {x, z}
---@param vehicle table
---@param settings CpCourseGeneratorSettings
---@param islandPolygons|nil table [[{x, z}]] island polygons, if not given, we'll attempt to find islands
function CourseGeneratorInterface.generate(fieldPolygon,
startPosition,
vehicle,
settings
settings,
islandPolygons
)
CourseGenerator.clearDebugObjects()
local field = CourseGenerator.Field('', 0, CpMathUtil.pointsFromGame(fieldPolygon))
Expand Down Expand Up @@ -54,8 +56,17 @@ function CourseGeneratorInterface.generate(fieldPolygon,
context:setIslandHeadlands(settings.nIslandHeadlands:getValue())
context:setIslandHeadlandClockwise(settings.islandHeadlandClockwise:getValue())
if settings.bypassIslands:getValue() then
context.field:findIslands()
context.field:setupIslands()
if islandPolygons then
-- islands were detected already, create them from the polygons and add to the field
for i, islandPolygon in ipairs(islandPolygons) do
context.field:addIsland(CourseGenerator.Island.createFromBoundary(i,
Polygon(CpMathUtil.pointsFromGame(islandPolygon))))
end
else
-- detect islands ourselves
context.field:findIslands()
context.field:setupIslands()
end
end

local status
Expand Down Expand Up @@ -197,7 +208,7 @@ function CourseGeneratorInterface.generateDefaultCourse()
vehicle:cpDetectFieldBoundary(x, z, nil, CourseGeneratorInterface.onFieldDetectionFinished)
end

function CourseGeneratorInterface.onFieldDetectionFinished(vehicle, fieldPolygon)
function CourseGeneratorInterface.onFieldDetectionFinished(vehicle, fieldPolygon, islandPolygons)
if fieldPolygon == nil then
CpUtil.infoVehicle(vehicle, "Not on a field, can't generate")
return
Expand All @@ -210,7 +221,7 @@ function CourseGeneratorInterface.onFieldDetectionFinished(vehicle, fieldPolygon
settings.sharpenCorners:setValue(true)
CpUtil.infoVehicle(vehicle, "Generating default course with %d headlands", settings.numberOfHeadlands:getValue())
local x, _, z = getWorldTranslation(vehicle.rootNode)
local ok, course = CourseGeneratorInterface.generate(fieldPolygon, {x = x, z = z}, vehicle, settings)
local ok, course = CourseGeneratorInterface.generate(fieldPolygon, {x = x, z = z}, vehicle, settings, islandPolygons)
if ok then
CourseGeneratorInterface.setCourse(vehicle, course)
end
Expand Down
5 changes: 5 additions & 0 deletions scripts/courseGenerator/Field.lua
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ function Field:getUnpackedVertices()
return self.unpackedVertices
end

---@param island CourseGenerator.Island
function Field:addIsland(island)
table.insert(self.islands, island)
end

-- Find islands (when running in the game)
function Field:findIslands()
if self.islandPoints == nil then
Expand Down
9 changes: 9 additions & 0 deletions scripts/courseGenerator/Island.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ function Island:init(id, perimeterPoints)
self:createFromPerimeterPoints(perimeterPoints)
end

---@param id number
---@param boundary Polygon
---@return CourseGenerator.Island
function Island.createFromBoundary(id, boundary)
local island = CourseGenerator.Island(id, {})
island.boundary = boundary
return island
end

function Island:getId()
return self.id
end
Expand Down
33 changes: 26 additions & 7 deletions scripts/field/FieldBoundaryDetector.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ function FieldBoundaryDetector:init(x, z, vehicle)
local fieldCourseSettings, implementData = FieldCourseSettings.generate(vehicle)
self.courseField = FieldCourseField.generateAtPosition(x, z, fieldCourseSettings, function(courseField, success)
if success then
self:info('Field boundary detection successful')
self:info('Field boundary detection successful, %d boundary points and %d islands',
#courseField.fieldRootBoundary.boundaryLine, #courseField.islands)
else
self:info('Field boundary detection failed')
end
Expand All @@ -43,14 +44,32 @@ function FieldBoundaryDetector:update(dt)
end
end

---@return table|nil [{x, y, z}] field polygon vertices
---@return table|nil [{x, y, z}] field polygon with game vertices
function FieldBoundaryDetector:getFieldPolygon()
local vertices = {}
if self.success then
for _, point in ipairs(self.result.fieldRootBoundary.boundaryLine) do
local x, z = point[1], point[2]
table.insert(vertices, { x = x, y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 1, z), z = z })
return self:getAsVertices(self.result.fieldRootBoundary.boundaryLine)
end
end

---@return table|nil [[{x, y, z}]] array of island polygons with game vertices (x, y, z)
function FieldBoundaryDetector:getIslandPolygons()
local islandPolygons = {}
if self.success then
for i, island in ipairs(self.result.islands) do
local islandBoundary = self:getAsVertices(island.rootBoundary.boundaryLine)
table.insert(islandPolygons, islandBoundary)
end
end
return islandPolygons
end

---@param boundaryLine table [[x, z]] array of arrays as the Giants functions return the field boundary
---@return table [{x, z}] array of vertices as the course generator needs it
function FieldBoundaryDetector:getAsVertices(boundaryLine)
local vertices = {}
for _, point in ipairs(boundaryLine) do
local x, z = point[1], point[2]
table.insert(vertices, { x = x, y = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, x, 1, z), z = z })
end
return vertices
end
end
26 changes: 18 additions & 8 deletions scripts/specializations/CpCourseGenerator.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ end

---@param x number world X coordinate to start the detection at
---@param z number world Z coordinate to start the detection at
---@param object table|nil optional object
---@param object table|nil optional object with callback
---@param onFinishedFunc function callback function to call when finished: onFinishedFunc([object,] fieldPolygon, islandPolygons)
function CpCourseGenerator:cpDetectFieldBoundary(x, z, object, onFinishedFunc)
local spec = self.spec_cpCourseGenerator
spec.fieldBoundaryDetector = FieldBoundaryDetector(x, z, self)
Expand All @@ -49,11 +50,12 @@ function CpCourseGenerator:onUpdate(dt)
if not spec.fieldBoundaryDetector:update(dt) then
-- done
spec.fieldPolygon = spec.fieldBoundaryDetector:getFieldPolygon()
spec.islandPolygons = spec.fieldBoundaryDetector:getIslandPolygons()
spec.fieldBoundaryDetector = nil
if spec.object then
spec.onFinishedFunc(spec.object, self, spec.fieldPolygon)
spec.onFinishedFunc(spec.object, self, spec.fieldPolygon, spec.islandPolygons)
else
spec.onFinishedFunc(self, spec.fieldPolygon)
spec.onFinishedFunc(self, spec.fieldPolygon, spec.islandPolygons)
end
end
end
Expand All @@ -63,14 +65,22 @@ function CpCourseGenerator:cpGetFieldPolygon()
return self.spec_cpCourseGenerator.fieldPolygon
end

-- For debug, if there is a field polygon, draw it
-- For debug, if there is a field polygon or island polygons, draw them
function CpCourseGenerator:cpDrawFieldPolygon()
local spec = self.spec_cpCourseGenerator
if spec.fieldPolygon then
for i = 2, #spec.fieldPolygon do
local p, n = spec.fieldPolygon[i - 1], spec.fieldPolygon[i]
local function drawPolygon(polygon)
for i = 2, #polygon do
local p, n = polygon[i - 1], polygon[i]
Utils.renderTextAtWorldPosition(p.x, p.y + 1.2, p.z, tostring(i - 1), getCorrectTextSize(0.012), 0)
DebugUtil.drawDebugLine(p.x, p.y + 1, p.z, n.x, n.y + 1, n.z, 0, 1, 0)
end
end
end
if spec.fieldPolygon then
drawPolygon(spec.fieldPolygon)
end
if spec.islandPolygons then
for _, p in ipairs(spec.islandPolygons) do
drawPolygon(p)
end
end
end

0 comments on commit 943ad7a

Please sign in to comment.