Weird window cutout thing I'm not sure how to fix

Hello!

I’m working on this wall system, however I have run into an issue where the wall extends if the window/doorframe is half off of the wall:

How do I fix this?

Thing that constructs the new wall:

    local function makeCutout(wallPart: BasePart, window: Model)
		local boundingBox = window.PrimaryPart :: BasePart

		local windowRelativeToWall = wallPart.Parent.WorldPivot:PointToObjectSpace(boundingBox.Position)
		local wallPartRelativeToWall = wallPart.Parent.WorldPivot:PointToObjectSpace(wallPart.Position)

		local windowTop = windowRelativeToWall.Y + (boundingBox.Size.Y / 2)
		local wallPartTop = wallPart.Size.Y / 2
		if windowTop < wallPartTop then
			local topSize = wallPartTop - windowTop
			local topPart = wallPart:Clone()
			local newPart = Instance.new('BoolValue')
			newPart.Parent = topPart
			newPart.Name = 'NewPart'
			newPart.Value = true
			
			collectionService:AddTag(topPart, 'WallPart')
			
			topPart.Name = 'WallPart'
			topPart.Parent = wallPart.Parent
			topPart.Transparency = 0
			topPart.Size = Vector3.new(boundingBox.Size.X, topSize, topPart.Size.Z)
			topPart.Position = wallPart.Parent.WorldPivot:PointToWorldSpace(
				Vector3.new(windowRelativeToWall.X,
					windowTop + topSize / 2,
					wallPartRelativeToWall.Z
				)
			)
		end
		local windowLeft = windowRelativeToWall.X - boundingBox.Size.X / 2
		local wallLeft = wallPartRelativeToWall.X - wallPart.Size.X / 2
		if windowLeft > wallLeft then
			local leftPart = wallPart:Clone()
			leftPart.Transparency = 0
			local leftSize = windowLeft - wallLeft
			local newPart = Instance.new('BoolValue')
			newPart.Parent = leftPart
			newPart.Value = true
			newPart.Name = 'NewPart'
			
			collectionService:AddTag(leftPart, 'WallPart')
			
			leftPart.Name = 'WallPart'
			leftPart.Parent = wallPart.Parent
			leftPart.Size = Vector3.new(leftSize, leftPart.Size.Y, leftPart.Size.Z)
			leftPart.Position = wallPart.Parent.WorldPivot:PointToWorldSpace(
				Vector3.new(
					windowLeft - leftSize / 2,
					wallPartRelativeToWall.Y,
					wallPartRelativeToWall.Z
				)
			)
		end
		local windowRight = windowRelativeToWall.X + boundingBox.Size.X / 2
		local wallRight = wallPartRelativeToWall.X + wallPart.Size.X / 2
		if windowRight < wallRight then
			local rightPart = wallPart:Clone()
			rightPart.Transparency = 0
			local rightSize = wallRight - windowRight
			local newPart = Instance.new('BoolValue')
			newPart.Parent = rightPart
			newPart.Value = true
			newPart.Name = 'NewPart'
			
			collectionService:AddTag(rightPart, 'WallPart')
			
			rightPart.Name = 'WallPart'
			rightPart.Parent = wallPart.Parent
			rightPart.Size = Vector3.new(rightSize, rightPart.Size.Y, rightPart.Size.Z)
			rightPart.Position = wallPart.Parent.WorldPivot:PointToWorldSpace(
				Vector3.new(
					windowRight + rightSize / 2,
					wallPartRelativeToWall.Y,
					wallPartRelativeToWall.Z
				)
			)
		end
		if wallPart.Name == 'WallPart' then
			wallPart:Destroy()
		end
	end

Got it done!

Basically, check if the leftmost part of the window is further left than the leftmost part of the wall, find the distance between these 2 points and then make a part that’s at the rightmost point of the wall, then subtract half of the distance between the first 2 points. Repeat but inverse for the rightmost part.

Here’s what I did:

			if topPartLeft < wallLeft then
				-- left
				topSizeX += topPartLeft - wallLeft
				xAxis += boundingBox.Size.X / 2
				xAxis -= topSizeX / 2
			elseif topPartRight > wallRight then
				-- right
				topSizeX += wallRight - topPartRight
				print(topSizeX)
				xAxis -= boundingBox.Size.X / 2
				xAxis += topSizeX / 2
			end

How do you manage to render the cutout so quick and smoothly? Back when I was messing with build systems I tried using SubtractAsync, which worked but was very delayed.

:SubtractAsync is quite slow. I’m using a cutout method which calculates the left, top, bottom (later, haven’t gotten to it but it’s more or less the same as top) and right. I can go more indepth if you want, let me know.

Yes please do. I don’t have any use for it atm but I am very curious as I lost a lot of brain cells trying to do it earlier with SubtractAsync.

Alright, here’s my methodology:

First off, basic information on how the wall works:
1- Wall is comprised of 2 parts: left and right
2- Wall has a folder called “Windows” which also takes into account doors
3- The cutout handler is an object called WallController (basic OOP) which is adorned to the wall and looks for changes of the children of the window folder.

