由于工作需要,我开始学习OCC(Open Cascade)。在网上查找资料时,大多数资源要么是文字教程,要么是YouTube视频,感觉没有什么适合快速上手的方式。
我需要一个可以通过修改代码就能直观看到结果的学习方式。
在GitHub上我发现了一位大佬的仓库(链接:OcctImgui),这个仓库基于ImGUI实现了OCC的基础功能。灵感来自“最快的学习方法就是自己学了再教别人”,于是决定发这篇博客,督促自己整理并发布一个OCC快速上手的系列教程。
在开始之前,我们需要了解一些基本概念:
1. 什么是OCC?
OCC(Open Cascade)是一个开源的CAD(计算机辅助设计)软件开发平台,提供强大的3D建模、几何处理和可视化工具。它广泛应用于工程设计、制造业以及其他涉及复杂几何建模的领域。
github:https://github.com/Open-Cascade-SAS/OCCT
2. 什么是ImGUI?
ImGUI(Immediate Mode GUI)是一种每帧动态生成界面的方式。与传统的GUI系统不同,ImGUI不保存界面状态。每次渲染时,所有的界面元素都被重新构建,允许用户快速生成、修改和更新界面。
3. 什么是Dear ImGUI?
Dear ImGUI是一个轻量级、开源的即时模式GUI库,专注于快速开发工具和调试界面。它的设计目标是提供一种简单、快速的方式来实现各种交互式界面,尤其适用于开发调试工具和内嵌式应用。
github:https://github.com/ocornut/imgui
掌握了这些基础知识后,我们就可以开始学习了!
首先,我将基于这位大佬的仓库复现相关内容,并编写一个动态创建场景的代码。为了便于写教程,我手动实现了一个继承自baseScene
的动态场景创建框架(只需继承baseScene
并编写scene
即可)。完成后,场景会自动在右侧框中显示,方便后续复习和教学。如下图只需要在displayScene
中编写想要学习的代码就可以自动在右边显示,点击即可渲染了。
效果图:
补充代码
- 场景基类: 方便写之后教学页面的
#include "pch.h"
#include "../Log.h"
#include <AIS_InteractiveContext.hxx>
#include <AIS_ViewController.hxx>
/**
* @class BaseScene
* @brief 场景基类,定义了场景的基本接口。
*
* 该类是一个抽象基类,提供了一个纯虚函数 displayScene(),要求所有派生类实现具体的场景显示逻辑。
*/
class BaseScene {
public:
BaseScene() = default;
/**
* @brief 析构函数,确保派生类正确销毁。
*/
virtual ~BaseScene() = default;
/**
* @brief 纯虚函数,派生类需实现具体的场景显示逻辑。
*
* @param context Open CASCADE 交互上下文,提供显示场景所需的 API。
*/
virtual void displayScene(Handle(V3d_View)& view, Handle(AIS_InteractiveContext)& context) = 0;
void setLog(OCCImguiTutorial::Log* log) { m_Log = log; };
private:
OCCImguiTutorial::Log* m_Log = nullptr;
};
- 场景选择器:自动添加渲染教学场景。
#include "SceneSelector.h"
#include "BoxScene.h"
#include "../imgui/imgui.h"
SceneSelector::SceneSelector() : sceneIndex(-1), currentScene(nullptr) {}
void SceneSelector::RegisterScene(const std::string& name, const std::function<std::shared_ptr<BaseScene>()>& createFunc) {
GetSceneRegistry().emplace_back(SceneEntry{ name, createFunc });
}
std::vector<SceneSelector::SceneEntry>& SceneSelector::GetSceneRegistry() {
static std::vector<SceneEntry> registry;
return registry;
}
void SceneSelector::renderGui() {
ImGui::Begin("Scene Selector");
if (ImGui::TreeNode("Scenes")) {
auto& registry = GetSceneRegistry();
for (int i = 0; i < registry.size(); ++i) {
const auto& entry = registry[i];
if (ImGui::Selectable(entry.name.c_str(), sceneIndex == i)) {
sceneIndex = i;
currentScene = entry.createFunc();
}
}
ImGui::TreePop();
}
ImGui::End();
}
std::shared_ptr<BaseScene> SceneSelector::getCurrentScene() const {
return currentScene;
}
- 教学场景头文件与cpp文件:注册一个教学场景,修改场景名和教学类,就可以自动显示了。
#pragma once
#include "BaseScene.h"
class BoxScene : public BaseScene {
public:
void displayScene(Handle(V3d_View)& view, Handle(AIS_InteractiveContext)& context) override {
gp_Ax2 anAxis;
anAxis.SetLocation(gp_Pnt(0.0, 0.0, 0.0));
Handle(AIS_Shape) aBox = new AIS_Shape(BRepPrimAPI_MakeBox(anAxis, 50, 50, 50).Shape());
context->Display(aBox, AIS_Shaded, 0, false);
}
};
#include "BoxScene.h"
#include "SceneSelector.h"
namespace {
struct Registrar {
Registrar() {
SceneSelector::RegisterScene("000-Demo-Box Scene", []() {
return std::make_shared<BoxScene>();
});
}
};
const Registrar registrar;
}
相关资源
- OCCT + ImGUI 仓库:https://github.com/eryar/OcctImgui
- OCCT 仓库:https://github.com/Open-Cascade-SAS/OCCT
- ImGUI 仓库: https://github.com/ocornut/imgui