draw optimizations

This commit is contained in:
IliaDenisov
2026-03-08 23:30:11 +02:00
parent fdcbb5d6f4
commit ac35360d60
18 changed files with 875 additions and 566 deletions
+68 -23
View File
@@ -73,40 +73,85 @@ type wrapShift struct {
dy int
}
// circleWrapShifts returns 1..4 wrap shifts (multiples of worldW/worldH) required to render
// all torus copies of the circle inside the canonical world domain.
// The (0,0) shift is always present.
func circleWrapShifts(cx, cy, radiusFp, worldW, worldH int) []wrapShift {
// If radius covers the whole axis, additional copies are not useful.
// (One copy already covers everything under any reasonable clip.)
if radiusFp >= worldW || radiusFp >= worldH {
return []wrapShift{{dx: 0, dy: 0}}
// circleWrapShiftsInto appends required torus-copy shifts for a circle into dst and returns the resulting slice.
// It never allocates if dst has enough capacity.
//
// The 0-shift is always included. Additional copies are included when the circle's bbox crosses world edges.
func circleWrapShiftsInto(dst []wrapShift, cx, cy, radiusFp, worldW, worldH int) []wrapShift {
dst = dst[:0]
// Always include the original.
dst = append(dst, wrapShift{dx: 0, dy: 0})
if radiusFp <= 0 {
return dst
}
xShifts := []int{0}
yShifts := []int{0}
minX := cx - radiusFp
maxX := cx + radiusFp
minY := cy - radiusFp
maxY := cy + radiusFp
if cx+radiusFp >= worldW {
xShifts = append(xShifts, -worldW)
needLeft := minX < 0
needRight := maxX > worldW
needTop := minY < 0
needBottom := maxY > worldH
// X-only copies.
if needLeft {
dst = append(dst, wrapShift{dx: +worldW, dy: 0})
}
if cx-radiusFp < 0 {
xShifts = append(xShifts, worldW)
if needRight {
dst = append(dst, wrapShift{dx: -worldW, dy: 0})
}
if cy+radiusFp >= worldH {
yShifts = append(yShifts, -worldH)
// Y-only copies.
if needTop {
dst = append(dst, wrapShift{dx: 0, dy: +worldH})
}
if cy-radiusFp < 0 {
yShifts = append(yShifts, worldH)
if needBottom {
dst = append(dst, wrapShift{dx: 0, dy: -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})
// Corner copies (combine X and Y).
if (needLeft || needRight) && (needTop || needBottom) {
var dxs [2]int
dxn := 0
if needLeft {
dxs[dxn] = +worldW
dxn++
}
if needRight {
dxs[dxn] = -worldW
dxn++
}
var dys [2]int
dyn := 0
if needTop {
dys[dyn] = +worldH
dyn++
}
if needBottom {
dys[dyn] = -worldH
dyn++
}
for i := 0; i < dxn; i++ {
for j := 0; j < dyn; j++ {
dst = append(dst, wrapShift{dx: dxs[i], dy: dys[j]})
}
}
}
return out
return dst
}
// circleWrapShifts is a compatibility wrapper that allocates.
// Prefer circleWrapShiftsInto in hot paths.
func circleWrapShifts(cx, cy, radiusFp, worldW, worldH int) []wrapShift {
var dst []wrapShift
return circleWrapShiftsInto(dst, cx, cy, radiusFp, worldW, worldH)
}
// circleCopyIntersectsTile checks whether the circle copy (shifted by dx/dy) intersects the tile segment.