Triangle 3d Perlin (Help)

Hi, I’m doing a project to create a cave with 3D perlin matrix and triangulated terrain.
But my script doesn’t work properly, it only works on 3D noise but I don’t know how to make one part fit to the other parts.

My code :

local X, Y, Z = 15, 10, 15  -- Grid size (terrain resolution)
local scale = 0.3  -- Noise scale (affects terrain variation)
local heightMultiplier = 25  -- Max terrain height
local caveThreshold = 0.03  -- Lower values create more caves
local cellSize = 5  -- Distance between grid points

-- Function to create a wedge part
local function createWedge()
	local wedge = Instance.new("WedgePart")
	wedge.Anchored = true
	wedge.Material = Enum.Material.Rock
	wedge.TopSurface = Enum.SurfaceType.Smooth
	wedge.BottomSurface = Enum.SurfaceType.Smooth
	return wedge
end

-- Function to draw a triangle using two wedges
local function drawTriangle(a, b, c)
	if not a or not b or not c then return end

	-- Compute edge vectors and normal
	local ab, ac, bc = b - a, c - a, c - b
	local normal = ab:Cross(ac).unit

	-- Prevent flat terrain errors
	if math.abs(normal:Dot(Vector3.new(0, 1, 0))) > 0.99 then return end 

	local center = (a + b + c) / 3  -- Triangle center
	local size1 = Vector3.new(0, (b - a).magnitude, (c - a).magnitude)
	local size2 = Vector3.new(0, (c - b).magnitude, (a - b).magnitude)

	-- Create and position the wedges correctly
	local w1, w2 = createWedge(), createWedge()
	w1.Size, w2.Size = size1, size2
	w1.CFrame = CFrame.lookAt((a + b) / 2, c) * CFrame.Angles(math.pi / 2, 0, 0)
	w2.CFrame = CFrame.lookAt((a + c) / 2, b) * CFrame.Angles(math.pi / 2, 0, 0)

	w1.Parent, w2.Parent = workspace, workspace
end

-- Store terrain data
local terrainGrid = {}

for x = 0, X do
	terrainGrid[x] = {}

	for y = 0, Y do
		terrainGrid[x][y] = {}

		for z = 0, Z do
			local noiseValue = math.noise(x * scale, y * scale, z * scale)

			-- Solid terrain if above threshold, else it's a cave
			if noiseValue > caveThreshold then
				terrainGrid[x][y][z] = Vector3.new(x * cellSize, y * cellSize, z * cellSize)
			else
				terrainGrid[x][y][z] = nil
			end
		end
	end
end

-- Generate terrain using triangles
for x = 0, X - 1 do
	for y = 0, Y - 1 do
		for z = 0, Z - 1 do
			local a = terrainGrid[x][y][z]
			local b = terrainGrid[x + 1][y][z]
			local c = terrainGrid[x][y + 1][z]
			local d = terrainGrid[x][y][z + 1]

			-- Connect terrain using triangular faces
			if a and b and c then drawTriangle(a, b, c) end
			if a and c and d then drawTriangle(a, c, d) end
		end
	end
end

My code generate :

I wanted :
image

PLS HELP !!! thx.

1 Like

It seems to resemble a cave, so you’re doing well, however, definitely don’t use wedge parts if you intend to draw mesh tris. (Wedge parts are extruded rectangular triangles, not tris) Try looking into EditableMeshes, and if you don’t want to get into that, try using Roblox’s default terrain system or if you still want it to look “custom” try creating basic cubes or balls or something where the mesh is instead of wedges.

2 Likes

can you help me with EditableMesh , i kinda dumb :>

local as = game:GetService("AssetService")

local mesh = as:CreateEditableMesh() -- Create a mesh

local mytrianglepoints = {} -- Define an array
mytrianglepoints[1] = p:AddVertex(Vector3.new(-1,0,0)) -- Add some points
mytrianglepoints[2] = p:AddVertex(Vector3.new(1,0,0))
mytrianglepoints[3] = p:AddVertex(Vector3.new(0,1,0))

mesh:AddTriangle(mytrianglepoints[1], mytrianglepoints[2], mytrianglepoints[3]) -- Draw a triangle

local part = as:CreateMeshPartAsync(Content.fromObject(mesh)) -- Associate a part with the mesh. Note: this needs to be done after the mesh is generated, or else it gives an error
part.Parent = game.Workspace
part.Anchored = true

-- I think you need to do something else to recalculate the collision, but I'm not sure what
2 Likes

CreateMeshPartAsync does update the collision based on the EditableMesh at the point you call it.
If you add more triangles or change the mesh after calling CreateMeshPartAsync, the collision won’t updates on it’s own. You’ll need CreateMeshPartAsync and then ApplyMesh to update the collision of the existing MeshPart.

1 Like