Its a major work in progress atm, but for one I’ve almost completely removed the “flashing”
that is amazing ur doing the lord’s work rn
Yoooo, can you message me the file for this, I wanna try it out and maybe look through the code to see what changed.
How did you manage to eliminate the flashing? What’s different than before? And was this with or without partcache/objectcache btw, this seems really cool.
Ive completely rewritten the logic for the module, and its kind of alot to explain so ill spare you the details for now until its fully functional. And this uses object cache. And I would send you a file but there are some major bugs that im still trying to work out.
Woah, that looks so much smoother
Literally out here saving so much time for people
Just for clarification, is it supposed to be buttery smooth like jujtusu shenanigans at the moment (meaning its a problem with my script) or is the lag normal. For me at least the game freezez for about 5 seconds when voxelizing LARGE areas bur other than that its usually fine. So im just wondering if lag is expected when voxleizing large areas
Yeah, with larger parts lag is expected. For now I’d just recommend dividing larger parts into smaller ones to circumvent the lag. Even with the newer version im working on there is still some delay on the destruction with large parts
I’m curious, what behavior causes flashing
I meet 2 situation of “Flash”
First 1 is some part flashing
Second 1 is global flashing which the whole part disapper
local function ClonePart(block)
local clone
if PartCacheEnabled then
clone = cache:GetPart()
CopyProperties(block, clone)
else
clone = block:Clone()
end
return clone
end
local function CreateClones(block, offsetVectors, halfSize, Parent, model, partTable)
for _, offsetVector in pairs(offsetVectors) do
local clone = ClonePart(block)
clone:SetAttribute("Voxel", true)
if ReplicatedStorage.DebuggingMode.Value then
clone.Color = Color3.fromRGB(math.random(1, 255), math.random(1, 255), math.random(1, 255))
end
clone.Parent = Parent or model
clone.Size = halfSize
clone.CFrame += block.CFrame:VectorToWorldSpace((halfSize / 2.0) * offsetVector)
table.insert(partTable, clone)
end
end
local function DivideBlock(block : Part, MinimumVoxelSize : number, Parent : Instance, TimeToReset : number)
local partTable = {}
local minimum = MinimumVoxelSize or miniumCubeSize
if block.Size.X > minimum or block.Size.Y > minimum or block.Size.Z > minimum then
if partCanSubdivide(block) then
partTable = CutPartinHalf(block, TimeToReset)
else
local model = block.Parent and block.Parent:IsA("Model") and block.Parent:GetAttribute("VoxelHolder") and block.Parent or Instance.new("Model")
if not model.Parent then
model.Name = "VoxelHolder"
model.Parent = voxelFolder
model:SetAttribute("VoxelHolder", true)
end
if TimeToReset and TimeToReset >= 0 then
Destroy(model, TimeToReset)
end
local Threshold = 1.5
local largest = math.max(block.Size.X, block.Size.Y, block.Size.Z)
local smallest = math.min(block.Size.X, block.Size.Y, block.Size.Z)
if smallest == block.Size.Y and smallest * Threshold <= largest then
local offsetVectors = {
Vector3.new(-1, 0, 1), Vector3.new(1, 0, -1),
Vector3.new(1, 0, 1), Vector3.new(-1, 0, -1)
}
local halfSize = Vector3.new(block.Size.X / 2, block.Size.Y, block.Size.Z / 2)
CreateClones(block, offsetVectors, halfSize, Parent, model, partTable)
elseif smallest == block.Size.X and smallest * Threshold <= largest then
local offsetVectors = {
Vector3.new(0, -1, 1), Vector3.new(0, 1, 1),
Vector3.new(0, -1, -1), Vector3.new(0, 1, -1)
}
local halfSize = Vector3.new(block.Size.X, block.Size.Y / 2, block.Size.Z / 2)
CreateClones(block, offsetVectors, halfSize, Parent, model, partTable)
elseif smallest == block.Size.Z and smallest * Threshold <= largest then
local offsetVectors = {
Vector3.new(1, -1, 0), Vector3.new(1, 1, 0),
Vector3.new(-1, -1, 0), Vector3.new(-1, 1, 0)
}
local halfSize = Vector3.new(block.Size.X / 2, block.Size.Y / 2, block.Size.Z)
CreateClones(block, offsetVectors, halfSize, Parent, model, partTable)
else
local offsetVectors = {
Vector3.new(1, 1, 1), Vector3.new(1, 1, -1),
Vector3.new(1, -1, 1), Vector3.new(1, -1, -1),
Vector3.new(-1, 1, 1), Vector3.new(-1, 1, -1),
Vector3.new(-1, -1, 1), Vector3.new(-1, -1, -1)
}
local halfSize = block.Size / 2.0
CreateClones(block, offsetVectors, halfSize, Parent, model, partTable)
end
if block.Parent and block.Parent:IsA("Model") and block.Parent:GetAttribute("VoxelHolder") then
if PartCacheEnabled then
for _, v in pairs(block:GetChildren()) do
v:Destroy()
end
for name in pairs(block:GetAttributes()) do
block:SetAttribute(name, nil)
end
cache:ReturnPart(block)
block.Parent = PartFolder
else
block:Destroy()
end
else
if not block:GetAttribute("Transparency") then
block:SetAttribute("Transparency", block.Transparency)
block:SetAttribute("Collide", block.CanCollide)
block:SetAttribute("Query", block.CanQuery)
end
block.Transparency = 1
block.CanCollide = false
block.CanQuery = false
block:SetAttribute(TagName, false)
for _, v in block:GetChildren() do
task.spawn(function()
if v:IsA("SurfaceGui") then
local enabled = v.Enabled
v.Enabled = false
repeat rs.Heartbeat:Wait() until model:HasTag("Destroying")
v.Enabled = enabled
elseif v:IsA("Decal") or v:IsA("Texture") then
local transparency = v.Transparency
v.Transparency = 1
repeat rs.Heartbeat:Wait() until model:HasTag("Destroying")
v.Transparency = transparency
end
end)
end
task.spawn(function()
if TimeToReset >= 0 then
repeat rs.Heartbeat:Wait() until model:HasTag("Destroying")
if block:GetAttribute("Transparency") then
block.Transparency = block:GetAttribute("Transparency")
end
if block:GetAttribute("CanQuery") then
block.CanQuery = block:GetAttribute("Query")
end
if block:GetAttribute("Collide") then
block.CanCollide = block:GetAttribute("Collide")
end
block:SetAttribute(TagName, true)
end
end)
end
end
elseif not block.Parent:GetAttribute("VoxelHolder") and not block:GetAttribute("Voxel") then
if block:GetAttribute("Transparency") then
block.Transparency = block:GetAttribute("Transparency")
end
if block:GetAttribute("CanQuery") then
block.CanQuery = block:GetAttribute("Query")
end
if block:GetAttribute("Collide") then
block.CanCollide = block:GetAttribute("Collide")
end
local clone = ClonePart(block)
clone.Parent = block.Parent
if TimeToReset and TimeToReset >= 0 then
Destroy(clone, TimeToReset)
end
block.Transparency = 1
block.CanCollide = false
block.CanQuery = false
block:SetAttribute(TagName, false)
for _, v in block:GetChildren() do
task.spawn(function()
if v:IsA("SurfaceGui") then
local enabled = v.Enabled
v.Enabled = false
task.wait(TimeToReset)
v.Enabled = enabled
elseif v:IsA("Decal") or v:IsA("Texture") then
local transparency = v.Transparency
v.Transparency = 1
task.wait(TimeToReset)
v.Transparency = transparency
end
end)
end
task.spawn(function()
task.wait(TimeToReset)
if block:GetAttribute("Transparency") then
block.Transparency = block:GetAttribute("Transparency")
end
if block:GetAttribute("CanQuery") then
block.CanQuery = block:GetAttribute("Query")
end
if block:GetAttribute("Collide") then
block.CanCollide = block:GetAttribute("Collide")
end
block:SetAttribute(TagName, true)
end)
end
return partTable
end
oh and by the way fix that everything is just flinging you when you use part cache for some reason
When we want to make parts come out of the destruction like jujtusu shenanigans, are we supposed to make new part instances or does the module already have a system that does that?
What do you mean? Either of the hitbox constructors return touching voxels, which you can reference for whatever
So with those returned parts, do i need to clone them and parent them to workspace?
You can do whatever you want with them. If you want to do some heavy physics calculations then yes id recommend cloning the parts on the client and destroying the original ones.
Is the VoxBreaker rework going well?
Its mostly done I’ve just had some complications with other projects which have been taking up my time. As well as one major bug which I’ve been struggling to work out.
how to fix that voxel size is relative to walls size…
You can see that voxels are longer in one direction and thinner in another…
I want them to be cubic.
Alright so bit of an update, I’m sharing the current state of this new version here:
VoxBreaker 2.0.rbxm (24.3 KB)
I’m not heavily announcing this massive new update yet, as the current version I just sent, is heavily bugged. Though a vast improvement from the previous version of the module. I revamped essentially everything, and It is much more readable and performant.
The main thing that changed was the logic, in that now parts are no longer cloned, but I am instead creating a table of part information that is divided. Essentially, before, the module was repeatedly dividing and cloning parts in a single instant. Now, the module is just repeatedly dividing a table of part information. Since there is no instancing in this process, the performance is heavily increased. This idea was suggested by @527366
Additionally, the module now uses object cache instead of part cache. I made the move due to numerous people suggesting it, as well as object cache generally having better results visually.
And of course, the thing that I’ve been teasing at for a long while, the new algorithm is also here. This new version has support for both the original algorithm, Octrees, and the new algorithm, which I couldn’t really find a name for, but it was sourced from Voxel Destruct
Performance wise, I’m not exactly sure how much more performant this new algorithm is, but it does have major differences visually. The biggest of which is that this algorithm produces perfectly cubic voxels, which is a concern I have received from several people now.
There is one new method, ReturnPart() which allows you to return parts to the cache outside of the module. Use this instead of destroying the voxels.
When you open the module, you may notice a greedy mesher in there, but the module does not currently have greedy meshing capabilities. I haven’t had the time to make a greedy meshing function that works, but I have found a way to implement greedy meshing without there being major loads on performance.
And something else I shared previously, was the improvements to part resetting. The logic for part resetting has been rewritten completely, and is now almost perfectly seemless.
Also, the module now uses tags instead of attributes.
Overall, performance wise, this is a massive improvement to the previous version. But like I said, there are 2 major bugs, and several features I have yet to add which are already in the previous version of the module. The first of these bugs is that chunks of parts are not getting created, leaving holes between voxels. The second is that moveable hitboxes are not detecting some voxels. Both of these are 100% logic errors, I’ve just been struggling to figure them out.
And then this new version is missing key features, such as textures being cloned onto voxels, and setting reset times below zero, which would normally prevent voxels from resetting entirely.
The reason why I’m releasing this entirely unfinished version is due to a lack of time for me to work on this module. I am currently balancing several projects with college, and I have had very little time to work on this module. I have also had a lot of trouble in figuring out the current bugs, and so instead of agonizing over fixing them, I’ve decided to just release it in it’s current state since I know some of you have been waiting quite a while for this.
The complete version of this may take a long while to be fully completed due to how little time I have, and given how unfinished it is, I am only sharing this here. The github, marketplace model, and test place have not been updated, and you can still get the previous version of the module in any of those places.