# Archer Render 使用说明 Archer Render是面向几何有限元模型的专用渲染引擎,使用C++, OpenGL, GLSL编写 ## 目录说明  ## 编译运行Demo 1. 前提 (windows平台为例,linux平台类似,需编译相应第三方库) 1. QT5.12 2. CMake 3. VS2017 2. 编译 1. cmake(vs2017 x64) 2. configure 3. build 3. 运行 1. 在bin路径Debug或者Release下运行相关exe ## Demo功能使用介绍 1. 新建一个模型,当前是一个四面体  2. 拾取四面体的一个三角面片  3. 七种视图模式和居中 4. 旋转/平移/缩放操作 ## Archer Render中的若干概念 1. 画布 画布是Archer Render里的顶层对象,所有的API调用都是从画布调用的,包括初始化,添加可渲染对象,渲染,拾取,鼠标事件响应,交互状态设置等等API,在后面将详细介绍。 2. 可渲染对象,可渲染部件,可渲染组 可渲染对象是顶层抽象,如名字所示,代表了所有可渲染的对象;可渲染部件是实例化渲染对象,完成了实际的绘制工作,相当于渲染对象管理中的最小单元;可渲染组是可渲染对象的集合;ArcherRender中的模型管理使用组合模式,如图所示,可以管理复杂的模型场景。  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<float> nodes; /*节点坐标*/ std::vector<float> node_normals; /*节点法向,仅几何和点云数据有效*/ std::vector<float> node_colors; /*节点颜色,仅点云数据有效*/ std::vector<float> node_scalars; /*节点scalar值,用于节点云图*/ ``` 3. 顶点信息 ```c++ std::vector<int> verts; /*顶点索引*/ unsigned int vert_type; /*顶点类型,用于拾取分类*/ unsigned int vert_identity; /*顶点一级标识,用于拾取*/ float vert_size; /*顶点大小*/ float vert_color[4]; /*顶点颜色*/ std::vector<int> vert_identities; /*顶点二级标识,用于拾取*/ std::vector<std::string> vert_text; /*顶点文本*/ std::vector<float> vert_scalars; /*顶点scalar值*/ ``` 4. 线段信息 ```c++ std::vector<int> lines; /*线段索引*/ unsigned int line_type; /*线段类型,用于拾取分类*/ unsigned int line_identity; /*线段一级标识,用于拾取*/ float line_width; /*线段宽度*/ float line_color[4]; /*线段颜色*/ std::vector<int> line_identities; /*线段二级标识,用于拾取*/ std::vector<float> line_scalars; /*线段scalar值*/ ``` 5. 面片信息 ```c++ std::vector<int> trias; /*三角形索引*/ unsigned int tria_type; /*三角形类型,用于拾取分类*/ unsigned int tria_identity; /*三角形一级标识,用于拾取*/ std::vector<int> tria_identities; /*三角形二级标识,用于拾取*/ std::vector<float> tria_scalars; /*三角形scalar值,用于单元云图*/ std::vector<int> quads; /*四边形索引*/ unsigned int quad_type; /*四边形类型,用于拾取分类*/ unsigned int quad_identity; /*四边形一级标识,用于拾取*/ std::vector<int> quad_identities; /*四边形二级标识,用于拾取*/ std::vector<float> 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; } }; ``` ## Canvas接入流程 以QT为例,在QT QOpenGLWidget的子类中重载以下事件函数并在其中调用Canvas子类提供的相应API:  接入流程如下:  ### 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<double, 3>& 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<void()> routine); /** * 添加命名绘制routine */ void addRenderRoutine(const std::string& name, std::function<void()> 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<std::array<double, 3>> & points, bool drawLines = false); /** * 绘制点 * @param points 坐标 * @param colors 颜色 */ void drawPoints(const std::vector<std::array<double, 3>> & points, const std::vector<std::array<float, 3>> & colors); /** * 绘制点球 * @param points 坐标 * @param colors 颜色 * @param radius 半径 */ void drawPoints(const std::vector<std::array<double, 3>> & points, const std::vector<std::array<float, 3>> & colors, const std::vector<float>& radius); /** * 绘制线 * @param type 类型,可选GL_LINES,GL_LINE_STRIP,GL_LINE_LOOP * @param points 坐标 * @param lineColor 颜色 * @param lineWidth 线宽 */ void drawLine(unsigned type, const std::vector<std::array<double, 3>> & points, float lineColor[3], float lineWidth); /** * 绘制平面 * @param pos 位置 * @param dir 法线 */ void drawPlane(const std::array<double, 3> & pos, const std::array<double, 3> & 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<std::array<float, 3>>& points, const std::vector<std::array<float, 3>>& directions, std::array<float, 3> color); /** * 绘制箭头 * @param points 坐标 * @param direction 方向 * @param color 颜色 */ void drawArrow(const std::vector<std::array<float, 3>>& points, std::array<float, 3> direction, std::array<float, 3> color); /** * 绘制圆锥 * @param points 坐标 * @param direction 方向 * @param color 颜色 */ void drawCone(const std::vector<std::array<float, 3>>& points, std::array<float, 3> direction, std::array<float, 3> color); /** * 绘制两个首尾相接圆锥 * @param points 坐标 * @param direction 方向 * @param drawHead/drawTail 头尾是否绘制 * @param colorHead/colorTail 头尾颜色 */ void drawTwoCones(const std::vector<std::array<float, 3>>& points, std::array<float, 3> direction, bool drawHead, std::array<float, 3> colorHead, bool drawTail, std::array<float, 3> colorTail); /** * 绘制圆 * @param c 圆心 * @param n 方向 * @param r 半径 * @param color 颜色 * @param lineWidth 线宽 */ void drawCircle(const std::array<float, 3>& c, const std::array<float, 3>& n, float r, const std::array<float, 3>& color, float lineWidth = 1.0f); ``` - 显示模式设置 ```c++ unsigned mode() const; void toggleGeomMode(); void toggleGeomModeOn(); void toggleGeomModeOff(); void toggleVertMode(); void toggleVertModeOn(); void toggleVertModeOff(); void toggleEdgeMode(); void toggleEdgeModeOn(); void toggleEdgeModeOff(); void toggleFaceMode(); void toggleFaceModeOn(); void toggleFaceModeOff(); void toggleMeshMode(); void toggleMeshModeOn(); void toggleMeshModeOff(); void toggleShadeModeOn(); void toggleWireframeMode(); void toggleWireframeModeOn(); void toggleWireframeModeOff(); void toggleSkinWireframeMode(); void toggleSkinWireframeModeOn(); void toggleSkinWireframeModeOff(); void toggleFeatureLineMode(); void toggleFeatureLineModeOn(); void toggleFeatureLineModeOff(); void toggleMeshLineMode(); void toggleMeshLineModeOn(); void toggleMeshLineModeOff(); void toggleNormCheckMode(); void toggleNormMode(); void toggleElemFringeMode(); void toggleElemFringeModeOn(); void toggleElemFringeModeOff(); void toggleQualityCheckMode(); void toggleQualityCheckModeOn(); void toggleQualityCheckModeOff(); void toggleFreeEdgeMode(); void toggleFreeEdgeModeOn(); void toggleFreeEdgeModeOff(); ``` - 设置颜色条参数 ```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); ```