增加两个模型

修改世界坐标系
测试鼠标旋转相机
This commit is contained in:
JackLee 2026-03-07 18:46:12 +08:00
parent b806ccbf1a
commit 406cd03b02
13 changed files with 9374 additions and 38611 deletions

View File

@ -17,6 +17,9 @@ bool InitLocalAxis(RenderOption& opt) {
opt.localAxisPlacement = new Geom_Axis2Placement(gp::XOY()); opt.localAxisPlacement = new Geom_Axis2Placement(gp::XOY());
opt.localAxis = new AIS_Trihedron(opt.localAxisPlacement); opt.localAxis = new AIS_Trihedron(opt.localAxisPlacement);
opt.localAxis->SetSize(50.0); opt.localAxis->SetSize(50.0);
opt.localAxis->SetDatumPartColor(Prs3d_DP_XAxis,Quantity_NOC_RED);
opt.localAxis->SetDatumPartColor(Prs3d_DP_YAxis,Quantity_NOC_GREEN);
opt.localAxis->SetDatumPartColor(Prs3d_DP_ZAxis,Quantity_NOC_BLUE);
opt.context->Display(opt.localAxis, 0, 0, true); opt.context->Display(opt.localAxis, 0, 0, true);
HILOG_INFO(NATIVE_TAG,"InitLocalAxis Done"); HILOG_INFO(NATIVE_TAG,"InitLocalAxis Done");
return true; return true;

View File

@ -16,7 +16,18 @@ bool InitWorldAxis(RenderOption& opt) {
// 添加世界坐标系(左下角) // 添加世界坐标系(左下角)
opt.worldAxisPlacement = new Geom_Axis2Placement(gp::XOY()); opt.worldAxisPlacement = new Geom_Axis2Placement(gp::XOY());
opt.worldAxis = new AIS_Trihedron(opt.worldAxisPlacement); opt.worldAxis = new AIS_Trihedron(opt.worldAxisPlacement);
opt.worldAxis->SetSize(30.0); // 小一点,作为指示器 opt.worldAxis->SetSize(100.0); // 小一点,作为指示器
opt.worldAxis->SetZLayer(Graphic3d_ZLayerId_TopOSD);
opt.worldAxis->SetTransformPersistence(
new Graphic3d_TransformPers(
Graphic3d_TMF_2d, // 2D 模式
Aspect_TOTP_LEFT_LOWER, // 左下角对齐
Graphic3d_Vec2i(100, 100) // 偏移量(像素)
)
);
opt.worldAxis->SetDatumPartColor(Prs3d_DP_XAxis,Quantity_NOC_RED);
opt.worldAxis->SetDatumPartColor(Prs3d_DP_YAxis,Quantity_NOC_GREEN);
opt.worldAxis->SetDatumPartColor(Prs3d_DP_ZAxis,Quantity_NOC_BLUE);
opt.context->Display(opt.worldAxis, 0, 0, false); opt.context->Display(opt.worldAxis, 0, 0, false);
HILOG_INFO(NATIVE_TAG,"InitWorldAxis Done"); HILOG_INFO(NATIVE_TAG,"InitWorldAxis Done");
return true; return true;

View File

@ -7,6 +7,7 @@
#ifndef OPENCAX_WORLDAXIS_H #ifndef OPENCAX_WORLDAXIS_H
#define OPENCAX_WORLDAXIS_H #define OPENCAX_WORLDAXIS_H
#include "../RenderStruct.h" #include "../RenderStruct.h"
#include <Prs3d_DatumParts.hxx>
namespace NativeOpenCAX { namespace NativeOpenCAX {
bool InitWorldAxis(RenderOption& opt); bool InitWorldAxis(RenderOption& opt);
void ChangeWorldAxis(); void ChangeWorldAxis();

View File

@ -77,39 +77,7 @@ std::string uuid_v4() {
<< "-" << std::setw(12) << std::setfill('0') << (random_part & 0xFFFFFFFFFFFF); << "-" << std::setw(12) << std::setfill('0') << (random_part & 0xFFFFFFFFFFFF);
return ss.str(); return ss.str();
} }
// 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 OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) {
// [StartExclude plugin_on_surface_created] // [StartExclude plugin_on_surface_created]
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "XComponent_Native", "OnSurfaceCreatedCB");
@ -216,6 +184,73 @@ void onEvent(ArkUI_NodeEvent *event) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "onBind", "on touch");
} }
} }
void OnMouseEventCB(OH_NativeXComponent* component, void* window) {
auto* pluginManager = NativeManager::GetInstance();
if (!pluginManager || !window) {
return;
}
auto *pluginManger = NativeManager::GetInstance();
pluginManger->OnMouseEvent(component, window);
}
void NativeManager::OnMouseEvent(OH_NativeXComponent *component, void *window) {
OH_NativeXComponent_MouseEvent event;
int32_t ret;
ret=OH_NativeXComponent_GetMouseEvent(component, window, &event);
std::lock_guard<std::mutex> lock(mapMutex);
//通过时间戳判断事件唯一性.保证单一时间戳只触发一次事件
if(event.timestamp==NativeManager::timestamp){
return;
}
NativeManager::timestamp=event.timestamp;
int64_t id = 0;
auto it = renderThreadMap.find(id);
if (it == renderThreadMap.end()) {
HILOG_WARN(NATIVE_TAG, "Render thread not found for rotation.");
return;
}
auto renderThread = it->second;
float curtX,curtY;
HILOG_WARN(NATIVE_TAG, "ALLButton:%{public}d",event.button);
HILOG_WARN(NATIVE_TAG, "ALLAction:%{public}d",event.action);
HILOG_WARN(NATIVE_TAG, "ALLTimestamp:%{public}d",event.timestamp);
//鼠标按下并且事件为鼠标中键
if(event.button==OH_NATIVEXCOMPONENT_LEFT_BUTTON&&event.action==OH_NATIVEXCOMPONENT_MOUSE_PRESS){
//记录按下时候的X.Y坐标
NativeManager::lastMouseX_=event.x;
NativeManager::lastMouseY_=event.y;
NativeManager::isMouseMiddleBtnPressed = true;
HILOG_WARN(NATIVE_TAG, "AtlastMouseX:%{public}d",NativeManager::lastMouseX_);
HILOG_WARN(NATIVE_TAG, "AtlastMouseY:%{public}d",NativeManager::lastMouseY_);
HILOG_WARN(NATIVE_TAG, "AtButton:%{public}d",event.button);
HILOG_WARN(NATIVE_TAG, "AtButtonAction:%{public}d",event.action);
HILOG_WARN(NATIVE_TAG, "AtisMouseMiddleBtnPressed:%{public}d",NativeManager::isMouseMiddleBtnPressed);
}else if(NativeManager::isMouseMiddleBtnPressed&&event.action==OH_NATIVEXCOMPONENT_MOUSE_MOVE){
// 计算鼠标移动距离
float deltaX = curtX - NativeManager::lastMouseX_;
float deltaY = curtY - NativeManager::lastMouseY_;
// 将像素移动量映射到旋转角度
// 这里的系数可以根据需要调整灵敏度
float rotationSpeed = 0.005f;
float angleX = deltaX * rotationSpeed;
float angleY = deltaY * rotationSpeed;
// 通知渲染线程执行旋转
// 由于渲染在线程里,需要通过命令队列发送指令
renderThread->setRotation(angleX, angleY);
// 更新最后的位置
//NativeManager::lastMouseX_ = deltaX;
//NativeManager::lastMouseY_ = deltaY;
HILOG_WARN(NATIVE_TAG, "MoveAngleX:%{public}d",angleX);
HILOG_WARN(NATIVE_TAG, "MoveAngleY:%{public}d",angleY);
HILOG_WARN(NATIVE_TAG, "MoveButton:%{public}d",event.button);
HILOG_WARN(NATIVE_TAG, "MoveButtonAction:%{public}d",event.action);
HILOG_WARN(NATIVE_TAG, "MoveIsMouseMiddleBtnPressed:%{public}d",NativeManager::isMouseMiddleBtnPressed);
}
else if(event.button==OH_NATIVEXCOMPONENT_LEFT_BUTTON&&event.action==OH_NATIVEXCOMPONENT_MOUSE_RELEASE){
//NativeManager::isMouseMiddleBtnPressed = false;
HILOG_WARN(NATIVE_TAG, "ReleaseIsMouseMiddleBtnPressed:%{public}d",NativeManager::isMouseMiddleBtnPressed);
}
}
static std::string value2String(napi_env env, napi_value value) { static std::string value2String(napi_env env, napi_value value) {
size_t stringSize = 0; size_t stringSize = 0;
napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize); napi_get_value_string_utf8(env, value, nullptr, 0, &stringSize);
@ -229,6 +264,7 @@ NativeManager::NativeManager() {
xSurfaceTouchEventCallBack.OnSurfaceCreated = OnSurfaceCreatedCB; xSurfaceTouchEventCallBack.OnSurfaceCreated = OnSurfaceCreatedCB;
xSurfaceTouchEventCallBack.OnSurfaceChanged = OnSurfaceChangedCB; xSurfaceTouchEventCallBack.OnSurfaceChanged = OnSurfaceChangedCB;
xSurfaceTouchEventCallBack.OnSurfaceDestroyed = OnSurfaceDestroyedCB; xSurfaceTouchEventCallBack.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
xMouseEventCallBack.DispatchMouseEvent= OnMouseEventCB;
} }
// 创建节点组件 // 创建节点组件
ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) { ArkUI_NodeHandle CreateNodeHandle(const std::string &tag) {

View File

@ -57,6 +57,7 @@ public:
void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window); void OnSurfaceDestroyed(OH_NativeXComponent* component, void* window);
void DispatchTouchEvent(OH_NativeXComponent* component, void* window); void DispatchTouchEvent(OH_NativeXComponent* component, void* window);
void OnSurfaceCreated(OH_NativeXComponent* component, void* window); void OnSurfaceCreated(OH_NativeXComponent* component, void* window);
void OnMouseEvent(OH_NativeXComponent *component, void *window);
private: private:
static NativeManager pluginManager_; static NativeManager pluginManager_;
std::unordered_map<std::string, OH_NativeXComponent*> nativeXComponentMap_; std::unordered_map<std::string, OH_NativeXComponent*> nativeXComponentMap_;
@ -67,8 +68,14 @@ public:
std::string modelPath_; std::string modelPath_;
uint64_t width_; uint64_t width_;
uint64_t height_; uint64_t height_;
int64_t timestamp;
static int32_t hasDraw_; static int32_t hasDraw_;
static int32_t hasChangeColor_; static int32_t hasChangeColor_;
//鼠标位置保存
float lastMouseX_;
float lastMouseY_;
//鼠标按下状态保存
bool isMouseMiddleBtnPressed;
static std::unordered_map<std::string, ArkUI_NodeHandle> nodeHandleMap_; static std::unordered_map<std::string, ArkUI_NodeHandle> nodeHandleMap_;
static std::unordered_map<void *, OH_ArkUI_SurfaceCallback *> callbackMap_; static std::unordered_map<void *, OH_ArkUI_SurfaceCallback *> callbackMap_;
static std::unordered_map<void *, OH_ArkUI_SurfaceHolder *> surfaceHolderMap_; static std::unordered_map<void *, OH_ArkUI_SurfaceHolder *> surfaceHolderMap_;

View File

@ -119,7 +119,7 @@ bool NativeRender::loadModel(const std::string& filePath) {
} }
// 调整相机到合适位置 // 调整相机到合适位置
rendOption.view->FitAll(0.05, Standard_True); rendOption.view->FitAll(0.5, Standard_True);
rendOption.view->ZFitAll(); rendOption.view->ZFitAll();
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "LoadModel","Successfully loaded STEP file with %{public}d shapes",numShapes); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "LoadModel","Successfully loaded STEP file with %{public}d shapes",numShapes);
return true; return true;
@ -136,28 +136,6 @@ void NativeRender::render() {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Render","View Is Null"); OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Render","View Is Null");
return; return;
} }
//glClearColor(1, 0, 0, 1);
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glViewport(0, 0, width_, height_);
// 应用旋转
//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));
// 执行渲染 // 执行渲染
rendOption.view->Redraw(); rendOption.view->Redraw();
} }
@ -171,8 +149,59 @@ void NativeRender::resize(int width, int height) {
} }
void NativeRender::setRotation(float xAngle, float yAngle) { void NativeRender::setRotation(float xAngle, float yAngle) {
axis.rotationX = xAngle; //axis.rotationX = xAngle;
axis.rotationY = yAngle; //axis.rotationY = yAngle;
if (rendOption.view.IsNull()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "addRotationDelta", "View Is Null");
return;
}
//Handle(Graphic3d_Camera) camera = rendOption.view->Camera();
// --- 方案一:直接对相机进行增量旋转 ---
// 这种方式模拟了“轨道”行为,绕着相机看向的目标点旋转。
// 获取当前相机状态
gp_Pnt currentEye = rendOption.camera->Eye();
gp_Pnt currentCenter = rendOption.camera->Center();
gp_Dir currentUp = rendOption.camera->Up();
// 计算当前的视线方向和距离
gp_Vec viewDir = currentCenter.XYZ() - currentEye.XYZ();
double distance = viewDir.Magnitude();
gp_Pnt rotationCenter = currentCenter; // 旋转中心设为当前目标点
// 创建旋转增量
gp_Quaternion rotX, rotY;
// 从 gp_Ax1 中提取方向向量 (gp_Dir -> gp_Vec)
gp_Vec xRotationAxis = rendOption.camera->Direction().XYZ().Crossed(currentUp.XYZ()); // 叉积得到X旋转轴
if (xRotationAxis.Magnitude() > gp::Resolution()) { // 防止零向量导致的无效四元数
rotX.SetVectorAndAngle(xRotationAxis, xAngle * M_PI / 180.0);
} else {
rotX.SetIdent(); // 如果叉积为零,则无旋转
}
// 从 gp_Ax1 中提取方向向量 (gp_Dir -> gp_Vec)
gp_Vec yRotationAxis = currentUp.XYZ(); // Y旋转轴就是当前的Up方向
if (yRotationAxis.Magnitude() > gp::Resolution()) {
rotY.SetVectorAndAngle(yRotationAxis, yAngle * M_PI / 180.0);
} else {
rotY.SetIdent(); // 如果Up向量无效则无旋转
}
// 组合旋转
gp_Quaternion totalRotation = rotY * rotX;
// 应用旋转到眼睛位置
gp_Vec newViewDir = totalRotation * viewDir.Normalized();
gp_Pnt newEye = rotationCenter.XYZ() - newViewDir.XYZ() * distance;
// 计算新的 Up 方向
gp_Dir newUp = totalRotation * currentUp;
// 设置新相机参数
rendOption.camera->SetEye(newEye);
rendOption.camera->SetCenter(rotationCenter);
rendOption.camera->SetUp(newUp);
HILOG_ERROR(NATIVE_TAG,"Rotation");
//rendOption.view->Redraw();
} }
void NativeRender::setZoomLevel(float zoom) { void NativeRender::setZoomLevel(float zoom) {

View File

@ -15,8 +15,9 @@
#include "TextStyle/TextStyle.h" #include "TextStyle/TextStyle.h"
#include "View/View.h" #include "View/View.h"
#include "Viewer/Viewer.h" #include "Viewer/Viewer.h"
#include <gp_Trsf.hxx>
#include <gp_EulerSequence.hxx>
#include <gp_Quaternion.hxx>
namespace NativeOpenCAX { namespace NativeOpenCAX {
class NativeRender { class NativeRender {
@ -33,6 +34,7 @@ public:
void setClearColor(float r, float g, float b, float a); void setClearColor(float r, float g, float b, float a);
void setZoomLevel(float zoom); void setZoomLevel(float zoom);
void setTranslation(float x, float y); void setTranslation(float x, float y);
void setCameraRotationMode(bool state);
private: private:
RenderOption rendOption; RenderOption rendOption;
AxisOption axis; AxisOption axis;

View File

@ -63,9 +63,8 @@ void NativeRenderThread::renderLoop() {
while (isRunning_) { while (isRunning_) {
RenderCommand command; RenderCommand command;
bool hasCommand = false; bool hasCommand = false;
{
std::unique_lock<std::mutex> lock(commandMutex_); std::unique_lock<std::mutex> lock(commandMutex_);
{
commandCondition_.wait_for(lock, std::chrono::milliseconds(16), [this] { commandCondition_.wait_for(lock, std::chrono::milliseconds(16), [this] {
return !commandQueue_.empty(); return !commandQueue_.empty();
}); });
@ -123,7 +122,7 @@ void NativeRenderThread::renderLoop() {
} }
// 控制帧率 // 控制帧率
usleep(16000); // ~60 FPS usleep(8333); // ~60 FPS
} }
} }

View File

@ -21,6 +21,7 @@ public:
void stop(); void stop();
void loadModel(const std::string& filePath); void loadModel(const std::string& filePath);
void setCameraRotationMode(bool state);
void setRotation(float xAngle, float yAngle); void setRotation(float xAngle, float yAngle);
void setTranslation(float x, float y); void setTranslation(float x, float y);
void resetView(); void resetView();
@ -57,8 +58,9 @@ private:
CommandType type; CommandType type;
std::string param1; // For file path std::string param1; // For file path
float param2, param3, param4, param5; float param2, param3, param4, param5;
bool param6;
RenderCommand() : type(CMD_EXIT), param1(""), param2(0.0f), param3(0.0f), param4(0.0f), param5(0.0f) {} 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) {} RenderCommand(CommandType t) : type(t), param1(""), param2(0), param3(0), param4(0), param5(0),param6(true) {}
}; };
std::queue<RenderCommand> commandQueue_; std::queue<RenderCommand> commandQueue_;

View File

@ -11,7 +11,7 @@ export struct ModelView {
private displayController: XComponentController = new XComponentController(); private displayController: XComponentController = new XComponentController();
private displayContrId: string = 'OCCTRender'; private displayContrId: string = 'OCCTRender';
@State modelPath: string = ''; @State modelPath: string = '';
@State modelName:string='linkrods.step'; @State modelName:string='2027.stp';
@State currentStatus: string = 'init'; @State currentStatus: string = 'init';
private nodeContent: NodeContent = new NodeContent(); private nodeContent: NodeContent = new NodeContent();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff