完善渲染整体逻辑.
已知BUG.OCCT的view没有绑定鸿蒙OHWindows*的窗口对象
This commit is contained in:
parent
77dd6edf5f
commit
eed0b54b30
@ -28,14 +28,16 @@ endforeach()
|
||||
# 添加源文件
|
||||
add_library(opencax SHARED
|
||||
# Header
|
||||
NativeEGLOCCT/EGLConst.h
|
||||
NativeEGLOCCT/EGLCore.h
|
||||
NativeEGLOCCT/NativeRender.h
|
||||
NativeEGLOCCT/NativeRenderThread.h
|
||||
NativeEGLOCCT/NativeManager.h
|
||||
# Cpp Src
|
||||
NativeEGLOCCT/EGLCore.cpp
|
||||
NativeEGLOCCT/NativeRender.cpp
|
||||
NativeEGLOCCT/NativeRenderThread.cpp
|
||||
NativeEGLOCCT/NativeManager.cpp
|
||||
napi_init.cpp
|
||||
)
|
||||
napi_init.cpp)
|
||||
|
||||
# 查找系统库
|
||||
find_library(EGL-lib EGL)
|
||||
|
||||
@ -1,159 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef NATIVEXCOMPONENT_EGLCONST_H
|
||||
#define NATIVEXCOMPONENT_EGLCONST_H
|
||||
// [Start egl_const_h]
|
||||
// EGLConst.h
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES3/gl3.h>
|
||||
|
||||
const unsigned int LOG_PRINT_DOMAIN = 0xFF00;
|
||||
|
||||
/**
|
||||
* Program 错误
|
||||
*/
|
||||
const GLuint PROGRAM_ERROR = 0;
|
||||
|
||||
/**
|
||||
* 位置错误。
|
||||
*/
|
||||
const GLint POSITION_ERROR = -1;
|
||||
|
||||
/**
|
||||
* 默认x坐标。
|
||||
*/
|
||||
const int DEFAULT_X_POSITION = 0;
|
||||
|
||||
/**
|
||||
* 默认y坐标。
|
||||
*/
|
||||
const int DEFAULT_Y_POSITION = 0;
|
||||
|
||||
/**
|
||||
* Gl 红色默认值。
|
||||
*/
|
||||
const GLfloat GL_RED_DEFAULT = 0.0;
|
||||
|
||||
/**
|
||||
* Gl 绿色默认值。
|
||||
*/
|
||||
const GLfloat GL_GREEN_DEFAULT = 0.0;
|
||||
|
||||
/**
|
||||
* Gl 蓝色默认值。
|
||||
*/
|
||||
const GLfloat GL_BLUE_DEFAULT = 0.0;
|
||||
|
||||
/**
|
||||
* Gl 透明度。
|
||||
*/
|
||||
const GLfloat GL_ALPHA_DEFAULT = 1.0;
|
||||
|
||||
/**
|
||||
* Pointer 数量。
|
||||
*/
|
||||
const GLint POINTER_SIZE = 2;
|
||||
|
||||
/**
|
||||
* Triangle fan 尺寸。
|
||||
*/
|
||||
const GLsizei TRIANGLE_FAN_SIZE = 4;
|
||||
|
||||
/**
|
||||
* 50%。
|
||||
*/
|
||||
const float FIFTY_PERCENT = 0.5;
|
||||
|
||||
/**
|
||||
* 位置句柄名字。
|
||||
*/
|
||||
const char POSITION_NAME[] = "a_position";
|
||||
|
||||
// [StartExclude egl_const_h]
|
||||
/**
|
||||
* numeric value 0.
|
||||
*/
|
||||
const int NUM_0 = 0;
|
||||
|
||||
/**
|
||||
* numeric value 4.
|
||||
*/
|
||||
const int NUM_4 = 4;
|
||||
// [EndExclude egl_const_h]
|
||||
|
||||
/**
|
||||
* 背景色 #f4f4f4.
|
||||
*/
|
||||
const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f};
|
||||
|
||||
// [StartExclude egl_const_h]
|
||||
/**
|
||||
* Background color #ffffff00.
|
||||
*/
|
||||
const GLfloat TRANSPARENT_COLOR[] = {255.0f / 255, 255.0f / 255, 255.0f / 255, 0.0f};
|
||||
// [EndExclude egl_const_h]
|
||||
|
||||
/**
|
||||
* Draw 颜色 #7E8FFB.
|
||||
*/
|
||||
const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f};
|
||||
|
||||
/**
|
||||
* Change 颜色 #92D6CC.
|
||||
*/
|
||||
const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f};
|
||||
|
||||
/**
|
||||
* 背景区域。
|
||||
*/
|
||||
const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {-1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, -1.0f, -1.0f};
|
||||
|
||||
const EGLint ATTRIB_LIST[] = {
|
||||
// 键,值。
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
// 结束。
|
||||
EGL_NONE};
|
||||
|
||||
const EGLint CONTEXT_ATTRIBS[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
|
||||
/**
|
||||
* 顶点着色器
|
||||
*/
|
||||
const char VERTEX_SHADER[] = "#version 300 es\n"
|
||||
"layout(location = 0) in vec4 a_position;\n"
|
||||
"layout(location = 1) in vec4 a_color; \n"
|
||||
"out vec4 v_color; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = a_position; \n"
|
||||
" v_color = a_color; \n"
|
||||
"} \n";
|
||||
|
||||
/**
|
||||
* 片元着色器。
|
||||
*/
|
||||
const char FRAGMENT_SHADER[] = "#version 300 es\n"
|
||||
"precision mediump float; \n"
|
||||
"in vec4 v_color; \n"
|
||||
"out vec4 fragColor; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" fragColor = v_color; \n"
|
||||
"} \n";
|
||||
// [End egl_const_h]
|
||||
#endif // NATIVEXCOMPONENT_EGLCONST_H
|
||||
@ -1,646 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "EGLCore.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <EGL/eglplatform.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <hilog/log.h>
|
||||
|
||||
#include "common.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
namespace {
|
||||
constexpr int32_t NUM_4 = 4;
|
||||
/**
|
||||
* Vertex shader.
|
||||
*/
|
||||
const char VERTEX_SHADER[] = "#version 300 es\n"
|
||||
"layout(location = 0) in vec4 a_position;\n"
|
||||
"layout(location = 1) in vec4 a_color; \n"
|
||||
"out vec4 v_color; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" gl_Position = a_position; \n"
|
||||
" v_color = a_color; \n"
|
||||
"} \n";
|
||||
|
||||
/**
|
||||
* Fragment shader.
|
||||
*/
|
||||
const char FRAGMENT_SHADER[] = "#version 300 es\n"
|
||||
"precision mediump float; \n"
|
||||
"in vec4 v_color; \n"
|
||||
"out vec4 fragColor; \n"
|
||||
"void main() \n"
|
||||
"{ \n"
|
||||
" fragColor = v_color; \n"
|
||||
"} \n";
|
||||
// [Start native_color]
|
||||
/**
|
||||
* 绘制背景颜色 #f4f4f4.
|
||||
*/
|
||||
const GLfloat BACKGROUND_COLOR[] = {244.0f / 255, 244.0f / 255, 244.0f / 255, 1.0f};
|
||||
EGLCore::EGLCore()
|
||||
: eglDisplay_(EGL_NO_DISPLAY),
|
||||
eglContext_(EGL_NO_CONTEXT),
|
||||
eglSurface_(EGL_NO_SURFACE),
|
||||
nativeWindow_(nullptr) {}
|
||||
|
||||
/**
|
||||
* 绘制图案颜色 #7E8FFB.
|
||||
*/
|
||||
const GLfloat DRAW_COLOR[] = {126.0f / 255, 143.0f / 255, 251.0f / 255, 1.0f};
|
||||
EGLCore::~EGLCore() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制图案改变后的颜色 #92D6CC.
|
||||
*/
|
||||
const GLfloat CHANGE_COLOR[] = {146.0f / 255, 214.0f / 255, 204.0f / 255, 1.0f};
|
||||
|
||||
/**
|
||||
* 绘制背景顶点
|
||||
*/
|
||||
const GLfloat BACKGROUND_RECTANGLE_VERTICES[] = {
|
||||
-1.0f, 1.0f,
|
||||
1.0f, 1.0f,
|
||||
1.0f, -1.0f,
|
||||
-1.0f, -1.0f};
|
||||
// [End native_color]
|
||||
/**
|
||||
* Get context parameter count.
|
||||
*/
|
||||
const size_t GET_CONTEXT_PARAM_CNT = 1;
|
||||
|
||||
/**
|
||||
* Fifty percent.
|
||||
*/
|
||||
const float FIFTY_PERCENT = 0.5;
|
||||
|
||||
/**
|
||||
* Pointer size.
|
||||
*/
|
||||
const GLint POINTER_SIZE = 2;
|
||||
|
||||
/**
|
||||
* Triangle fan size.
|
||||
*/
|
||||
const GLsizei TRIANGLE_FAN_SIZE = 4;
|
||||
|
||||
/**
|
||||
* Egl red size default.
|
||||
*/
|
||||
const int EGL_RED_SIZE_DEFAULT = 8;
|
||||
|
||||
/**
|
||||
* Egl green size default.
|
||||
*/
|
||||
const int EGL_GREEN_SIZE_DEFAULT = 8;
|
||||
|
||||
/**
|
||||
* Egl blue size default.
|
||||
*/
|
||||
const int EGL_BLUE_SIZE_DEFAULT = 8;
|
||||
|
||||
/**
|
||||
* Egl alpha size default.
|
||||
*/
|
||||
const int EGL_ALPHA_SIZE_DEFAULT = 8;
|
||||
|
||||
/**
|
||||
* Default x position.
|
||||
*/
|
||||
const int DEFAULT_X_POSITION = 0;
|
||||
|
||||
/**
|
||||
* Default y position.
|
||||
*/
|
||||
const int DEFAULT_Y_POSITION = 0;
|
||||
|
||||
/**
|
||||
* Gl red default.
|
||||
*/
|
||||
const GLfloat GL_RED_DEFAULT = 0.0;
|
||||
|
||||
/**
|
||||
* Gl green default.
|
||||
*/
|
||||
const GLfloat GL_GREEN_DEFAULT = 0.0;
|
||||
|
||||
/**
|
||||
* Gl blue default.
|
||||
*/
|
||||
const GLfloat GL_BLUE_DEFAULT = 0.0;
|
||||
|
||||
/**
|
||||
* Gl alpha default.
|
||||
*/
|
||||
const GLfloat GL_ALPHA_DEFAULT = 1.0;
|
||||
|
||||
/**
|
||||
* Program error.
|
||||
*/
|
||||
const GLuint PROGRAM_ERROR = 0;
|
||||
|
||||
/**
|
||||
* Shape vertices size.
|
||||
*/
|
||||
const int SHAPE_VERTICES_SIZE = 8;
|
||||
|
||||
/**
|
||||
* Position handle name.
|
||||
*/
|
||||
const char POSITION_NAME[] = "a_position";
|
||||
|
||||
/**
|
||||
* Position error.
|
||||
*/
|
||||
const GLint POSITION_ERROR = -1;
|
||||
|
||||
/**
|
||||
* Config attribute list.
|
||||
*/
|
||||
const EGLint ATTRIB_LIST[] = {
|
||||
// Key,value.
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, EGL_RED_SIZE_DEFAULT,
|
||||
EGL_GREEN_SIZE, EGL_GREEN_SIZE_DEFAULT,
|
||||
EGL_BLUE_SIZE, EGL_BLUE_SIZE_DEFAULT,
|
||||
EGL_ALPHA_SIZE, EGL_ALPHA_SIZE_DEFAULT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
|
||||
// End.
|
||||
EGL_NONE};
|
||||
|
||||
/**
|
||||
* Context attributes.
|
||||
*/
|
||||
const EGLint CONTEXT_ATTRIBS[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE};
|
||||
} // namespace
|
||||
// [Start native_create_context_init]
|
||||
bool EGLCore::EglContextInit(void* window, int width, int height)
|
||||
{
|
||||
// [StartExclude native_create_context_init]
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute");
|
||||
if ((window == nullptr) || (width <= 0) || (height <= 0)) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit: param error");
|
||||
bool EGLCore::init(OHNativeWindow* window) {
|
||||
if (!window) {
|
||||
printf("Native window is null\n");
|
||||
return false;
|
||||
}
|
||||
// [EndExclude native_create_context_init]
|
||||
UpdateSize(width, height);
|
||||
eglWindow_ = static_cast<EGLNativeWindowType>(window);
|
||||
|
||||
// 初始化display
|
||||
nativeWindow_ = window;
|
||||
|
||||
// 获取EGL display
|
||||
eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (eglDisplay_ == EGL_NO_DISPLAY) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglGetDisplay: unable to get EGL display");
|
||||
printf("eglGetDisplay failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 初始化EGL
|
||||
EGLint majorVersion;
|
||||
EGLint minorVersion;
|
||||
if (!eglInitialize(eglDisplay_, &majorVersion, &minorVersion)) {
|
||||
OH_LOG_Print(
|
||||
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglInitialize: unable to get initialize EGL display");
|
||||
if (!eglInitialize(eglDisplay_, nullptr, nullptr)) {
|
||||
printf("eglInitialize failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 选择配置
|
||||
const EGLint maxConfigSize = 1;
|
||||
// 配置EGL
|
||||
EGLint attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
EGL_DEPTH_SIZE, 16,
|
||||
EGL_STENCIL_SIZE, 0,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLint numConfigs;
|
||||
if (!eglChooseConfig(eglDisplay_, ATTRIB_LIST, &eglConfig_, maxConfigSize, &numConfigs)) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglChooseConfig: unable to choose configs");
|
||||
if (!eglChooseConfig(eglDisplay_, attribs, &eglConfig_, 1, &numConfigs) || numConfigs == 0) {
|
||||
printf("eglChooseConfig failed\n");
|
||||
return false;
|
||||
}
|
||||
// 创建环境
|
||||
return CreateEnvironment();
|
||||
|
||||
// 创建EGL surface
|
||||
eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, (NativeWindowType)nativeWindow_, nullptr);
|
||||
if (eglSurface_ == EGL_NO_SURFACE) {
|
||||
printf("eglCreateWindowSurface failed: 0x%x\n", eglGetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建EGL context
|
||||
EGLint contextAttribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 3,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, contextAttribs);
|
||||
if (eglContext_ == EGL_NO_CONTEXT) {
|
||||
printf("eglCreateContext failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 激活上下文
|
||||
makeCurrent();
|
||||
|
||||
// 检查GL错误
|
||||
GLenum glError = glGetError();
|
||||
if (glError != GL_NO_ERROR) {
|
||||
printf("OpenGL error after initialization: 0x%x\n", glError);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 设置GL视口
|
||||
glViewport(0, 0, 1280, 720); // 默认大小,实际会随窗口变化
|
||||
|
||||
return true;
|
||||
}
|
||||
// [End native_create_context_init]
|
||||
// [Start native_create_environment]
|
||||
bool EGLCore::CreateEnvironment()
|
||||
{
|
||||
// 创建Surface
|
||||
if (eglWindow_ == nullptr) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglWindow_ is null");
|
||||
return false;
|
||||
}
|
||||
eglSurface_ = eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL);
|
||||
if (eglSurface_ == nullptr) {
|
||||
OH_LOG_Print(
|
||||
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglCreateWindowSurface: unable to create surface");
|
||||
return false;
|
||||
}
|
||||
// 创建context
|
||||
eglContext_ = eglCreateContext(eglDisplay_, eglConfig_, EGL_NO_CONTEXT, CONTEXT_ATTRIBS);
|
||||
|
||||
void EGLCore::makeCurrent() {
|
||||
if (!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_)) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "eglMakeCurrent failed");
|
||||
return false;
|
||||
}
|
||||
// 创建program
|
||||
program_ = CreateProgram(VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
if (program_ == PROGRAM_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "CreateProgram: unable to create program");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// [End native_create_environment]
|
||||
// [Start native_background]
|
||||
// 绘制背景颜色
|
||||
void EGLCore::Background()
|
||||
{
|
||||
GLint position = PrepareDraw();
|
||||
if (position == POSITION_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background get position failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ExecuteDraw(position, BACKGROUND_COLOR,
|
||||
BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background execute draw failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FinishDraw()) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Background FinishDraw failed");
|
||||
return;
|
||||
printf("eglMakeCurrent failed: 0x%x\n", eglGetError());
|
||||
}
|
||||
}
|
||||
// [End native_background]
|
||||
// [Start native_draw]
|
||||
void EGLCore::Draw(int& hasDraw)
|
||||
{
|
||||
flag_ = false;
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "Draw");
|
||||
GLint position = PrepareDraw();
|
||||
if (position == POSITION_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw get position failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// 绘制背景
|
||||
if (!ExecuteDraw(position, BACKGROUND_COLOR,
|
||||
BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw background failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// 将五角星分为五个四边形,计算其中一个四边形的四个顶点
|
||||
GLfloat rotateX = 0;
|
||||
GLfloat rotateY = FIFTY_PERCENT * height_;
|
||||
GLfloat centerX = 0;
|
||||
// Convert DEG(54° & 18°) to RAD
|
||||
GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
|
||||
// Convert DEG(18°) to RAD
|
||||
GLfloat leftX = -rotateY * (M_PI / 180 * 18);
|
||||
GLfloat leftY = 0;
|
||||
// Convert DEG(18°) to RAD
|
||||
GLfloat rightX = rotateY * (M_PI / 180 * 18);
|
||||
GLfloat rightY = 0;
|
||||
|
||||
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
|
||||
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
|
||||
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
|
||||
|
||||
if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert DEG(72°) to RAD
|
||||
GLfloat rad = M_PI / 180 * 72;
|
||||
// Rotate four times
|
||||
// 在文件egl_core.cpp中定义,NUM_4的值为4
|
||||
for (int i = 0; i < NUM_4; ++i) {
|
||||
// 旋转得其他四个四边形的顶点
|
||||
Rotate2d(centerX, centerY, &rotateX, &rotateY, rad);
|
||||
Rotate2d(centerX, centerY, &leftX, &leftY, rad);
|
||||
Rotate2d(centerX, centerY, &rightX, &rightY, rad);
|
||||
|
||||
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
|
||||
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
|
||||
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
|
||||
|
||||
// 绘制图形
|
||||
if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 结束绘制
|
||||
if (!FinishDraw()) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed");
|
||||
return;
|
||||
}
|
||||
hasDraw = 1;
|
||||
|
||||
flag_ = true;
|
||||
}
|
||||
// [End native_draw]
|
||||
// [Start native_change_color]
|
||||
void EGLCore::ChangeColor(int& hasChangeColor)
|
||||
{
|
||||
if (!flag_) {
|
||||
return;
|
||||
}
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor");
|
||||
GLint position = PrepareDraw();
|
||||
if (position == POSITION_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor get position failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// 绘制背景
|
||||
if (!ExecuteDraw(position, BACKGROUND_COLOR,
|
||||
BACKGROUND_RECTANGLE_VERTICES, sizeof(BACKGROUND_RECTANGLE_VERTICES))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor execute draw background failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
|
||||
GLfloat rotateX = 0;
|
||||
GLfloat rotateY = FIFTY_PERCENT * height_;
|
||||
GLfloat centerX = 0;
|
||||
// Convert DEG(54° & 18°) to RAD
|
||||
GLfloat centerY = -rotateY * (M_PI / 180 * 54) * (M_PI / 180 * 18);
|
||||
// Convert DEG(18°) to RAD
|
||||
GLfloat leftX = -rotateY * (M_PI / 180 * 18);
|
||||
GLfloat leftY = 0;
|
||||
// Convert DEG(18°) to RAD
|
||||
GLfloat rightX = rotateY * (M_PI / 180 * 18);
|
||||
GLfloat rightY = 0;
|
||||
|
||||
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
|
||||
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
|
||||
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
|
||||
|
||||
// 使用新的颜色绘制
|
||||
if (!ExecuteDrawNewStar(0, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert DEG(72°) to RAD
|
||||
GLfloat rad = M_PI / 180 * 72;
|
||||
// Rotate four times
|
||||
// 在文件egl_core.cpp中定义,NUM_4的值为4
|
||||
for (int i = 0; i < NUM_4; ++i) {
|
||||
// 旋转得其他四个四边形的顶点
|
||||
Rotate2d(centerX, centerY, &rotateX, &rotateY, rad);
|
||||
Rotate2d(centerX, centerY, &leftX, &leftY, rad);
|
||||
Rotate2d(centerX, centerY, &rightX, &rightY, rad);
|
||||
// 确定绘制四边形的顶点,使用绘制区域的百分比表示
|
||||
const GLfloat shapeVertices[] = { centerX / width_, centerY / height_, leftX / width_, leftY / height_,
|
||||
rotateX / width_, rotateY / height_, rightX / width_, rightY / height_ };
|
||||
|
||||
// 使用新的颜色绘制
|
||||
if (!ExecuteDrawNewStar(position, CHANGE_COLOR, shapeVertices, sizeof(shapeVertices))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 结束绘制
|
||||
if (!FinishDraw()) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ChangeColor FinishDraw failed");
|
||||
}
|
||||
hasChangeColor = 1;
|
||||
}
|
||||
// [StartExclude native_change_color]
|
||||
// [Start native_prepare_draw]
|
||||
// 绘前准备,获取position,创建成功时position值从0开始
|
||||
GLint EGLCore::PrepareDraw()
|
||||
{
|
||||
if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (eglContext_ == nullptr) ||
|
||||
(!eglMakeCurrent(eglDisplay_, eglSurface_, eglSurface_, eglContext_))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "PrepareDraw: param error");
|
||||
return POSITION_ERROR;
|
||||
}
|
||||
|
||||
// 该gl函数没有返回值。
|
||||
glViewport(DEFAULT_X_POSITION, DEFAULT_Y_POSITION, width_, height_);
|
||||
glClearColor(GL_RED_DEFAULT, GL_GREEN_DEFAULT, GL_BLUE_DEFAULT, GL_ALPHA_DEFAULT);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glUseProgram(program_);
|
||||
|
||||
return glGetAttribLocation(program_, POSITION_NAME);
|
||||
}
|
||||
// [End native_prepare_draw]
|
||||
// [Start native_execute_draw]
|
||||
// 依据传入参数在指定区域绘制指定颜色
|
||||
bool EGLCore::ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize)
|
||||
{
|
||||
if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 该gl函数没有返回值。
|
||||
glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
|
||||
glEnableVertexAttribArray(position);
|
||||
glVertexAttrib4fv(1, color);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
|
||||
glDisableVertexAttribArray(position);
|
||||
|
||||
return true;
|
||||
}
|
||||
// [End native_execute_draw]
|
||||
bool EGLCore::ExecuteDrawStar(
|
||||
GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize)
|
||||
{
|
||||
if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// The gl function has no return value.
|
||||
glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
|
||||
glVertexAttribPointer(1, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, color);
|
||||
glEnableVertexAttribArray(position);
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttrib4fv(1, color);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
|
||||
glDisableVertexAttribArray(position);
|
||||
glDisableVertexAttribArray(1);
|
||||
|
||||
return true;
|
||||
}
|
||||
// [EndExclude native_change_color]
|
||||
bool EGLCore::ExecuteDrawNewStar(
|
||||
GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize)
|
||||
{
|
||||
if ((position > 0) || (color == nullptr) || (vertSize / sizeof(shapeVertices[0])) != SHAPE_VERTICES_SIZE) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "ExecuteDraw: param error");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 该gl函数没有返回值。
|
||||
glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices);
|
||||
glEnableVertexAttribArray(position);
|
||||
glVertexAttrib4fv(1, color);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, TRIANGLE_FAN_SIZE);
|
||||
glDisableVertexAttribArray(position);
|
||||
|
||||
return true;
|
||||
}
|
||||
// [End native_change_color]
|
||||
void EGLCore::Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta)
|
||||
{
|
||||
GLfloat tempX = cos(theta) * (*rotateX - centerX) - sin(theta) * (*rotateY - centerY);
|
||||
GLfloat tempY = sin(theta) * (*rotateX - centerX) + cos(theta) * (*rotateY - centerY);
|
||||
*rotateX = tempX + centerX;
|
||||
*rotateY = tempY + centerY;
|
||||
}
|
||||
// [Start native_finish_draw]
|
||||
// 结束绘制操作
|
||||
bool EGLCore::FinishDraw()
|
||||
{
|
||||
// 强制刷新缓冲
|
||||
glFlush();
|
||||
glFinish();
|
||||
bool EGLCore::swapBuffers() {
|
||||
return eglSwapBuffers(eglDisplay_, eglSurface_);
|
||||
}
|
||||
// [End native_finish_draw]
|
||||
// [Start native_load_shader]
|
||||
GLuint EGLCore::LoadShader(GLenum type, const char* shaderSrc)
|
||||
{
|
||||
if ((type <= 0) || (shaderSrc == nullptr)) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader type or shaderSrc error");
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
|
||||
GLuint shader = glCreateShader(type);
|
||||
if (shader == 0) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCreateShader unable to load shader");
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
void EGLCore::destroy() {
|
||||
if (eglDisplay_ != EGL_NO_DISPLAY) {
|
||||
if (eglContext_ != EGL_NO_CONTEXT) {
|
||||
eglDestroyContext(eglDisplay_, eglContext_);
|
||||
eglContext_ = EGL_NO_CONTEXT;
|
||||
}
|
||||
|
||||
// 该gl函数没有返回值。
|
||||
glShaderSource(shader, 1, &shaderSrc, nullptr);
|
||||
glCompileShader(shader);
|
||||
if (eglSurface_ != EGL_NO_SURFACE) {
|
||||
eglDestroySurface(eglDisplay_, eglSurface_);
|
||||
eglSurface_ = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
GLint compiled;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
|
||||
if (compiled != 0) {
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLint infoLen = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
|
||||
if (infoLen <= 1) {
|
||||
glDeleteShader(shader);
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
|
||||
char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1));
|
||||
if (infoLog != nullptr) {
|
||||
memset(infoLog, 0, infoLen + 1);
|
||||
glGetShaderInfoLog(shader, infoLen, nullptr, infoLog);
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glCompileShader error = %s", infoLog);
|
||||
free(infoLog);
|
||||
infoLog = nullptr;
|
||||
}
|
||||
glDeleteShader(shader);
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
// [End native_load_shader]
|
||||
// [Start native_create_program]
|
||||
GLuint EGLCore::CreateProgram(const char* vertexShader, const char* fragShader)
|
||||
{
|
||||
if ((vertexShader == nullptr) || (fragShader == nullptr)) {
|
||||
OH_LOG_Print(
|
||||
LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram: vertexShader or fragShader is null");
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
|
||||
GLuint vertex = LoadShader(GL_VERTEX_SHADER, vertexShader);
|
||||
if (vertex == PROGRAM_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram vertex error");
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
|
||||
GLuint fragment = LoadShader(GL_FRAGMENT_SHADER, fragShader);
|
||||
if (fragment == PROGRAM_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram fragment error");
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
if (program == PROGRAM_ERROR) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram program error");
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
|
||||
// 该gl函数没有返回值。
|
||||
glAttachShader(program, vertex);
|
||||
glAttachShader(program, fragment);
|
||||
glLinkProgram(program);
|
||||
|
||||
GLint linked;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &linked);
|
||||
if (linked != 0) {
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
return program;
|
||||
}
|
||||
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "createProgram linked error");
|
||||
GLint infoLen = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
|
||||
if (infoLen > 1) {
|
||||
char* infoLog = (char*)malloc(sizeof(char) * (infoLen + 1));
|
||||
memset(infoLog, 0, infoLen + 1);
|
||||
glGetProgramInfoLog(program, infoLen, nullptr, infoLog);
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "glLinkProgram error = %s", infoLog);
|
||||
free(infoLog);
|
||||
infoLog = nullptr;
|
||||
}
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
glDeleteProgram(program);
|
||||
return PROGRAM_ERROR;
|
||||
}
|
||||
// [End native_create_program]
|
||||
// [Start native_update_size]
|
||||
void EGLCore::UpdateSize(int width, int height)
|
||||
{
|
||||
// width_和height_在头文件中定义
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
if (width_ > 0) {
|
||||
widthPercent_ = FIFTY_PERCENT * height_ / width_;
|
||||
eglTerminate(eglDisplay_);
|
||||
eglDisplay_ = EGL_NO_DISPLAY;
|
||||
}
|
||||
}
|
||||
// [End native_update_size]
|
||||
// [Start native_release]
|
||||
void EGLCore::Release()
|
||||
{
|
||||
// 释放Surface
|
||||
if ((eglDisplay_ == nullptr) || (eglSurface_ == nullptr) || (!eglDestroySurface(eglDisplay_, eglSurface_))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroySurface failed");
|
||||
}
|
||||
// 释放context
|
||||
if ((eglDisplay_ == nullptr) || (eglContext_ == nullptr) || (!eglDestroyContext(eglDisplay_, eglContext_))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglDestroyContext failed");
|
||||
}
|
||||
// 释放display
|
||||
if ((eglDisplay_ == nullptr) || (!eglTerminate(eglDisplay_))) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Release eglTerminate failed");
|
||||
}
|
||||
}
|
||||
// [End native_release]
|
||||
} // namespace NativeXComponentSample
|
||||
|
||||
} // namespace NativeOpenCAX
|
||||
@ -12,49 +12,30 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef NATIVE_XCOMPONENT_EGL_CORE_H
|
||||
#define NATIVE_XCOMPONENT_EGL_CORE_H
|
||||
|
||||
#ifndef EGLCORE_H
|
||||
#define EGLCORE_H
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <GLES3/gl3.h>
|
||||
#include "string"
|
||||
#include <native_window/external_window.h>
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
class EGLCore {
|
||||
public:
|
||||
explicit EGLCore() {}
|
||||
~EGLCore() {}
|
||||
bool EglContextInit(void* window, int width, int height);
|
||||
bool CreateEnvironment();
|
||||
void Draw(int& hasDraw);
|
||||
void Background();
|
||||
void ChangeColor(int& hasChangeColor);
|
||||
void Release();
|
||||
void UpdateSize(int width, int height);
|
||||
EGLCore();
|
||||
~EGLCore();
|
||||
|
||||
bool init(OHNativeWindow* window);
|
||||
void makeCurrent();
|
||||
bool swapBuffers();
|
||||
void destroy();
|
||||
EGLSurface getSurface() const { return eglSurface_; }
|
||||
|
||||
private:
|
||||
GLuint LoadShader(GLenum type, const char* shaderSrc);
|
||||
GLuint CreateProgram(const char* vertexShader, const char* fragShader);
|
||||
GLint PrepareDraw();
|
||||
bool ExecuteDraw(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize);
|
||||
bool ExecuteDrawStar(GLint position, const GLfloat* color, const GLfloat shapeVertices[], unsigned long vertSize);
|
||||
bool ExecuteDrawNewStar(GLint position, const GLfloat* color,
|
||||
const GLfloat shapeVertices[], unsigned long vertSize);
|
||||
void Rotate2d(GLfloat centerX, GLfloat centerY, GLfloat* rotateX, GLfloat* rotateY, GLfloat theta);
|
||||
bool FinishDraw();
|
||||
|
||||
private:
|
||||
EGLNativeWindowType eglWindow_;
|
||||
EGLDisplay eglDisplay_ = EGL_NO_DISPLAY;
|
||||
EGLConfig eglConfig_ = EGL_NO_CONFIG_KHR;
|
||||
EGLSurface eglSurface_ = EGL_NO_SURFACE;
|
||||
EGLContext eglContext_ = EGL_NO_CONTEXT;
|
||||
GLuint program_;
|
||||
bool flag_ = false;
|
||||
int width_;
|
||||
int height_;
|
||||
GLfloat widthPercent_;
|
||||
EGLDisplay eglDisplay_;
|
||||
EGLContext eglContext_;
|
||||
EGLSurface eglSurface_;
|
||||
EGLConfig eglConfig_;
|
||||
OHNativeWindow* nativeWindow_;
|
||||
};
|
||||
} // namespace NativeXComponentSample
|
||||
#endif // NATIVE_XCOMPONENT_EGL_CORE_H
|
||||
} // namespace NativeOpenCAX
|
||||
#endif // EGLCORE_H
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
#include "arkui/native_node_napi.h"
|
||||
#include "arkui/native_interface.h"
|
||||
#include "common.h"
|
||||
|
||||
#include <map>
|
||||
#define COLUMN_MARGIN 10
|
||||
#define XC_WIDTH 800
|
||||
#define XC_HEIGHT 600
|
||||
@ -44,13 +44,17 @@ OH_NativeXComponent_Callback NativeManager::callback_;
|
||||
ArkUI_NodeHandle xc;
|
||||
int32_t NativeManager::hasDraw_ = 0;
|
||||
int32_t NativeManager::hasChangeColor_ = 0;
|
||||
static std::map<int64_t, std::shared_ptr<NativeRenderThread>> renderThreadMap;
|
||||
static std::mutex mapMutex;
|
||||
|
||||
NativeManager::~NativeManager() {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "~NativeManager");
|
||||
nativeXComponentMap_.clear();
|
||||
if (eglcore_ != nullptr) {
|
||||
delete eglcore_;
|
||||
eglcore_ = nullptr;
|
||||
int64_t id = 0;
|
||||
std::lock_guard<std::mutex> lock(mapMutex);
|
||||
if (renderThreadMap.find(id) != renderThreadMap.end()) {
|
||||
renderThreadMap[id]->stop();
|
||||
renderThreadMap.erase(id);
|
||||
}
|
||||
|
||||
for (auto iter = pluginManagerMap_.begin(); iter != pluginManagerMap_.end(); ++iter) {
|
||||
@ -62,38 +66,38 @@ NativeManager::~NativeManager() {
|
||||
pluginManagerMap_.clear();
|
||||
}
|
||||
// Surface回调事件
|
||||
void OnSurfaceCreatedNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
auto window = OH_ArkUI_XComponent_GetNativeWindow(holder); // 获取native window
|
||||
auto eglCore = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
eglCore->EglContextInit(window, 800, 600);
|
||||
}
|
||||
void OnSurfaceChangedNative(OH_ArkUI_SurfaceHolder *holder, uint64_t width, uint64_t height) {
|
||||
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
render->UpdateSize(width, height); // 设置绘制区域大小
|
||||
render->Draw(NativeManager::hasDraw_); // 绘制五角星
|
||||
}
|
||||
void OnSurfaceDestroyedNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "on destroyed");
|
||||
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
render->Release(); // 销毁eglSurface相关资源
|
||||
}
|
||||
void OnSurfaceShowNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface show");
|
||||
}
|
||||
void OnSurfaceHideNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface hide");
|
||||
}
|
||||
void OnFrameCallbackNative(ArkUI_NodeHandle node, uint64_t timestamp, uint64_t targetTimestamp) {
|
||||
if (!NativeManager::surfaceHolderMap_.count(node)) {
|
||||
return;
|
||||
}
|
||||
static uint64_t count = 0;
|
||||
count++;
|
||||
// 在头文件plugin_manager.h中定义,FRAME_COUNT的值为50
|
||||
if (count % FRAME_COUNT == 0) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "OnFrameCallback count = %{public}ld", count);
|
||||
}
|
||||
}
|
||||
//void OnSurfaceCreatedNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
// auto window = OH_ArkUI_XComponent_GetNativeWindow(holder); // 获取native window
|
||||
// auto eglCore = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
// eglCore->EglContextInit(window, 800, 600);
|
||||
//}
|
||||
//void OnSurfaceChangedNative(OH_ArkUI_SurfaceHolder *holder, uint64_t width, uint64_t height) {
|
||||
// EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
// render->UpdateSize(width, height); // 设置绘制区域大小
|
||||
// //render->Draw(NativeManager::hasDraw_); // 绘制五角星
|
||||
//}
|
||||
//void OnSurfaceDestroyedNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
// OH_LOG_Print(LOG_APP, LOG_ERROR, 0xff00, "onBind", "on destroyed");
|
||||
// EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
// render->Release(); // 销毁eglSurface相关资源
|
||||
//}
|
||||
//void OnSurfaceShowNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
// OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface show");
|
||||
//}
|
||||
//void OnSurfaceHideNative(OH_ArkUI_SurfaceHolder *holder) {
|
||||
// OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on surface hide");
|
||||
//}
|
||||
//void OnFrameCallbackNative(ArkUI_NodeHandle node, uint64_t timestamp, uint64_t targetTimestamp) {
|
||||
// if (!NativeManager::surfaceHolderMap_.count(node)) {
|
||||
// return;
|
||||
// }
|
||||
// static uint64_t count = 0;
|
||||
// count++;
|
||||
// // 在头文件plugin_manager.h中定义,FRAME_COUNT的值为50
|
||||
// if (count % FRAME_COUNT == 0) {
|
||||
// OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "OnFrameCallback count = %{public}ld", count);
|
||||
// }
|
||||
//}
|
||||
void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
|
||||
// [StartExclude plugin_on_surface_created]
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB");
|
||||
@ -144,79 +148,38 @@ void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window) {
|
||||
auto *pluginManger = NativeManager::GetInstance();
|
||||
pluginManger->OnSurfaceDestroyed(component, window);
|
||||
}
|
||||
void DispatchTouchEventCB(OH_NativeXComponent *component, void *window) {
|
||||
// [StartExclude plugin_dispatch_touch_event]
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Callback", "DispatchTouchEventCB");
|
||||
int32_t ret;
|
||||
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
|
||||
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
|
||||
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
|
||||
if (ret != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
std::string id(idStr);
|
||||
// [EndExclude plugin_dispatch_touch_event]
|
||||
auto *pluginManger = NativeManager::GetInstance();
|
||||
pluginManger->DispatchTouchEvent(component, window);
|
||||
}
|
||||
//NativeManager回调
|
||||
void NativeManager::OnSurfaceCreated(OH_NativeXComponent *component, void *window) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceCreated");
|
||||
int32_t ret;
|
||||
char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {};
|
||||
uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
|
||||
ret = OH_NativeXComponent_GetXComponentId(component, idStr, &idSize);
|
||||
ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
|
||||
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
|
||||
eglcore_->EglContextInit(window, width_, height_);
|
||||
eglcore_->Background();
|
||||
OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
|
||||
int64_t id = 0;
|
||||
std::lock_guard<std::mutex> lock(mapMutex);
|
||||
if (renderThreadMap.find(id) == renderThreadMap.end()) {
|
||||
auto renderThread = std::make_shared<NativeRenderThread>();
|
||||
renderThreadMap[id] = renderThread;
|
||||
renderThread->start(reinterpret_cast<OHNativeWindow*>(window));
|
||||
}
|
||||
}
|
||||
void NativeManager::OnSurfaceDestroyed(OH_NativeXComponent *component, void *window) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "PluginManager::OnSurfaceDestroyed");
|
||||
}
|
||||
void NativeManager::DispatchTouchEvent(OH_NativeXComponent *component, void *window) {
|
||||
int32_t ret = OH_NativeXComponent_GetTouchEvent(component, window, &touchEvent_);
|
||||
if (ret == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
|
||||
float tiltX = 2.2;
|
||||
float tiltY = 2.2;
|
||||
OH_NativeXComponent_TouchPointToolType toolType =
|
||||
OH_NativeXComponent_TouchPointToolType::OH_NATIVEXCOMPONENT_TOOL_TYPE_LENS;
|
||||
OH_NativeXComponent_GetTouchPointToolType(component, 0, &toolType);
|
||||
OH_NativeXComponent_GetTouchPointTiltX(component, 0, &tiltX);
|
||||
OH_NativeXComponent_GetTouchPointTiltY(component, 0, &tiltY);
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native",
|
||||
"Touch Info : x=%{public}f, y=%{public}f screenx=%{public}f, screeny=%{public}f,"
|
||||
"type=%{public}d, force=%{public}f, tiltX=%{public}f, tiltY=%{public}f, toolType=%{public}d",
|
||||
touchEvent_.x, touchEvent_.y, touchEvent_.screenX, touchEvent_.screenY, touchEvent_.type,
|
||||
touchEvent_.force, tiltX, tiltY, toolType);
|
||||
if (touchEvent_.type == OH_NativeXComponent_TouchEventType::OH_NATIVEXCOMPONENT_UP) {
|
||||
eglcore_->ChangeColor(hasChangeColor_);
|
||||
}
|
||||
} else {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "touch fail");
|
||||
}
|
||||
|
||||
int32_t size = 0;
|
||||
OH_NativeXComponent_HistoricalPoint *points = nullptr;
|
||||
|
||||
if (OH_NativeXComponent_GetHistoricalPoints(component, window, &size, &points) ==
|
||||
OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native", "HistoricalPoints size=%{public}d",
|
||||
size);
|
||||
for (auto i = 0; i < size; i++) {
|
||||
auto point = points[i];
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "XComponent_Native",
|
||||
"HistoricalPoint %{public}d Info : id=%{public}d, x=%{public}f, y=%{public}f, "
|
||||
"type=%{public}d, timeStamp=%{public}lld, sourceTool=%{public}d",
|
||||
i, point.id, point.x, point.y, point.type, point.timeStamp, point.sourceTool);
|
||||
int64_t id = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mapMutex);
|
||||
if (renderThreadMap.find(id) != renderThreadMap.end()) {
|
||||
renderThreadMap[id]->stop();
|
||||
renderThreadMap.erase(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
void NativeManager::OnSurfaceChanged(OH_NativeXComponent *component, void *window) {
|
||||
int32_t ret = OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native",
|
||||
"OnSurfaceChanged ret=%{public}d width=%{public}lu, height=%{public}lu", ret, width_, height_);
|
||||
OH_NativeXComponent_GetXComponentSize(component, window, &width_, &height_);
|
||||
int64_t id = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mapMutex);
|
||||
if (renderThreadMap.find(id) != renderThreadMap.end()) {
|
||||
renderThreadMap[id]->resizeWindow(width_, height_);
|
||||
}
|
||||
}
|
||||
}
|
||||
void onEvent(ArkUI_NodeEvent *event) {
|
||||
auto eventType = OH_ArkUI_NodeEvent_GetEventType(event); // 获取组件事件类型
|
||||
@ -225,7 +188,6 @@ void onEvent(ArkUI_NodeEvent *event) {
|
||||
ArkUI_NodeHandle handle = OH_ArkUI_NodeEvent_GetNodeHandle(event); // 获取触发该事件的组件对象
|
||||
auto holder = NativeManager::surfaceHolderMap_[handle];
|
||||
EGLCore *render = reinterpret_cast<EGLCore *>(OH_ArkUI_SurfaceHolder_GetUserData(holder));
|
||||
render->Draw(NativeManager::hasDraw_); // 绘制五角星
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch");
|
||||
}
|
||||
}
|
||||
@ -237,35 +199,11 @@ static std::string value2String(napi_env env, napi_value value) {
|
||||
napi_get_value_string_utf8(env, value, &valueString[0], stringSize + 1, &stringSize);
|
||||
return valueString;
|
||||
}
|
||||
napi_value NativeManager::NapiDrawPattern(napi_env env, napi_callback_info info) {
|
||||
// [StartExclude plugin_draw_pattern]
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern");
|
||||
if ((env == nullptr) || (info == nullptr)) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern: env or info is null");
|
||||
return nullptr;
|
||||
}
|
||||
// [EndExclude plugin_draw_pattern]
|
||||
// 获取环境变量参数
|
||||
napi_value thisArg;
|
||||
if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
|
||||
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeManager", "NapiDrawPattern: napi_get_cb_info fail");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto *pluginManger = NativeManager::GetInstance();
|
||||
// 调用绘制方法
|
||||
pluginManger->eglcore_->Draw(hasDraw_);
|
||||
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "NativeManager", "render->eglCore_->Draw() executed");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
// XComponent回调事件
|
||||
NativeManager::NativeManager() {
|
||||
eglcore_ = new EGLCore();
|
||||
callback_.OnSurfaceCreated = OnSurfaceCreatedCB;
|
||||
callback_.OnSurfaceChanged = OnSurfaceChangedCB;
|
||||
callback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
|
||||
callback_.DispatchTouchEvent = DispatchTouchEventCB;
|
||||
}
|
||||
// 创建节点组件
|
||||
ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {
|
||||
@ -419,5 +357,18 @@ napi_value NativeManager::SetNeedSoftKeyboard(napi_env env, napi_callback_info i
|
||||
OH_ArkUI_XComponent_SetNeedSoftKeyboard(node, needSoftKeyboard); // 设置是否需要软键盘
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
napi_value NativeManager::NapiLoadModel(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);
|
||||
std::string path = value2String(env, args[0]);
|
||||
int64_t id = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mapMutex);
|
||||
if (renderThreadMap.find(id) != renderThreadMap.end()) {
|
||||
renderThreadMap[id]->loadModel(std::string(path));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace NativeOpenCAX
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
#include "EGLCore.h"
|
||||
#include "arkui/native_node.h"
|
||||
#include "arkui/native_node_napi.h"
|
||||
|
||||
#include "NativeRenderThread.h"
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
|
||||
@ -47,9 +47,9 @@ public:
|
||||
return &NativeManager::pluginManager_;
|
||||
}
|
||||
static napi_value createNativeNode(napi_env env, napi_callback_info info);
|
||||
static napi_value NapiDrawPattern(napi_env env, napi_callback_info info);
|
||||
static napi_value SetFrameRate(napi_env env, napi_callback_info info);
|
||||
static napi_value SetNeedSoftKeyboard(napi_env env, napi_callback_info info);
|
||||
static napi_value NapiLoadModel(napi_env env, napi_callback_info info);
|
||||
// CApi XComponent
|
||||
void OnSurfaceChanged(OH_NativeXComponent* component, void* window);
|
||||
void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window);
|
||||
@ -61,10 +61,10 @@ private:
|
||||
std::unordered_map<std::string, NativeManager*> pluginManagerMap_;
|
||||
public:
|
||||
// [StartExclude plugin_manager_h_part]
|
||||
EGLCore *eglcore_;
|
||||
uint64_t width_;
|
||||
uint64_t height_;
|
||||
OH_NativeXComponent_TouchEvent touchEvent_;
|
||||
std::string modelPath_;
|
||||
static int32_t hasDraw_;
|
||||
static int32_t hasChangeColor_;
|
||||
static std::unordered_map<std::string, ArkUI_NodeHandle> nodeHandleMap_;
|
||||
|
||||
279
entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp
Normal file
279
entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
#include "NativeRender.h"
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <OSD_Environment.hxx>
|
||||
#include <AIS_InteractiveObject.hxx>
|
||||
#include <Prs3d_Drawer.hxx>
|
||||
#include <Prs3d_ShadingAspect.hxx>
|
||||
#include <Graphic3d_MaterialAspect.hxx>
|
||||
#include <Graphic3d_NameOfMaterial.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <BRepPrimAPI_MakeSphere.hxx>
|
||||
#include <BRepPrimAPI_MakeCylinder.hxx>
|
||||
#include <Graphic3d_TextureEnv.hxx>
|
||||
#include <V3d_TypeOfOrientation.hxx>
|
||||
#include <Aspect_TypeOfTriedronPosition.hxx>
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
|
||||
NativeRender::NativeRender()
|
||||
: rotationX_(0.0f),
|
||||
rotationY_(0.0f),
|
||||
zoomLevel_(1.0f),
|
||||
width_(0),
|
||||
height_(0),
|
||||
clearColor_(Quantity_NOC_BLACK),
|
||||
translationX_(0.0f),
|
||||
translationY_(0.0f)
|
||||
{
|
||||
setupViewer();
|
||||
setupContext();
|
||||
setupView();
|
||||
}
|
||||
|
||||
NativeRender::~NativeRender() {
|
||||
shapes_.clear();
|
||||
}
|
||||
|
||||
bool NativeRender::init(int width, int height) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
if (view_.IsNull()) {
|
||||
return false;
|
||||
}
|
||||
view_->SetBackgroundColor(clearColor_);
|
||||
view_->MustBeResized();
|
||||
view_->Redraw();
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeRender::setupViewer() {
|
||||
Handle(Aspect_DisplayConnection) displayConnection;
|
||||
|
||||
// 创建图形驱动
|
||||
static Handle(OpenGl_GraphicDriver) graphicDriver;
|
||||
if (graphicDriver.IsNull()) {
|
||||
graphicDriver = new OpenGl_GraphicDriver(displayConnection, Standard_False);
|
||||
graphicDriver->ChangeOptions().buffersNoSwap = Standard_True;
|
||||
}
|
||||
graphicDriver_ = graphicDriver;
|
||||
|
||||
// 创建V3d_Viewer
|
||||
viewer_ = new V3d_Viewer(graphicDriver_);
|
||||
viewer_->SetDefaultLights();
|
||||
viewer_->SetLightOn();
|
||||
}
|
||||
|
||||
void NativeRender::setupContext() {
|
||||
context_ = new AIS_InteractiveContext(viewer_);
|
||||
context_->SetDisplayMode(AIS_Shaded, Standard_False); // 默认使用着色模式
|
||||
}
|
||||
|
||||
void NativeRender::setupView() {
|
||||
view_ = viewer_->CreateView();
|
||||
|
||||
// 设置渲染参数
|
||||
view_->ChangeRenderingParams().Method = Graphic3d_RM_RASTERIZATION;
|
||||
view_->ChangeRenderingParams().IsShadowEnabled = Standard_False;
|
||||
view_->ChangeRenderingParams().IsReflectionEnabled = Standard_False;
|
||||
view_->ChangeRenderingParams().IsAntialiasingEnabled = Standard_True;
|
||||
view_->ChangeRenderingParams().Resolution = 2;
|
||||
|
||||
// 设置背景渐变
|
||||
view_->SetBgGradientColors(
|
||||
Quantity_Color(Quantity_NOC_GRAY),
|
||||
Quantity_Color(Quantity_NOC_BLACK),
|
||||
Aspect_GFM_VER, // 垂直渐变
|
||||
Standard_False
|
||||
);
|
||||
|
||||
// 设置默认相机位置
|
||||
view_->SetProj(V3d_XposYnegZpos);
|
||||
|
||||
// 设置相机参数
|
||||
Handle(Graphic3d_Camera) camera = view_->Camera();
|
||||
camera->SetFOVy(45.0); // 使用正确的FOV设置API
|
||||
camera->SetZRange(1.0, 10000.0);
|
||||
}
|
||||
|
||||
bool NativeRender::loadModel(const std::string& filePath) {
|
||||
// 清除现有模型
|
||||
for (auto& shape : shapes_) {
|
||||
context_->Remove(shape, Standard_False);
|
||||
}
|
||||
shapes_.clear();
|
||||
|
||||
// 加载STEP文件
|
||||
STEPControl_Reader reader;
|
||||
IFSelect_ReturnStatus status = reader.ReadFile(filePath.c_str());
|
||||
if (status != IFSelect_RetDone) {
|
||||
printf("Error: Failed to read STEP file: %s\n", filePath.c_str());
|
||||
loadDefaultModel();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 将文件内容转换为OCCT形状
|
||||
reader.TransferRoots();
|
||||
int numShapes = reader.NbShapes();
|
||||
if (numShapes <= 0) {
|
||||
printf("Error: No shapes found in STEP file\n");
|
||||
loadDefaultModel();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 加载所有形状
|
||||
for (Standard_Integer i = 1; i <= numShapes; i++) {
|
||||
TopoDS_Shape shape = reader.Shape(i);
|
||||
if (!shape.IsNull()) {
|
||||
Handle(AIS_Shape) aisShape = new AIS_Shape(shape);
|
||||
|
||||
// 设置材质
|
||||
Handle(Prs3d_Drawer) drawer = aisShape->Attributes();
|
||||
Handle(Prs3d_ShadingAspect) shadingAspect = new Prs3d_ShadingAspect();
|
||||
|
||||
// 随机颜色
|
||||
int colorIndex = i % 7;
|
||||
Quantity_Color color;
|
||||
switch (colorIndex) {
|
||||
case 0: color = Quantity_NOC_RED; break;
|
||||
case 1: color = Quantity_NOC_GREEN; break;
|
||||
case 2: color = Quantity_NOC_BLUE1; break;
|
||||
case 3: color = Quantity_NOC_YELLOW; break;
|
||||
case 4: color = Quantity_NOC_MAGENTA1; break;
|
||||
case 5: color = Quantity_NOC_CYAN1; break;
|
||||
case 6: color = Quantity_NOC_ORANGE; break;
|
||||
default: color = Quantity_NOC_WHITE;
|
||||
}
|
||||
|
||||
shadingAspect->SetColor(color);
|
||||
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
|
||||
drawer->SetShadingAspect(shadingAspect);
|
||||
|
||||
context_->Display(aisShape, Standard_True);
|
||||
shapes_.push_back(aisShape);
|
||||
}
|
||||
}
|
||||
|
||||
// 调整相机到合适位置
|
||||
view_->FitAll(0.05, Standard_True);
|
||||
view_->ZFitAll();
|
||||
printf("Successfully loaded STEP file with %d shapes\n", numShapes);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeRender::loadDefaultModel() {
|
||||
// 创建一个默认的3D立方体
|
||||
TopoDS_Shape box = BRepPrimAPI_MakeBox(10.0, 10.0, 10.0).Shape();
|
||||
Handle(AIS_Shape) aisBox = new AIS_Shape(box);
|
||||
|
||||
// 设置材质和颜色
|
||||
Handle(Prs3d_Drawer) drawer = aisBox->Attributes();
|
||||
Handle(Prs3d_ShadingAspect) shadingAspect = new Prs3d_ShadingAspect();
|
||||
shadingAspect->SetColor(Quantity_NOC_RED);
|
||||
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
|
||||
drawer->SetShadingAspect(shadingAspect);
|
||||
|
||||
context_->Display(aisBox, Standard_True);
|
||||
shapes_.push_back(aisBox);
|
||||
|
||||
// 创建一个球体
|
||||
TopoDS_Shape sphere = BRepPrimAPI_MakeSphere(gp_Pnt(20.0, 0.0, 0.0), 5.0).Shape();
|
||||
Handle(AIS_Shape) aisSphere = new AIS_Shape(sphere);
|
||||
shadingAspect = new Prs3d_ShadingAspect();
|
||||
shadingAspect->SetColor(Quantity_NOC_BLUE1);
|
||||
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
|
||||
aisSphere->Attributes()->SetShadingAspect(shadingAspect);
|
||||
context_->Display(aisSphere, Standard_True);
|
||||
shapes_.push_back(aisSphere);
|
||||
|
||||
// 创建一个圆柱体
|
||||
TopoDS_Shape cylinder = BRepPrimAPI_MakeCylinder(3.0, 15.0).Shape();
|
||||
Handle(AIS_Shape) aisCylinder = new AIS_Shape(cylinder);
|
||||
shadingAspect = new Prs3d_ShadingAspect();
|
||||
shadingAspect->SetColor(Quantity_NOC_GREEN);
|
||||
shadingAspect->SetMaterial(Graphic3d_NOM_PLASTIC);
|
||||
aisCylinder->Attributes()->SetShadingAspect(shadingAspect);
|
||||
|
||||
gp_Trsf transform;
|
||||
transform.SetTranslation(gp_Vec(-15.0, -15.0, 0.0));
|
||||
aisCylinder->SetLocalTransformation(transform);
|
||||
|
||||
context_->Display(aisCylinder, Standard_True);
|
||||
shapes_.push_back(aisCylinder);
|
||||
|
||||
// 调整相机
|
||||
view_->FitAll(0.05, Standard_True);
|
||||
view_->ZFitAll();
|
||||
printf("Loaded default model (cube, sphere, cylinder)\n");
|
||||
}
|
||||
|
||||
//setTranslation
|
||||
void NativeRender::setTranslation(float x, float y) {
|
||||
translationX_ = x;
|
||||
translationY_ = y;
|
||||
}
|
||||
|
||||
void NativeRender::render() {
|
||||
if (view_.IsNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 应用旋转
|
||||
Handle(Graphic3d_Camera) camera = view_->Camera();
|
||||
// 计算旋转
|
||||
gp_Quaternion rotation;
|
||||
rotation.SetEulerAngles(gp_EulerSequence::gp_Extrinsic_XYZ,
|
||||
rotationX_ * M_PI / 180.0,
|
||||
rotationY_ * M_PI / 180.0,
|
||||
0.0);
|
||||
|
||||
// 计算相机位置
|
||||
gp_Dir camDir(0.0, 1.0, 0.0);
|
||||
gp_Vec camVec = rotation * gp_Vec(camDir);
|
||||
gp_Pnt camPos = gp_Pnt(0.0, 0.0, 0.0).Translated(camVec.Reversed() * 50.0 * zoomLevel_);
|
||||
|
||||
// 设置相机参数
|
||||
camera->SetEye(camPos);
|
||||
camera->SetCenter(gp_Pnt(translationX_, translationY_, 0.0));
|
||||
camera->SetUp(gp_Dir(0.0, 0.0, 1.0));
|
||||
// 执行渲染
|
||||
view_->Redraw();
|
||||
}
|
||||
|
||||
void NativeRender::resize(int width, int height) {
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
if (!view_.IsNull() && nativeWindow_ != nullptr) {
|
||||
view_->SetWindow(nativeWindow_);
|
||||
view_->MustBeResized();
|
||||
}
|
||||
}
|
||||
|
||||
void NativeRender::setRotation(float xAngle, float yAngle) {
|
||||
rotationX_ = xAngle;
|
||||
rotationY_ = yAngle;
|
||||
}
|
||||
|
||||
void NativeRender::setZoomLevel(float zoom) {
|
||||
zoomLevel_ = std::max(0.1f, std::min(zoom, 5.0f)); // 限制缩放范围
|
||||
}
|
||||
|
||||
void NativeRender::resetView() {
|
||||
rotationX_ = 0.0f;
|
||||
rotationY_ = 0.0f;
|
||||
zoomLevel_ = 1.0f;
|
||||
|
||||
if (!view_.IsNull()) {
|
||||
view_->SetProj(V3d_XposYnegZpos);
|
||||
view_->FitAll(0.05, Standard_False);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeRender::setClearColor(float r, float g, float b, float a) {
|
||||
clearColor_ = Quantity_Color(r, g, b, Quantity_TOC_RGB);
|
||||
if (!view_.IsNull()) {
|
||||
view_->SetBackgroundColor(clearColor_);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace NativeRenderer
|
||||
64
entry/src/main/cpp/NativeEGLOCCT/NativeRender.h
Normal file
64
entry/src/main/cpp/NativeEGLOCCT/NativeRender.h
Normal file
@ -0,0 +1,64 @@
|
||||
#ifndef NATIVE_RENDER_H
|
||||
#define NATIVE_RENDER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <Standard_Handle.hxx>
|
||||
#include <AIS_InteractiveContext.hxx>
|
||||
#include <V3d_View.hxx>
|
||||
#include <V3d_Viewer.hxx>
|
||||
#include <OpenGl_GraphicDriver.hxx>
|
||||
#include <AIS_Shape.hxx>
|
||||
#include <STEPControl_Reader.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <Graphic3d_GraphicDriver.hxx>
|
||||
#include <Aspect_DisplayConnection.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Quantity_Color.hxx>
|
||||
#include <gp_Quaternion.hxx>
|
||||
#include <gp_EulerSequence.hxx>
|
||||
|
||||
class Aspect_Window;
|
||||
class gp_Quaternion;
|
||||
class Graphic3d_Camera;
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
class NativeRender {
|
||||
public:
|
||||
NativeRender();
|
||||
~NativeRender();
|
||||
|
||||
bool init(int width, int height);
|
||||
bool loadModel(const std::string& filePath);
|
||||
void render();
|
||||
void resize(int width, int height);
|
||||
void setRotation(float xAngle, float yAngle);
|
||||
void resetView();
|
||||
void setClearColor(float r, float g, float b, float a);
|
||||
void setZoomLevel(float zoom);
|
||||
void setTranslation(float x, float y);
|
||||
|
||||
private:
|
||||
void setupViewer();
|
||||
void setupContext();
|
||||
void setupView();
|
||||
void loadDefaultModel();
|
||||
|
||||
Handle(OpenGl_GraphicDriver) graphicDriver_;
|
||||
Handle(V3d_Viewer) viewer_;
|
||||
Handle(V3d_View) view_;
|
||||
Handle(AIS_InteractiveContext) context_;
|
||||
std::vector<Handle(AIS_Shape)> shapes_;
|
||||
|
||||
float rotationX_;
|
||||
float rotationY_;
|
||||
float zoomLevel_;
|
||||
int width_;
|
||||
int height_;
|
||||
float translationX_;
|
||||
float translationY_;
|
||||
Quantity_Color clearColor_;
|
||||
Aspect_Window* nativeWindow_;
|
||||
};
|
||||
} // namespace NativeRender
|
||||
#endif // NATIVE_RENDER_H
|
||||
190
entry/src/main/cpp/NativeEGLOCCT/NativeRenderThread.cpp
Normal file
190
entry/src/main/cpp/NativeEGLOCCT/NativeRenderThread.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#include "NativeRenderThread.h"
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
|
||||
NativeRenderThread::NativeRenderThread()
|
||||
: isRunning_(false),
|
||||
nativeWindow_(nullptr),
|
||||
windowWidth_(1280),
|
||||
windowHeight_(720) {}
|
||||
|
||||
NativeRenderThread::~NativeRenderThread() {
|
||||
stop();
|
||||
}
|
||||
|
||||
bool NativeRenderThread::start(OHNativeWindow* window) {
|
||||
if (isRunning_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nativeWindow_ = window;
|
||||
|
||||
// 初始化EGL
|
||||
if (!eglCore_.init(nativeWindow_)) {
|
||||
printf("Failed to initialize EGL\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 初始化OCCT渲染器
|
||||
if (!renderer_.init(windowWidth_, windowHeight_)) {
|
||||
printf("Failed to initialize OCCT renderer\n");
|
||||
eglCore_.destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
isRunning_ = true;
|
||||
renderThread_ = std::thread(&NativeRenderThread::renderLoop, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NativeRenderThread::stop() {
|
||||
if (!isRunning_) {
|
||||
return;
|
||||
}
|
||||
|
||||
isRunning_ = false;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
commandQueue_.push(RenderCommand(CMD_EXIT));
|
||||
}
|
||||
commandCondition_.notify_one();
|
||||
|
||||
if (renderThread_.joinable()) {
|
||||
renderThread_.join();
|
||||
}
|
||||
|
||||
eglCore_.destroy();
|
||||
}
|
||||
|
||||
void NativeRenderThread::renderLoop() {
|
||||
while (isRunning_) {
|
||||
RenderCommand command;
|
||||
bool hasCommand = false;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(commandMutex_);
|
||||
commandCondition_.wait_for(lock, std::chrono::milliseconds(16), [this] {
|
||||
return !commandQueue_.empty();
|
||||
});
|
||||
|
||||
if (!commandQueue_.empty()) {
|
||||
command = commandQueue_.front();
|
||||
commandQueue_.pop();
|
||||
hasCommand = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasCommand) {
|
||||
switch (command.type) {
|
||||
case CMD_LOAD_MODEL:
|
||||
renderer_.loadModel(command.param1);
|
||||
break;
|
||||
case CMD_SET_ROTATION:
|
||||
renderer_.setRotation(command.param2, command.param3);
|
||||
break;
|
||||
case CMD_SET_TRANSLATION:
|
||||
renderer_.setTranslation(command.param2, command.param3);
|
||||
break;
|
||||
case CMD_RESET_VIEW:
|
||||
renderer_.resetView();
|
||||
break;
|
||||
case CMD_SET_CLEAR_COLOR:
|
||||
renderer_.setClearColor(command.param2, command.param3, command.param4, command.param5);
|
||||
break;
|
||||
case CMD_RESIZE:
|
||||
windowWidth_ = static_cast<int>(command.param2);
|
||||
windowHeight_ = static_cast<int>(command.param3);
|
||||
renderer_.resize(windowWidth_, windowHeight_);
|
||||
break;
|
||||
case CMD_EXIT:
|
||||
isRunning_ = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRunning_) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 渲染
|
||||
eglCore_.makeCurrent();
|
||||
renderer_.render();
|
||||
eglCore_.swapBuffers();
|
||||
|
||||
// 调用渲染完成回调
|
||||
Callback callback;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(callbackMutex_);
|
||||
callback = renderCompleteCallback_;
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
// 控制帧率
|
||||
usleep(16000); // ~60 FPS
|
||||
}
|
||||
}
|
||||
|
||||
void NativeRenderThread::loadModel(const std::string& filePath) {
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
RenderCommand cmd(CMD_LOAD_MODEL);
|
||||
cmd.param1 = filePath;
|
||||
commandQueue_.push(cmd);
|
||||
commandCondition_.notify_one();
|
||||
}
|
||||
|
||||
void NativeRenderThread::setRotation(float xAngle, float yAngle) {
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
RenderCommand cmd(CMD_SET_ROTATION);
|
||||
cmd.param2 = xAngle;
|
||||
cmd.param3 = yAngle;
|
||||
commandQueue_.push(cmd);
|
||||
commandCondition_.notify_one();
|
||||
}
|
||||
|
||||
void NativeRenderThread::setTranslation(float x, float y) {
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
RenderCommand cmd(CMD_SET_TRANSLATION);
|
||||
cmd.param2 = x;
|
||||
cmd.param3 = y;
|
||||
commandQueue_.push(cmd);
|
||||
commandCondition_.notify_one();
|
||||
}
|
||||
|
||||
void NativeRenderThread::resetView() {
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
commandQueue_.push(RenderCommand(CMD_RESET_VIEW));
|
||||
commandCondition_.notify_one();
|
||||
}
|
||||
|
||||
void NativeRenderThread::setClearColor(float r, float g, float b, float a) {
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
RenderCommand cmd(CMD_SET_CLEAR_COLOR);
|
||||
cmd.param2 = r;
|
||||
cmd.param3 = g;
|
||||
cmd.param4 = b;
|
||||
cmd.param5 = a;
|
||||
commandQueue_.push(cmd);
|
||||
commandCondition_.notify_one();
|
||||
}
|
||||
|
||||
void NativeRenderThread::resizeWindow(int width, int height) {
|
||||
std::lock_guard<std::mutex> lock(commandMutex_);
|
||||
RenderCommand cmd(CMD_RESIZE);
|
||||
cmd.param2 = static_cast<float>(width);
|
||||
cmd.param3 = static_cast<float>(height);
|
||||
commandQueue_.push(cmd);
|
||||
commandCondition_.notify_one();
|
||||
}
|
||||
|
||||
void NativeRenderThread::registerRenderCompleteCallback(Callback callback) {
|
||||
std::lock_guard<std::mutex> lock(callbackMutex_);
|
||||
renderCompleteCallback_ = callback;
|
||||
}
|
||||
} // namespace OCCTRenderer
|
||||
73
entry/src/main/cpp/NativeEGLOCCT/NativeRenderThread.h
Normal file
73
entry/src/main/cpp/NativeEGLOCCT/NativeRenderThread.h
Normal file
@ -0,0 +1,73 @@
|
||||
#ifndef NATIVE_RENDER_THREAD_H
|
||||
#define NATIVE_RENDER_THREAD_H
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <queue>
|
||||
#include <functional>
|
||||
|
||||
#include "EGLCore.h"
|
||||
#include "NativeRender.h"
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
|
||||
class NativeRenderThread {
|
||||
public:
|
||||
NativeRenderThread();
|
||||
~NativeRenderThread();
|
||||
|
||||
bool start(OHNativeWindow* window);
|
||||
void stop();
|
||||
|
||||
void loadModel(const std::string& filePath);
|
||||
void setRotation(float xAngle, float yAngle);
|
||||
void setTranslation(float x, float y);
|
||||
void resetView();
|
||||
void setClearColor(float r, float g, float b, float a);
|
||||
void resizeWindow(int width, int height);
|
||||
|
||||
using Callback = std::function<void()>;
|
||||
void registerRenderCompleteCallback(Callback callback);
|
||||
|
||||
private:
|
||||
void renderLoop();
|
||||
|
||||
std::thread renderThread_;
|
||||
std::atomic<bool> isRunning_;
|
||||
|
||||
OHNativeWindow* nativeWindow_;
|
||||
EGLCore eglCore_;
|
||||
NativeRender renderer_;
|
||||
|
||||
std::mutex commandMutex_;
|
||||
std::condition_variable commandCondition_;
|
||||
|
||||
enum CommandType {
|
||||
CMD_LOAD_MODEL,
|
||||
CMD_SET_ROTATION,
|
||||
CMD_SET_TRANSLATION,
|
||||
CMD_RESET_VIEW,
|
||||
CMD_SET_CLEAR_COLOR,
|
||||
CMD_RESIZE,
|
||||
CMD_EXIT
|
||||
};
|
||||
|
||||
struct RenderCommand {
|
||||
CommandType type;
|
||||
std::string param1; // For file path
|
||||
float param2, param3, param4, param5;
|
||||
RenderCommand() : type(CMD_EXIT), param1(""), param2(0.0f), param3(0.0f), param4(0.0f), param5(0.0f) {}
|
||||
RenderCommand(CommandType t) : type(t), param1(""), param2(0), param3(0), param4(0), param5(0) {}
|
||||
};
|
||||
|
||||
std::queue<RenderCommand> commandQueue_;
|
||||
|
||||
std::mutex callbackMutex_;
|
||||
Callback renderCompleteCallback_;
|
||||
|
||||
int windowWidth_;
|
||||
int windowHeight_;
|
||||
};
|
||||
} // namespace NaitveRenderThread
|
||||
#endif //NATIVE_RENDER_THREAD_H
|
||||
@ -29,6 +29,7 @@ static napi_value NativeLoadSoTest(napi_env env, napi_callback_info info)
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
namespace NativeOpenCAX {
|
||||
EXTERN_C_START
|
||||
static napi_value Init(napi_env env, napi_value exports) {
|
||||
@ -40,7 +41,7 @@ static napi_value Init(napi_env env, napi_value exports) {
|
||||
napi_property_descriptor desc[] = {
|
||||
// [StartExclude napi_init_part]
|
||||
{"createNativeNode", nullptr, NativeManager::createNativeNode, nullptr, nullptr, nullptr,napi_default, nullptr },
|
||||
{"drawPattern", nullptr, NativeManager::NapiDrawPattern, nullptr, nullptr,nullptr, napi_default, nullptr},
|
||||
{"loadModel", nullptr, NativeManager::NapiLoadModel, nullptr, nullptr, nullptr, napi_default, nullptr},
|
||||
{"setFrameRate", nullptr, NativeManager::SetFrameRate, nullptr, nullptr, nullptr, napi_default, nullptr},
|
||||
{"setNeedSoftKeyboard", nullptr, NativeManager::SetNeedSoftKeyboard, nullptr, nullptr, nullptr, napi_default,nullptr},
|
||||
{"nativeLoadTest", nullptr, NativeLoadSoTest, nullptr, nullptr, nullptr, napi_default, nullptr},
|
||||
|
||||
30
entry/src/main/cpp/types/libopencax/Index.d.ts
vendored
30
entry/src/main/cpp/types/libopencax/Index.d.ts
vendored
@ -1,24 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { NodeContent } from '@ohos.arkui.node';
|
||||
type XComponentContextStatus = {
|
||||
hasDraw: boolean,
|
||||
hasChangeColor: boolean
|
||||
};
|
||||
export const createNativeNode: (content: NodeContent, tag: string) => void;
|
||||
export const drawPattern: () => void;
|
||||
export const setFrameRate: (id: string, min: number, max: number, expected: number) => void;
|
||||
export const setNeedSoftKeyboard: (id: string, needSoftKeyborad: boolean) => void;
|
||||
export interface NativeXOpenCAX {
|
||||
setFrameRate(nodeId: string, min: number, max: number, expected: number): void;
|
||||
setNeedSoftKeyboard(nodeId: string, need: boolean): void;
|
||||
}
|
||||
export function createNativeNode(nodeContent: any, nodeId: string): void;
|
||||
export function loadModel(stepFilePath: string): void;
|
||||
@ -66,8 +66,7 @@ export struct ModelView {
|
||||
Button('加载模型').onClick(()=>{
|
||||
try {
|
||||
console.info('Model copied to:', this.modelPath);
|
||||
NativeOpenCAX.drawPattern();
|
||||
//NativeOpenCAX.loadModel(this.displayContrId,this.modelPath);
|
||||
NativeOpenCAX.loadModel(this.modelPath);
|
||||
} catch (e) {
|
||||
hilog.error(0x0000, 'ModelView', `LoadModel Failed: ${JSON.stringify(e)}`);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user