Planet Sphere generator with Perlin Noise

Have you ever wanted to create a sphere on ROBLOX? Not a basic old base part sphere, ew disgusting. I’m talking a proper Sphere. A sphere with bits, as I believe as it is technically referred.

Introducing my patent pending:

SPHERE MODULE!!

Amazing, Incredible and delightful things you can do with this module:

  • Create actual proper round procedurally generated planets!
  • Get a usable coordinate system that won’t have you begging for death!
  • Use Perlin noise for random terrain!

HOW TO USE THE MODULE (patent pending)

get the module obviously:

In whatever script you may have delightfully decided to procure, you must require the module

local sphereModule = require(game.ReplicatedStorage.sphereModule) -- location of the module (patent pending)

CREATING A SPHERE CONSTRUCTOR!!!
To work with the module, you use a sphere constructor. To create one,

local sphereCon = sphereModule.sphereConstructor() -- no arguments

CREATING THE SPHERE!! (ish)

I need to make a confession, I lied. This module patent pending doesn’t create spheres. It creates the points of a sphere, if that’s confusing let me show you visually what it creates:

Now it doesn’t actually create parts, It returns an array of ordered rotation matri (CFRAMES)
Yes I will be using matri instead of matrixes

It is YOUR responsibility to make the sphere, the module just tells you where everything is.

Anyway, lets make the “sphere”

The sphere needs a few arguments

  • The CFrame to make the sphere(which means yes it can be inclined)
  • the Radius of the sphere
sphereConstruct.newSphere(CFrame.new(0,0,0), 100)

Now THIS RETURNS NOTHING to access the CFrames we get to use that grid system I hinted at earlier! How I love this grid system!

The grid system is probably the sole thing that ties this module together, and makes the 2 main features of it work.

To access a part of the grid, use this function

sphereCon.getPosition(x,z)

this will return the CFRAME assigned at that position.
Now the X axis is the uppy downy one and it ranges from -8 to 8
The Z access, the lefty righty one goes from 0 to 35

And dont worry, over or under indexing the grid will automatically wrap arround, for example indexing x at 9 will return x at -8

So, to create a part at every single CFrame of the sphere, you could do

for x = -8,8 do
	for z = 0, 35 do
		local part = Instance.new("Part")
		part.Anchored = true
		part.Parent = workspace
		part.CFrame = sphereCon.getPosition(x,z)
	end
end

Which results in:

Now, I can’t really think of a good use case of this next function, but if you for some reason had the CFrame of the part and want its coordinates on the grid using that, this is how you could use the
getPositionFromCFrame(cframe)

local x, z = getPositionFromCFrame(part.CFrame)
-- returns the position of part in the grid, nil if not in grid

Now, we want PERLIN NOISE!!

One of the drawbacks of using the type of sphere we use is that the nodes of the sphere get blocked up near the poles, example:

What this does is create “more noise” in some areas rather then others, creating a non-realistic terrain.

Now, to fix the PERLIN NOISE generation the script uses a function that automatically calculates the offset to the x and z values of the noise to to make it equal throughout the surface.

Yay! Now, how do we use it?

First lets look at the function:

sphereCon.getNoise(x, y, seed, smoothness, min, max)

Basically X and Y are your… X and Y coordinates on the grid.
Smoothness is the what your x and y are divided by, effectively, the higher the number, the smoother the terrain. Experiment with it!

Seed, Min, and Max are all explained in this wonderful article by Nexus:

Now the function returns a value, the Y value of the CFrame

Basically, to apply the perlin noise to all the parts of the sphere you could do:

local seed = Random.new():NextNumber() -- generates a number 0-1
for x = -8,8 do
	for z = 0, 35 do
		local noise = sphereConstruct.getNoise(x,z,seed,2,0,25)
		local part = Instance.new("Part")
		part.Anchored = true
		part.Parent = workspace
 		part.CFrame = sphereConstruct.getPosition(x,z) * CFrame.new(0,0,noise)
	end
end

Which results in:

Yay we did it! Now, I won’t be covering the polygonal terrain because I think it stray’s off from the course of this article, but a good source I personally used to create the terrain is this video:
(not by me)

KNOWN ISSUES:

  • the SEAM where the z Coordinate wraps around the sphere doesn’t properly use terrain generation, However at levels of Perlin noise you would use anyway for planet generation to look natural it is nearly unnoticeable. Will not be fixed.

  • The ammount of parts is fixed, meaning with larger spheres things can be unnaturally far apart.
    Will be fixed shortly

Enjoy!

4 Likes