UE4.27中的景观创建

发布于 2025-01-12 21:38:23 字数 739 浏览 2 评论 0 原文

我正在尝试使用 Python Unreal API 创建景观>unreal.EditorLevelLibrary.spawn_actor_from_class() 生成一个 LandscapeProxy actor,然后使用以下命令更改其高度图landscape_import_heightmap_from_render_target() ="nofollow noreferrer">LandscapeProxy 类。

生成的 actor 属于 LandscapePlaceholder 类 不支持高度图操作。如何转换它还是我应该走其他路?

I'm trying to create a landscape with Python Unreal API using unreal.EditorLevelLibrary.spawn_actor_from_class() to spawn a LandscapeProxy actor then alter its heightmap using landscape_import_heightmap_from_render_target() of the LandscapeProxy class.

Spawned actor is of class LandscapePlaceholder which does not support heightmap operations. How to convert it or should I go another way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧城空念 2025-01-19 21:38:23

UE4 中的景观/地形 API

地形是基于“高度图”概念构建的特殊角色。每个地形都是一个组件网格(ULandscapeComponent)。每个组件都映射到保存高度数据的纹理。景观组件概念影响结果的性能和质量。组件是地形的最小渲染单元
(可以从渲染和碰撞的角度剔除的最小几何体)。 关于景观组件的简短说明

要构建新地形(或 UE4 中的景观),您需要一张高度图。 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 和 mipmap)。您可以有 1 个部分(1x1 四边形)或 2 个部分(2x2 四边形)。不支持其他值。四边形的数量与纹理大小相关,因此有效值为:7x7、15x15、31x31、63x63、127x127、255x255(请注意相差一的怪异,因为所有地形工具都使用最大值而不是大小)。您需要仔细选择地形的大小 以及高度图。

获取/创建 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()

检索 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 是表示网格的特殊结构。您可以使用它来生成新的静态网格物体。您可以通过以下方式从景观生成新的 FRawMesh:

# lod is optional, by default it is 0
raw_mesh = landscape.landscape_export_to_raw_mesh([lod])

地形的尺寸通常很大。

高度图 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])

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

The Landscape/Terrain API

Terrains in UE4 are special actors built over the 'heightmap' concept. Each Terrain is a grid of components (ULandscapeComponent). Each component is mapped to a texture holding height data. The landscape component concept impacts performance and quality of the result. A component is the minimal render unit of a terrain
(minimal geometry that can be culled both from the rendering and collisions point of view). A brief explanation on landscape components.

To build a new terrain (or Landscape in UE4) you need a heightmap. From this heightmap the UE4 API will generate textures mapped to components. Heightmaps are simple arrays of unsigned 16bit values (0 to 65535 with 32768 value considered 'sea level'). In Python (for performance reasons and integration with NumPy) heightmaps are bytearray's (you eventually need to recast them).

Creating a new Landscape

Creating a heightmap with random values:

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)

Now 'data' we can use for the landscape API. Before filling a landscape we need to spawn it:

from unreal_engine.classes import Landscape

new_landscape = ue.get_editor_world().actor_spawn(Landscape)

Do not run the previous script as the editor does not like uninitialized terrain (it will crash). Fill the terrain with the heightmap data created before. Choose how many components we need (the grid resolution) and how many quads are required for each component (component geometry is formed by quad primitives). Once we know terrain size we can expand/adapt the heightmap accordingly:

unreal_engine.heightmap_expand(data, original_width, original_height, terrain_width, terrain_height)

This will generate a heightmap with the optimal dimensions for the landscape.

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)

Instead of specifying quads per component we are using the 'section' concept. UE4 allows another level of subdivision for better control of optimizations (LOD and mipmapping). You can have 1 section (1x1 quad) or 2 (2x2 quads). Other values are not supported. Number of quads is related to textures size, so valid values are: 7x7, 15x15, 31x31, 63x63, 127x127, 255x255 (note the off-by-one weirdness as all terrain tools work with max value and not size). You need to carefully choose the size of the terrain as well as the heightmap.

Getting/Creating ULandscapeInfo

Information about a Landscape/Terrain are stored in a uobject called ULandscapeInfo. To retrieve it (or eventually create a new one if you are making weird operations) you have following two functions:

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

Retrieving ULandscapeComponent's textures

To access height values of a terrain, retrieve them from each component:

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

This will print texture width, height and data size of each landscape component.

Exporting the Terrain to a FRawMesh

FRawMesh is a special structure representing a mesh. You can use it to generate a new StaticMesh. You can generate a new FRawMesh from a landscape with:

# lod is optional, by default it is 0
raw_mesh = landscape.landscape_export_to_raw_mesh([lod])

Terrains generally are huge in size.

The Heightmap api

A heightmap high-level API is exposed to simplify heightmap manipulation.

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

If width and height are not specified it will try to retrieve them from the file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文