diff --git a/entry/build-profile.json5 b/entry/build-profile.json5 index 1bd9d4eb..94c68961 100644 --- a/entry/build-profile.json5 +++ b/entry/build-profile.json5 @@ -17,7 +17,7 @@ "arkOptions": { "runtimeOnly" : { "packages": [ - "libOCCTRender.so" + "libocctrender.so" ] } } diff --git a/entry/oh-package-lock.json5 b/entry/oh-package-lock.json5 index 31b060cd..d1581864 100644 --- a/entry/oh-package-lock.json5 +++ b/entry/oh-package-lock.json5 @@ -6,13 +6,13 @@ "lockfileVersion": 3, "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.", "specifiers": { - "libOCCTRender.so@src/main/cpp/types/libOCCTRender": "libOCCTRender.so@src/main/cpp/types/libOCCTRender" + "libocctrender.so@src/main/cpp/types/libocctrender": "libocctrender.so@src/main/cpp/types/libocctrender" }, "packages": { - "libOCCTRender.so@src/main/cpp/types/libOCCTRender": { - "name": "libOCCTRender.so", + "libocctrender.so@src/main/cpp/types/libocctrender": { + "name": "libocctrender.so", "version": "1.0.0", - "resolved": "src/main/cpp/types/libOCCTRender", + "resolved": "src/main/cpp/types/libocctrender", "registryType": "local" } } diff --git a/entry/oh-package.json5 b/entry/oh-package.json5 index ab43ae2b..301af059 100644 --- a/entry/oh-package.json5 +++ b/entry/oh-package.json5 @@ -6,6 +6,6 @@ "author": "", "license": "", "dependencies": { - "libOCCTRender.so": "file:./src/main/cpp/types/libOCCTRender" + "libocctrender.so": "file:./src/main/cpp/types/libocctrender" } } \ No newline at end of file diff --git a/entry/src/main/cpp/CMakeLists.txt b/entry/src/main/cpp/CMakeLists.txt index 70e0368f..6139e7e9 100644 --- a/entry/src/main/cpp/CMakeLists.txt +++ b/entry/src/main/cpp/CMakeLists.txt @@ -14,31 +14,8 @@ include_directories(${NATIVERENDER_ROOT_PATH} ${NATIVERENDER_ROOT_PATH}/include) # OCCT库配置 -set(OCCT_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include/opencascade) set(OCCT_LIB_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}) - -# 添加OCCT库 link_directories(${OCCT_LIB_DIR}) -include_directories(${OCCT_INCLUDE_DIR}) - -# 添加源文件 -add_library(OCCTRender SHARED - napi_init.cpp - #Header - EGLCore/EGLCore.h - OCCTRender/OCCTRender.h - OCCTRenderThread/OCCTRenderThread.h - #Cpp Src - EGLCore/EGLCore.cpp - OCCTRender/OCCTRender.cpp - OCCTRenderThread/OCCTRenderThread.cpp - ) - -find_library(EGL-lib EGL) -find_library(GLES-lib GLESv3) -find_library(hilog-lib hilog_ndk.z) -find_library(libace-lib ace_ndk.z) -find_library(libuv-lib uv) set(OCCT_LIBS ${OCCT_LIB_DIR}/libTKernel.so.7.9 @@ -77,8 +54,26 @@ set(OCCT_LIBS ${OCCT_LIB_DIR}/libbrotlidec.so.1 ${OCCT_LIB_DIR}/libbrotlienc.so.1 ) +# 添加源文件 +add_library(occtrender SHARED + napi_init.cpp + #Header + EGLCore/EGLCore.h + OCCTRender/OCCTRender.h + OCCTRenderThread/OCCTRenderThread.h + #Cpp Src + EGLCore/EGLCore.cpp + OCCTRender/OCCTRender.cpp + OCCTRenderThread/OCCTRenderThread.cpp + ) -target_link_libraries(OCCTRender PUBLIC +find_library(EGL-lib EGL) +find_library(GLES-lib GLESv3) +find_library(hilog-lib hilog_ndk.z) +find_library(libace-lib ace_ndk.z) +find_library(libuv-lib uv) + +target_link_libraries(occtrender PUBLIC # OCCT核心库 ${OCCT_LIBS} #EGL Hilog库 diff --git a/entry/src/main/cpp/OCCT方案.txt b/entry/src/main/cpp/OCCT方案.txt new file mode 100644 index 00000000..e1b6964c --- /dev/null +++ b/entry/src/main/cpp/OCCT方案.txt @@ -0,0 +1,12 @@ +按照下面要求生成实现代码: +1-HarmonyOS API 版本:22 +2-OpenGL ES 版本:3.0 +3-OCCT 版本:7.9.3 +4-分别用类名字为EGLCore OCCTRenderThread OCCTRender实现 +5-实现主线程和渲染线程分离.渲染线程循环渲染 +6-实现通过loadmodel加载step文件进行渲染step模型 +7-实现鼠标旋转相机观察渲染的模型. +8-Arkui通过XComponent的Native进行调用实现. +9-不得使用android的实现代码.使用鸿蒙原生API实现 +10-在napi_init.cpp文件中写出给arkui调用的函数.包括回调函数 +11-在Index.d.ts文件中写出暴露给arkui调用的代码 \ No newline at end of file diff --git a/entry/src/main/cpp/napi_init.cpp b/entry/src/main/cpp/napi_init.cpp index c7ed47ec..84105738 100644 --- a/entry/src/main/cpp/napi_init.cpp +++ b/entry/src/main/cpp/napi_init.cpp @@ -1,140 +1,115 @@ #include "napi/native_api.h" -//#include "OCCTRenderThread/OCCTRenderThread.h" +#include "OCCTRenderThread/OCCTRenderThread.h" #include #include -//#define LOG_TAG "NAPI_INIT" -//#define LOGI(...) (LOG_TAG, __VA_ARGS__) -// -////存储 XComponent ID 到 OCCTRenderThread 实例的映射 -//static std::map g_renderThreads; -// -////NAPI: 初始化渲染器(绑定 XComponent) -//static napi_value InitRenderer(napi_env env, napi_callback_info info) { -// size_t argc = 3; -// napi_value args[3]; -// napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); -// -// // 参数1: xcomponentId (string) -// char xcompId[256]; -// size_t xcompIdLen; -// napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &xcompIdLen); -// -// // 参数2: nativeWindow (EGLNativeWindowType, 实际是 void*) -// EGLNativeWindowType window = nullptr; -// napi_get_value_external(env, args[1], reinterpret_cast(&window)); -// -// // 参数3: { width, height } -// int32_t width = 0, height = 0; -// napi_valuetype type; -// napi_typeof(env, args[2], &type); -// if (type == napi_object) { -// napi_value w, h; -// napi_get_named_property(env, args[2], "width", &w); -// napi_get_named_property(env, args[2], "height", &h); -// napi_get_value_int32(env, w, &width); -// napi_get_value_int32(env, h, &height); -// } -// -// // 创建渲染线程 -// LOGI('Init RenderThread'); -// auto* renderThread = new OCCTRenderThread(window, width, height); -// renderThread->start(); -// LOGI('Deno Init RenderThread'); -// g_renderThreads[std::string(xcompId)] = renderThread; -// -// return nullptr; -//} -// -//// NAPI: 加载 STEP 模型 -//static napi_value LoadModel(napi_env env, napi_callback_info info) { -// LOGI('Start LoadModel'); -// size_t argc = 2; -// napi_value args[2]; -// napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); -// -// char xcompId[256]; -// size_t len; -// napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); -// -// char modelPath[1024]; -// size_t pathLen; -// napi_get_value_string_utf8(env, args[1], modelPath, sizeof(modelPath), &pathLen); -// LOGI('Find RenderThread'); -// auto it = g_renderThreads.find(std::string(xcompId)); -// if (it != g_renderThreads.end()) { -// LOGI('LoadModel Began'); -// it->second->loadModel(modelPath); -// } -// -// return nullptr; -//} -// -//// NAPI: 鼠标/触摸事件(可选,用于旋转) -//static napi_value OnMouseEvent(napi_env env, napi_callback_info info) { -// size_t argc = 3; -// napi_value args[3]; -// napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); -// -// char xcompId[256]; -// size_t len; -// napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); -// -// double dx, dy; -// napi_get_value_double(env, args[1], &dx); -// napi_get_value_double(env, args[2], &dy); -// -// auto it = g_renderThreads.find(std::string(xcompId)); -// if (it != g_renderThreads.end()) { -// it->second->onMouseEvent(static_cast(dx), static_cast(dy)); -// } -// -// return nullptr; -//} -// -//// NAPI: 销毁渲染器 -//static napi_value DestroyRenderer(napi_env env, napi_callback_info info) { -// size_t argc = 1; -// napi_value args[1]; -// napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); -// -// char xcompId[256]; -// size_t len; -// napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); -// -// auto it = g_renderThreads.find(std::string(xcompId)); -// if (it != g_renderThreads.end()) { -// it->second->stop(); -// delete it->second; -// g_renderThreads.erase(it); -// } -// -// return nullptr; -//} +#define LOG_TAG "NAPI_INIT" +#define LOGI(...) (LOG_TAG, __VA_ARGS__) -static napi_value Add(napi_env env, napi_callback_info info) -{ - size_t argc = 2; - napi_value args[2] = {nullptr}; +//存储 XComponent ID 到 OCCTRenderThread 实例的映射 +static std::map g_renderThreads; +//NAPI: 初始化渲染器(绑定 XComponent) +static napi_value InitRenderer(napi_env env, napi_callback_info info) { + size_t argc = 3; + napi_value args[3]; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); - napi_valuetype valuetype0; - napi_typeof(env, args[0], &valuetype0); + // 参数1: xcomponentId (string) + char xcompId[256]; + size_t xcompIdLen; + napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &xcompIdLen); - napi_valuetype valuetype1; - napi_typeof(env, args[1], &valuetype1); + // 参数2: nativeWindow (EGLNativeWindowType, 实际是 void*) + EGLNativeWindowType window = nullptr; + napi_get_value_external(env, args[1], reinterpret_cast(&window)); - double value0; - napi_get_value_double(env, args[0], &value0); + // 参数3: { width, height } + int32_t width = 0, height = 0; + napi_valuetype type; + napi_typeof(env, args[2], &type); + if (type == napi_object) { + napi_value w, h; + napi_get_named_property(env, args[2], "width", &w); + napi_get_named_property(env, args[2], "height", &h); + napi_get_value_int32(env, w, &width); + napi_get_value_int32(env, h, &height); + } - double value1; - napi_get_value_double(env, args[1], &value1); + // 创建渲染线程 + LOGI('Init RenderThread'); + auto* renderThread = new OCCTRenderThread(window, width, height); + renderThread->start(); + LOGI('Deno Init RenderThread'); + g_renderThreads[std::string(xcompId)] = renderThread; - napi_value sum; - napi_create_double(env, value0 + value1, &sum); + return nullptr; +} - return sum; +// NAPI: 加载 STEP 模型 +static napi_value LoadModel(napi_env env, napi_callback_info info) { + LOGI('Start LoadModel'); + size_t argc = 2; + napi_value args[2]; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + char xcompId[256]; + size_t len; + napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); + + char modelPath[1024]; + size_t pathLen; + napi_get_value_string_utf8(env, args[1], modelPath, sizeof(modelPath), &pathLen); + LOGI('Find RenderThread'); + auto it = g_renderThreads.find(std::string(xcompId)); + if (it != g_renderThreads.end()) { + LOGI('LoadModel Began'); + it->second->loadModel(modelPath); + } + + return nullptr; +} + +// NAPI: 鼠标/触摸事件(可选,用于旋转) +static napi_value OnMouseEvent(napi_env env, napi_callback_info info) { + size_t argc = 3; + napi_value args[3]; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + char xcompId[256]; + size_t len; + napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); + + double dx, dy; + napi_get_value_double(env, args[1], &dx); + napi_get_value_double(env, args[2], &dy); + + auto it = g_renderThreads.find(std::string(xcompId)); + if (it != g_renderThreads.end()) { + it->second->onMouseEvent(static_cast(dx), static_cast(dy)); + } + + return nullptr; +} + +// NAPI: 销毁渲染器 +static napi_value DestroyRenderer(napi_env env, napi_callback_info info) { + size_t argc = 1; + napi_value args[1]; + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + char xcompId[256]; + size_t len; + napi_get_value_string_utf8(env, args[0], xcompId, sizeof(xcompId), &len); + + auto it = g_renderThreads.find(std::string(xcompId)); + if (it != g_renderThreads.end()) { + it->second->stop(); + delete it->second; + g_renderThreads.erase(it); + } + + return nullptr; } EXTERN_C_START @@ -143,11 +118,10 @@ static napi_value Init(napi_env env, napi_value exports) { return nullptr; } napi_property_descriptor desc[] = { - //{"initRenderer", nullptr, InitRenderer,nullptr, nullptr, nullptr, napi_default, nullptr}, - //{"loadModel", nullptr, LoadModel,nullptr, nullptr, nullptr, napi_default, nullptr}, - //{"onMouseEvent", nullptr, OnMouseEvent,nullptr, nullptr, nullptr, napi_default, nullptr}, - //{"destroyRenderer", nullptr, DestroyRenderer,nullptr, nullptr, nullptr, napi_default, nullptr}, - { "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr } + {"initRenderer", nullptr, InitRenderer,nullptr, nullptr, nullptr, napi_default, nullptr}, + {"loadModel", nullptr, LoadModel,nullptr, nullptr, nullptr, napi_default, nullptr}, + {"onMouseEvent", nullptr, OnMouseEvent,nullptr, nullptr, nullptr, napi_default, nullptr}, + {"destroyRenderer", nullptr, DestroyRenderer,nullptr, nullptr, nullptr, napi_default, nullptr}, }; if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) { @@ -158,17 +132,17 @@ static napi_value Init(napi_env env, napi_value exports) { EXTERN_C_END // 编写接口的描述信息,根据实际需要可以修改对应参数 -static napi_module OCCTModel = { +static napi_module occtmodel = { .nm_version = 1, .nm_flags = 0, .nm_filename = nullptr, .nm_register_func = Init, - .nm_modname = "OCCTRender", + .nm_modname = "occtrender", .nm_priv = ((void*)0), .reserved = { 0 } }; extern "C" __attribute__((constructor)) void RegisterModule(void) { - napi_module_register(&OCCTModel); + napi_module_register(&occtmodel); } \ No newline at end of file diff --git a/entry/src/main/cpp/types/libOCCTRender/Index.d.ts b/entry/src/main/cpp/types/libOCCTRender/Index.d.ts index db67e6da..a7686267 100644 --- a/entry/src/main/cpp/types/libOCCTRender/Index.d.ts +++ b/entry/src/main/cpp/types/libOCCTRender/Index.d.ts @@ -1,6 +1,5 @@ // Index.d.ts -//export const initRenderer:(id: string, nativeWindow: any, size: { width: number; height: number }) => void; -//export const loadModel:(id: string, modelPath: string)=> void; -//export const onMouseEvent:(id: string, dx: number, dy: number)=> void; -//export const destroyRenderer:(id: string)=> void; -export const add: (a: number, b: number) => number; \ No newline at end of file +export const initRenderer:(id: string, nativeWindow: any, size: { width: number; height: number }) => void; +export const loadModel:(id: string, modelPath: string)=> void; +export const onMouseEvent:(id: string, dx: number, dy: number)=> void; +export const destroyRenderer:(id: string)=> void; diff --git a/entry/src/main/cpp/types/libOCCTRender/oh-package.json5 b/entry/src/main/cpp/types/libOCCTRender/oh-package.json5 index 7f40c34d..f9bec4ec 100644 --- a/entry/src/main/cpp/types/libOCCTRender/oh-package.json5 +++ b/entry/src/main/cpp/types/libOCCTRender/oh-package.json5 @@ -1,5 +1,5 @@ { - "name": "libOCCTRender.so", + "name": "libocctrender.so", "types": "./Index.d.ts", "version": "1.0.0", "description": "Please describe the basic information." diff --git a/entry/src/main/ets/pages/modelView.ets b/entry/src/main/ets/pages/modelView.ets index 27e7205e..5085d9f4 100644 --- a/entry/src/main/ets/pages/modelView.ets +++ b/entry/src/main/ets/pages/modelView.ets @@ -2,7 +2,7 @@ import { hilog } from '@kit.PerformanceAnalysisKit'; import fs from '@ohos.file.fs'; import fileIO from '@ohos.fileio'; import { Context } from '@kit.AbilityKit'; -//import OCCTRender from 'libOCCTRender.so'; +import OCCTRender from 'libocctrender.so'; const DOMAIN = 0x0000; @@ -46,63 +46,64 @@ export struct ModelView { } build() { Flex({ direction: FlexDirection.Column }) { - Button('加载模型').onClick(()=>{ - try { - // 调用 native 初始化渲染器 - console.log('displayContrId:', this.displayContrId); - console.log('NativeWindow:', this.nativeWindow); - console.log('ModelPath:', this.modelPath); - hilog.info(0x0000, 'ModelView', 'Load Model'); - // 复制模型文件并获取路径 - console.info('Model copied to:', this.modelPath); - // 调用 native 加载 - //OCCTRender.loadModel(this.displayContrId, this.modelPath); - } catch (e) { - hilog.error(0x0000, 'ModelView', `LoadModel Failed: ${JSON.stringify(e)}`); - } + Row(){ + Button('加载模型').onClick(()=>{ + try { + // 调用 native 初始化渲染器 + console.log('displayContrId:', this.displayContrId); + console.log('NativeWindow:', this.nativeWindow); + console.log('ModelPath:', this.modelPath); + hilog.info(0x0000, 'ModelView', 'Load Model'); + // 复制模型文件并获取路径 + console.info('Model copied to:', this.modelPath); + // 调用 native 加载 + OCCTRender.loadModel(this.displayContrId, this.modelPath); + } catch (e) { + hilog.error(0x0000, 'ModelView', `LoadModel Failed: ${JSON.stringify(e)}`); + } + }) + Button('日志测试').onClick(async()=>{ + //NAPI日志接口测试 + let OCCTRender = await import("libocctrender.so") + }) + } + XComponent({ + id: this.displayContrId, + type: 'surface', + controller: this.displayController }) - Button('日志测试').onClick(async()=>{ - //NAPI日志接口测试 - let OCCTRender = await import("libOCCTRender.so") - hilog.info(DOMAIN, 'testTag', 'Test NAPI 2 + 3 = %{public}d', OCCTRender.add(2, 3)); - }) - // XComponent({ - // id: this.displayContrId, - // type: 'surface', - // controller: this.displayController - // }) - // .onLoad(() => { - // // 获取 native window(必须在 onLoad 后才能获取) - // this.nativeWindow = this.displayController.getXComponentSurfaceId(); - // if (this.nativeWindow === undefined || this.nativeWindow === '') { - // hilog.error(0x0000, 'ModelView', 'Failed to get native window'); - // return; - // } - // // 获取 XComponent 尺寸 - // let width = 0; - // let height = 0; - // try { - // //OCCTRender.initRenderer(this.displayContrId, this.nativeWindow, { width: 800, height: 600 }); - // console.info('Init Render Good'); - // }catch(e){ - // console.info('Init Render Faile'); - // } - // }) - // .onDestroy(() => { - // // 销毁时清理资源 - // //OCCTRender.destroyRenderer(this.displayContrId); - // }) - // .onTouch((event) => { - // // 简单鼠标/触摸拖拽旋转 - // if (event.type === TouchType.Move) { - // const dx = event.tiltX; - // const dy = event.tiltY; - // //occt.onMouseEvent(this.xcomponentId, dx, dy); - // } - // }) - // .width('100%') - // .height('100%') - // .backgroundColor('#333333'); + .onLoad(() => { + // 获取 native window(必须在 onLoad 后才能获取) + this.nativeWindow = this.displayController.getXComponentSurfaceId(); + if (this.nativeWindow === undefined || this.nativeWindow === '') { + hilog.error(0x0000, 'ModelView', 'Failed to get native window'); + return; + } + // 获取 XComponent 尺寸 + let width = 0; + let height = 0; + try { + OCCTRender.initRenderer(this.displayContrId, this.nativeWindow, { width: 800, height: 600 }); + console.info('Init Render Good'); + }catch(e){ + console.info('Init Render Faile'); + } + }) + .onDestroy(() => { + // 销毁时清理资源 + OCCTRender.destroyRenderer(this.displayContrId); + }) + .onTouch((event) => { + // 简单鼠标/触摸拖拽旋转 + if (event.type === TouchType.Move) { + const dx = event.tiltX; + const dy = event.tiltY; + //occt.onMouseEvent(this.xcomponentId, dx, dy); + } + }) + .width('100%') + .height('100%') + .backgroundColor('#333333'); } .width('100%') .height('100%');