planets created from 1d perlin noise terrain look weird

Question:

i am trying to make planets using pyglet but they end up looking like stars result

here is my code
also i need a way to convert a batch to a sprite (to move it easily)



import pyglet
from pyglet import shapes
import opensimplex
import math
import time
brtd = 0
######## planets###########
class planetobj():
    def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home  never will thy become infected with the virus that has a closedcure"):
     self.seed = seed
     self.age = age
     self.position = position
     self.color = color
     self.name = name
     self.description = description
    def gplanet(self,size):
     opensimplex.seed(self.seed)
     done = 0
     xc = 0
     c = 0
     self.terrain = []
     start = opensimplex.noise2(x=0, y=self.age)
     while (done == 0 or xc < 50) and not xc > 100 :
         xc = xc + 1
         c = c + size
         value = opensimplex.noise2(x=xc, y=self.age)
         self.terrain.append(value * size)
         if xc > 50:
          if math.floor(value * 100 ) == math.floor(start * 100):
             self.done = 1

    def mkplanet(self, x,y):
      self.batch = pyglet.graphics.Batch() 
      corner1 = (x,y)
      self.trias = []
      counter = 0
      cornerback = [0,0]
      for i in self.terrain:
            counter += 1
            radi = (360 / len(self.terrain)) * counter
            radi2 = (360 / len(self.terrain)) * ((counter + 1 ) % len(self.terrain))
            theta = self.terrain[(counter +1 ) % len(self.terrain)]
            corner3 = (x + math.sin(radi) * ( i )  ,math.cos(radi) * ( i ) + y )
            corner2 = (x + math.sin(radi2) * ( theta )  ,math.cos(radi2) * ( theta ) + y )
            self.trias.append(shapes.Triangle( x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch)     )
############ basic game logic  & rendering ###########
scr_X = 400
scr_Y = 300
window =  pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch() 

earth = planetobj()
earth.gplanet(200)
planets = []
planets.append(earth)

earth.mkplanet( 50 ,50)
@window.event
def on_draw():
    window.clear()
    earth.batch.draw()
pyglet.app.run()

i tried changing the values that get divided by ‘len(self.terrain)’
but i could not find out how to make the planets look round

EDIT
thank you kind commenter (and also the rest of stackoverflow)

now i made a working version feel free to use it
”’

import opensimplex
import math
import pyglet
from pyglet import shapes
pi = 3.1459
debug = 0
class planetobj():
       def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=" 127.0.0.1 , home sweet home  never will thy become infected with the virus that has a closedcure"):
        self.seed = seed
        self.age = age
        self.position = position
        self.color = color
        self.name = name
        self.description = description
    def gplanet(self,size):
     self.batch = pyglet.graphics.Batch()
     opensimplex.seed(self.seed)
     done = 0
     xc = 0
     c = 0
     self.terrain = []
     start = opensimplex.noise2(x=0, y=self.age)
     while (done == 0 or xc < 50) and not xc > 100 :
          xc = xc + 1
          c = c + size
          value = opensimplex.noise2(x=xc, y=self.age)
          self.terrain.append(value * 10 + size)
          if xc > 36:
              if math.floor(value * 100 ) == math.floor(start * 100):
                  self.done = 1

    def mkplanet(self, x,y):
        global debug
        corner1 = (x,y)
        self.trias = []
        deltatheta = 360 / len(self.terrain)
        for counter,i in enumerate(self.terrain):
            theta1 = ((deltatheta * counter)/180) * 3.1459
            theta2 = (deltatheta * (counter + 2)/180) * 3.1459
            radius = self.terrain[counter]
            print(str(theta1) + "," + str(theta2))
            radius2 = self.terrain[(counter + 1 )% len(self.terrain)]
            corner2 = (x + radius2 * math.cos(theta1), y + radius * math.sin(theta1))
            corner3 = ( (x + radius2 * math.cos(theta2)), (y + radius2 * math.sin(theta2)))
            self.trias.append(shapes.Triangle(x,y,corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch)     )
            if debug == 1:
             self.trias.append(shapes.Circle(  corner2[0], corner2[1], 2, color=(255, counter % 255, 40), batch=self.batch)     )
             self.trias.append(shapes.Circle(  corner3[0],  corner3[1], 2, color=(255,255, 255), batch=self.batch)     )
            

############ basic game logic  & rendering ###########
scr_X = 400
scr_Y = 300
window =  pyglet.window.Window(scr_X,scr_Y)
samplebatch = pyglet.graphics.Batch() 

earth = planetobj()
earth.gplanet(150)


earth.mkplanet( 250,150)
print(earth.batch)
earth.batch.draw
@window.event
def on_draw():
    window.clear()
    earth.batch.draw()
    print("drawing")
pyglet.app.run()

”’

Asked By: user432910

||

Answers:

OK, I’ve corrected your trigonometry, but there are some other issues. The random values you get back from the noise generator are between -1 and 1. You are then multiplying that by the planet size, which gives you wild variations from wedge to wedge. What you want is to have a basic wedge size, which you use the noise to adjust bit by bit. Here, I’m saying that the noise should be 3% of the wedge size (size/30).

I didn’t want to download opensimplex, so I’ve used a uniform random number generator. I’m also using matplotlib to plot the triangle, but see if this is closer to what you intended.

import math
import random
import numpy as np
import matplotlib.pyplot as plt

class planetobj():
    def __init__(self,seed=1234,age=68,position=(0,0),color=(0,1,0),name="planet",description=""):
        self.seed = seed
        self.age = age
        self.position = position
        self.color = color
        self.name = name
        self.description = description

    def gplanet(self,size):
        done = 0
        xc = 0
        self.terrain = []
        start = random.uniform(-1,1)
        while (done == 0 or xc < 50) and not xc > 100 :
            xc = xc + 1
            value = random.uniform(-1,1)
            self.terrain.append(size + value * size / 30)
            if xc > 50 and math.floor(value * 100) == math.floor(start * 100):
                done = 1

    def mkplanet(self, x,y):
        corner1 = (x,y)
        self.trias = []
        deltatheta = 360 / len(self.terrain)
        for counter,i in enumerate(self.terrain):
            theta1 = deltatheta * counter
            theta2 = deltatheta * (counter + 1)
            radius = self.terrain[counter] 
            corner2 = (x + radius * math.cos(theta1), y + radius * math.sin(theta1))
            corner3 = (x + radius * math.cos(theta2), y + radius * math.sin(theta2))
#            self.trias.append(shapes.Triangle( x, y, corner2[0], corner2[1], corner3[0], corner3[1], color=(255, counter % 255, 255), batch=self.batch)     )
            self.trias.append(( x, y, corner2[0], corner2[1], corner3[0], corner3[1], (1.0,(counter%255)/255,1.0) ))


earth = planetobj()
earth.gplanet(200)

earth.mkplanet(50 ,50)
print(earth.trias)
plt.figure()
plt.scatter( [48,48,52,52],[-50,50,-50,50] )
for t in earth.trias:
    tri = np.array(t[:6]).reshape(3,2)
    plt.gca().add_patch(plt.Polygon( tri, color=t[6] ))
plt.show()

Output:
enter image description here

Answered By: Tim Roberts