节点为功能相对独立的、封装了特定模块的算法集合,主要包含以下几个部分:
创建一个完整的节点包含如下步骤:
定义输入节点(可选):
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();
状态更新后处理函数。
一个节点对应的GUI视图由两部分组成,即Node Editor视图和Property Editor视图。
Node Editor主要展示节点对应的输入和输出,支持利用鼠标进行数据之间的连接和断开连接操作,典型视图如下:
Property Editor窗口则显示每个节点的状态变量以及控制参数信息。例如,当鼠标单击StaticBoundary节点时,Property Editor窗口显示的属性信息如下图所示:
控制变量用于展示通过Fvar定义的变量,Property Editor窗口可以实现对控制变量进行快速更改。
bool:
例如当FVar中Visible勾选时,仿真过程中,将会把该节点渲染出来;如果取消勾选,则仿真过程中,不会渲染该节点。
float或者double:
Vec3f或者Vec3d:
FilePath:
其中FilePath对应系统路径,用于支持本地文件读取功能。
FState属性允许将Node Editor窗口中,节点FState类型的属性信息显示和隐藏。例如,ParticleFluid节点把Velocity属性勾选时,Node Editor窗口中对应输出会增加Velocity属性,从而使Velocity可以作为其他节点输入。