Files
galaxy-game/client/world/renderer_points.go
T
IliaDenisov e37a67bc99 cleanup
2026-03-08 10:15:34 +02:00

136 lines
3.5 KiB
Go

package world
import "math"
// drawPointsFromPlan keeps backward compatibility for older tests/helpers.
func drawPointsFromPlan(drawer PrimitiveDrawer, plan RenderPlan, allowWrap bool) {
// Default world sizes are unknown here, so this wrapper is no longer suitable for wrap-aware points.
// Keep it for historical call sites only if they pass through Render().
// Prefer calling drawPointsFromPlanWithRadius with world sizes.
drawPointsFromPlanWithRadius(drawer, plan, 0, 0, DefaultRenderStyle().PointRadiusPx, allowWrap)
}
// drawPointsFromPlanWithRadius executes a points-only draw from an already built render plan,
// using the provided screen-space radius. If worldW/worldH are zero, wrap copies are disabled.
func drawPointsFromPlanWithRadius(drawer PrimitiveDrawer, plan RenderPlan, worldW, worldH int, radiusPx float64, allowWrap bool) {
// Convert screen radius to world-fixed conservatively (ceil), so wrap copies are not missed.
rPxInt := int(math.Ceil(radiusPx))
if rPxInt < 0 {
rPxInt = 0
}
rWorldFp := 0
if rPxInt > 0 {
rWorldFp = PixelSpanToWorldFixed(rPxInt, plan.ZoomFp)
}
for _, td := range plan.Tiles {
if td.ClipW <= 0 || td.ClipH <= 0 {
continue
}
points := make([]Point, 0, len(td.Candidates))
for _, it := range td.Candidates {
p, ok := it.(Point)
if !ok {
continue
}
points = append(points, p)
}
if len(points) == 0 {
continue
}
type pointCopy struct {
p Point
dx int
dy int
}
copiesToDraw := make([]pointCopy, 0, len(points))
for _, p := range points {
var shifts []wrapShift
if allowWrap {
shifts = pointWrapShifts(p, rWorldFp, worldW, worldH)
} else {
shifts = []wrapShift{{dx: 0, dy: 0}}
}
for _, s := range shifts {
if pointCopyIntersectsTile(p, rWorldFp, s.dx, s.dy, td.Tile) {
copiesToDraw = append(copiesToDraw, pointCopy{p: p, dx: s.dx, dy: s.dy})
}
}
}
if len(copiesToDraw) == 0 {
continue
}
drawer.Save()
drawer.ClipRect(float64(td.ClipX), float64(td.ClipY), float64(td.ClipW), float64(td.ClipH))
for _, pc := range copiesToDraw {
p := pc.p
px := worldSpanFixedToCanvasPx((p.X+td.Tile.OffsetX+pc.dx)-plan.WorldRect.minX, plan.ZoomFp)
py := worldSpanFixedToCanvasPx((p.Y+td.Tile.OffsetY+pc.dy)-plan.WorldRect.minY, plan.ZoomFp)
drawer.AddPoint(float64(px), float64(py), radiusPx)
}
drawer.Fill()
drawer.Restore()
}
}
func pointWrapShifts(p Point, rWorldFp, worldW, worldH int) []wrapShift {
// If world sizes are unknown, do not generate wrap copies.
if worldW <= 0 || worldH <= 0 {
return []wrapShift{{dx: 0, dy: 0}}
}
xShifts := []int{0}
yShifts := []int{0}
if p.X+rWorldFp >= worldW {
xShifts = append(xShifts, -worldW)
}
if p.X-rWorldFp < 0 {
xShifts = append(xShifts, worldW)
}
if p.Y+rWorldFp >= worldH {
yShifts = append(yShifts, -worldH)
}
if p.Y-rWorldFp < 0 {
yShifts = append(yShifts, worldH)
}
out := make([]wrapShift, 0, len(xShifts)*len(yShifts))
for _, dx := range xShifts {
for _, dy := range yShifts {
out = append(out, wrapShift{dx: dx, dy: dy})
}
}
return out
}
func pointCopyIntersectsTile(p Point, rWorldFp, dx, dy int, tile WorldTile) bool {
segMinX := tile.OffsetX + tile.Rect.minX
segMaxX := tile.OffsetX + tile.Rect.maxX
segMinY := tile.OffsetY + tile.Rect.minY
segMaxY := tile.OffsetY + tile.Rect.maxY
px := p.X + tile.OffsetX + dx
py := p.Y + tile.OffsetY + dy
minX := px - rWorldFp
maxX := px + rWorldFp
minY := py - rWorldFp
maxY := py + rWorldFp
if maxX <= segMinX || minX >= segMaxX || maxY <= segMinY || minY >= segMaxY {
return false
}
return true
}