I’m trying to make procedural planets with icosphere generated by code. Generating the acutal icosphere wasn’t a problem thanks to the DevForum but i really don’t know how i could implement in my current code a NOISE to make the planets look better with hills, mountains and more. Here’s the code of the module script
local function createTriangle(A: Vector3, B: Vector3, C: Vector3, thickness: number): UnionOperation
local AB, AC, BC = B - A, C - A, C - B
local XVector = AC:Cross(AB).Unit
local YVector = BC:Cross(XVector).Unit
local ZVector = BC.Unit
local height = math.abs(AB:Dot(YVector))
local WedgePart1 = Instance.new('WedgePart')
WedgePart1.BottomSurface = Enum.SurfaceType.Smooth
WedgePart1.Size = Vector3.new(thickness, height, math.abs(AB:Dot(ZVector)))
WedgePart1.CFrame = CFrame.fromMatrix((A + B) / 2, XVector, YVector, ZVector)
local WedgePart2 = Instance.new('WedgePart')
WedgePart2.BottomSurface = Enum.SurfaceType.Smooth
WedgePart2.Size = Vector3.new(thickness, height, math.abs(AC:Dot(ZVector)))
WedgePart2.CFrame = CFrame.fromMatrix((A + C) / 2, -XVector, YVector, -ZVector)
WedgePart1.Parent = game
local Triangle = WedgePart1:UnionAsync({WedgePart2})
WedgePart1:Destroy(); WedgePart2:Destroy()
return Triangle
end
return function (radius: number, subdivisions: number?, properties: {any}?, thickness: number?, offset: number?, halve: boolean?, noiseFactor: number?): nil
-- set default values
subdivisions, properties, thickness, offset, noiseFactor = subdivisions or 2, properties or { Anchored = true, UsePartColor = true }, thickness or 0.001, offset or 0, noiseFactor or 0.1
-- icosahedron data
local vertices = {{-1, TAU, 0}, {1, TAU, 0}, {-1, -TAU, 0}, {1, -TAU, 0}, {0, -1, TAU}, {0, 1, TAU}, {0, -1, -TAU}, {0, 1, -TAU}, {TAU, 0, -1}, {TAU, 0, 1}, {-TAU, 0, -1}, {-TAU, 0, 1}}
local faces = {{1, 12, 6}, {1, 6, 2}, {1, 2, 8}, {1, 8, 11}, {1, 11, 12}, {2, 6, 10}, {6, 12, 5}, {12, 11, 3}, {11, 8, 7}, {8, 2, 9}, {4, 10, 5}, {4, 5, 3}, {4, 3, 7}, {4, 7, 9}, {4, 9, 10}, {5, 10, 6}, {3, 5, 12}, {7, 3, 11}, {9, 7, 8}, {10, 9, 2}}
-- convert vertices tables to Vector3s, and point indices of each face to those Vector3s
for i, vertex in vertices do vertices[i] = Vector3.new(vertex[1], vertex[2], vertex[3]) end
for t, triangle in faces do for p, pointIndex in triangle do faces[t][p] = vertices[pointIndex] end end
for _ = 1, subdivisions do
-- split every face into 4 faces by adding vertices in the middle of its edges
for _ = 1, #faces do
local vertices = table.remove(faces, 1)
local AB = addNoise((vertices[1] + vertices[2]) / 2, noiseFactor)
local BC = addNoise((vertices[2] + vertices[3]) / 2, noiseFactor)
local CA = addNoise((vertices[3] + vertices[1]) / 2, noiseFactor)
table.insert(faces, {vertices[1], AB, CA})
table.insert(faces, {vertices[2], BC, AB})
table.insert(faces, {vertices[3], CA, BC})
table.insert(faces, {AB, BC, CA})
end
end
local Model = Instance.new('Model', workspace)
local Offset = CFrame.new(thickness / 2 - offset, 0, 0)
for i, face in ipairs(faces) do
local Triangle = createTriangle(face[1].Unit * radius, face[2].Unit * radius, face[3].Unit * radius, thickness)
Triangle.CFrame *= Offset
for property, value in properties do Triangle[property] = value end
Triangle.Parent = Model
Model.Name = string.format('Icosphere_%i %i%%', subdivisions, i / #faces * 100)
end
if halve then
-- rotate sphere so that one of the halving lines is on the XZ plane
Model.WorldPivot = CFrame.Angles(0, 0, -0.5535746812820435)
Model:PivotTo(CFrame.new())
for _, Triangle in Model:GetChildren() do
Triangle.PivotOffset = CFrame.new(-Triangle.Size.X / 2, 0, 0)
if Triangle:GetPivot().Position.Y < 0 then Triangle:Destroy() end
end
end
Model.WorldPivot = CFrame.new()
Model.Name = 'Icosphere_' .. subdivisions
end
if you have any idea how could i achieve this, lemme know!