节点

1、功能简介

节点为功能相对独立的、封装了特定模块的算法集合,主要包含以下几个部分:

  • 控制变量:采用宏定义DEF_VAR形式定义的数据;
  • 输入节点:利用宏定义DEF_NODE_PORT或者DEF_NODE_PORTS形式定义;
  • 输出节点:当前实现只支持节点自身作为默认输出,不需显式定义;
  • 输入数据:采用宏定义DEF_ *_ IN形式定义的数据;
  • 输出数据:采用宏定义DEF_ *_ OUT形式义的数据;
  • 状态变量:采用宏定义DEF_ *_ STATE形式定义的数据;
  • 模块管线:主要包含仿真管线和渲染管线,分别采用animationPipeline()和graphicsPipeline()函数进行调用。

2、如何实现一个自定义节点

创建一个完整的节点包含如下步骤:

  • 定义输入节点(可选):

    DEF_NODE_PORT(T, name, desc)
    

    该宏定义定义单一节点输入,其中T表示节点类型,name表示名称,desc表示输入节点描述信息,访问方式为import+数据名称

    DEF_NODE_PORTS(T, name, desc)
    

    该宏定义可定义输入节点数组,其可接入0到任意数量类型为T的节点作为输入,访问方式为import+数据名称+s

  • 定义输入数据(可选):

    DEF_VAR_IN(T, name, desc)
    

    定义输入类型为T、名称为name的单一数据类型作为输入。

    DEF_ARRAY_IN(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的一维数组作为输入。

    DEF_ARRAY2D_IN(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的二维数组作为输入。

    DEF_ARRAY3D_IN(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的三维数组作为输入。

    DEF_INSTANCE_IN(T, name, desc)
    

    定义输入类型为T、名称为name的实例作为输入。

    DEF_ARRAYLIST_IN(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的一维动态列表数组作为输入。

  • 定义输出数据(可选):

    DEF_VAR_OUT(T, name, desc)
    

    定义输入类型为T、名称为name的单一数据类型作为输出。

    DEF_ARRAY_OUT(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的一维数组作为输出。

    DEF_ARRAY2D_OUT(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的二维数组作为输出。

    DEF_ARRAY3D_OUT(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的三维数组作为输出。

    DEF_INSTANCE_OUT(T, name, desc)
    

    定义输入类型为T、名称为name的实例作为输出。

    DEF_ARRAYLIST_OUT(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的一维动态列表数组作为输出。

  • 定义状态变量

    DEF_VAR(T, name, value, desc)
    

    定义类型为T、名称为name、初值类型为value的单一数据类型作为状态变量。

    DEF_ARRAY_STATE(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的一维数组作为状态变量。

    DEF_ARRAY2D_STATE(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的二维数组作为状态变量。

    DEF_ARRAY3D_STATE(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的三维数组作为状态变量。

    DEF_INSTANCE_STATE(T, name, desc)
    

    定义输入类型为T、名称为name的实例作为状态变量。

    DEF_ARRAYLIST_STATE(T, name, device, desc)
    

    在device(CPU/GPU)设备上定义类型为T、名称为name的一维动态列表数组作为状态变量。

  • 创建功能模块:

    以RigidBodySystem为例,其构造函数中创建的功能模块如下:

    //创建自碰撞检测模块
    auto elementQuery = std::make_shared<NeighborElementQuery<TDataType>>();
    this->currentTopology()->connect(elementQuery->inDiscreteElements());
    this->stateCollisionMask()->connect(elementQuery->inCollisionMask());
    this->animationPipeline()->pushModule(elementQuery);
      
    //创建边界包围盒碰撞检测功能模块
    auto cdBV = std::make_shared<CollistionDetectionBoundingBox<TDataType>>();
    this->currentTopology()->connect(cdBV->inDiscreteElements());
    this->animationPipeline()->pushModule(cdBV);
      
    //创建合并触点功能模块
    auto merge = std::make_shared<ContactsUnion<TDataType>>();
    elementQuery->outContacts()->connect(merge->inContactsA());
    cdBV->outContacts()->connect(merge->inContactsB());
    this->animationPipeline()->pushModule(merge);
      
    //创建刚体动力学求解模块
    auto iterSolver = std::make_shared<IterativeConstraintSolver<TDataType>>();
    this->varTimeStep()->connect(iterSolver->inTimeStep());
    this->varFrictionEnabled()->connect(iterSolver->varFrictionEnabled());
    this->stateMass()->connect(iterSolver->inMass());
    this->stateCenter()->connect(iterSolver->inCenter());
    this->stateVelocity()->connect(iterSolver->inVelocity());
    this->stateAngularVelocity()->connect(iterSolver->inAngularVelocity());
    this->stateRotationMatrix()->connect(iterSolver->inRotationMatrix());
    this->stateInertia()->connect(iterSolver->inInertia());
    this->stateQuaternion()->connect(iterSolver->inQuaternion());
    this->stateInitialInertia()->connect(iterSolver->inInitialInertia());
      
    merge->outContacts()->connect(iterSolver->inContacts());
      
    this->animationPipeline()->pushModule(iterSolver);
    

节点构造函数仅包含默认管线,管线功能模块可在外部进行动态添加和删除。详情参加GL_ParticleFluid样例阐述如何为节点渲染管线添加自动渲染模块。

  • 重载虚函数

    virtual void preUpdateStates();
    

    状态更新前处理函数。

    virtual void updateStates();
    

    状态更新函数,若子类不重载该函数,默认调用pipeline执行内置算法流程。

    virtual void postUpdateStates();
    

    状态更新后处理函数。

3、QT GUI视图

一个节点对应的GUI视图由两部分组成,即Node Editor视图和Property Editor视图。

Node Editor主要展示节点对应的输入和输出,支持利用鼠标进行数据之间的连接和断开连接操作,典型视图如下:

Property Editor窗口则显示每个节点的状态变量以及控制参数信息。例如,当鼠标单击StaticBoundary节点时,Property Editor窗口显示的属性信息如下图所示:

(1)控制变量

控制变量用于展示通过Fvar定义的变量,Property Editor窗口可以实现对控制变量进行快速更改。

  • bool:

例如当FVar中Visible勾选时,仿真过程中,将会把该节点渲染出来;如果取消勾选,则仿真过程中,不会渲染该节点。

  • float或者double:

  • Vec3f或者Vec3d:

  • FilePath:

其中FilePath对应系统路径,用于支持本地文件读取功能。

(2)状态变量

FState属性允许将Node Editor窗口中,节点FState类型的属性信息显示和隐藏。例如,ParticleFluid节点把Velocity属性勾选时,Node Editor窗口中对应输出会增加Velocity属性,从而使Velocity可以作为其他节点输入。