Why are there these line shaped holes in my raycasting model pixelator?

I have found a temporary solution. I have solved this issue by casting 5 rays that each have different offsets to make sure that they don’t miss an area while scanning the model. And you no longer get holes!

Here are some results:

--== SETTINGS ==--

local ModelToPixelate = workspace:WaitForChild("Model") -- The model to pixelate

local ScanningSize = 150 -- The area to scan in all 3 axis

local ScanDistance = 500 -- How far the scanning ray is casted 

local KeepMaterials = true -- Use the same materials that the model has

local KeepTransparency = true -- Use the same transparent areas that the model has

local DebugMode = true -- Show the scanning ray's Origin position


--== FUNCTIONS ==--

local BlockCount = 0
local BlockSize = 1
local DebugBrick1

local ModelMover = require(script:WaitForChild("ModelMover"))

local function round(n)
	return math.ceil(n - 0.5)
end

local PixelsGroup = Instance.new("Model")
PixelsGroup.Name = "Pixelated " .. ModelToPixelate.Name
PixelsGroup.Parent = ModelToPixelate

function CreateBlock(PartColour, PartMaterial, PartPosition, PartTransparency)
	print("Created block" .. BlockCount)
	local Block = Instance.new("Part")
	Block.Name = "PixelBlock"
	Block.Anchored = true
	Block.Size = Vector3.new(BlockSize, BlockSize, BlockSize)
	Block.TopSurface = Enum.SurfaceType.Smooth
	Block.BottomSurface = Enum.SurfaceType.Smooth
	Block.Color = PartColour
	Block.Position = Vector3.new(round(PartPosition.X), round(PartPosition.Y), round(PartPosition.Z))
	if PartMaterial and KeepMaterials then
		Block.Material = PartMaterial
	else
		Block.Material = Enum.Material.SmoothPlastic
	end
	if PartTransparency and KeepTransparency then
		Block.Transparency = PartTransparency
	end
	Block.Parent = PixelsGroup
	BlockCount = BlockCount + 1
	return Block
end

function ScanFaceAndPixelate(Origin, Direction)
	
	--print("ORIGIN")
	--print(Origin)
	--print("DIRECTION")
	--print(Direction)
	
	if DebugBrick1 then
		DebugBrick1.Position = Origin
	end
	
	local Params = RaycastParams.new()
	Params.FilterType = Enum.RaycastFilterType.Whitelist
	Params.FilterDescendantsInstances = {ModelToPixelate}
	
	local function CastRay(OffsetX, OffsetZ)
		local ScanRay = workspace:Raycast(Origin + Vector3.new(OffsetX, 0, OffsetZ), Direction + Vector3.new(OffsetX, 0, OffsetZ), Params)
		if ScanRay then
			local Hit = ScanRay.Instance
			if Hit and Hit:IsA("BasePart") and Hit.Name ~= "PixelBlock" then
				--print("RAY HIT POS")
				--print(ScanRay.Position)
				CreateBlock(Hit.Color, Hit.Material, ScanRay.Position)
			end
		end
	end
	
	CastRay(0, 0)
	CastRay(0.25, 0.25)
	CastRay(0.5, 0.5)
	CastRay(-0.5, -0.5)
	CastRay(-0.25, -0.25)
	
end


--== MAIN ==--

if ModelToPixelate and ModelToPixelate.PrimaryPart then
	
	local OriginalModelToPixelateCFrame = ModelToPixelate:GetPrimaryPartCFrame()

	local CurrentPos = Vector3.new(ScanningSize / 2, ScanningSize / 2, ScanningSize / 2)

	if DebugMode then
		DebugBrick1 = CreateBlock(Color3.fromRGB(255, 0, 0), nil, CurrentPos)
		DebugBrick1.Shape = Enum.PartType.Ball
		DebugBrick1.Name = "DebugPart"
		DebugBrick1.Parent = workspace
		DebugBrick1.Transparency = 0.5
		DebugBrick1.CanCollide = false
	end


	-- Begin pixelating the model


	function ScanModel()
		local CurrentPos = Vector3.new(ScanningSize / 2, ScanningSize / 2, ScanningSize / 2)
		for index = 1, ScanningSize do
			wait()
			for index = 1, ScanningSize do
				--print(CurrentPos)
				CurrentPos = CurrentPos - Vector3.new(BlockSize, 0, 0)
				ScanFaceAndPixelate(CurrentPos, CurrentPos - Vector3.new(0, ScanDistance, 0))
			end
			CurrentPos = Vector3.new(ScanningSize / 2, ScanningSize / 2, CurrentPos.Z) - Vector3.new(0, 0, BlockSize)
		end
	end
	
	print("Scanning side 1 out of 6 | Front")
	ModelToPixelate:SetPrimaryPartCFrame(CFrame.Angles(0, 0, 0))
	--local cframes = ModelMover.GetCFrameTable(ModelToPixelate)
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, CFrame.Angles(math.rad(0), math.rad(0), math.rad(0)), cframes)
	ScanModel()
	
	print("Scanning side 2 out of 6 | Right")
	ModelToPixelate:SetPrimaryPartCFrame(CFrame.Angles(math.rad(90), 0, 0))
	--cframes = ModelMover.GetCFrameTable(ModelToPixelate)
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, CFrame.Angles(math.rad(90), math.rad(0), math.rad(0)), cframes)
	ScanModel()
	
	print("Scanning side 3 out of 6 | Back")
	ModelToPixelate:SetPrimaryPartCFrame(CFrame.Angles(math.rad(180), 0, 0))
	--cframes = ModelMover.GetCFrameTable(ModelToPixelate)
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, CFrame.Angles(math.rad(180), math.rad(0), math.rad(0)), cframes)
	ScanModel()
	
	print("Scanning side 4 out of 6 | Left")
	ModelToPixelate:SetPrimaryPartCFrame(CFrame.Angles(math.rad(270), 0, 0))
	--cframes = ModelMover.GetCFrameTable(ModelToPixelate)
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, CFrame.Angles(math.rad(270), math.rad(0), math.rad(0)), cframes)
	ScanModel()
	
	print("Scanning side 5 out of 6 | Top")
	ModelToPixelate:SetPrimaryPartCFrame(CFrame.Angles(0, 0, math.rad(90)))
	--cframes = ModelMover.GetCFrameTable(ModelToPixelate)
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, CFrame.Angles(math.rad(0), math.rad(0), math.rad(90)), cframes)
	ScanModel()
	
	print("Scanning side 6 out of 6 | Bottom")
	ModelToPixelate:SetPrimaryPartCFrame(CFrame.Angles(0, 0, math.rad(270)))
	--cframes = ModelMover.GetCFrameTable(ModelToPixelate)
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, CFrame.Angles(math.rad(0), math.rad(0), math.rad(270)), cframes)
	ScanModel()
	
	--ModelMover.SetPrimaryPartCFrame(ModelToPixelate, OriginalModelToPixelateCFrame, cframes)
	ModelToPixelate:SetPrimaryPartCFrame(OriginalModelToPixelateCFrame)
	
	if DebugBrick1 then
		DebugBrick1:Destroy()
	end
	
	PixelsGroup.Parent = workspace
	
	print(ModelToPixelate.Name .. " has been successfully pixelated! | " ..  BlockCount .. " parts created")
else
	error("ModelToPixelate is nil or ModelToPixelate has no set PrimaryPart")
end