Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # To the extent possible under law, the author has dedicated all copyright
- # and related and neighboring rights to this software to the public domain
- # worldwide. This software is distributed without any warranty.
- # See <http://creativecommons.org/publicdomain/zero/1.0/>. */
- import sys
- print([sys.prefix, getattr(sys, "real_prefix", None)])
- import math
- import time
- import numpy
- import argparse
- from PIL import Image, ImageDraw
- fnv_offset_basis = 14695981039346656037
- fnv_prime = 1099511628211
- rng_s0 = 0
- rng_s1 = 0
- def fnv1a(ts, px, py):
- return (((((fnv_offset_basis ^ ts) * fnv_prime) ^ px) * fnv_prime) ^ py) * fnv_prime
- #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
- def xorshift(x):
- x += 0x9e3779b97f4a7c15
- y = x
- y = (y ^ (y >> 30)) * 0xbf58476d1ce4e5b9
- y = (y ^ (y >> 27)) * 0x94d049bb133111eb
- x += 0x9e3779b97f4a7c15
- z = x
- z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9
- z = (z ^ (z >> 27)) * 0x94d049bb133111eb
- return y ^ (y >> 31), z ^ (z >> 31)
- def Seed(ts, px, py):
- global rng_s0
- global rng_s1
- fnv = fnv1a(ts, px, py)
- rng_s0, rng_s1 = xorshift(fnv)
- #from http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c, ported to Go, then to Python
- def rotl(x, k):
- return (x << k) | (x >> (64 - k))
- #from http://vigna.di.unimi.it/xorshift/xoroshiro128plus.c, ported to Go, then to Python
- def RandNext():
- global rng_s0
- global rng_s1
- s0 = rng_s0
- s1 = rng_s1
- result = s0 + s1
- s1 ^= s0
- rng_s0 = rotl(s0, 24) ^ s1 ^ (s1 << 16)
- rng_s1 = rotl(s1, 37)
- return result
- def main(argv):
- numPoints = 0
- startTime = time.monotonic()
- parser = argparse.ArgumentParser(description='Worley parameters')
- parser.add_argument("-dimx", default=640, type=int, help="the width of each image, in pixels")
- parser.add_argument("-dimy", default=480, type=int, help="the height of each image, in pixels")
- parser.add_argument("-grid", default=32, type=int, help="The width and height of each grid in pixels")
- parser.add_argument("-amount", default=1, type=int, help="The number of images to generate")
- 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.")
- 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.")
- 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.")
- args = parser.parse_args()
- dimx = args.dimx
- dimy = args.dimy
- gridsize = args.grid
- amount = args.amount
- rcol = args.red
- gcol = args.green
- bcol = args.blue
- for i in range(amount):
- imgStartTime = time.monotonic()
- img, numPoints = worley(dimx, dimy, gridsize, i, int(imgStartTime*1024.0*1024.0), 8-rcol, 8-gcol, 8-bcol)
- img.save("worley"+str(i+1)+".png", "PNG")
- endTime = time.monotonic()
- timeTaken = endTime - startTime
- print("Finished generating and writing "+str(amount)+" "+str(dimx)+"x"+str(dimy)+" images with "+str(numPoints)+" points in "+str(timeTaken)+"s.\n")
- def worley(dimx, dimy, gridsize, imgNum, timeSeed, rcol, gcol, bcol):
- img = image = Image.new("RGB", (dimx, dimy))
- pixels = image.load()
- clist = numpy.zeros(dimx*dimy)
- px = py = 0
- gridshift = 0
- gs = gridsize
- while gs > 1:
- gridshift += 1
- gs >>= 1
- maxDist = 0.0
- cpos = 0
- for py in range(dimy):
- gpy = py >> gridshift
- for px in range(dimx):
- gpx = px >> gridshift
- #calculate color
- minDist = 0xfffffff
- for gy in range(gpy-1, gpy+2):
- for gx in range(gpx-1, gpx+2):
- Seed(timeSeed, gx, gy)
- numPoints = probLookup(RandNext())
- for _ in range(numPoints):
- x = (((RandNext() >> 16) & (gridsize - 1))) + (gx << gridshift)
- y = (((RandNext() >> 16) & (gridsize - 1))) + (gy << gridshift)
- x -= px
- y -= py
- sqDist = x*x + y*y
- if sqDist < minDist:
- minDist = sqDist
- dist = math.sqrt(float(minDist))
- if dist > maxDist:
- maxDist = dist
- clist[cpos] = dist * 255.0
- cpos += 1
- cpos = 0
- totalNumPoints = 0
- lgpx = 0xff
- lgpy = 0xff
- for py in range(dimy):
- gpy = py >> gridshift
- for px in range(dimx):
- gpx = px >> gridshift
- if gpx != lgpx or gpy != lgpy:
- Seed(timeSeed, gpx, gpy)
- numPoints = probLookup(RandNext())
- totalNumPoints += numPoints
- lgpx = gpx
- lgpy = gpy
- #assign color to pixel
- shade = int(clist[cpos] / maxDist) & 0xff
- pixels[px, py] = (shade >> rcol, shade >> gcol, shade >> bcol)
- cpos += 1
- return img, totalNumPoints
- def probLookup(value):
- value >>= 32
- if value < 393325350:
- return 1
- if value < 1022645910:
- return 2
- if value < 1861739990:
- return 3
- if value < 2700834071:
- return 4
- if value < 3372109335:
- return 5
- if value < 3819626178:
- return 6
- if value < 4075350088:
- return 7
- if value < 4203212043:
- return 8
- return 9
- #returns 0 if gridshift is fine, otherwise returns a suggested value
- def checkGridSizeValid(dimx, dimy, gridshift):
- sgs = gridshift
- while():
- gridsizex = dimx >> sgs
- gridsizey = dimy >> sgs
- if gridsizex > 0xffff or gridsizey > 0xffff:
- sgs += 1
- elif sgs == gridshift:
- return 0
- else:
- return sgs
- if __name__ == "__main__":
- main(sys.argv)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement