317 lines
11 KiB
C++
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
|