我正在尝试使用Python Unreal API创建一个景观,使用unreal.EditorLevelLibrary.spawn_actor_from_class()
生成LandscapeProxy
参与者,然后使用LandscapeProxy类的landscape_import_heightmap_from_render_target()
更改其高度图。
Spawned actor属于LandscapePlaceholder类,它不支持高度映射操作。如何转换它,或者我应该换一种方式?
景观/地形API
UE4中的人族是基于"高度图"概念构建的特殊角色。每个地形都是一个组件网格(ULandscapeComponent(。每个组件都映射到一个包含高度数据的纹理。景观组成部分概念会影响结果的性能和质量。组件是地形的最小渲染单元(可以从渲染和碰撞角度剔除的最小几何体(。关于景观组成部分的简要说明。
要构建一个新的地形(或UE4中的Landscape(,您需要一个高度图。根据该高度映射,UE4 API将生成映射到组件的纹理。高度图是无符号16位值的简单数组(0到65535,32768值被视为"海平面"(。在Python中(出于性能原因和与NumPy的集成(,高度映射是字节数组的(您最终需要重新编译它们(。
创造新的风景
创建具有随机值的高度图:
import unreal_engine as ue
import struct
import random
width = 1024
height = 1024
heightmap = []
# fill the heightmap with random values
for y in range(0, height):
for x in range(0, width):
heightmap.append(random.randint(0, 65535))
data = struct.pack('{0}H'.format(width * height), *heightmap)
现在我们可以将"数据"用于景观API。在填充景观之前,我们需要生成它:
from unreal_engine.classes import Landscape
new_landscape = ue.get_editor_world().actor_spawn(Landscape)
不要运行上一个脚本,因为编辑器不喜欢未初始化的地形(它会崩溃(。使用之前创建的高度地图数据填充地形。选择我们需要的组件数量(网格分辨率(以及每个组件需要的四边形数量(组件几何体由四边形基本体形成(。一旦我们知道地形大小,我们就可以相应地扩展/调整高度图:
unreal_engine.heightmap_expand(data, original_width, original_height, terrain_width, terrain_height)
这将生成一个具有最佳景观尺寸的高度图。
import unreal_engine as ue
import struct
import random
from unreal_engine.classes import Landscape
width = 1024
height = 1024
heightmap = []
for y in range(0, height):
for x in range(0, width):
heightmap.append(random.randint(0, 65535))
data = struct.pack('{0}H'.format(width * height), *heightmap)
quads_per_section = 63
number_of_sections = 1
components_x = 8
components_y = 8
fixed_data = ue.heightmap_expand(data, width, height, quads_per_section * number_of_sections * components_x + 1, quads_per_section * number_of_sections * components_y + 1)
landscape = ue.get_editor_world().actor_spawn(Landscape)
landscape.landscape_import(quads_per_section, number_of_sections, components_x, components_y, fixed_data)
landscape.set_actor_scale(1,1,1)
我们使用"截面"概念,而不是为每个组件指定四边形。UE4允许另一级别的细分以更好地控制优化(LOD和mipmapping(。您可以有1个截面(1x1四边形(或2个截面(2x2四边形(。不支持其他值。四边形的数量与纹理大小有关,因此有效值为:7x7、15x15、31x31、63x63、127x127、255x255(请注意,由于所有地形工具都使用最大值而非大小,因此会出现一点奇怪之处(。您需要仔细选择地形的大小以及高度图。
获取/创建ULandscapeInfo
有关景观/地形的信息存储在一个名为ULandscapeInfo的对象中。要检索它(或者如果你正在进行奇怪的操作,最终创建一个新的(,你有以下两个功能:
landscape_info = landscape.get_landscape_info()
# create a new ULandscapeInfo, required if you do not import an heightmap in a manually spawned landscape
landscape_info = landscape.create_landscape_info()
检索ULandscapeComponent的纹理
要访问地形的高度值,请从每个组件中检索它们:
import unreal_engine as ue
for component in landscape.LandscapeComponents:
heightmap_texture = component.HeightmapTexture
print('{0}x{1} -> {2}'.format(heightmap_texture.texture_get_width(), heightmap_texture.texture_get_height(), len(heightmap_texture.texture_get_source_data())))
这将打印每个横向组件的纹理宽度、高度和数据大小。
将地形导出到FRawMesh
FRawMesh是一种表示网格的特殊结构。您可以使用它来生成新的StaticMesh。您可以使用从景观生成新的FRawMesh
# lod is optional, by default it is 0
raw_mesh = landscape.landscape_export_to_raw_mesh([lod])
Terrains一般都是巨大的。
Heightmap api
公开了高度映射高级API以简化高度映射操作。
# expand the heightmap to fit the new size
expanded_data = ue.heightmap_expand(data, data_width, data_height, new_width, new_height)
# import a heightmap file (r16 or grayscale 16bit png) and returns a bytearray
data = ue.heightmap_import(filename[,width, height])
如果没有指定宽度和高度,它将尝试从文件中检索它们。