Alright, now how the cutout works:
First, find the wall part and the window’s position relative to the wall’s bounding box.
Also note that I’m making the assumption that you know how object and world spaces work.

Also note that “Wall” is the wall’s bounding box, “wallPart” is the part of the wall (note how I said the wall was comprised of 2 parts), and “boundingBox” is the window’s bounding box.

        local windowRelativeToWall = wallPart.Parent.PrimaryPart.CFrame:PointToObjectSpace(boundingBox.Position)
		local wallPartRelativeToWall = wallPart.Parent.PrimaryPart.CFrame:PointToObjectSpace(wallPart.Position)

Next, find the topmost, leftmost, rightmost, and bottommost (not shown here but would be the inverse of the topmost) part of the wallPart and of the window

Also note that when I say “left”, I mean negative X, when I say “top”, I mean positive Y, and when I say “right”, I mean positive X

windowTop is the topmost face of the window’s bounding box and wallPartTop is the topmost face of the wallPart

        local windowTop = windowRelativeToWall.Y + (boundingBox.Size.Y / 2)
		local wallPartTop = wallPart.Size.Y / 2
		local windowLeft = windowRelativeToWall.X - boundingBox.Size.X / 2
		local wallLeft = wallPartRelativeToWall.X - wallPart.Size.X / 2
		local windowRight = windowRelativeToWall.X + boundingBox.Size.X / 2
		local wallRight = wallPartRelativeToWall.X + wallPart.Size.X / 2

Now, to calculate the leftmost part, find the difference between the window’s leftmost face’s position and the wallPart’s leftmost face’s position and ensure that the leftmost face of the window isn’t further left than the wallPart’s leftmost face which is why we compare here:

if windowLeft > wallLeft then

If the window’s leftmost face is further left than the wallPart’s leftmost face then ignore it, otherwise, create the new part:

			local leftPart = wallPart:Clone()
			leftPart.Transparency = 0 -- sometimes my parts are transparent and other times they aren't so this just ensures that the cloned part is not transparent

Now, find the distance between the window’s leftmost face and the wallPart’s leftmost face:

			local leftSize = windowLeft - wallLeft

Next, let’s calculate its size. This is pretty self explanatory. It will never be taller or shorter than itself so,

			leftPart.Size = Vector3.new(leftSize, leftPart.Size.Y, leftPart.Size.Z)

Next, let’s find its position.

We will take the window’s position and translate it to the world space assuming the wall’s bounding box is the 0,0,0 local to the wallPart’s world position

Next, the window will be the window’s leftmost face’s position and then even further left by half of its size on the X axis, the other 2 axes are the same:

			leftPart.Position = wallPart.Parent.PrimaryPart.CFrame:PointToWorldSpace(
				Vector3.new(
					windowLeft - leftSize / 2,
					wallPartRelativeToWall.Y,
					wallPartRelativeToWall.Z
				)
			)

The right is the exact same as the left but it uses the opposite operators (replace - with +)

Now, for the top, we have to check that the window’s top part isn’t higher than the wall’s topmost part, otherwise ignore it:

if windowTop < wallPartTop then

Next, calculate its size by subtracting the window’s top face from the wallPart’s top face:

local topSize = wallPartTop - windowTop

Next, we have to check if the window’s left face is further left than the leftmost part of the wall, as well as the rightmost part:

            local topPartLeft = windowRelativeToWall.X - boundingBox.Size.X / 2
			local topPartRight = windowRelativeToWall.X + boundingBox.Size.X / 2

Next, we have to create a temporary “anchor” which is essentially the window’s top face’s position:

			local topSizeX = boundingBox.Size.X
			local xAxis = windowRelativeToWall.X

Now, to do the actual left and right calculations:

First’ let’s check if the window’s leftmost face is further left than the wall’s leftmost face:

            if topPartLeft < wallLeft then

Since it’s further left, let’s find the distance between the window’s leftmost face and the wallPart’s leftmost face, this will give us the distance between the end of the wall and the window’s rightmost face

				topSizeX += topPartLeft - wallLeft

Next, let’s adjust the position by creating a sort of anchor on the wall’s rightmost face

				xAxis += boundingBox.Size.X / 2

Finally, let’s offset it by half of the top part’s size on the X axis:

				xAxis -= topSizeX / 2

Calculating if it’s further right than the rightmost face is the exact same, just switch operators again:

			elseif topPartRight > wallRight then
				-- right
				topSizeX += wallRight - topPartRight
				xAxis -= boundingBox.Size.X / 2
				xAxis += topSizeX / 2
			end

Finally, let’s create the part’s top part based on our adjusted size and position:

			topPart.Size = Vector3.new(
				topSizeX,
				topSize,
				topPart.Size.Z
			)
			topPart.Position = wallPart.Parent.PrimaryPart.CFrame:PointToWorldSpace(
				Vector3.new(
					xAxis,
					windowTop + topSize / 2,
					wallPartRelativeToWall.Z
				)
			)

Calculating the bottom would be the same as calculating the top but switch the operators (switch + and -, don’t switch * and /)

And yeah, that’s about it.

Hi, I know this topic is 4 months old but I was wondering if you could help me make this system work for more than 1 window at a time with it still running smoothly?
Thanks