为了一个学校项目,我正在尝试编写一个地形生成器。我是一个完全的python新手,但我已经研究了很多关于地形生成的知识。这是我现在的代码:
#imports
import maya.cmds as cmds
import random
#variables
landsub = 100 #number of subdivisions on the plane
landsize = 400 #size of the plane
maxheight = 100
land = cmds.polyPlane( sx=landsub, sy=landsub, w=landsize, h=landsize)
vtxCount = cmds.polyEvaluate(v=True)
print land
values = [random.triangular(0,1,0) for i in xrange(10)]
#code
for x in range(vtxCount):
cmds.select(cl=True)
cmds.select(land[0] + '.vtx[' + str(x) + ']')
cmds.move(values[x] * maxheight, y=True, absolute=True)
cmds.select(land[0])
#cmds.polySmooth(dv = 1)我正在尝试(努力)使maxheight和vtxCount变量相互依赖;最大高度上的顶点数应该是最小的,不断增加,直到大多数顶点都在最小高度上。在我目前的代码中,大多数顶点似乎都在中等高度,很少有最小高度的顶点。我已经寻找了很长一段时间的解决方案,但我不熟悉我可以在python中做什么,因此很难为我的代码找到正确的命令。
我真心希望有人能帮助我,为我指明正确的方向!感谢您的阅读
发布于 2018-12-05 23:55:52
你可以这样做
#imports
import maya.cmds as cmds
import random
#variables
landsub = 100 #number of subdivisions on the plane
landsize = 400 #size of the plane
maxheight = 100
land = cmds.polyPlane( sx=landsub, sy=landsub, w=landsize, h=landsize)
vtxCount = range(cmds.polyEvaluate(v=True))
random.shuffle(vtxCount)
values = [random.triangular(0,1,0) for i in xrange(10)]
values_count = len(values)
SEED = 448
random.seed(SEED)
optimize_setter = []
#code
for x in vtxCount:
mod = x % values_count
# cmds.move(values[mod-1] * maxheight, land[0] + '.vtx[' + str(x) + ']',y=True, absolute=True)
optimize_setter += [float(0),values[mod-1]*maxheight,float(0)]
cmds.setAttr('pPlane1.vtx[:]', *optimize_setter)
cmds.select(land[0])如果您希望0附近有更多的值,则可以将值更改为具有更多的.1值。我不知道你有什么问题。
values = []
high_values = [random.triangular(0,1,0) for i in xrange(3)]
low_values = [random.uniform(0, .2), for i in xrange(7)]
values = low_values + high_values编辑
#imports
import maya.cmds as cmds
import random
#variables
landsub = 100 #number of subdivisions on the plane
landsize = 400 #size of the plane
maxheight = 15
land = cmds.polyPlane( sx=landsub, sy=landsub, w=landsize, h=landsize)
vtxnb = cmds.polyEvaluate(v=True)
vtxCount = range(vtxnb)
values = []
high_values = [random.triangular(0,1,0) for i in xrange(vtxnb/10)]
low_values = [random.uniform(0, .3) for i in xrange(vtxnb/2)]
values = low_values + high_values
values_count = len(values)
SEED = 448
random.seed(SEED)
random.shuffle(vtxCount)
random.shuffle(values)
optimize_setter = []
#code
for x in vtxCount:
mod = x % values_count
# cmds.move(values[mod-1] * maxheight, land[0] + '.vtx[' + str(x) + ']',y=True, absolute=True)
optimize_setter += [float(0),values[mod-1]*maxheight,float(0)]
cmds.setAttr('pPlane1.vtx[:]', *optimize_setter)
cmds.select(land[0])发布于 2018-12-08 07:11:25
地形生成是一个有趣的问题,不幸的是,它经常需要大量的小提琴才能得到令人满意的结果。
问题的'maya‘部分在@drweeny的回答中得到了很好的处理:你只需要批量设置polyPlane的.vtx属性。这里有一个类似的方法,主要的区别是这个函数接受一个位置数组,它的工作方式类似于位图:它是一个列表,它的内容是列表,表示高度图中的行和列,即:[ [0,1], [2,3] ]表示
[0, 1]
[2, 3]作为一个网格。将其转换为多平面非常简单:
def array_to_plane (array):
# this expects that array is an list-of-lists
# arranged as [ [0,1,2], [3,4,5], ... etc ]
h = len(array)
w = len(array[0])
# this makes a plane with the same number of samples as your array
plane, _ = cmds.polyPlane(width = 1, height = 1, sx = w -1 , sy=h-1)
# the zeros are here just so the final argument list is a set of xyz
# positions
setter = []
for row in array:
for column in row:
setter.append (0.0)
setter.append (column)
setter.append (0.0)
cmds.setAttr(plane + '.vtx[:]', *setter, type='double3')
return plane有趣和棘手的部分实际上是填充网格,使地形看起来不太像随机噪声。有很多技术,但基本的是:
随机化
您确实希望将随机数应用于您的高度贴图。幸运的是,python的random module对于不同分布的噪声有很多很好的选择。下面是一个将随机数插入地图网格的简单函数:
def randomize(map, scale):
rows = len(map)
columns = len(map[0]
# loop over the map and add random values
for r in range(rows):
for c in range(columns):
map[r][c] += (random.gauss(0,1) * scale)比例尺
随机数网格看起来不像地形--它太混乱了。一种非常常见的技术是以不同的物理大小应用随机化,以模拟大小特征的混合。要做到这一点,最简单的方法是从一个小地图开始,然后逐步放大它--这将为您提供不同大小的混合特征。
这里有一种便宜的方法来获取一个高度图网格,并在每个维度上将其内容加倍。如果你这样做几次,并在上面添加一些随机化,你就会得到从非常大到非常小的混合特征。
def upsize(heightmap):
output = []
for row in heightmap:
new_row = []
for each_value in row:
# first double the entries in the horizontal direction
new_row.append(each_value)
new_row.append(each_value)
# then add two copies of the row to the output.
# don't add it twice -- add a copy to keep
# the data independent
output.append(new_row)
output.append(new_row[:])
return output在像[ [0,1], [2,3] ]这样的地图上运行它会生成像[ [0,0,1,1], [0,0,1,1], [2,2,3,3], [2,2,3,3]]这样的地图
过滤
您不希望heightmap中的每个样本都独立于其邻居:这在自然界中很少见,而且看起来非常糟糕。在photoshop这样的程序中,你可以使用'kernel'生成模糊效果,它基本上只是像素和它的邻居的加权平均值。这里有很多选择(这是一个很好的研究你的项目的领域)。这是一个非常简单的模糊内核,它取一个我们的贴图网格,并返回一个模糊的新内核;你会看到,在添加不同的像素权重后,我们还使用了线性插值来控制模糊的强度:
def blur(map):
output = []
for row in map:
output.append(row[:])
width = len(map[0])
height = len(map)
for row in range (1, height-1):
for column in range (1, height-1):
v = 0
v += map [row-1][column - 1]
v += map [row-1][column] * 2
v += map [row-1][column + 1]
v += map [row][column - 1] * 2
v += map [row][column] * 4
v += map [row][column + 1] * 2
v += map [row+1][column - 1]
v += map [row+1][column] * 2
v += map [row+1][column + 1]
v = v / 16.0
# lerp the final output based on amount; 0 = no blur, 1 = full blur)
output[row][column] = v
return output这一步有很多选项,这些选项会影响最终输出的效果。您可以使用Photoshop's custom filter非常轻松地尝试使用过滤器内核,它实际上只是一个简单的内核编辑器。
把它们放在一起
有了随机化,缩放和过滤,你就有足够的能力来制作一个有趣的地形生成工具包。共同的主线是,你在“像素”的“位图”上做所有的艰苦工作,排列成一个列表-lists,当你完成后,你把它交给玛雅来制作一个最终的对象。
这里有一个非常基本的方法来把它们放在一起。我鼓励你把它拆开,然后用满足你创造性想法的方式把它重新组合起来。将这些部分编写为单独的函数,在heightmap列表上工作,这使得添加或调整行为变得很容易,而不会破坏整个过程。
def fractalize(iterations, scale=1.0, seed = None):
# this lets you make it repeatable if you want
if seed:
random.seed(seed)
# make a 2-2 starter map
map = [ [0.0, 0.0], [0.0, 0.0] ]
randomize(map, scale)
for n in range(1, iterations):
map = upsize(map)
map = blur(map)
# this turns down the randomization
# in each successive step... you could
# use many formulas here for different effects
randomize(map, scale / 2**n)
return array_to_plane(map)
fractalize(7, 0.125, seed=1234)请注意该迭代次数:每次迭代都会使顶点数增加四倍,因此将其设置得太高会使maya下沉。值为8会生成一个具有255 x 255个顶点的平面;请谨慎使用。
让它成为你自己的一些东西:*什么时候--以及多久一次--你想添加模糊?*如果你使用一个不同的模糊内核会发生什么?*如果你改变randomize(map, scale / 2**n)到其他公式会发生什么?*你可以对位图做什么来模拟水位?
https://stackoverflow.com/questions/53632937
复制相似问题