我的三维mandelbulb制作fractal成长之路

三维分形,从mandelbulb开始做起,比2d多了一维,结果发现制作难度多了不少。

三维制作从python开始,这样制作会快一点。找资料https://github.com/jtauber/mandelbulb,这个比较浅显易懂,但制作了2d图片效果,没有3d的制作。

通过改造用python画出了3D效果,但的确很难看,作为成长记录一下。

按github中的方式制作图片,有垂直俯视效果
制作的3d效果灰度图-好难看
平视彩色1
半俯视彩色1
底部按顶部亮平视2
半俯视图
空心效果的半俯视图,由于点比上面实心少,托转容易点

目前还在考虑如何做渲染,以期望达到他人连续的效果。

着色采用下面方式,每一层一个颜色,底部暗,顶部亮
c=hsv2rgb(height*4+100,(55+height)*2/256.0,(55+height)*2/256.0)

图片比较丑陋,先分享一下python代码吧。

import zlib
import struct
import array
from math import sqrt, atan2, cos, sin
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import math
import numpy as np
#R, G, B是 [0, 255]. H 是[0, 360]. S, V 是 [0, 1].
def hsv2rgb(h, s, v):
    h = float(h%360)
    s = float(s)
    v = float(v)
    h60 = h / 60.0
    h60f = math.floor(h60)
    hi = int(h60f) % 6
    f = h60 - h60f
    p = v * (1 - s)
    q = v * (1 - f * s)
    t = v * (1 - (1 - f) * s)
    r, g, b = 0, 0, 0
    if hi == 0: r, g, b = v, t, p
    elif hi == 1: r, g, b = q, v, p
    elif hi == 2: r, g, b = p, v, t
    elif hi == 3: r, g, b = p, q, v
    elif hi == 4: r, g, b = t, p, v
    elif hi == 5: r, g, b = v, p, q
    r, g, b = int(r * 255), int(g * 255), int(b * 255)
    return r/255.0, g/255.0, b/255.0

def rgb2hsv(r, g, b):
    r, g, b = r/255.0, g/255.0, b/255.0
    mx = max(r, g, b)
    mn = min(r, g, b)
    df = mx-mn
    if mx == mn:
        h = 0
    elif mx == r:
        h = (60 * ((g-b)/df) + 360) % 360
    elif mx == g:
        h = (60 * ((b-r)/df) + 120) % 360
    elif mx == b:
        h = (60 * ((r-g)/df) + 240) % 360
    if mx == 0:
        s = 0
    else:
        s = df/mx
    v = mx
    return h, s, v
H = 400
W = 400

# just do as a dictionary as it starts off sparse

cc1=[]
xx1=[]
yy1=[]
zz1=[]
heights={}
for height in range(0, 55, 1):
    print ("height %d" % height)
    filename = "mandel8_%02d.values" % height
    
    f = open(filename)
    
    header = f.readline()
    assert header == "H %s W %s\n" % (H, W), header

    im=[[0 for col in range(W)]for row in range(H)]
    for xx in range(W):
        for yy in range(H):
            value = int(f.readline().strip())
            im[yy][xx]=value
            if value == 0:  #and (xx, yy) not in heights:
                heights[xx, yy] = 1

    a=[[0 for col in range(W)]for row in range(H)]
         
    for i in range(0,W):
          for j in range(1,H):
             if(im[j][i]!=0 and im[j-1][i]==0):
                    a[j][i]=1
             if(im[j][i]==0 and im[j-1][i]!=0):
                    a[j-1][i]=1
                     
    for i in range(0,H):
          for j in range(1,W):
              if(im[i][j]!=0 and im[i][j-1]==0):
                    a[i][j]=1
              if(im[i][j]==0 and im[i][j-1]!=0):
                    a[i][j-1]=1 
    for xx in range(W):
        for yy in range(H):             
            if a[yy][xx] != 0:  #and (xx, yy) not in heights:
                heights[xx, yy] = height
                xx1.append(xx)
                yy1.append(yy)
                zz1.append(height)
                #c=(height*4/256.0,height*4/256.0,height*4/256.0)
                c=hsv2rgb(height*4+100,(55+height)*2/256.0,(55+height)*2/256.0)
                cc1.extend(c)

def output_chunk(out, chunk_type, data):
    out.write(struct.pack("!I", len(data)))
    btt=bytes(chunk_type,encoding="utf8")
    out.write(btt)
    out.write(data)
    checksum = zlib.crc32(data, zlib.crc32(btt))
    out.write(struct.pack("!I", checksum))

def get_data(width, height, rgb_func):
    compressor = zlib.compressobj()
    data = array.array("B")
    for y in range(height):
        data.append(0)
        for x in range(width):
            data.extend([min(255, max(0, v)) for v in rgb_func(x, y)])
    compressed = compressor.compress(data.tostring())
    flushed = compressor.flush()
    return compressed + flushed

def write_png(filename, width, height, rgb_func):
    out = open(filename, "wb")
    out.write(struct.pack("8B", 137, 80, 78, 71, 13, 10, 26, 10))
    output_chunk(out, "IHDR", struct.pack("!2I5B", width, height, 8, 2, 0, 0, 0))
    output_chunk(out, "IDAT", get_data(width, height, rgb_func))
    output_chunk(out, "IEND", bytes("",encoding="utf8"))
    out.close()


def func(x, y):
    c = 4 * heights.get((x, y), 63)
    return c, c, c


write_png("heightfield.png", W, H, func)
h = 400
w = 400
fig = plt.figure(figsize=(16,16))
#plt.axis('off')     #不显示坐标尺寸
ax1 = fig.add_subplot(111,projection='3d')     #第三个子图
ax1.set_title('mandelbulb' )      #在3维坐标显示变形图 
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_zlabel('z')
myx=np.array(xx1).flatten()
myy=np.array(yy1).flatten()
myz=np.array(zz1).flatten()
myc=np.array(cc1).reshape(-1,3)
erea=1;

ax1.scatter(myx,myy,myz,s=erea, c=myc, alpha=1.0 )
#ax1.view_init(0, 40.0)
plt.show()
别人家程序的效果
发布了29 篇原创文章 · 获赞 5 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/foolpanda1168/article/details/82290161