使用python在UE4.27中创建景观

nwsw7zdq  于 2022-10-30  发布在  Python
关注(0)|答案(1)|浏览(129)

我一直在尝试用python脚本using the python unreal API在ue中创建一个风景。我用正常的方法使用unreal.EditorLevelLibrary.spawn_actor_from_class()生成一个LandscapeProxy演员,然后使用LandscapeProxy类的landscape_import_heightmap_from_render_target()修改它的heightmap。

  • 不幸的是 * 衍生的演员是类LandscapePlaceholder,它不支持任何heightmap操作,由于没有示例和缺乏python unreal API的文档,我似乎也找不到转换它的方法。

有没有一种方法可以转换,或者我应该走另一条路?

mrfwxfqh

mrfwxfqh1#

景观/地形API

UE4中的地形是基于“高度图”概念构建的特殊角色。
每个Terrain都是一个组件网格(ULandscapeComponent).每个组件都Map到一个保存高度数据得纹理.
景观组件的概念非常重要,因为它影响着结果的性能和质量。组件是地形的最小渲染单元(因此,从渲染和碰撞的Angular 来看,它是可以剔除的最小几何体)。
有关景观组成部分的简要说明,请访问:https://docs.unrealengine.com/latest/INT/Engine/Landscape/TechnicalGuide/#componentsections
要构建一个新的地形(或者UE4中的Landscape),你需要得到一个heightmap。UE4 api将从这个heightmap生成Map到组件的纹理。
高度图是无符号16位值的简单数组(0到65535,32768值被视为“海平面”)。
在Python中(出于性能原因,也为了简化与numpy的集成),heightsmap被表示为bytearray的(所以最终需要重新转换它们)。

创造新的风景

我们首先用随机值创建一个高度图:

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)

注意:不要运行前面的脚本,因为编辑器不喜欢未初始化的地形。(读作:它将残酷地崩溃)
现在是时候用我们之前创建的heightmap数据填充地形了,我们需要选择需要多少个组件(网格分辨率),以及每个组件需要多少个四边形(每个组件几何体都是由简单的四边形图元组成的)。
一旦我们知道了地形的大小,我们就可以使用一个特殊的UE4 api函数相应地扩展/调整heightmap:

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...)。更多详细信息,请访问:
https://docs.unrealengine.com/latest/INT/Engine/Landscape/TechnicalGuide/#componentsections
您可以有1个部分(1x 1四元组)或2个部分(2x2四元组)。不支持其他值。
甚至四边形的数量也与纹理大小相关,因此有效值为:7 x7、15 x15、31 x31、63 x63、127 x127、255 x255(请注意相差1的怪异之处,因为所有地形工具都使用最大值而不是大小)
请注意,您需要仔细选择地形的大小以及高度图:
https://docs.unrealengine.com/latest/INT/Engine/Landscape/TechnicalGuide/index.html#calculatingheightmapdimensions

获取/创建ULandscapeInfo

有关景观/地形的信息存储在一个名为ULandscapeInfo的特殊uobject中。
要检索它(或者如果您正在进行奇怪的操作,最终创建一个新的),您有以下两个函数:

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()

正在检索ULandscape组件的纹理

如果要访问terrain的高度值,则需要从每个组件中检索它们:

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是一种特殊的网格表示结构,可以在UE4中生成新的静态网格。
更多信息可在此处检索:
https://github.com/20tab/UnrealEnginePython/blob/master/tutorials/SnippetsForStaticAndSkeletalMeshes.md
您可以使用此函数从风景中生成新的FRawMesh:


# lod is optional, by default it is 0

raw_mesh = landscape.landscape_export_to_raw_mesh([lod])

请记住,地形通常是巨大的大小:)

高度图API

公开了一个heightmap高级api,以简化heightmap操作。


# 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])

如果未指定宽度和高度,系统将尝试从文件中检索它们

相关问题