ForCAX/entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp
JackLee 406cd03b02 增加两个模型
修改世界坐标系
测试鼠标旋转相机
2026-03-07 18:46:12 +08:00

229 lines
7.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "NativeRender.h"
#ifndef NATIVE_TAG
#define NATIVE_TAG "NativeRender"
#endif
namespace NativeOpenCAX {
NativeRender::NativeRender()
{
}
NativeRender::~NativeRender() {
shapes_.clear();
}
bool NativeRender::init(int width, int height,EGLCore* eglCore) {
rendOption.eglCore=eglCore;
rendOption.width=width;
rendOption.height=height;
if(!InitGraphicDriver(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitGraphicDriver Fail!");
return false;
}
if(!InitTextSyle(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitTextSyle Fail!");
return false;
}
if(!InitViewer(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitViewer Fail!");
return false;
}
if(!InitCtx(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitCtx Fail!");
return false;
}
if(!InitWorldAxis(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitWorldAxis Fail!");
return false;
}
if(!InitLocalAxis(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitLocalAxis Fail!");
return false;
}
if(!InitView(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitView Fail!");
return false;
}
if(!InitCamera(rendOption)){
HILOG_ERROR(NATIVE_TAG,"InitCamera Fail!");
return false;
}
return true;
}
bool NativeRender::loadModel(const std::string& filePath) {
// 清除现有模型
for (auto& shape : shapes_) {
rendOption.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());
return false;
}
// 将文件内容转换为OCCT形状
reader.TransferRoots();
int numShapes = reader.NbShapes();
if (numShapes <= 0) {
printf("Error: No shapes found in STEP file\n");
return false;
}
// 加载所有形状
for (Standard_Integer i = 1; i <= numShapes; i++) {
TopoDS_Shape shape = reader.Shape(i);
Bnd_Box bbox;
BRepBndLib::Add(shape, bbox);
double xmin, ymin, zmin, xmax, ymax, zmax;
bbox.Get(xmin, ymin, zmin, xmax, ymax, zmax);
gp_Pnt center((xmin + xmax) / 2.0, (ymin + ymax) / 2.0, (zmin + zmax) / 2.0);
gp_Vec translation(-center.X(), -center.Y(), -center.Z());
gp_Trsf move;
move.SetTranslation(translation);
BRepBuilderAPI_Transform transformer(shape, move);
shape=transformer.Shape();
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);
rendOption.context->Display(aisShape, Standard_True);
shapes_.push_back(aisShape);
}
}
// 调整相机到合适位置
rendOption.view->FitAll(0.5, Standard_True);
rendOption.view->ZFitAll();
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "LoadModel","Successfully loaded STEP file with %{public}d shapes",numShapes);
return true;
}
//setTranslation
void NativeRender::setTranslation(float x, float y) {
axis.translationX = x;
axis.translationY = y;
}
void NativeRender::render() {
if (rendOption.view.IsNull()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Render","View Is Null");
return;
}
// 执行渲染
rendOption.view->Redraw();
}
void NativeRender::resize(int width, int height) {
rendOption.width = width;
rendOption.height = height;
if (!rendOption.view.IsNull()) {
rendOption.view->MustBeResized();
}
}
void NativeRender::setRotation(float xAngle, float yAngle) {
//axis.rotationX = xAngle;
//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) {
axis.zoomLevel = std::max(0.1f, std::min(zoom, 5.0f)); // 限制缩放范围
}
void NativeRender::resetView() {
axis.rotationX = 0.0f;
axis.rotationY = 0.0f;
axis.zoomLevel = 1.0f;
if (!rendOption.view.IsNull()) {
rendOption.view->SetProj(V3d_XposYnegZpos);
rendOption.view->FitAll(0.05, Standard_False);
}
}
void NativeRender::setClearColor(float r, float g, float b, float a) {
rendOption.clearColor = Quantity_Color(r, g, b, Quantity_TOC_RGB);
if (!rendOption.view.IsNull()) {
rendOption.view->SetBackgroundColor(rendOption.clearColor);
}
}
} // namespace NativeRenderer