better shortcut detection, improves polygon test

This commit is contained in:
Ryan Oldenburg 2022-06-25 13:47:51 -05:00
parent 71766a16f4
commit 7225883aa9
2 changed files with 24 additions and 6 deletions

View file

@ -1,4 +1,4 @@
import chroma, common, system/memory, vmath
import bumpy, chroma, common, system/memory, vmath
const allowSimd* = not defined(pixieNoSimd) and not defined(tcc)
@ -51,6 +51,20 @@ proc `*`*(color: ColorRGBX, opacity: float32): ColorRGBX {.raises: [].} =
a = ((color.a * x) div 255).uint8
rgbx(r, g, b, a)
proc intersectsInside*(a, b: Segment, at: var Vec2): bool {.inline.} =
## Checks if the a segment intersects b segment (excluding endpoints).
## If it returns true, at will have point of intersection
let
s1 = a.to - a.at
s2 = b.to - b.at
denominator = (-s2.x * s1.y + s1.x * s2.y)
s = (-s1.y * (a.at.x - b.at.x) + s1.x * (a.at.y - b.at.y)) / denominator
t = (s2.x * (a.at.y - b.at.y) - s2.y * (a.at.x - b.at.x)) / denominator
if s > 0 and s < 1 and t > 0 and t < 1:
at = a.at + (t * s1)
return true
proc fillUnsafe*(
data: var seq[uint8], value: uint8, start, len: int
) {.inline, raises: [].} =

View file

@ -1205,7 +1205,7 @@ proc partitionSegments(
entry0 = partition.entries[0].segment
entry1 = partition.entries[1].segment
var at: Vec2
if not intersects(entry0, entry1, at):
if not intersectsInside(entry0, entry1, at):
# These two segments do not intersect, enable shortcut
partition.twoNonintersectingSpanningSegments = true
# Ensure entry[0] is on the left
@ -1916,7 +1916,7 @@ proc fillShapes(
if allEntriesInScanlineSpanIt and tmp == 2:
var at: Vec2
if not intersects(
if not intersectsInside(
partitions[partitionIndex].entries[entryIndices[0]].segment,
partitions[partitionIndex].entries[entryIndices[1]].segment,
at
@ -1925,9 +1925,13 @@ proc fillShapes(
var
left = partitions[partitionIndex].entries[entryIndices[0]]
right = partitions[partitionIndex].entries[entryIndices[1]]
# Ensure left is on the left
if left.segment.at.x > right.segment.at.x:
swap left, right
block:
# Ensure left is actually on the left
let
maybeLeftMaxX = max(left.segment.at.x, left.segment.to.x)
maybeRightMaxX = max(right.segment.at.x, right.segment.to.x)
if maybeLeftMaxX > maybeRightMaxX:
swap left, right
let requiresAntiAliasing =
left.segment.requiresAntiAliasing or