Adaptive Voxelizer

Some backstory

Adaptive Voxelizer is a module that I created some time ago for a project that never made it to fruition. That project was abandoned, and so was this module, until I found it in my files. I decided to publish it and save it from an untimely death.


JUST GIVE ME THE MODULE

Please, at least read the important notice below.


Adaptive Voxelizer is a voxelization module I created a while back. It does nothing but split any given part into smaller parts. I know, you’re thinking why I made yet another solution to something that already has several free solutions to be found on the DevForum alone. “What makes this unique,” you may ask. Valid point, and that’s where the “Adaptive” part of the name comes into play.

This module is designed to automatically calculate the best number of parts to divide the part given. You input the size, in studs, that you want the voxels to be. The module will then evenly break your part into the number of parts that will let each voxel’s size be as close as possible to the input size. That means, if you have a part 5 studs long and want to break it so that the voxel size is 2, the module will break that part in half so that each part is 2.5 studs. Do the same with a part 57.7 studs, and it will break into 28 parts that are 2.061 studs long each. When you have a part 1.75 studs, It will not break the part at all.

IMPORTANT NOTICE WHEN USING THIS

This module is incomplete. While it works to break parts, I abandoned the project this is from before I could code additional functionality. I advise against using this module out of the box. For any real in-game usage, you will likely have to add additional custom functionality.

I likely will not maintain this. If there is enough interest I might consider updating the module.


Source code because setting up a GitHub for this isn't worth it

The module:

-- AdaptiveVoxelizer
local Properties = require(script.PropertiesModule)

local VoxelSize = 4 -- Voxel size in studs

local AdaptiveVoxelizer = {}

function AdaptiveVoxelizer.VoxelizeBlock(part: Part, voxelSize: number?)
	if voxelSize then
		VoxelSize = voxelSize
	end
	
	local Properties = Properties.GetProperties(part)
	
	local SizeX = part.Size.X
	local SizeY = part.Size.Y
	local SizeZ = part.Size.Z
	
	local RotX = part.Size.X
	local RotY = part.Size.Y
	local RotZ = part.Size.Z
	
	local PartCF = part.CFrame
	
	-- Values that help with generating parts
	
	local PartsToGenerateX = math.clamp(math.floor(SizeX / VoxelSize), 1, math.huge)
	local PartsToGenerateY = math.clamp(math.floor(SizeY / VoxelSize), 1, math.huge)
	local PartsToGenerateZ = math.clamp(math.floor(SizeZ / VoxelSize), 1, math.huge)
	
	local PartSizeX = SizeX / PartsToGenerateX
	local PartSizeY = SizeY / PartsToGenerateY
	local PartSizeZ = SizeZ / PartsToGenerateZ
	
	local XCorner = -(SizeX / 2) + (PartSizeX / 2)
	local YCorner = -(SizeY / 2) + (PartSizeY / 2)
	local ZCorner = -(SizeZ / 2) + (PartSizeZ / 2)
	
	part:Destroy()
	
	local Parts = {}
	
	for x = 1, PartsToGenerateX do
		for y = 1, PartsToGenerateY do
			for z = 1, PartsToGenerateZ do
				local P = Instance.new("Part")
				
				for _, name in pairs(Properties) do
					if name ~= "Parent" then
						P[name] = part[name]
					end
				end
				
				P.Size = Vector3.new(
					PartSizeX,
					PartSizeY,
					PartSizeZ
				)
				
				local Offset = CFrame.new(
					XCorner + ((x - 1) * PartSizeX),
					YCorner + ((y - 1) * PartSizeY),
					ZCorner + ((z - 1) * PartSizeZ)
				)
				
				P.CFrame = PartCF:ToWorldSpace(Offset)
				P.Parent = workspace
				
				table.insert(Parts, P)
			end
		end
	end
	
	return Parts
end

return AdaptiveVoxelizer

The Properties+ module: loueque/Properties: Reads all properties of a standalone instance that are available to a developer, readonly, or public properties are also returned. (github.com)


API

function AdaptiveVoxelizer.VoxelizeBlock(part: Part, voxelSize: number?)

Voxelizes any block. Returns an index of all the parts generated. Part is the part that you want to voxelize. voxelSize is the size that voxels should try to be. If not provided, defaults to 4.


Thank you for taking the time to read this post. Have a great (insert what you call the time of day it is where you are).


Credits

loueque’s Properties+ module:

5 Likes

Yo, can you try to add hitboxes, and greedy meshing to it? ( nvm its been a long time since this was posted lol )

Hitboxes should work fine, I’m not quite sure what you mean. Greedy meshing is also outside the scope of what this was.

Also yes i still do care about my ancient projects so if you’re willing to get traction started on this post i’d be happy to come back to this :stuck_out_tongue: