Advertisement
Trafalgar

python 3 worley

May 8th, 2019
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.53 KB | None | 0 0
  1. #!/usr/bin/python
  2. # To the extent possible under law, the author has dedicated all copyright
  3. # and related and neighboring rights to this software to the public domain
  4. # worldwide. This software is distributed without any warranty.
  5.  
  6. # See <http://creativecommons.org/publicdomain/zero/1.0/>. */
  7.  
  8. import sys
  9. print([sys.prefix, getattr(sys, "real_prefix", None)])
  10. import math
  11. import time
  12. import numpy
  13. import argparse
  14. from PIL import Image, ImageDraw
  15.  
  16. fnv_offset_basis = 14695981039346656037
  17. fnv_prime = 1099511628211
  18.  
  19. rng_s0 = 0
  20. rng_s1 = 0
  21.  
  22. def fnv1a(ts, px, py):
  23.     return (((((fnv_offset_basis ^ ts) * fnv_prime) ^ px) * fnv_prime) ^ py) * fnv_prime
  24.  
  25. #from http://xorshift.di.unimi.it/splitmix64.c, ported to Go and adjusted to output two uint64s instead of one at a time, and then ported to Python
  26. def xorshift(x):
  27.     x += 0x9e3779b97f4a7c15
  28.     y = x
  29.     y = (y ^ (y >> 30)) * 0xbf58476d1ce4e5b9
  30.     y = (y ^ (y >> 27)) * 0x94d049bb133111eb
  31.     x += 0x9e3779b97f4a7c15
  32.     z = x
  33.     z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9
  34.     z = (z ^ (z >> 27)) * 0x94d049bb133111eb
  35.     return y ^ (y >> 31), z ^ (z >> 31)
  36.  
  37. def Seed(ts, px, py):
  38.     global rng_s0
  39.     global rng_s1
  40.     fnv = fnv1a(ts, px, py)
  41.     rng_s0, rng_s1 = xorshift(fnv)
  42.  
  43. #from http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c, ported to Go, then to Python
  44. def rotl(x, k):
  45.     return (x << k) | (x >> (64 - k))
  46.  
  47.  
  48. #from http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c, ported to Go, then to Python
  49. def RandNext():
  50.     global rng_s0
  51.     global rng_s1
  52.     s0 = rng_s0
  53.     s1 = rng_s1
  54.     result = s0 + s1
  55.  
  56.     s1 ^= s0
  57.     rng_s0 = rotl(s0, 24) ^ s1 ^ (s1 << 16)
  58.     rng_s1 = rotl(s1, 37)
  59.  
  60.     return result
  61.  
  62. def main(argv):
  63.     numPoints = 0
  64.     startTime = time.monotonic()
  65.  
  66.     parser = argparse.ArgumentParser(description='Worley parameters')
  67.     parser.add_argument("-dimx", default=640, type=int, help="the width of each image, in pixels")
  68.     parser.add_argument("-dimy", default=480, type=int, help="the height of each image, in pixels")
  69.     parser.add_argument("-grid", default=32, type=int, help="The width and height of each grid in pixels")
  70.     parser.add_argument("-amount", default=1, type=int, help="The number of images to generate")
  71.     parser.add_argument("-red", default=8, type=int, help="How red it should be on a scale from 0-8, where 8 is as red as possible, 7 is half as red, 6 is half as red as that, etc, and 0 means no red.")
  72.     parser.add_argument("-green", default=0, type=int, help="How green it should be on a scale from 0-8, where 8 is as green as possible, 7 is half as green, 6 is half as green as that, etc, and 0 means no green.")
  73.     parser.add_argument("-blue", default=0, type=int, help="How blue it should be on a scale from 0-8, where 8 is as blue as possible, 7 is half as blue, 6 is half as blue as that, etc, and 0 means no blue.")
  74.     args = parser.parse_args()
  75.     dimx = args.dimx
  76.     dimy = args.dimy
  77.     gridsize = args.grid
  78.     amount = args.amount
  79.     rcol = args.red
  80.     gcol = args.green
  81.     bcol = args.blue
  82.    
  83.     for i in range(amount):
  84.         imgStartTime = time.monotonic()
  85.         img, numPoints = worley(dimx, dimy, gridsize, i, int(imgStartTime*1024.0*1024.0), 8-rcol, 8-gcol, 8-bcol)
  86.         img.save("worley"+str(i+1)+".png", "PNG")
  87.  
  88.     endTime = time.monotonic()
  89.     timeTaken = endTime - startTime
  90.     print("Finished generating and writing "+str(amount)+" "+str(dimx)+"x"+str(dimy)+" images with "+str(numPoints)+" points in "+str(timeTaken)+"s.\n")
  91.  
  92. def worley(dimx, dimy, gridsize, imgNum, timeSeed, rcol, gcol, bcol):
  93.     img = image = Image.new("RGB", (dimx, dimy))
  94.     pixels = image.load()
  95.     clist = numpy.zeros(dimx*dimy)
  96.     px = py = 0
  97.  
  98.     gridshift = 0
  99.     gs = gridsize
  100.     while gs > 1:
  101.         gridshift += 1
  102.         gs >>= 1
  103.    
  104.     maxDist = 0.0
  105.  
  106.     cpos = 0
  107.     for py in range(dimy):
  108.         gpy = py >> gridshift
  109.         for px in range(dimx):
  110.             gpx = px >> gridshift
  111.             #calculate color
  112.             minDist = 0xfffffff
  113.             for gy in range(gpy-1, gpy+2):
  114.                 for gx in range(gpx-1, gpx+2):
  115.                     Seed(timeSeed, gx, gy)
  116.                     numPoints = probLookup(RandNext())
  117.                     for _ in range(numPoints):
  118.                         x = (((RandNext() >> 16) & (gridsize - 1))) + (gx << gridshift)
  119.                         y = (((RandNext() >> 16) & (gridsize - 1))) + (gy << gridshift)
  120.                         x -= px
  121.                         y -= py
  122.                         sqDist = x*x + y*y
  123.                         if sqDist < minDist:
  124.                             minDist = sqDist
  125.             dist = math.sqrt(float(minDist))
  126.             if dist > maxDist:
  127.                 maxDist = dist
  128.             clist[cpos] = dist * 255.0
  129.             cpos += 1
  130.  
  131.     cpos = 0
  132.     totalNumPoints = 0
  133.     lgpx = 0xff
  134.     lgpy = 0xff
  135.     for py in range(dimy):
  136.         gpy = py >> gridshift
  137.         for px in range(dimx):
  138.             gpx = px >> gridshift
  139.             if gpx != lgpx or gpy != lgpy:
  140.                 Seed(timeSeed, gpx, gpy)
  141.                 numPoints = probLookup(RandNext())
  142.                 totalNumPoints += numPoints
  143.                 lgpx = gpx
  144.                 lgpy = gpy
  145.             #assign color to pixel
  146.             shade = int(clist[cpos] / maxDist) & 0xff
  147.             pixels[px, py] = (shade >> rcol, shade >> gcol, shade >> bcol)
  148.             cpos += 1
  149.     return img, totalNumPoints
  150.  
  151. def probLookup(value):
  152.     value >>= 32
  153.     if value < 393325350:
  154.         return 1
  155.     if value < 1022645910:
  156.         return 2
  157.     if value < 1861739990:
  158.         return 3
  159.     if value < 2700834071:
  160.         return 4
  161.     if value < 3372109335:
  162.         return 5
  163.     if value < 3819626178:
  164.         return 6
  165.     if value < 4075350088:
  166.         return 7
  167.     if value < 4203212043:
  168.         return 8
  169.     return 9
  170.  
  171. #returns 0 if gridshift is fine, otherwise returns a suggested value
  172. def checkGridSizeValid(dimx, dimy, gridshift):
  173.     sgs = gridshift
  174.     while():
  175.         gridsizex = dimx >> sgs
  176.         gridsizey = dimy >> sgs
  177.         if gridsizex > 0xffff or gridsizey > 0xffff:
  178.             sgs += 1
  179.         elif sgs == gridshift:
  180.             return 0
  181.         else:
  182.             return sgs
  183.  
  184. if __name__ == "__main__":
  185.     main(sys.argv)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement