当前位置: 首页 > news >正文

虚幻地形高度图生成及测试

虚幻地形高度图生成及测试

虚幻引擎地形系统将高度数据存储在高度图中,这是一个灰阶图像,使用黑白色值来存储地貌高程。在高度图中,纯黑色值表示最低点,纯白色值表示最高点。支持16位灰阶PNG、8位灰阶r8及16位灰阶r16格式。

本文测试使用开源的opencvcgal库将地形网格体采样插值生成栅格,并写入到16位灰阶PNG图片中,结果可支持导入虚幻UE Landscape

示例代码

#include<iostream>
#include<cmath>#include<CGAL/Surface_mesh.h>
#include<CGAL/Surface_mesh/IO/PLY.h>#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/Delaunay_triangulation_2.h>#include <CGAL/Polygon_mesh_processing/locate.h>#include <opencv2/opencv.hpp>using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Projection_traits = CGAL::Projection_traits_xy_3<Kernel>;
using Point_2 = Kernel::Point_2;
using Point_3 = Kernel::Point_3;// Triangulated Irregular Network
using TIN = CGAL::Delaunay_triangulation_2<Projection_traits>;
using Mesh = CGAL::Surface_mesh<Point_3>;int main(){Mesh mesh;CGAL::IO::read_PLY("test.ply",mesh);CGAL::Bbox_3 bbox = CGAL::bbox_3(mesh.points().begin(), mesh.points().end());std::cout << "with:" << bbox.x_span() << "\nheight:" << bbox.y_span() << std::endl;int width = std::ceil(bbox.x_span());int height = std::ceil(bbox.y_span());width = std::max(width, height);height = width;// 特殊处理,虚幻地形表示的范围为512单位 (可略)//  int max_multiple = std::ceil(bbox.zmax() / 512);//  int min_multiple = std::ceil(std::abs(bbox.zmin()) / 512);//  min_multiple = bbox.zmin() < 0 ? min_multiple : 0;int maxHeight = max_multiple * 512;int minHeight = min_multiple * 512;int maxGray = (1 << 16) - 1;//65535 cv::Mat image(height, width, CV_16UC1);TIN tin (mesh.points().begin(), mesh.points().end());TIN::Face_handle location;for (std::size_t y = 0; y < height; ++y)for (std::size_t x = 0; x < width; ++x){Point_3 query(bbox.xmin() + x * (bbox.xmax() - bbox.xmin()) / double(width),bbox.ymin() + (height - y) * (bbox.ymax() - bbox.ymin()) / double(height),0); // not relevant for location in 2Dlocation = tin.locate(query, location);// Points outside the convex hull will be colored blackif (!tin.is_infinite(location)){std::array<double, 3> barycentric_coordinates= CGAL::Polygon_mesh_processing::barycentric_coordinates(Point_2(location->vertex(0)->point().x(), location->vertex(0)->point().y()),Point_2(location->vertex(1)->point().x(), location->vertex(1)->point().y()),Point_2(location->vertex(2)->point().x(), location->vertex(2)->point().y()),Point_2(query.x(), query.y()),Kernel());double height_at_query= (barycentric_coordinates[0] * location->vertex(0)->point().z()+ barycentric_coordinates[1] * location->vertex(1)->point().z()+ barycentric_coordinates[2] * location->vertex(2)->point().z());// 重新映射高度值到0~65535double height_ratio = (height_at_query + minHeight) / (maxHeight+minHeight);image.at<uint16_t>(y,x)=(uint16_t)(height_ratio* maxGray);}else {image.at<uint16_t>(y, x) = (uint16_t)0;}}cv::imwrite("output.png", image);return 0;
}

测试运行

cmake_minimum_required(VERSION 3.1...3.23)
project(main)
# cgal
find_package(CGAL REQUIRED)
# opencv 
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )create_single_source_cgal_program("main.cpp")
target_link_libraries(main PRIVATE ${OpenCV_LIBS})

编译&构建
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=D:\vcpkg\scripts\buildsystems\vcpkg.cmake
cmake --build build --config Debug

结果

测试地形网格
在这里插入图片描述

生成的灰度图
在这里插入图片描述

导入虚幻Landscape
在这里插入图片描述

参考

  1. https://dev.epicgames.com/documentation/zh-cn/unreal-engine/importing-and-exporting-landscape-heightmaps-in-unreal-engine
  2. https://blog.csdn.net/mrbaolong/article/details/141643001?spm=1001.2014.3001.5501

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 数据结构树(C语言版)
  • 华为OD机试 - 猜数字 - 穷举搜索(Java 2024 E卷 100分)
  • docker实战基础三(Docker基础命令)
  • 深度学习100问54:什么是自动图像描述
  • Pyspark中的ROW对象使用
  • [Doc][px4][ros2][gazebo][yolov8]PX4-ROS2-Gazebo-YOLOv8
  • SQL 数据查询
  • 《JavaEE进阶》----8.<SpringMVC实践项目:【简易对话留言板(数据存在内存中)】>
  • 3134. 找出唯一性数组的中位数
  • Go父类调用子类方法(虚函数调用)
  • k8s中pod基础及https密钥、horber仓库
  • 修改服务器DNS解析及修改自动对时时区
  • 零信任赋予安全牙齿,AI促使它更锋利
  • JAVA vs Python:谁更适合后端开发?
  • 软件工程-图书管理系统的需求分析
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 3.7、@ResponseBody 和 @RestController
  • CSS 提示工具(Tooltip)
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • Github访问慢解决办法
  • IDEA常用插件整理
  • JavaScript设计模式系列一:工厂模式
  • JavaScript学习总结——原型
  • Median of Two Sorted Arrays
  • mockjs让前端开发独立于后端
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • vue从创建到完整的饿了么(18)购物车详细信息的展示与删除
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 删除表内多余的重复数据
  • 通过npm或yarn自动生成vue组件
  • 正则表达式
  • 阿里云ACE认证之理解CDN技术
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • (52)只出现一次的数字III
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (JS基础)String 类型
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (一) storm的集群安装与配置
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .NET C# 使用 iText 生成PDF
  • .NET CORE Aws S3 使用
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET MVC第三章、三种传值方式
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .net 反编译_.net反编译的相关问题
  • .NET 命令行参数包含应用程序路径吗?
  • .Net6使用WebSocket与前端进行通信
  • .net下的富文本编辑器FCKeditor的配置方法
  • @Slf4j idea标红Cannot resolve symbol ‘log‘
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • @取消转义