鸿蒙原子化服务+CryEngine:一键生成3D可视化工具的小程序开发

进修的泡芙
发布于 2025-6-9 20:37
浏览
0收藏

引言

鸿蒙(HarmonyOS)的原子化服务(Atomic Service)以“轻量化、即点即用”为核心,用户无需安装完整应用,通过“原子化卡片”即可快速调用高频功能。结合CryEngine的高性能3D渲染能力,可开发一款“一键生成3D测量/标注工具”的原子化小程序,实现“拍照→生成3D模型→实时标注→导出数据”的全流程轻量化操作。本文将从原子化服务架构设计、CryEngine集成、3D交互逻辑到代码实现,详解开发全流程。

一、核心需求与技术架构

1.1 需求场景

用户通过原子化卡片快速完成以下操作:
3D建模:上传或拍摄房间/家具照片,自动生成简化3D模型。

测量标注:在3D模型上点击两点测量距离,或框选区域计算面积。

数据导出:生成测量报告(文本/图片),支持分享至鸿蒙设备或其他应用。

1.2 技术架构

原子化服务作为前端入口,负责用户交互与轻量化逻辑;CryEngine作为渲染引擎,嵌入原子化服务中处理3D模型加载、交互渲染;鸿蒙分布式能力(如@ohos.distributedData)实现测量数据的跨设备同步。

架构图如下:

原子化卡片(鸿蒙UI) → 触发CryEngine渲染 → 3D模型加载 → 用户交互(触摸/手势) → 测量算法计算 → 结果展示/导出

二、环境准备与工具链

2.1 硬件与软件需求
开发机:Windows 10/11(CryEngine编辑器仅支持Windows)。

目标设备:鸿蒙手机/平板(如华为MatePad 11,API 9+,支持原子化服务)。

工具链:

CryEngine 5.1(Vulkan渲染后端,需集成鸿蒙NDK)。

DevEco Studio 3.2+(鸿蒙原子化服务开发)。

3D建模工具(Blender,用于生成测试模型)。

2.2 原子化服务注册与配置
创建原子化服务工程:

在DevEco Studio中新建“Atomic Service”工程(包名:com.example.3dmeasure),选择“API 9”(支持原子化卡片)。
配置CryEngine集成:

将CryEngine的Vulkan渲染库(.so文件)放入entry/src/main/jniLibs/arm64-v8a目录。

