229 lines
7.4 KiB
C++
229 lines
7.4 KiB
C++
#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
|