Created
January 8, 2022 06:11
-
-
Save samneggs/0b3890eaf219e24c3676fd7861de64e4 to your computer and use it in GitHub Desktop.
Pseudo Perlin noise mapped onto 3D matrix in MicroPython
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from LCD_3inch5 import LCD_3inch5 | |
from machine import Pin | |
import framebuf | |
from time import sleep_ms, sleep_us, ticks_diff, ticks_us, sleep | |
from micropython import const | |
import array | |
from usys import exit | |
import gc | |
from random import randint | |
from math import sin,cos,pi, radians | |
MAXSCREEN_X = const(240) | |
MAXSCREEN_Y = const(240) | |
GRID_SIZE = const(10) | |
GRID_POINTS = const(25) | |
NUM_POINTS = const(GRID_POINTS*GRID_POINTS) | |
TEXTURE_HEIGHT = const(30) #47 | |
TEXTURE_WIDTH = const(200)# 90 | |
SCALE = const(14) | |
xcoord=array.array('h', 0 for _ in range(NUM_POINTS)) | |
ycoord=array.array('h', 0 for _ in range(NUM_POINTS)) | |
zcoord=array.array('h', 0 for _ in range(NUM_POINTS)) | |
# blit_image_file borrowed from Stewart Watkiss | |
# http://www.penguintutor.com/programming/picodisplayanimations | |
def blit_image_file(buf,filename,width,height,cw,ch): # file width, file height, char width, char height | |
with open (filename, "rb") as file: | |
file_position = 0 | |
char_position = 0 | |
ecount = 0 | |
current_byte = file.read(4) # header | |
while file_position < (width * height * 2): | |
current_byte = file.read(1) | |
# if eof | |
if len(current_byte) == 0: | |
break | |
# copy to buffer | |
buf[char_position] = ord(current_byte) #and LCD.red | |
char_position += 1 | |
file_position += 1 | |
if char_position == (cw * ch* 2): | |
char_position = 0 | |
file.close() | |
return | |
@micropython.viper | |
def init_arry(width:int,height:int,seed_arry): | |
seed_addr=ptr16(seed_arry) | |
for i in range(width*height): | |
seed_addr[i] = int(randint(0,0xffff)) | |
@micropython.viper | |
def init_matrix(s:int,s2:int): | |
texture_addr=ptr16(texture) | |
xc=ptr16(xcoord) | |
yc=ptr16(ycoord) | |
zc=ptr16(zcoord) | |
i=0 | |
for y in range(0,GRID_POINTS): | |
for x in range(0,GRID_POINTS): | |
h = texture_addr[TEXTURE_WIDTH*((0+y)%(TEXTURE_HEIGHT-1)) + ((s+x)%(TEXTURE_WIDTH-1))]>>12 | |
xc[i]=x*GRID_SIZE # sin(radians(x*s))*10) # int((x*GRID_SIZE)+sin(radians(y*s))*30) | |
yc[i]=20+y*GRID_SIZE #(y*GRID_SIZE)#*y//2 | |
zc[i]=h+y*s2//20 # h+y*s//20 int( sin(radians(y*s))*10+cos(radians(x*s))*10) | |
i+=1 | |
# Based on Javidx9 C code | |
# OneLoneCoder.com - What Is Perlin Noise? Video: https://youtu.be/6-0UaeJBumA | |
@micropython.viper | |
def PerlinNoise2D(nWidth:int,nHeight:int,Seed_arry,nOctaves:int,fBias:int, Output_arry,s:int): | |
seed_addr=ptr16(Seed_arry) | |
output_addr=ptr16(Output_arry) | |
color_addr=ptr16(color_l2) | |
for x in range(nWidth): | |
for y in range(nHeight): | |
fNoise = 0 | |
fScaleAcc = 0 | |
fScale = s | |
for o in range(nOctaves): | |
nPitch = nWidth >> o | |
nSampleX1 = (x // nPitch) * nPitch | |
nSampleY1 = (y // nPitch) * nPitch | |
nSampleX2 = (nSampleX1 + nPitch) % nWidth | |
nSampleY2 = (nSampleY1 + nPitch) % nWidth | |
fBlendX = ((x - nSampleX1)<<SCALE) // nPitch | |
fBlendY = ((y - nSampleY1)<<SCALE) // nPitch | |
fSampleT = ((((1<<SCALE) - fBlendX) * seed_addr[nSampleY1 * nWidth + nSampleX1])>>SCALE) + ((fBlendX * seed_addr[nSampleY1 * nWidth + nSampleX2])>>SCALE) | |
fSampleB = ((((1<<SCALE) - fBlendX) * seed_addr[nSampleY2 * nWidth + nSampleX1])>>SCALE) + ((fBlendX * seed_addr[nSampleY2 * nWidth + nSampleX2])>>SCALE) | |
fScaleAcc += fScale | |
fNoise += ((((fBlendY * (fSampleB - fSampleT))>>SCALE) + fSampleT) // fScale) | |
fScale = fScale // fBias | |
output_addr[y * nWidth + x] = color_addr[(fNoise // fScaleAcc)] | |
def plot(): | |
for i in range(0,NUM_POINTS-1): | |
x1=xcoord[i]+zcoord[i] | |
y1=ycoord[i]-zcoord[i] | |
x2=xcoord[i+1]+zcoord[i+1] | |
y2=ycoord[i+1]-zcoord[i+1] | |
if (i+1) % (GRID_POINTS) > 0 : | |
screen.line(x1,y1,x2,y2,color_l2[zcoord[i]]) | |
if i < NUM_POINTS-GRID_POINTS : | |
x3=xcoord[i+GRID_POINTS]+zcoord[i+GRID_POINTS] | |
y3=ycoord[i+GRID_POINTS]-zcoord[i+GRID_POINTS] | |
screen.line(x1,y1,x3,y3,color_l2[zcoord[i]]) | |
lcd.show_xy(0,0,MAXSCREEN_X-1,MAXSCREEN_Y-1,screen) | |
screen.fill(0) | |
def fade(input_color1, input_color2): | |
color1=input_color1<<8 | input_color1>>8 # byte swap to normal RBG565 | |
red1 =color1>>11& 0b11111 # extract red #13 | |
green1=color1>>6 & 0b11111 # extract green | |
blue1 =color1 & 0b11111 # extract blue | |
color2=input_color2<<8 | input_color2>>8 # byte swap | |
red2 =color2>>11& 0b11111 # extract red | |
green2=color2>>6 & 0b11111 # extract green | |
blue2 =color2 & 0b11111 # extract blue | |
inc_red =(red2- red1)/31 # find increment step | |
inc_green=(green2-green1)/31 | |
inc_blue =(blue2- blue1)/31 | |
for i in range(0,32): | |
red3 =red1 +int(i*inc_red) # build colors by steps | |
green3=green1+int(i*inc_green) | |
blue3 =blue1 +int(i*inc_blue) | |
color3=red3<<11 | green3<<6 | blue3 # combine RGB | |
color_l2.append((color3 & 0x00FF)<<8 | (color3>>8)) # byte swap to LCD RGB565 | |
if __name__=='__main__': | |
lcd = LCD_3inch5() | |
lcd.bl_ctrl(100) | |
lcd.Fill(lcd.BLACK) | |
color_l2 = array.array('H', []) | |
#fade(lcd.BLACK,lcd.BLUE) | |
fade(lcd.BLUE,lcd.GREEN) | |
fade(lcd.GREEN,lcd.YELLOW) | |
fade(lcd.YELLOW,lcd.ORANGE) | |
fade(lcd.ORANGE,lcd.RED) | |
fade(lcd.RED,lcd.WHITE) | |
buffer1=bytearray(TEXTURE_WIDTH*TEXTURE_HEIGHT*2) # random | |
texture=bytearray(TEXTURE_WIDTH*TEXTURE_HEIGHT*2) # Perlin | |
texture_draw=framebuf.FrameBuffer(texture,TEXTURE_WIDTH,TEXTURE_HEIGHT,framebuf.RGB565) | |
init_arry(TEXTURE_WIDTH,TEXTURE_HEIGHT,buffer1) | |
lcd.show_xy(0,0,TEXTURE_WIDTH-1,TEXTURE_HEIGHT-1,buffer1) | |
PerlinNoise2D(TEXTURE_WIDTH,TEXTURE_HEIGHT,buffer1,6,1, texture,50) | |
texture_draw.fill_rect(0,0,60,10,0) | |
texture_draw.text('PI PICO',0,0,0xffff) | |
lcd.show_xy(MAXSCREEN_X,0,MAXSCREEN_X+TEXTURE_WIDTH-1,TEXTURE_HEIGHT-1,texture) | |
display_buffer=bytearray(MAXSCREEN_X * MAXSCREEN_Y * 2) | |
screen=framebuf.FrameBuffer(display_buffer, MAXSCREEN_X , MAXSCREEN_Y, framebuf.RGB565) | |
#texture=framebuf.FrameBuffer(buffer2,TEXTURE_WIDTH,TEXTURE_HEIGHT,framebuf.RGB565) | |
#blit_image_file(buffer2,"wall.bin",90,47,90,47) | |
while(1): | |
s2=0 | |
for s in range(1,TEXTURE_WIDTH): | |
init_matrix(s,s2) | |
plot() | |
if s<TEXTURE_WIDTH//2: | |
s2+=1 | |
else: | |
s2-=1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment