ForCAX/entry/src/main/cpp/NativeEGLOCCT/NativeRender.cpp
2026-03-04 19:43:11 +08:00

317 lines
11 KiB
C++

#include "NativeRender.h"
#include "Aspect_NeutralWindow.hxx"
#include <GLES3/gl3.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 <Graphic3d_TextureEnv.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <V3d_TypeOfOrientation.hxx>
#include <Aspect_TypeOfTriedronPosition.hxx>
namespace NativeOpenCAX {
NativeRender::NativeRender()
: rotationX_(0.0f),
rotationY_(0.0f),
zoomLevel_(1.0f),
width_(1280),
height_(720),
clearColor_(Quantity_NOC_BLACK),
translationX_(0.0f),
translationY_(0.0f)
{
}
NativeRender::~NativeRender() {
shapes_.clear();
}
bool NativeRender::init(int width, int height,EGLCore* eglCore) {
eglCore_=eglCore;
initTextStyle();
initViewer();
initContext();
initView();
if (view_.IsNull()) {
return false;
}
view_->SetBackgroundColor(clearColor_);
view_->MustBeResized();
view_->RedrawImmediate();
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit","NativeRender Init Done");
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit","width: %{public}d",width_);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "NativeRenderInit","height: %{public}d",height_);
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Render", "GL Error before render: 0x%{public}x", glGetError());
return true;
}
void NativeRender::initViewer(){
displayPixelRatio();
Handle(Aspect_DisplayConnection) displayConnection=new Aspect_DisplayConnection();
// 创建图形驱动
if (graphicDriver_.IsNull()) {
graphicDriver_ = new OpenGl_GraphicDriver(displayConnection,Standard_False);
graphicDriver_->ChangeOptions().buffersNoSwap = Standard_True;
graphicDriver_->InitEglContext(eglGetCurrentDisplay(), eglGetCurrentContext(), eglCore_->getConfig());
}
// 创建V3d_Viewer
viewer_ = new V3d_Viewer(graphicDriver_);
viewer_->SetDefaultBackgroundColor (Quantity_NOC_BLACK);
viewer_->SetDefaultLights();
viewer_->SetLightOn();
}
float NativeRender::displayPixelRatio(){
float densityPixels;
NativeDisplayManager_ErrorCode errCode = OH_NativeDisplayManager_GetDefaultDisplayVirtualPixelRatio(&densityPixels);
if (errCode == NativeDisplayManager_ErrorCode::DISPLAY_MANAGER_OK) {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "DMSTest", "rotation=%{public}d", densityPixels);
return densityPixels;
} else {
OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "DMSTest",
"GetDefaultDisplayRotation errCode=%{public}d", errCode);
}
}
void NativeRender::initContext(){
context_ = new AIS_InteractiveContext(viewer_);
context_->SetDisplayMode(AIS_Shaded, Standard_False); // 默认使用着色模式
context_->SetPixelTolerance (int(displayPixelRatio() * 6.0)); // increase tolerance and adjust to hi-dpi screens
}
void NativeRender::initView() {
Handle(Aspect_NeutralWindow) m_Window = new Aspect_NeutralWindow();
m_Window->SetSize (width_, height_);
view_ = viewer_->CreateView();
// 设置渲染参数
view_->SetImmediateUpdate (false);
//view_->ChangeRenderingParams().ToShowStats = true;
view_->ChangeRenderingParams().Resolution = (unsigned int )(96.0 * displayPixelRatio() + 0.5);
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_->ChangeRenderingParams().StatsTextAspect = text_->Aspect();
view_->ChangeRenderingParams().StatsTextHeight = (int )text_->Height();
// 设置背景渐变
view_->SetBgGradientColors(
Quantity_Color(Quantity_NOC_GRAY),
Quantity_Color(Quantity_NOC_BLACK),
Aspect_GFM_VER, // 垂直渐变
Standard_False
);
// 设置默认相机位置
view_->SetProj(V3d_XposYnegZpos);
//可选:显示坐标轴
view_->ZBufferTriedronSetup();
// 设置相机参数
Handle(Graphic3d_Camera) camera = view_->Camera();
camera->SetFOVy(45.0); // 使用正确的FOV设置API
camera->SetZRange(1.0, 1000.0);
view_->SetWindow(m_Window,(Aspect_RenderingContext )eglGetCurrentContext());
}
void NativeRender::initTextStyle(){
text_ = new Prs3d_TextAspect();
text_->SetFont (Font_NOF_ASCII_MONO);
text_->SetHeight (12);
text_->Aspect()->SetColor (Quantity_NOC_GRAY95);
text_->Aspect()->SetColorSubTitle (Quantity_NOC_BLACK);
text_->Aspect()->SetDisplayType (Aspect_TODT_SHADOW);
text_->Aspect()->SetTextFontAspect (Font_FA_Bold);
text_->Aspect()->SetTextZoomable (false);
text_->SetHorizontalJustification (Graphic3d_HTA_LEFT);
text_->SetVerticalJustification (Graphic3d_VTA_BOTTOM);
}
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();
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "LoadModel","Successfully loaded STEP file with %{public}d shapes",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();
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "LoadDefaultModel","Loaded default model (cube, sphere, cylinder)");
}
//setTranslation
void NativeRender::setTranslation(float x, float y) {
translationX_ = x;
translationY_ = y;
}
void NativeRender::render() {
if (view_.IsNull()) {
OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_PRINT_DOMAIN, "Render","View Is Null");
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));
// 执行渲染
view_->Redraw();
}
void NativeRender::resize(int width, int height) {
width_ = width;
height_ = height;
if (!view_.IsNull()) {
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