From ed7fe542ec149a13f9b869afdd4f607698f7e54c Mon Sep 17 00:00:00 2001 From: Jennifer Taylor Date: Thu, 5 Aug 2021 17:33:30 +0000 Subject: [PATCH] Fix clipping calculations when textures come through the camera. --- bemani/format/afp/blend/perspective.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/bemani/format/afp/blend/perspective.py b/bemani/format/afp/blend/perspective.py index a0aef33..a2fc16b 100644 --- a/bemani/format/afp/blend/perspective.py +++ b/bemani/format/afp/blend/perspective.py @@ -19,6 +19,8 @@ def perspective_calculate( # v/Z since those ARE linear, and work backwards from there. xy: List[Point] = [] uvz: Dict[Point, Point] = {} + minz: Optional[float] = None + maxz: Optional[float] = None for (texx, texy) in [ (0, 0), (texwidth, 0), @@ -32,6 +34,15 @@ def perspective_calculate( imgx = ((imgloc.x - camera.x) * (focal_length / distance)) + camera.x imgy = ((imgloc.y - camera.y) * (focal_length / distance)) + camera.y + if minz is None: + minz = distance + else: + minz = min(distance, minz) + if maxz is None: + maxz = distance + else: + maxz = max(distance, maxz) + xy_point = Point(imgx, imgy) xy.append(xy_point) uvz[xy_point] = Point( @@ -46,10 +57,20 @@ def perspective_calculate( miny = max(int(min(p.y for p in xy)), 0) maxy = min(int(max(p.y for p in xy)) + 1, imgheight) - if maxx <= minx or maxy <= miny: - # This image is entirely off the screen! + if minz is None or maxz is None: + raise Exception("Logic error!") + + if minx <= 0.0 and maxz <= 0.0: + # This is entirely behind the camera, clip it. return (None, minx, miny, maxx, maxy) + if minz < 0 and maxz > 0: + # This clips through the camera, default to drawing the whole image. + minx = 0 + maxx = imgwidth + miny = 0 + maxy = imgheight + # Now that we have three points, construct a matrix that allows us to calculate # what amount of each u/z, v/z and 1/z vector we need to interpolate values. The # below matrix gives us an affine transform that will convert a point that's in