From 3040d65e3ea8789af597cd8a56bef630cf2479a4 Mon Sep 17 00:00:00 2001 From: Zjsxstar Date: Mon, 28 Apr 2025 21:20:51 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9demo=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81AI=E5=88=86=E6=9E=90=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Zjsxstar --- README_zh.md | 12 +-- entry/src/main/cpp/render/egl_core.cpp | 131 +++++++++++++++---------- entry/src/main/cpp/render/egl_core.h | 4 + entry/src/main/ets/pages/Index.ets | 107 ++++++++++++-------- 4 files changed, 155 insertions(+), 99 deletions(-) diff --git a/README_zh.md b/README_zh.md index cff0d35..d83446d 100644 --- a/README_zh.md +++ b/README_zh.md @@ -2,7 +2,7 @@ ### 介绍 -本示例主要介绍开发者如何使用ArkTS XComponent组件进行自绘制,主要包括:XComponent组件使用, +本示例主要介绍开发者如何使用ArkTS XComponent组件进行自绘制以及AI分析能力,主要包括:XComponent组件使用, SurfaceId获取方法,Surface生命周期回调使用,NativeWindow创建等知识点。开发者基于ArkTS侧获取的SurfaceId, 在Native侧调用OH_NativeWindow_CreateNativeWindowFromSurfaceId接口创建出NativeWindow实例后,使用OpenGL ES/EGL接口在XComponent组件上进行图形绘制。功能主要包括点击按钮绘制一个五角星,并可以通过点击XComponent区域改变五角星的颜色。 @@ -83,7 +83,7 @@ XComponentController ### 约束与限制 -1. 本示例仅支持标准系统上运行,支持设备:rk3568 +1. 本示例仅支持标准系统上运行,支持设备:手机、PC 2. 本示例为Stage模型,支持API12版本SDK,SDK版本号(API Version 12 Release),镜像版本号(5.0 Release) @@ -91,12 +91,8 @@ XComponentController ### 下载 -如需单独下载本工程,执行如下命令: +如需下载本工程,执行如下命令: ``` -git init -git config core.sparsecheckout true -echo code/BasicFeature/Native/ArkTSXComponent/ > .git/info/sparse-checkout -git remote add origin https://gitee.com/openharmony/applications_app_samples.git -git pull origin master +git clone https://gitee.com/harmonyos_samples/XComponent.git ``` diff --git a/entry/src/main/cpp/render/egl_core.cpp b/entry/src/main/cpp/render/egl_core.cpp index 7112fd0..d47df6f 100644 --- a/entry/src/main/cpp/render/egl_core.cpp +++ b/entry/src/main/cpp/render/egl_core.cpp @@ -26,6 +26,10 @@ #include "../common/common.h" #include "plugin_render.h" +#define PI 3.14159265 +static std::vector starVertices; +static std::vector starColors; + namespace NativeXComponentSample { namespace { constexpr int32_t NUM_4 = 4; @@ -189,8 +193,55 @@ const EGLint CONTEXT_ATTRIBS[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; } // namespace +void EGLCore::CreateStar() +{ + starVertices.clear(); + float ratio = 1.0f; + constexpr float inner = 0.3f; + constexpr float outer = 0.95f; + constexpr GLfloat CenterX = 0.0f; + constexpr GLfloat CenterY = 0.0f; + constexpr float pentaAngle = 2. * PI / 5.f; + for (int i = 0; i < 5; ++i) { + starVertices.push_back(CenterX); + starVertices.push_back(CenterY); + starVertices.push_back(CenterX + inner * cosf(-PI * 0.5f - pentaAngle * 2.f - pentaAngle * i) * ratio); + starVertices.push_back(CenterY + inner * sinf(-PI * 0.5f - pentaAngle * 2.f - pentaAngle * i)); + starVertices.push_back(CenterX + outer * cosf(PI * 0.5f - pentaAngle * i) * ratio); + starVertices.push_back(CenterY + outer * sinf(PI * 0.5f - pentaAngle * i)); + starVertices.push_back(CenterX + inner * cosf(-PI * 0.5f - pentaAngle * 3.f - pentaAngle * i) * ratio); + starVertices.push_back(CenterY + inner * sinf(-PI * 0.5f - pentaAngle * 3.f - pentaAngle * i)); + } +} + +void EGLCore::CreateStarColor() +{ + starColors.clear(); + constexpr float inner = 0.5f; + constexpr float outer = 2.f; + constexpr GLfloat CenterX = 0.f; + constexpr GLfloat CenterY = 0.f; + constexpr float pentaAngle = 2. * PI / 5.f; + for (int i = 0; i < 5; ++i) { + starColors.push_back(251.0f / 255); + starColors.push_back(126.0f / 255); + starColors.push_back(126.0f / 255); + starColors.push_back(88.0f / 255); + starColors.push_back(50.f / 255); + starColors.push_back(50.f / 255); + starColors.push_back(251.f / 255); + starColors.push_back(126.f / 255); + starColors.push_back(126.f / 255); + starColors.push_back(88.0f / 255); + starColors.push_back(50.f / 255); + starColors.push_back(50.f / 255); + } +} + bool EGLCore::EglContextInit(void* window) { + CreateStar(); + CreateStarColor(); OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "EGLCore", "EglContextInit execute"); eglWindow_ = static_cast(window); @@ -272,63 +323,43 @@ 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; - } - - // Divided into five quadrilaterals and calculate one of the quadrilateral's Vertices - 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_ }; + DrawStar(); + hasDraw = 1; + flag_ = true; +} - if (!ExecuteDrawStar(position, DRAW_COLOR, shapeVertices, sizeof(shapeVertices))) { - OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw execute draw shape failed"); +void EGLCore::DrawTriangleFan(GLint position, const GLfloat shapeVertices[], uint32_t length) +{ + if (position > 0) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "DrawTriangleFan: param error"); return; } + glVertexAttribPointer(position, POINTER_SIZE, GL_FLOAT, GL_FALSE, 0, shapeVertices); + glEnableVertexAttribArray(position); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, starColors.data()); + glEnableVertexAttribArray(1); + glDrawArrays(GL_TRIANGLE_FAN, 0, length / 2); + glDisableVertexAttribArray(position); + glDisableVertexAttribArray(1); +} - // Convert DEG(72°) to RAD - GLfloat rad = M_PI / 180 * 72; - // Rotate four times - 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; +void EGLCore::DrawStar() { + 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"); } - } + glViewport(0, 0, width_, height_); + glClearColor(0.9, 0.9, 0.9, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glUseProgram(program_); + GLint position = glGetAttribLocation(program_, POSITION_NAME); + DrawTriangleFan(position, starVertices.data(), starVertices.size()); - if (!FinishDraw()) { - OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "Draw FinishDraw failed"); - return; + glFlush(); + glFinish(); + if (!eglSwapBuffers(eglDisplay_, eglSurface_)) { + OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "EGLCore", "DrawStar FinishDraw: failed"); } - hasDraw = 1; - - flag_ = true; } void EGLCore::ChangeColor(int& hasChangeColor) diff --git a/entry/src/main/cpp/render/egl_core.h b/entry/src/main/cpp/render/egl_core.h index 0f25ca0..5ac63d4 100644 --- a/entry/src/main/cpp/render/egl_core.h +++ b/entry/src/main/cpp/render/egl_core.h @@ -31,6 +31,10 @@ public: void ChangeColor(int& hasChangeColor); void Release(); void UpdateSize(int width, int height); + void CreateStar(); + void CreateStarColor(); + void DrawStar(); + void DrawTriangleFan(GLint position, const GLfloat shapeVertices[], uint32_t length); private: GLuint LoadShader(GLenum type, const char* shaderSrc); diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index e8fab8b..fb9f6b8 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -45,51 +45,25 @@ struct XComponentExample { types: [ImageAnalyzerType.SUBJECT, ImageAnalyzerType.TEXT], aiController: this.aiController }; - @State xcWidth: string = "320px"; - @State xcHeight: string = "480px"; + @State xcWidth: string = "720px"; + @State xcHeight: string = "720px"; @State currentStatus: string = "index"; build() { Column({ space: 5 }) { - Button("change size") - .onClick(() => { - this.xcWidth = "640px"; - this.xcHeight = "720px"; - }) - Button('start AI analyze') - .onClick(() => { - this.xComponentController.startImageAnalyzer(this.config) - .then(() => { - console.log("analysis complete"); - }) - .catch((error: BusinessError) => { - console.log("error code: " + error.code); - }) - }) - Button('stop AI analyze') - .onClick(() => { - this.xComponentController.stopImageAnalyzer(); - }) - Button('get analyzer types') - .onClick(() => { - this.aiController.getImageAnalyzerSupportTypes(); - }) - Button('Draw Star') - .fontSize('16fp') - .fontWeight(500) - .margin({ bottom: 24 }) - .onClick(() => { - let surfaceId = this.xComponentController.getXComponentSurfaceId(); - this.xComponentController.getXComponentSurfaceRect(); - nativeRender.DrawPattern(BigInt(surfaceId)); - let hasDraw: boolean = false; - if (nativeRender.GetXComponentStatus(BigInt(surfaceId))) { - hasDraw = nativeRender.GetXComponentStatus(BigInt(surfaceId)).hasDraw; - } - if (hasDraw) { - this.currentStatus = "draw star"; - } - }) + Row() { + Text('Native XComponent Sample') + .fontSize('24fp') + .fontWeight(500) + .margin({ + left: 24, + top: 12 + }) + } + .margin({ top: 24 }) + .width('100%') + .height(56) + XComponent({ type: XComponentType.SURFACE, controller: this.xComponentController, @@ -98,9 +72,60 @@ struct XComponentExample { .width(this.xcWidth) .height(this.xcHeight) .enableAnalyzer(true) + .onClick(() => { + let surfaceId = this.xComponentController.getXComponentSurfaceId(); + nativeRender.ChangeColor(BigInt(surfaceId)); + let hasChangeColor: boolean = false; + if (nativeRender.GetXComponentStatus(BigInt(surfaceId))) { + hasChangeColor = nativeRender.GetXComponentStatus(BigInt(surfaceId)).hasChangeColor; + } + if (hasChangeColor) { + this.currentStatus = "change color"; + } + }) Text(this.currentStatus) .fontSize('24fp') .fontWeight(500) + Column() { + Button('start AI analyze') + .onClick(() => { + this.xComponentController.startImageAnalyzer(this.config) + .then(() => { + console.log("analysis complete"); + }) + .catch((error: BusinessError) => { + console.log("error code: " + error.code); + }) + }) + .margin(2) + Button('stop AI analyze') + .onClick(() => { + this.xComponentController.stopImageAnalyzer(); + }) + .margin(2) + Button('get analyzer types') + .onClick(() => { + this.aiController.getImageAnalyzerSupportTypes(); + }) + .margin(2) + Button('Draw Star') + .fontSize('16fp') + .fontWeight(500) + .margin({ bottom: 24 }) + .onClick(() => { + let surfaceId = this.xComponentController.getXComponentSurfaceId(); + this.xComponentController.getXComponentSurfaceRect(); + nativeRender.DrawPattern(BigInt(surfaceId)); + let hasDraw: boolean = false; + if (nativeRender.GetXComponentStatus(BigInt(surfaceId))) { + hasDraw = nativeRender.GetXComponentStatus(BigInt(surfaceId)).hasDraw; + } + if (hasDraw) { + this.currentStatus = "draw star"; + } + }) + .margin(2) + }.justifyContent(FlexAlign.Center) } .width("100%") } -- Gitee