draw optimizations
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user