数据

1、Field功能简介

Field是对基本数据类型的封装,从而实现节点以及模块之间的数据传递。典型的数据类型包含如下几类:

  • 基本类型:指数据量比较小,可以在CPU和GPU进行直接传递的数据,典型的包括bool、int、float、double等标量数据以及Vec3f、Vec3d、Mat3f、Mat3d等张量数据。Field可通过FVar来完成数据的定义和传递;
  • 静态数组:指数据尺寸固定的连续存储空间,包括一维数组、二维数组、三维数组等。Field宏定义采用DEF_ARRAY{2D, 3D}_{*}的形式。
  • 动态数组:指数据尺寸动态变化的连续存储空间,包括List、Map、Set、MultiSet、Pair、Stack等类型的数据。Field宏定义采用DEF_ARRAYLIST_{*}的形式。
  • 引用类型:针对复杂类型,采用类似C++指针的方式进行数据定义。Field宏定义采用DEF_INSTANCE_{*}的形式。

Field之间的连接和断开主要依赖以下两个函数实现,连接过程中会进行数据有效性验证,如有效则返回true,无效返回false。

virtual bool connect(FBase* dst) = 0;
virtual bool disconnect(FBase* dst);

FBase作为所有Field的基类,其功能主要是对Field的连接状态进行统一管理。

connect(FBase* dst)在FBase中被定义为纯虚函数,因而其具体实现依赖于特定Field。该设计主要为了对数据连接行为进行有效的验证,防止将数据连接到错误的类型。

假设存在A、B、C三个Field类型数据,他们的连接关系设置为A->B->C。此时为了降低数据转换和存储开销,当我们对C的数据进行操作时,会根据其连接关系返回最顶端(这里对应的是A)的数据指针进行操作。

2、Field数据类型

  • FVar:继承自FBase,是对单一数据类型的封装,包括标量数据,如int、float、double等;矢量数据,如Vec3f等;二阶张量数据,如Mat3f;文件路径类型数据,如FilePath。节点和模块中可以通过使用DEF_VAR/DEF_VAR_IN等宏定义来进行定义:

    DEF_VAR(Real, TangentialFriction, 0.0, "Tangential friction");
    

    其中Real代表数据类型,TangentialFriction代表数据名称,0.0代表初值,“Tangential friction"则表示数据的说明。通过DEF_VAR定义的数据实际使用过程中可以通var+数据名称的方式对数据进行操作。假设我们需要将上述Field连接到另一个功能模块,则可以调用如下接口进行:

    this->varRestDensity()->connect(...);
    

    常见数据类型定义及GUI视图如下:

    (1)FVar,int类型:

    C++代码定义:

    DEF_VAR(int, Types, 4, "winds Types");
    

    Qt视图:

    (2)FVar,float类型:

    C++代码定义:

    DEF_VAR_IN(Real, Radius, "Search radius");
    

    Qt视图:

    (3)FVar,bool类型:

    C++代码定义:

    DEF_VAR(bool, Active, true, "Indicating whether the simulation is on for this node!");
    

    Qt视图:

    (4)FVar,FilePath类型:

    C++代码定义:

    DEF_VAR(FilePath, FileName, "", "");
    

    Qt视图:

    (5)FVar,Vec3f类型:

    C++代码定义:

    DEF_VAR(Vec3f, Location, 0, "Node location");
    

    Qt视图:

    (6)FVarPEnum数据:枚举数据类型。通过DEF_ENUM定义数据,通过var+数据名称的对数据进行操作。ENUM类型定义如下:

    C++代码定义:

    DECLARE_ENUM(EKernelType,
              KT_Smooth = 0,
              KT_Spiky = 1);
      
    DEF_ENUM(EKernelType, KernelType, EKernelType::KT_Spiky, "Rendering mode");
    

    Qt视图:

    参数类型为int、uint、Vec3f、Vec3d的FVar数据需要调用setRange()函数设置数据的有效范围,否则Qt界面可能会显示异常。

  • FArray:对Array.h中定义的一维数组进行封装,类似于STL中的vector。根据其在节点/模块中的不同功能,我们采用如下三种形式定义:

    DEF_ARRAY_IN(Coord, Position, DeviceType::GPU, "Output");						//输入
    

    输入数据,访问方式为in+数据名称,即inPosition()。

    DEF_ARRAY_OUT(Coord, Position, DeviceType::GPU, "Output");						//输出
    

    输出数据,访问方式为out+数据名称,即outPosition()。

    DEF_ARRAY_STATE(Coord, Position, DeviceType::GPU, "Internal state");			//内部状态变量
    

    状态变量,访问方式为state+数据名称,即statePosition()。

  • FArrayList:对ArrayList.h数据进行封装,用于支持CPU/GPU兼容的动态数据类型。其定义方式与FArray类似,即:

    DEF_ARRAYLIST_IN(Coord, Position, DeviceType::GPU, "Input");						//输入
    

    输入数据,访问方式为in+数据名称,即inPosition()。

    DEF_ARRAYLIST_OUT(Coord, Position, DeviceType::GPU, "Output");						//输出
    

    输出数据,访问方式为out+数据名称,即outPosition()。

    DEF_ARRAYLIST_STATE(Coord, Position, DeviceType::GPU, "Internal state");			//内部状态变量
    

    状态变量,访问方式为state+数据名称,即statePosition()。

  • FInstance:主要为了支持存在继承关系的数据之间的连接,典型应用为利用FInstance定义不同拓扑结构数据:

    DEF_INSTANCE_IN(PointSet<TDataType>, PointSet, "PointSet is derived from TopologyModule");						//输入
    

    输入数据,访问方式为in+数据名称,任意继承自PointSet的子类都可以连接到该数据。

    DEF_INSTANCE_OUT(PointSet<TDataType>, PointSet, "Output");						//输出
    

    输出数据,访问方式为out+数据名称

    DEF_INSTANCE_STATE(PointSet<TDataType>, PointSet, "Internal state");			//内部状态变量
    

    状态变量,访问方式为state+数据名称,在Qt界面中,显示如下: