UE4并没有明确提供相关接口实现地形网格的导出,只有在导出所选项的地方可以导出地形网格数据。

所以想要获取到地形网格,就需要一点手段。下图中红框所示可以获取到导出FBX模型的时候,编辑器的执行堆栈。下个断点就可以。

Mesh数据并没有直接暴露给我们使用,使用了一个FLandscapeComponentDataInterface的类来读取数据,类初始化的时候需要提供ULandscapeComponent对象指针(储存在ALandscapeProxy类,可以通过转型获取)。

auto Landscape = dynamic_cast<ALandscapeProxy*>(AActor);
if (!Landscape)return;

const int32 ComponentSizeQuads = ((Landscape->ComponentSizeQuads + 1)>> Landscape->ExportLOD) - 1;
const float ScaleFactor = (float)Landscape->ComponentSizeQuads / (float)ComponentSizeQuads;
const int32 NumComponents = Landscape>LandscapeComponents.Num();
const int32 VertexCountPerComponent = FMath::Square(ComponentSizeQuads + 1);

for (int32 ComponentIndex = 0; ComponentIndex < Landscape>LandscapeComponents.Num(); ComponentIndex++)
{
	ULandscapeComponent* Component = Landscape>LandscapeComponents[ComponentIndex];
	FLandscapeComponentDataInterface CDI(Component, Landscape>ExportLOD);
	for (int32 VertIndex = 0; VertIndex < VertexCountPerComponent; VertIndex++)
	{
	int32 VertX, VertY;
	CDI.VertexIndexToXY(VertIndex, VertX, VertY);

	FVector Position = CDI.GetLocalVertex(VertX, VertY) + Component>GetRelativeLocation();
        // 此处Position即为UE4地形网格顶点
}

不过此时获取的仅仅是网格顶点数据,并不包含索引数据。FLandscapeComponentDataInterface同时也提供了获取法线,切线,副切线的函数(GetLocalTangentVectors)。注意函数参数为:

(顶点X索引,顶点Y索引,切线引用,副切线引用,法线引用)

FVector Normal, TangentX, TangentY;
CDI.GetLocalTangentVectors(VertX, VertY, TangentX, TangentY, Normal);

//UV纹理坐标
FVector2D TextureUV = FVector2D(VertX * ScaleFactor + Component>GetSectionBase().X,
 VertY * ScaleFactor + Component->GetSectionBase().Y);

顶点索引需要我们自己创建

for (int32 ComponentIndex = 0; ComponentIndex < NumComponents; ComponentIndex++)
{
	int32 BaseVertIndex = ComponentIndex * VertexCountPerComponent;
	for (int32 Y = 0; Y < ComponentSizeQuads; Y++)
	{
		for (int32 X = 0; X < ComponentSizeQuads; X++)
		{
			IndicesData.emplace_back(BaseVertIndex + (X + 0) + (Y + 0) * (ComponentSizeQuads + 1));
			IndicesData.emplace_back(BaseVertIndex + (X + 1) + (Y + 1) * (ComponentSizeQuads + 1));
			IndicesData.emplace_back(BaseVertIndex + (X + 1) + (Y + 0) * (ComponentSizeQuads + 1));

			IndicesData.emplace_back(BaseVertIndex + (X + 0) + (Y + 0) * (ComponentSizeQuads + 1));
			IndicesData.emplace_back(BaseVertIndex + (X + 0) + (Y + 1) * (ComponentSizeQuads + 1));
			IndicesData.emplace_back(BaseVertIndex + (X + 1) + (Y + 1) * (ComponentSizeQuads + 1));
		}
	}
}

需要注意的是,顶点索引数据是从一个四边形中切出来的,所以在循环中需要添加两次三角形。

通过这些顶点数据,我们就可以自己操作生成静态网格了

分类: C++

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注