[TOC]
# Archer Render 使用说明
Archer Render是面向几何有限元模型的专用渲染引擎,使用C++, OpenGL, GLSL编写
## 功能介绍
### 大规模几何模型渲染
1. 绘制几何顶点

2. 绘制几何边

3. 绘制几何面

### 大规模网格模型渲染
1. 绘制点/线/三角形/四边形网格

2. 网格线

3. 法线双面\法线

4. 节点数据光滑云图/节点数据等值云图
5. 单元数据云图

### 点云绘制
### 绘制文本

### 交互
1. 旋转/平移/缩放/居中
2. 七视图
3. 旋转中心/局部放大
### 点/线/三角形/四边形的拾取

### 基本图元绘制
### 3D/2D 空间坐标转换
### 脚本化数据返回(旋转,平移,缩放等)
### 7千万
https://www.bilibili.com/video/BV14y4y1x7D7/
### 基于Phong明暗处理单元云图渲染

### 支持多color bar、多个云图独立渲染
## 目录说明

## 编译运行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功能使用介绍

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中的模型管理使用组合模式,如图所示,可以管理复杂的模型场景。

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接入流程
接入流程如下:
具体操作步骤如下:
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

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);
```