在build.gradle中添加依赖:

      android {
     sourceSets {
         main {
             jniLibs.srcDirs = ['libs', 'src/main/jniLibs/']

}

声明原子化服务能力:

在config.json中添加原子化服务元数据:
“app”: {

   "abilities": [

“name”: “.MainAbility”,

       "type": "atomicService",
       "icon": "$media:icon",
       "label": "3D测量工具",
       "skills": [

“entities”: [“entity.system.home”],

           "actions": ["action.system.measure"]

]

]

}

三、CryEngine集成:轻量化3D渲染模块

3.1 原子化服务中嵌入CryEngine视图

原子化服务的主界面由AbilitySlice管理,需将CryEngine的渲染视图(CRenderView)嵌入其中。关键代码如下:

ArkTS端(主界面)
// MainAbilitySlice.ets
import nativeEngine from ‘@ohos.nativeEngine’;

@Entry
@Component
struct MainAbilitySlice {
private nativeView: nativeEngine.NativeView = null;

aboutToAppear() {
// 初始化CryEngine
nativeEngine.invoke(‘InitCryEngine’, (err, data) => {
if (err.code === 0) {
// 创建并挂载CryEngine渲染视图
this.nativeView = new nativeEngine.NativeView({
width: ‘100%’,
height: ‘100%’,
backgroundColor: ‘#FFFFFF’
});
this.content.insertAdjacentView(this.nativeView, ‘beforeEnd’);
else {

    Text('引擎初始化失败!')
      .fontSize(20)
      .color('#FF0000')

});

build() {

Column() {
  if (this.nativeView) {
    this.nativeView

else {

    Text('正在加载3D引擎...')
      .fontSize(20)
      .color('#666666')

}

.width('100%')
.height('100%')

}

C++端(引擎初始化)
// EngineInit.cpp
include <hilog/log.h>

include <ohos/aafwk/content/window.h>

include “CryEngine.h”

// 鸿蒙窗口句柄(通过AbilitySlice传递)
extern OHOS::Window* g_harmonyWindow;

// 全局引擎指针
CCrySystem* g_pSystem = nullptr;

bool InitCryEngineForAtomic() {
// 初始化CryEngine核心系统
g_pSystem = CCrySystem::GetInstance();
if (!g_pSystem->Initialize()) {
HILOG_ERROR(“CryEngine system init failed”);
return false;
// 创建Vulkan渲染器(适配鸿蒙)

CRenderer* pRenderer = gEnv->pRenderer;
SRendererInitParams rendererParams;
rendererParams.pWindow = g_harmonyWindow->GetNativeWindow(); // 绑定鸿蒙窗口
rendererParams.eRenderer = eRenderer_Vulkan;
rendererParams.width = 1080; // 原子化服务默认宽度
rendererParams.height = 1920; // 原子化服务默认高度
if (!pRenderer->Initialize(rendererParams)) {
HILOG_ERROR(“Renderer init failed”);
return false;
// 设置资源路径(指向原子化服务本地Assets)

gEnv->pFileIO->SetAlias(“@assets@”, “@ohos.assets@/CryEngine/Assets”);
return true;
// 导出为鸿蒙可调用的函数

extern “C” attribute((visibility(“default”))) bool InitEngine() {
return InitCryEngineForAtomic();

四、3D测量核心逻辑:从交互到计算

4.1 3D模型加载与简化

为实现“一键生成”,需将用户上传的照片或场景快速转换为3D模型。这里采用照片建模简化方案:使用预训练的深度学习模型(如MiDaS)生成深度图,结合CryEngine的网格生成工具快速创建简化模型。

代码示例:模型生成(C++)
// ModelGenerator.cpp
include “CryEngine.h”

include <opencv2/opencv.hpp> // 使用OpenCV处理深度图

// 生成简化3D模型(基于深度图)
bool GenerateSimplifiedModel(const std::string& depthImagePath, const std::string& outputPath) {
// 读取深度图(假设已通过AI模型生成)
cv::Mat depthMap = cv::imread(depthImagePath, cv::IMREAD_ANYDEPTH);
if (depthMap.empty()) {
HILOG_ERROR(“Depth map load failed”);
return false;
// 创建CryEngine网格

_smart_ptr<IMesh> pMesh = gEnv->pRenderer->CreateMesh();
std::vector<Vec3> vertices;
std::vector<Vec2> texCoords;
std::vector<uint16> indices;

// 简化网格生成(按固定步长采样深度图)
int step = 10; // 控制模型面数(步长越大,面数越少)
for (int y = 0; y < depthMap.rows; y += step) {
for (int x = 0; x < depthMap.cols; x += step) {
float depth = depthMap.at<ushort>(y, x) / 1000.0f; // 深度值转米
Vec3 pos(x 0.01f, -y 0.01f, -depth); // 坐标转换(假设相机朝Z轴负方向)
vertices.push_back(pos);
texCoords.push_back(Vec2(x / (float)depthMap.cols, y / (float)depthMap.rows));
if (x > 0 && y > 0) {
uint16 topLeft = (y/step)*((depthMap.cols/step)) + (x/step);
uint16 topRight = topLeft + 1;
uint16 bottomLeft = topLeft + (depthMap.cols/step);
indices.push_back(topLeft);
indices.push_back(bottomLeft);
indices.push_back(topRight);
}

// 设置网格数据

pMesh->SetVertices(vertices.data(), vertices.size());
pMesh->SetTexCoords(texCoords.data(), texCoords.size());
pMesh->SetIndices(indices.data(), indices.size());

// 保存模型到Assets
gEnv->pFileIO->WriteFile(outputPath, pMesh->GetRawData(), pMesh->GetRawSize());
return true;

4.2 触摸交互与测量逻辑

用户在3D模型上点击两点,计算两点间距离;框选区域时,通过凸包算法计算面积。

代码示例:测量逻辑(C++)
// MeasureTool.cpp
include “CryEngine.h”

include <vector>

include <algorithm> // 用于凸包计算

// 计算两点间距离
float CalculateDistance(const Vec3& p1, const Vec3& p2) {
return sqrt(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2) + pow(p2.z - p1.z, 2));
// 计算多边形面积(凸包)

float CalculatePolygonArea(const std::vector<Vec2>& points) {
if (points.size() < 3) return 0.0f;

// 凸包算法(Andrew’s Monotone Chain)
std::vector<Vec2> hull;
std::sort(points.begin(), points.end(), const Vec2& a, const Vec2& b {
return a.x < b.x || (a.x == b.x && a.y < b.y);
});

// 构建下凸包
for (const auto& p : points) {
while (hull.size() >= 2 && Cross(hull.back() - hull[hull.size()-2], p - hull.back()) <= 0) {
hull.pop_back();
hull.push_back§;

// 构建上凸包

size_t lower_size = hull.size();
for (auto it = points.rbegin(); it != points.rend(); ++it) {
const auto& p = *it;
while (hull.size() > lower_size && Cross(hull.back() - hull[hull.size()-2], p - hull.back()) <= 0) {
hull.pop_back();
hull.push_back§;

// 计算面积

float area = 0.0f;
for (size_t i = 0; i < hull.size() - 1; ++i) {
area += Cross(hull[i], hull[i+1]);
return fabs(area) / 2.0f;

// 处理触摸事件(传递自鸿蒙UI)

void OnTouchEvent(const TouchEvent& event) {
static std::vector<Vec3> selectedPoints;

if (event.type == TouchType::DOWN) {
// 将屏幕坐标转换为3D世界坐标(需考虑相机投影)
Vec3 worldPos = ConvertScreenToWorld(event.touches[0].x, event.touches[0].y);
selectedPoints.push_back(worldPos);

// 渲染选中点(添加球体标记)
AddSphereMarker(worldPos, 0.05f, Vec3(1, 0, 0)); // 红色标记

else if (event.type == TouchType::UP && selectedPoints.size() >= 2) {

// 计算距离并显示
float distance = CalculateDistance(selectedPoints[0], selectedPoints[1]);
ShowMeasurementResult("距离:%.2f米", distance);

// 清空选中点
selectedPoints.clear();

}

4.3 结果展示与导出

测量结果通过原子化卡片的文本组件展示,并支持导出为图片或文本文件(利用鸿蒙的@ohos.fileio接口)。

ArkTS端(结果展示)
// MainAbilitySlice.ets
import fileio from ‘@ohos.fileio’;

@State resultText: string = ‘’;
@State measurementImage: Resource = $r(‘app.media.default_image’);

// 显示测量结果
function showResult(text: string) {
this.resultText = text;
// 导出结果为图片

function exportResult() {
// 获取CryEngine渲染的当前帧为图片
nativeEngine.invoke(‘CaptureRenderImage’, (err, imagePath) => {
if (err.code === 0) {
// 保存图片到本地
fileio.open(imagePath, fileio.OpenMode.READ_ONLY).then((fd) => {
fileio.write(fd, imagePath, ‘measurement_result.png’).then(() => {
prompt.showToast({ message: ‘导出成功’ });
});
});
});

build() {

Column() {
// 3D渲染视图
if (this.nativeView) {
this.nativeView
// 测量结果显示

Text(this.resultText)
  .fontSize(20)
  .margin({ top: 20 })

// 导出按钮
Button('导出结果')
  .onClick(() => this.exportResult())
  .margin({ top: 20 })

}

五、测试与优化:轻量化体验保障

5.1 性能瓶颈与优化策略
瓶颈 现象 解决方案

3D渲染卡顿 帧率<30FPS 启用动态分辨率缩放(DRS);降低模型面数(目标<5000面)。
模型生成耗时 照片转3D耗时>5s 优化深度图生成算法(使用轻量级AI模型);预加载常用场景模型。
触摸交互延迟 点击响应慢 优化坐标转换算法(使用近似计算);减少渲染线程阻塞。

5.2 调试工具推荐
鸿蒙调试:使用DevEco Studio的“Device Manager”查看原子化服务状态,通过“HiProfiler”分析应用性能。

CryEngine调试:启用Render Debugger(Ctrl+Alt+F11)查看渲染耗时,检查材质/光照是否正确应用。

结语

通过鸿蒙原子化服务的轻量化入口与CryEngine的高性能3D渲染能力,我们开发了一款“一键生成3D测量/标注工具”的小程序。核心在于利用鸿蒙的原子化服务机制实现即点即用,结合CryEngine的快速模型生成与交互渲染能力,将传统3D测量工具的复杂流程简化为“拍照→生成→标注→导出”的一站式操作。未来可扩展支持更多场景(如家具摆放模拟、空间规划),或结合鸿蒙的空间计算能力(如AR投影),进一步提升工具的实用性。

附录:完整项目结构示例

3DMeasureAtomic/
├── entry/src/main/ets/ # 鸿蒙原子化服务代码
├── MainAbilitySlice.ets # 主界面逻辑

└── MeasurementResult.ets # 结果展示组件

├── entry/src/main/cpp/ # C++渲染与测量逻辑
├── EngineInit.cpp # 引擎初始化

├── ModelGenerator.cpp # 模型生成

└── MeasureTool.cpp # 测量计算

├── jniLibs/arm64-v8a/ # CryEngine动态库
└── libCryEngine.so

└── Assets/ # CryEngine资源
├── Models/ # 测试模型(简化房间、家具)
└── Textures/ # 材质贴图(PNG/JPG)

分类
收藏
回复
举报
回复
    相关推荐