[TOC] # Archer Render 使用说明 Archer Render是面向几何有限元模型的专用渲染引擎,使用C++, OpenGL, GLSL编写 ## 功能介绍 ### 大规模几何模型渲染 1. 绘制几何顶点 ![image-20210330134706193](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330134706193.png) 2. 绘制几何边 ![image-20210330135236925](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330135236925.png) 3. 绘制几何面 ![image-20210330134958132](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330134958132.png) ### 大规模网格模型渲染 1. 绘制点/线/三角形/四边形网格 ![image-20210330140035267](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330140035267.png) 2. 网格线 ![image-20210330140159524](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330140159524.png) 3. 法线双面\法线 ![image-20210330141244468](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330141244468.png) 4. 节点数据光滑云图/节点数据等值云图 image-20210330141450594 5. 单元数据云图 ![image-20210330141826579](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330141826579.png) ### 点云绘制 image-20210330140553187 ### 绘制文本 ![image-20210330145632051](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330145632051.png) ### 交互 1. 旋转/平移/缩放/居中 2. 七视图 3. 旋转中心/局部放大 ### 点/线/三角形/四边形的拾取 ![image-20210330150124978](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210330150124978.png) ### 基本图元绘制 image-20210330151345971 ### 3D/2D 空间坐标转换 ### 脚本化数据返回(旋转,平移,缩放等) ### 7千万 https://www.bilibili.com/video/BV14y4y1x7D7/ ### 基于Phong明暗处理单元云图渲染 ![mesh_contour_nodal_average](.\picture\mesh_contour_nodal_average.png) ### 支持多color bar、多个云图独立渲染 multi-colorbar ## 目录说明 ![image-20210329213515119](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210329213515119.png) ## 编译运行Demo 1. 前提 (windows平台为例,linux平台类似,需编译相应第三方库) 1. QT5.12 2. CMake 3. VS2019 2. 编译 1. cmake(vs2019 x64) 2. configure 3. build 3. 运行 1. 在bin路径Debug或者Release下运行相关exe ## Demo功能使用介绍 ![image-20210401125648081](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210401125648081.png) 1. 文件操作 - 支持如下后缀几何文件(.igs *.iges *.brep .step .stp .stl) - 支持如下后缀网格文件(.bdf .nas .inp *.stl *.obj *.ply *.vtk) 2. 视图操作 - 七视图 - 居中 - 局部放大 - 旋转中心 3. 模型操作 - 屏幕点击隐藏部件 - 全显示 - 全隐藏 - 反转 4. 几何显示 - 显示几何 - 显示网格 - 显示点 - 显示边 - 显示面 5. 网格显示 - 无网格线显示 - 网格线显示 - 表面线框显示 - 全线框显示 6. 单元显示 - 三角形单元显示 - 四边形单元显示 - 四面体单元显示 - 金字塔单元显示 - 棱柱单元显示 - 六面体单元显示 ## Archer Render中的若干概念 1. 画布 画布是Archer Render里的顶层对象,所有的API调用都是从画布调用的,包括初始化,添加可渲染对象,渲染,拾取,鼠标事件响应,交互状态设置等等API,在后面将详细介绍。 2. 可渲染对象,可渲染部件,可渲染组 可渲染对象是顶层抽象,如名字所示,代表了所有可渲染的对象;可渲染部件是实例化渲染对象,完成了实际的绘制工作,相当于渲染对象管理中的最小单元;可渲染组是可渲染对象的集合;ArcherRender中的模型管理使用组合模式,如图所示,可以管理复杂的模型场景。 ![image-20210322220229143](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210322220229143.png) 3. ViewData ArcherRender可以说是数据驱动的,这个数据就是ViewData,每一个可渲染部件的渲染内容就来自于ViewData,ViewData是对可渲染数据的抽象,外部调用通过填充ViewData来实现数据的可视化。ViewData包含基本信息,节点信息,顶点信息,线段信息,面片信息几个部分。 1. 基本信息 ```c++ std::string name; /*名字*/ double color[3]; /*颜色*/ double trans; /*透明度*/ bool point_cloud; /*点云数据*/ bool mesh; /*false:几何数据;true:网格数据*/ bool flynode; /*无引用点数据*/ bool wireframe; /*线框数据*/ bool selection; /*选择集数据*/ bool polygon; /*多边形数据*/ bool featureLines; /*特征线数据*/ bool freeEdges; /*自由边数据*/ ``` 2. 节点信息 ```c++ std::vector nodes; /*节点坐标*/ std::vector node_normals; /*节点法向,仅几何和点云数据有效*/ std::vector node_colors; /*节点颜色,仅点云数据有效*/ std::vector node_scalars; /*节点scalar值,用于节点云图*/ ``` 3. 顶点信息 ```c++ std::vector verts; /*顶点索引*/ unsigned int vert_type; /*顶点类型,用于拾取分类*/ unsigned int vert_identity; /*顶点一级标识,用于拾取*/ float vert_size; /*顶点大小*/ float vert_color[4]; /*顶点颜色*/ std::vector vert_identities; /*顶点二级标识,用于拾取*/ std::vector vert_text; /*顶点文本*/ std::vector vert_scalars; /*顶点scalar值*/ ``` 4. 线段信息 ```c++ std::vector lines; /*线段索引*/ unsigned int line_type; /*线段类型,用于拾取分类*/ unsigned int line_identity; /*线段一级标识,用于拾取*/ float line_width; /*线段宽度*/ float line_color[4]; /*线段颜色*/ std::vector line_identities; /*线段二级标识,用于拾取*/ std::vector line_scalars; /*线段scalar值*/ ``` 5. 面片信息 ```c++ std::vector trias; /*三角形索引*/ unsigned int tria_type; /*三角形类型,用于拾取分类*/ unsigned int tria_identity; /*三角形一级标识,用于拾取*/ std::vector tria_identities; /*三角形二级标识,用于拾取*/ std::vector tria_scalars; /*三角形scalar值,用于单元云图*/ std::vector quads; /*四边形索引*/ unsigned int quad_type; /*四边形类型,用于拾取分类*/ unsigned int quad_identity; /*四边形一级标识,用于拾取*/ std::vector quad_identities; /*四边形二级标识,用于拾取*/ std::vector quad_scalars; /*四边形scalar值,用于单元云图*/ ``` 4. 鼠标状态 该结构对鼠标状态进行抽象,在画布canvas的鼠标事件处理以及交互状态中都有使用。 ```c++ struct MouseState { int x; /*鼠标位置x*/ int y; /*鼠标位置y*/ int delta; /*滚轴delta值*/ bool ctrlDown; /*control键是否落下*/ bool shiftDown; /*shift键是否落下*/ bool altDown; /*alt键是否落下*/ bool isDragging; /*是否在拖拽*/ bool leftDown; /*左键是否按下*/ bool middleDown; /*中键是否按下*/ bool rightDown; /*右键是否按下*/ }; ``` 5. 交互状态 交互状态是对渲染引擎可能面对的交互需求的抽象,需要自定义并通过画布API设置当前交互状态。交互状态在画布中采用堆栈进行管理,最顶层的交互状态有效,通过出栈的方式恢复到之前的交互状态,在画布设置交互状态时会默认设置成可堆栈的;不可堆栈的交互状态有最高优先级。最典型的应用就是拾取操作。 ```c++ class InteractorState { public: /** * 处理左键按下消息 */ virtual void OnLeftDown(const MouseState& ms) {} /** * 处理左键抬起消息 */ virtual void OnLeftUp(const MouseState& ms) {} /** * 处理左键双击消息 */ virtual void OnLeftDClick(const MouseState& ms) {} /** * 处理中键按下消息 */ virtual void OnMiddleDown(const MouseState& ms) {} /** * 处理中键抬起消息 */ virtual void OnMiddleUp(const MouseState& ms) {} /** * 处理中键双击消息 */ virtual void OnMiddleDClick(const MouseState& ms) {} /** * 处理右键按下消息 */ virtual void OnRightDown(const MouseState& ms) {} /** * 处理右键抬起消息 */ virtual void OnRightUp(const MouseState& ms) {} /** * 处理右键双击消息 */ virtual void OnRightDClick(const MouseState& ms) {} /** * 处理鼠标移动消息 */ virtual bool OnMotion(const MouseState& ms) { return false; } /** * 在该交互状态激活时执行的操作,比如设置鼠标形状 */ virtual void OnActivate() {} /** * 在该交互状态弹出时执行的操作,比如恢复鼠标形状 */ virtual void OnDeactive() {} public: /** * 查询该交互状态是否为可堆栈的 */ bool stackable() const { return _stackable; } /** * 设置该交互状态是否为可堆栈的 */ void setStackable(bool flag) { _stackable = flag; } }; ``` ## SDK接入流程 接入流程如下: image-20210322215950685 具体操作步骤如下: 1. 包含头文件 ```cmake include_directories( ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/public ) ``` 2. 设置库路径 ```cmake link_directories(${CMAKE_SOURCE_DIR}/lib) ``` ```cmake target_link_libraries(${MODULE_NAME} ArcherRender) ``` 3. 自定义画布并实例化 ```c++ #include "canvas.h" namespace my { namespace modelrender { class mrCanvas : public render::Canvas { public: static mrCanvas* s_instance; public: static mrCanvas* Instance(); void Delete(); void loadModel(); protected: virtual void refresh(); private: mrCanvas(); mrCanvas(const mrCanvas&); mrCanvas& operator=(const mrCanvas&); }; } } ``` 4. 在QT事件中调用画布实例API ![image-20210322210920923](http://wenhuisimright.gitee.io/archerrenderdoc/picture/image-20210322210920923.png) 5. 自定义QOpenGLWidget ```c++ #include #include class QMouseEvent; class SceneWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: static SceneWidget* Instance(); static void setInstance(SceneWidget* w); explicit SceneWidget(QWidget* parent = 0); ~SceneWidget(); protected: void initializeGL() override; void resizeGL(int w, int h) override; void paintGL() override; virtual void mousePressEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); virtual void mouseDoubleClickEvent(QMouseEvent* event); virtual void mouseMoveEvent(QMouseEvent* event); #if QT_CONFIG(wheelevent) virtual void wheelEvent(QWheelEvent* event); #endif }; ``` 6. 初始化 ```c++ void SceneWidget::initializeGL() { initializeOpenGLFunctions(); if (!my::modelrender::mrCanvas::Instance()->Initialize()) { qCritical() << "rendering engine initialize failed!"; return; } } ``` 7. 渲染事件 ```c++ void SceneWidget::paintGL() { my::modelrender::mrCanvas::Instance()->Render(0); } ``` 8. 窗口大小变化事件 ```c++ void SceneWidget::resizeGL(int w, int h) { my::modelrender::mrCanvas::Instance()->OnSize(w, h); } ``` 9. 鼠标事件 ```c++ void SceneWidget::mousePressEvent(QMouseEvent* event) { my::render::MouseState ms; ms.ctrlDown = event->modifiers() & Qt::ControlModifier; ms.shiftDown = event->modifiers() & Qt::ShiftModifier; ms.altDown = event->modifiers() && Qt::AltModifier; ms.x = event->pos().x(); ms.y = event->pos().y(); if (event->button() == Qt::LeftButton) { my::modelrender::mrCanvas::Instance()->OnLeftDown(ms); } else if (event->button() == Qt::RightButton) { my::modelrender::mrCanvas::Instance()->OnRightDown(ms); } else if (event->button() == Qt::MiddleButton) { my::modelrender::mrCanvas::Instance()->OnMiddleDown(ms); } } void SceneWidget::mouseReleaseEvent(QMouseEvent* event) { my::render::MouseState ms; ms.ctrlDown = event->modifiers() & Qt::ControlModifier; ms.shiftDown = event->modifiers() & Qt::ShiftModifier; ms.altDown = event->modifiers() && Qt::AltModifier; ms.x = event->pos().x(); ms.y = event->pos().y(); if (event->button() == Qt::LeftButton) { my::modelrender::mrCanvas::Instance()->OnLeftUp(ms); #if 0 //脚本记录以回放旋转平移操作 if (ms.ctrlDown) { float quat[4]; my::modelrender::mrCanvas::Instance()->quaternion(quat); QString cmd = QString::asprintf("view.rotate(%f, %f, %f, %f)", quat[0], quat[1], quat[2], quat[3]); script::ScriptManager::Instance()->record(cmd); } else if (ms.shiftDown) { float pan[2]; my::modelrender::mrCanvas::Instance()->translation(pan); QString cmd = QString::asprintf("view.translate(%f, %f)", pan[0], pan[1]); script::ScriptManager::Instance()->record(cmd); } #endif } else if (event->button() == Qt::RightButton) { #if 0 //脚本记录以回放缩放 if (ms.ctrlDown || ms.shiftDown) { float zoom; my::modelrender::mrCanvas::Instance()->scaling(zoom); QString cmd = QString::asprintf("view.scale(%f)", zoom); script::ScriptManager::Instance()->record(cmd); } #endif } else if (event->button() == Qt::MiddleButton) { #if 0 //脚本记录以平移 if (ms.ctrlDown || ms.shiftDown) { float pan[2]; my::modelrender::mrCanvas::Instance()->translation(pan); QString cmd = QString::asprintf("view.translate(%f, %f)", pan[0], pan[1]); script::ScriptManager::Instance()->record(cmd); } #endif } } void SceneWidget::mouseMoveEvent(QMouseEvent* event) { my::render::MouseState ms; ms.ctrlDown = event->modifiers() & Qt::ControlModifier; ms.shiftDown = event->modifiers() & Qt::ShiftModifier; ms.altDown = event->modifiers() && Qt::AltModifier; ms.leftDown = event->buttons() & Qt::LeftButton; ms.middleDown = event->buttons() & Qt::MiddleButton; ms.rightDown = event->buttons() & Qt::RightButton; ms.isDragging = true; ms.x = event->pos().x(); ms.y = event->pos().y(); my::modelrender::mrCanvas::Instance()->OnMotion(ms); } #if QT_CONFIG(wheelevent) void SceneWidget::wheelEvent(QWheelEvent* event) { my::render::MouseState ms; ms.ctrlDown = event->modifiers() & Qt::ControlModifier; ms.shiftDown = event->modifiers() & Qt::ShiftModifier; ms.altDown = event->modifiers() && Qt::AltModifier; ms.leftDown = event->buttons() & Qt::LeftButton; ms.middleDown = event->buttons() & Qt::MiddleButton; ms.rightDown = event->buttons() & Qt::RightButton; ms.isDragging = true; ms.x = event->pos().x(); ms.y = event->pos().y(); ms.delta = event->delta(); if (ms.ctrlDown || ms.shiftDown) { float dxs = (float)(ms.x - this->width() / 2) / (float)this->width(); float dys = -(float)(ms.y - this->height() / 2) / (float)this->height(); my::modelrender::mrCanvas::Instance()->scaleHere(dxs, dys, ms.delta); } } #endif ``` 10. 添加/更新可渲染部件 ```c++ void mrCanvas::loadModel() { //清除所有部件 Clear(); //演示云图功能 #define _FRINGE_MODE__ 1 #ifdef _FRINGE_MODE__ this->setColorBarVisibility(true); this->setColorBarRange(0.0, 5.0); this->setColorBarLevel(10); this->setColorBarHueRange(360, 240); this->setColorBarUpdate(); //节点云图 //this->toggleNodalFringeModeOn(); //单元云图 this->toggleElemFringeModeOn(); #endif //填充可视化数据 my::render::ViewData vd; vd.color[0] = 1.0; vd.color[1] = 0.0; vd.color[2] = 0.0; vd.trans = 1.0; //网格数据,自行计算单元法向 vd.mesh = true; vd.nodes.push_back(0.0); vd.nodes.push_back(0.0); vd.nodes.push_back(0.0); vd.node_scalars.push_back(0.0); ... //数据类型,用于拾取分类 vd.tria_type = eElem; //一级标识 vd.tria_identity = 2; vd.trias.push_back(0); vd.trias.push_back(2); vd.trias.push_back(1); //二级标识 vd.tria_identities.push_back(0); vd.tria_scalars.push_back(0.0); ... //创建新的可视化部件 my::render::RenderablePart* p = new my::render::RenderablePart(1); //更新数据 p->Update(vd); //添加到场景中 Add(p); //重新计算包围盒 RecomputeBoundingBox(); //刷新 refresh(); } ``` ### Canvas接口详解 - 初始化 ```c++ /** * 在所有Canvas操作之前调用,初始化渲染引擎,失败返回false,成功返回true * 例如在QT QOpenGLWidget的intializeGL中调用 */ static bool Initialize(); ``` - 渲染 ```c++ /** * 绘制API * @param ist 为后处理预留 * 例如在QT QOpenGLWidget的paintGL中调用 */ void Render(int ist); /** * 窗口大小变化响应API, * @param w 窗口宽度 * @param h 窗口高度 */ void OnSize(int w, int h); /** * 返回canvas宽度 */ int width() const; /** * 返回canvas高度 */ int height() const; /** * 需要在子类中重载,并调用相关平台的refresh函数刷新 */ virtual void refresh() {} ``` - 鼠标事件处理 ```c++ /** * 处理鼠标左/中/右键按下/抬起/双击事件,处理鼠标移动事件,处理鼠标滚轴事件 */ void OnLeftDown(const MouseState& ms); void OnLeftUp(const MouseState& ms); void OnLeftDClick(const MouseState& ms); void OnMiddleDown(const MouseState& ms); void OnMiddleUp(const MouseState& ms); void OnMiddleDClick(const MouseState& ms); void OnRightDown(const MouseState& ms); void OnRightUp(const MouseState& ms); void OnRightDClick(const MouseState& ms); void OnMotion(const MouseState& ms); void OnWheel(const MouseState& ms); ``` - 添加可渲染对象 ```c++ /** * 添加一个可渲染对象到canvas中,通常这里应该是添加一个可渲染组,因为主程序应该会对可渲染对象管理,所以仅添加根节点即可, * 也就是一个渲染组。 */ void Add(Renderable* ren); /** * 清空可渲染对象集合 */ void Clear(); /** * 重新计算包围盒 */ void RecomputeBoundingBox(); ``` - 视图操作 ```c++ /** * 居中 */ void viewFit(); /** * 左/右/上/下/前/后/等视图 */ void viewLeft(); void viewRight(); void viewTop(); void viewBottom(); void viewFront(); void viewBack(); void viewIso(); /** * 缩放到指定框内,四个参数为屏幕坐标归一化值 */ void zoomIn(float x0, float y0, float x1, float y1); /** * 设置旋转中心 */ void setRotateCenter(float x, float y, float z); /** * 根据鼠标位置和滚轴delta值进行缩放 */ void scaleHere(float dxs, float dys, int delta); ``` - 拾取接口, 通常与自定义交互状态配合以达到拾取状态的保存恢复 ```c++ /** * 在ms指定位置拾取指定类型type的一级标识pid */ bool pick(const MouseState& ms, unsigned type, int& pid); /** * 在ms指定位置拾取指定类型type的一级标识pid,以及三维的位置信息xyz */ bool pick(const MouseState& ms, unsigned type, int& pid, std::array& xyz); /** * 在ms指定位置拾取指定类型type的一级标识pid以及二级标识fid */ bool pick(const MouseState& ms, unsigned type, int& pid, int& fid); ``` - 交互状态设置 ```c++ /** * 设置交互状态,默认是可堆栈的;如果不可堆栈,该交互状态将拥有最高优先级 */ void setInteractorState(InteractorState* state, bool stackable = true); /** * 弹出交互状态,并恢复之前的交互状态;与前者配对使用 */ void popInteractorState(bool stackable = true); ``` - 挂载绘制routine,与下面的基本对象绘制配合使用,即在设置的routine中调用基本对象绘制API ```c++ /** * 设置当前的绘制routinue,使用[](){}设置将清空 */ void setRenderRoutine(std::function routine); /** * 添加命名绘制routine */ void addRenderRoutine(const std::string& name, std::function routine); /** * 查询命名绘制routine */ bool hasRenderRoutine(const std::string& name); /** * 删除命名绘制routine */ void delRenderRoutine(const std::string& name); /** * 清空命名绘制routine */ void clrRenderRoutine(); ``` - 基本对象绘制 ```c++ /** * 绘制点/线 * @param points 坐标 * @param drawLines 是否连成线 */ void drawPoints(const std::vector> & points, bool drawLines = false); /** * 绘制点 * @param points 坐标 * @param colors 颜色 */ void drawPoints(const std::vector> & points, const std::vector> & colors); /** * 绘制点球 * @param points 坐标 * @param colors 颜色 * @param radius 半径 */ void drawPoints(const std::vector> & points, const std::vector> & colors, const std::vector& radius); /** * 绘制线 * @param type 类型,可选GL_LINES,GL_LINE_STRIP,GL_LINE_LOOP * @param points 坐标 * @param lineColor 颜色 * @param lineWidth 线宽 */ void drawLine(unsigned type, const std::vector> & points, float lineColor[3], float lineWidth); /** * 绘制平面 * @param pos 位置 * @param dir 法线 */ void drawPlane(const std::array & pos, const std::array & dir); /** * 绘制字符串 * @param x,y,z 坐标 * @param str 待绘制字符串 * @param fontSize 字体大小 */ void drawString(double x, double y, double z, const char* str, int fontSize); /** * 绘制箭头 * @param points 坐标 * @param directions 方向 * @param color 颜色 */ void drawArrow(const std::vector>& points, const std::vector>& directions, std::array color); /** * 绘制箭头 * @param points 坐标 * @param direction 方向 * @param color 颜色 */ void drawArrow(const std::vector>& points, std::array direction, std::array color); /** * 绘制圆锥 * @param points 坐标 * @param direction 方向 * @param color 颜色 */ void drawCone(const std::vector>& points, std::array direction, std::array color); /** * 绘制两个首尾相接圆锥 * @param points 坐标 * @param direction 方向 * @param drawHead/drawTail 头尾是否绘制 * @param colorHead/colorTail 头尾颜色 */ void drawTwoCones(const std::vector>& points, std::array direction, bool drawHead, std::array colorHead, bool drawTail, std::array colorTail); /** * 绘制圆 * @param c 圆心 * @param n 方向 * @param r 半径 * @param color 颜色 * @param lineWidth 线宽 */ void drawCircle(const std::array& c, const std::array& n, float r, const std::array& color, float lineWidth = 1.0f); ``` - 显示模式设置 可渲染对象目前可分为5大类: 1. 文本渲染(通过设置vd.vert_text) 2. 点云渲染(通过设置vd.point_cloud) 3. 网格渲染(通过设置vd.mesh) 4. 后处理渲染(通过设置vd.post_contour) 5. 几何渲染(默认情况) 选定上述五种类型之后,可和以下的类型组合: 1. wireframe(通过设置vd.wireframe) 2. selection(通过设置vd.selection) 3. flynode(通过设置vd.flynode) 4. polygon(通过设置vd.polygon) 5. freeEdges(通过设置vd.freeEdges) 6. twoSide(通过设置vd.twoSide) 7. contact(通过设置vd.contact) 8. cones(通过设置vd.cones) 9. spheres(通过设置vd.spheres) 10. cylinder(通过设置vd.cylinder) 11. showNormal(通过设置vd.showNormal) 12. noBounds(通过设置vd.noBounds) 13. optBlock(通过设置vd.optBlock) 14. opt2DCross(通过设置vd.opt2DCross) 15. opt2DDoubleCross(通过设置vd.opt2DDoubleCross) 16. opt3DCross(通过设置vd.opt3DCross) 17. opt3DDoubleCross(通过设置vd.opt3DDoubleCross) 18. circle(通过设置vd.circle) 19. vectors(通过设置vd.vectors) ```c++ unsigned mode() const; /** * 几何模式的渲染对象的开关控制接口 * 默认情况下(不设置vd.vert_text, vd.point_cloud, vd.mesh, vd.post_contour), * 使用ViewData创建的可渲染对象为几何模式的渲染对象 */ void toggleGeomMode(); void toggleGeomModeOn(); void toggleGeomModeOff(); /** * 几何顶点的渲染对象的开关控制接口 * 当渲染对象为几何模式时候,控制显隐顶点 */ void toggleVertMode(); void toggleVertModeOn(); void toggleVertModeOff(); /** * 几何边的渲染对象开关的控制接口 * 当渲染对象为几何模式时候,控制显隐边 */ void toggleEdgeMode(); void toggleEdgeModeOn(); void toggleEdgeModeOff(); /** * 几何边的渲染对象开关的控制接口 * 当渲染对象为几何模式时候,控制显隐面 */ void toggleFaceMode(); void toggleFaceModeOn(); void toggleFaceModeOff(); /** * 网格模式的渲染对象的开关控制接口 * 使用vd.mesh=true指定渲染对象为网格模式 */ void toggleMeshMode(); void toggleMeshModeOn(); void toggleMeshModeOff(); /** * 1D网格渲染对象开关的控制接口 * 当渲染对象为网格模式时候,控制显隐1D网格 */ void toggleMesh1DMode(); void toggleMesh1DModeOn(); void toggleMesh1DModeOff(); /** * shade模式开关的控制接口 * 当渲染对象为网格模式时候,开关shade显示模式 */ void toggleShadeModeOn(); /** * wire frame模式开关的控制接口 * 当渲染对象为网格模式时候,开关 wire frame显示模式 */ void toggleWireframeMode(); void toggleWireframeModeOn(); void toggleWireframeModeOff(); /** * skin wire frame模式开关的控制接口 * 当渲染对象为网格模式时候,开关 skin wire frame显示模式 */ void toggleSkinWireframeMode(); void toggleSkinWireframeModeOn(); void toggleSkinWireframeModeOff(); /** * feature line模式开关的控制接口 * 当渲染对象为网格模式时候,开关 feature line显示模式 */ void toggleFeatureLineMode(); void toggleFeatureLineModeOn(); void toggleFeatureLineModeOff(); /** * free edge模式开关的控制接口 * 当渲染对象为网格模式时候,开关 free edge显示模式 */ void toggleFreeEdgeMode(); void toggleFreeEdgeModeOn(); void toggleFreeEdgeModeOff(); void toggleConstraintMode(); void toggleConstraintModeOn(); void toggleConstraintModeOff(); void toggleContactMode(); void toggleContactModeOn(); void toggleContactModeOff(); /** * mesh line模式开关的控制接口 * 当渲染对象为网格模式时候,开关 mesh line显示模式 */ void toggleMeshLineMode(); void toggleMeshLineModeOn(); void toggleMeshLineModeOff(); /** * norm check模式开关的控制接口 * 当渲染对象为网格模式时候,开关 norm check显示模式 */ void toggleNormCheckMode(); /** * norm模式开关的控制接口 * 当渲染对象为网格模式时候,开关 norm 显示模式 */ void toggleNormMode(); /** * 单元值渲染模式开关的控制接口 * 当渲染对象为网格模式时候,开关单元值显示模式 * 单元上需要渲染的值通过vd.tria_scalars或者quad_scalars传入 */ void toggleElemFringeMode(); void toggleElemFringeModeOn(); void toggleElemFringeModeOff(); /** * 单元质量检查渲染模式开关的控制接口 * 当渲染对象为网格模式时候,开关单元值显示模式 * 单元上需要渲染的值通过vd.tria_scalars或者quad_scalars传入 */ void toggleQualityCheckMode(); void toggleQualityCheckModeOn(); void toggleQualityCheckModeOff(); /** * 节点值渲染模式1开关的控制接口 * 当渲染对象为网格模式时候,开关节点值Gouraud显示模式 * 节点上需要渲染的值通过vd.node_scalars传入 * 使用vd.smooth = true,设置Gouraud渲染模式 */ void toggleNodalFringeMode(); void toggleNodalFringeModeOn(); void toggleNodalFringeModeOff(); /** * 节点值Phong渲染模式开关的控制接口 * 当渲染对象为网格模式时候,开关节点值Phong显示模式 * 节点上需要渲染的值通过vd.node_scalars传入 * 使用vd.smooth = true, 设置Phong渲染模式 */ void toggleNodalContourMode(); void toggleNodalContourModeOn(); void toggleNodalContourModeOff(); /** * 后处理单元值渲染模式开关的控制接口 * 当渲染对象为后处理模式时候,开关单元值显示模式 * 单元上需要渲染的值通过vd.tria_scalars或者quad_scalars传入 */ void togglePostElemFringeMode(); void togglePostElemFringeModeOn(); void togglePostElemFringeModeOff(); /** * 后处理节点值Gouraud渲染模式开关的控制接口 * 当渲染对象为后处理模式时候,开关节点值Gouraud显示模式 * 单元上需要渲染的值通过vd.tria_scalars或者quad_scalars传入 * 使用vd.smooth = true, 设置Gouraud渲染模式 */ void togglePostNodalFringeMode(); void togglePostNodalFringeModeOn(); void togglePostNodalFringeModeOff(); /** * 后处理节点值Gouraud渲染模式开关的控制接口 * 当渲染对象为后处理模式时候,开关节点值Gouraud显示模式 * 单元上需要渲染的值通过vd.tria_scalars或者quad_scalars传入 * 使用vd.smooth = true, 设置Phong渲染模式 */ void togglePostNodalContourMode(); void togglePostNodalContourModeOn(); void togglePostNodalContourModeOff(); void toggleFPS(); void toggleOptCrossOn(); void toggleOptCrossOff(); void toggleLabelModeOn(); void toggleLabelModeOff(); void toggleColorModeOn(); void toggleColorModeOff(); void toggleCircleModeOn(); void toggleCircleModeOff(); void toggleEdgeColorModeOn(); void toggleEdgeColorModeOff(); void toggleVectorMode(); void toggleVectorModeOn(); void toggleVectorModeOff(); ``` - 设置颜色条参数 ```c++ /** * 设置颜色条开关 */ void setColorBarVisibility(bool v); /** * 设置颜色条最大值最小值 */ void setColorBarRange(float min, float max); /** * 设置颜色条起始颜色和结束颜色hue值,360-蓝色, 240-红色 */ void setColorBarHueRange(int min, int max); /** * 设置颜色条标题 */ void setColorBarTitle(const std::string& title); /** * 设置颜色条级数 */ void setColorBarLevel(int level); /** * 设置颜色条门槛值,用于质量检查 */ void setColorBarThreshold(float threshold); /** * 设置颜色条门槛值显示与否,用于质量检查 */ void setColorBarShowThresholdOnly(bool flag); /** * 设置颜色条更新 */ void setColorBarUpdate(); ``` - 光照调节 ```c++ void setLightEnable(int index, int enable); void setLightPosition(int index, float x, float y, float z, float w); void setLightAmbient(int index, float r, float g, float b, float a); void setLightDiffuse(int index, float r, float g, float b, float a); void setLightSpecular(int index, float r, float g, float b, float a); void setLightShininess(float s); ``` - 坐标系开关 ```c++ void setAxesVisibility(bool v); ``` - 全局颜色设置 ```c++ void setBackgroundGroundColor(float c[3]); void setBackgroundSkyColor(float c[3]); void setMeshLineColor(float c[4]); ``` - 三维到屏幕二维坐标变换 ```c++ void toScreen(double x, double y, double z, double& wx, double& wy); ``` - 脚本驱动相关API ```c++ /** * 返回旋转四元数 */ void quaternion(float quat[4]); /** * 使用记录的四元数进行旋转 */ void rotate(float q0, float q1, float q2, float q3); /** * 返回平移二元数 */ void translation(float pan[2]); /** * 使用记录的二元数进行平移 */ void translate(float p0, float p1); /** * 返回缩放系数 */ void scaling(float& z); /** * 使用记录的缩放系数进行缩放 */ void scale(float z); ``` ## 使用示例 ### 可渲染对象索引 ArcherRender主要分为两大类:可渲染对象与可渲染组。其中可渲染组继承自可渲染对象,可渲染组中包含可渲染对象。在可渲染组中,有一个索引与可渲染对象的映射表 * std::unordered_map _renderables; 索引值包括两个部分:id和subId。其中id部分是partId,subId是子索引。一般会用到id值,subId只有在有需要的时候用到。比如创建一个part的渲染组,可以设置id值为partId,subId值为具体的渲染项的id,比如几何的subId为1, 网格的subId为2等等。也可以只设置id值(具体由用户决定)。 用户可通过索引值得到可渲染对象: * Renderable* findById(const int& id, int subId = 0); 通过也可以通过渲染对象得到对应的索引值: * int getUniqueIdx(Renderable* ren); 用户在使用void Add(Renderable* obj) 添加可渲染对象时,需要设置可渲染对象的索引编号,使用: * void setId(int id) * void setSubId(int id) 如果不设置编号,则使用默认编号(从1开始计数)。 ### RenderableGroup类 RenderableGroup类是可渲染组的基类,用户可继承该类创建自己的可渲染组。 ```C++ class mrModel : public render::RenderableGroup { public: mrModel(); ~mrModel(); ... }; ``` ### Canvas类 Canvas类负责客户端画布初始化工作,包括注册各类型可渲染组。ArcherRender默认提供ModelRender、SelectionRender以及TemporaryRender类型组号(见renderable.h中FrameRenderId),并且用户可以自定义自己的类型组号(从UserDefinedRender开始)。然后将渲染组在Canvas中注册 ```C++ mrModel* ren = new mrModel(); ren->setFrameRenderable(true); ren->setColorTable(color); //! 设置model颜色表,如果没有,可以忽略 ren->setId(render::Renderable::ModelRender); Add(ren); mrSelectionModel* sel = new mrSelectionModel(); sel->setFrameRenderable(true); sel->setId(render::Renderable::SelectionRender); Add(sel); int userIdx = render::Renderable::UserDefinedRender; mrUserDefinedModel* user = new mrUserDefinedModel(); user->setFrameRenderable(true); user->setId(userIdx++); ... //! 在注册完最后,调用PostAdd,配置画布 this->PostAdd(); ``` 对于网格剖分场景,Canvas提供了两个接口函数,用于优化该场景: * void BeforeDoMeshing(); * void PostDoMeshing(); 分别在网格剖分开始和结束时候调用: ```C++ BeforeDoMeshing(); //! 剖分网格等操作 ... PostDoMeshing(); ``` ### 更新操作 更新操作包括:导入模型创建可渲染对象、新增可渲染对象、删除可渲染对象以及修改可渲染对象等。主要涉及的接口包括: * void BeforeUpdate(); * void BeforeUpdate(Renderable* ren); * void BeforeUpdate(const std::vector& renderables); * void PostUpdate(); * void PostUpdate(Renderable* ren); * void PostUpdate(const std::vector& renderables); 其中BeforeUpdate接口放置到更新操作的开始,PostUpdate接口放置到更新操作的结束。 1. 在可渲染对象组中添加完可渲染对象之后,调用PostUpdate接口 ```C++ //! 增加可渲染对象 Add(...) ... PostUpdate(); ``` 2. 在可渲染对象组中更新所有的可渲染对象(支持增加渲染对象) ```C++ BeforeUpdate(); //! 删除组内所有可渲染对象,并重新获取viewData创建 ... PostUpdate(); ``` 3. 在可渲染对象组中更新某一个可渲染对象 ```C++ Renderable* ren = getOldRen(); BeforeUpdate(ren); //! 删除ren,并重新获取viewData创建 ... ren = getNewRen(); PostUpdate(ren); ``` 4. 在可渲染对象组中更新多个可渲染对象 ```C++ std::vector rens = getOldRens(); BeforeUpdate(rens); //! 删除rens,并重新获取viewData创建rens ... rens = getNewRens(); PostUpdate(rens); ``` 5. 在可渲染对象组中删除某一个可渲染对象 ```C++ Renderable* ren = getOldRen(); BeforeUpdate(ren); //! 删除rens Delete(ren); PostUpdate(); ``` 6. 在可渲染对象组中增加一个可渲染对象 ```C++ Renderable* ren = getRen(); //! 添加ren Add(ren); PostUpdate(ren); ``` 7. 在可渲染对象组中增加多个可渲染对象(优于逐个增加可渲染对象) ```C++ std::vector rens = getRens(); //! 添加rens for(const auto& it : rens){ Add(it); } PostUpdate(rens); ```