在 FEMFX 中,场景类 FmScene 包含了仿真场景中几乎所有的对象、信息等,比如 tetMesh 、constraints、rigidBodies、params 等等数据。下面对 FmScene 中的成员变量进行梳理。
具体的数据可分为三部分:软体(四面体单元)和刚体、约束及碰撞、其他
一、软体及刚体相关
其中,与软体(四面体单元)及刚体 有关的成员变量为:
FmTetMeshBuffer** tetMeshBuffers; // Array of pointers to FmTetMesh buffers
uint* awakeTetMeshIds; // Ids of awake tet meshes in current simulation step (that are not SIMULATION_DISABLED)
uint* awakeRigidBodyIds; // Ids of awake rigid bodies in current simulation step (that are not SIMULATION_DISABLED)
uint* sleepingTetMeshIds; // Ids of sleeping tet meshes in current simulation step (that are not SIMULATION_DISABLED); points into awakeTetMeshIds array
uint* sleepingRigidBodyIds; // Ids of sleeping rigid bodies in current simulation step (that are not SIMULATION_DISABLED); points into awakeRigidBodyIds array
FmTetMesh** tetMeshPtrFromId; // Map from FmTetMesh::objectId to tet mesh pointer
uint* tetMeshIdxFromId; // Map from FmTetMesh::objectId to index in awake ids list
uint* rigidBodyIdxFromId; // Map from FmRigidBody::objectId to index in awake ids list
FmFreeIds freeTetMeshIds; // Array of free mesh ids
FmFreeIds freeRigidBodyIds; // Array of free rigid body ids
FmRigidBody** rigidBodies; // Array of pointers to rigid bodies
uint numRigidBodySlots; // Number of rigid body slots used, some of which may be marked deleted
uint numAwakeRigidBodies; // Number of awake rigid bodies simulated in current step
uint numAwakenedRigidBodies; // Number of rigid bodies added to ids list on waking
uint maxRigidBodies;
uint numTetMeshBufferSlots; // Number of entries in tetMeshBuffers array (some of which may be NULL if removed)
uint numAwakeTetMeshes; // Number of awake tet meshes simulated in current step
uint numAwakenedTetMeshes; // Number of tet meshes added to ids list on waking
uint numTetMeshesTotal; // Number of tet meshes created in all tet mesh buffers, must not exceed maxTetMeshes
uint maxTetMeshBuffers;
uint maxTetMeshes;
uint maxSceneVerts;
uint maxTetMeshBufferFeatures;
uint numSleepingTetMeshes; // Number of sleeping tet meshes, placed at end awakeTetMeshIds array
uint numSleepingRigidBodies; // Number of sleeping rigid bodies, placed at end awakeRigidBodyIds array
在这里解释一下相关成员变量的含义、存储方法,并由此探讨 FEMFX 仿真流程的执行理念。
首先,解释一下刚体和软体在 FEMFX 中的类型定义。
在 FEMFX 中,一个刚体定义为类型 FmRigidBody
,由该刚体而产生的碎片,仍然依附与该刚体,相关数据也存储于该 FmRigidBody
中。此外, FmRigidBody
中还包含了质量、摩擦系数、惯性张量、速度、以及碰撞相关的变量。其中,该刚体的碰撞对象仍然为 FmTetMeshBuffer
类型,这样一个好处就是,在碰撞检测时,不用区分是刚体还是软体。
软体(也就是 tetMesh)定义为类型 FmTetMeshBuffer
,由该软体产生的碎片,仍然依附于该软体,相关数据存储于 FmTetMeshBuffer
中。其中,包括了像 tetMesh 网格数据、solver 求解数据、碎片数据、节点数据等等。
回到刚体、软体在 FmScene
中的存储。在 FEMFX 中,数据多以指针的形式存储。同样,对于 FmScene
中的刚体 FmRigidBody
和软体 FmTetMeshBuffer
也都是用二级指针指向一系列这些对象的指针数组。示意:
此外,通过上述变量可知,与软体、刚体有关的还有 Ids
Slot
等编号,及由指针到编号的映射 tetMeshPtrFromId
,以及 Awake
Sleeping
等状态,以及 numTetMeshBuffer
、numTetMesh
等数量统计。
总体上来讲,可以这么解释:(FmTetMeshBuffer**)tetMeshBuffers
指向了一个数组 tetMeshBuffers[xx]
,其中每一个单元称之为一个 Slot
,存放有一个 TetMeshBuffer*
指针,该指针又指向了一个 TetMeshBuffer
实例,参见以上图片。
TetMeshBuffer*
指针在 tetMeshBuffers[xx]
中的位置,记作了 meshBufferIdx
,并写入了 TetMeshBuffer::bufferId
中。此外,numTetMeshBufferSlots
是 tetMeshBuffers[xx]
中已经被使用的单元个数,不过已使用的这些里面也存在被移除(NULL)的情况。
前面提到,每个 TetMeshBuffer
对应一个初始时的软体,由此产生的碎片,也会存放在这里。也就是说,每个 TetMeshBuffer
里面有许多(>=1)个 TetMesh
。每一个 TetMesh
都会拥有一个全局独一无二的 objectId
。(由 FmFreeIds
管理和生成。)
那么,(1)各个 TetMesh
以指针的形式存放在 TetMeshBuffer::tetMeshes
中。并且,他的 objectId
则存放在 TetMesh::objectId
中。另外,在 FmScene::tetMeshPtrFromId[]
中,建立了由 objectId
到 *TetMesh
指针的映射。
(2)在每个 TetMesh
中,也记录了它是属于哪个 TetMeshBuffer
的。通过 TetMeshe::bufferId
记录。
(3)每当添加新的 TetMesh
时,也会将它的 objectId
追加到 FmScene::awakeTetMeshIds[]
中。同时,在 FmScene::tetMeshIdxFromId[]
中也会建立从 id 到 idx 的映射,即 tetMeshIdxFromId[id] = idx 。这里面,id 为 tetMesh 的 objectId,而 idx 为该 tetMesh 的 objectId 在 FmScene::awakeTetMeshIds[]
中的位置,即 awakeTetMeshIds[Idx] = objectId 。
刚体相关的成员函数也有类似的功能。
下面分别介绍一下各个变量的具体含义和用法:
FmScene::tetMeshBuffers
为二级指针,指向了存放 tetMeshBufer
的数组。用法为,gScene->tetMeshBuffers[bufferId]
指向了一个 tetMeshBuffer
实例。
FmScene::awakeTetMeshIds
指向了存放 awake 状态的 tetMesh 的 objectId 的数组。也就是说,gScene->awakeTetMeshIds[0]
中存放的是一个处于 awake 状态的 tetMesh
实例的 objectId。在 tetMeshBuffers
中存放有许多个(>=1)tetMesh
,存放在 FmTetMeshBuffers::tetMeshs[]
中,而每一个 tetMesh
都有一个全局独一无二的 objectId
。
FmScene::awakeRigidBodyIds
同理,存放的处于 awake 状态的 rigidObject 的 objectId。
FmScene::sleepingTetMeshIds
同理。
FmScene::sleepingRigidBodyIds
同理。
FmScene::tetMeshPtrFromId
指向一个数组,建立由 tetMesh
的 objectId
到 指向该 tetMesh
的指针的映射。用法为,gScene->tetMeshPtrFromId[tetMesh->objectId] = tetMesh
FmScene::tetMeshIdxFromId
指向一个数组,建立由 tetMesh
的 objectId
到 该 objectId
在 FmScene::awakeRigidBodyIds
中位置的映射。用法为,idx = gScene->tetMeshIdxFromId[tetMesh->objectId]; gScene->awakeTetMeshIds[idx] == tetMesh->objectId;
FmScene::rigidBodyIdxFromId
同理。
FmScene::freeTetMeshIds
FmScene::freeRigidBodyIds
FmScene::rigidBodies
同理,为二级指针,指向了存放 FmRigidBody
的数组。
FmScene::numRigidBodySlots
为已经被使用的 rigidBody Slot 的数量。在 rigidBodies[]
中,每个单元称之为一个 slot 。
FmScene::numAwakeRigidBodies
为(xxx)处于 awake 状态的 rigidBody 的个数。
FmScene::numAwakenedRigidBodies
为(xxx)处于 awake 状态的 rigidBody 的个数。
FmScene::maxRigidBodies
为 FmScene
中可容纳的 rigidBody 的最大个数。在初始化时即确定下来,并由此确定 rigidBodies[]
数组等的大小。
FmScene::numTetMeshBufferSlots
同理。
FmScene::numAwakeTetMeshes
同理。
FmScene::numAwakenedTetMeshes
同理。
FmScene::numTetMeshesTotal
同理。
FmScene::maxTetMeshBuffers
该 gScene
中可容纳的 tetMeshBuffer
的数量。
FmScene::maxTetMeshes
该 gScene
中可容纳的 tetMesh
的数量。在初始化时便确定下来,由此确定 sleepingTetMeshIds[]
tetMeshIdxFromId[]
等数组的大小。
FmScene::maxSceneVerts
FmScene::maxTetMeshBufferFeatures
FmScene::numSleepingTetMeshes
FmScene::numSleepingRigidBodies
以上便是 FmScene
中各个成员函数的含义,并顺带介绍了 FmTetMeshBuffer
FmTetMesh
FmRigidBody
等的数据结构,以及其中的 bufferId objectId ptr 等编号方式,以及 awake sleeping 等状体的记录方式。