Rigid Body Collision

Introduction


本节将介绍刚体碰撞的基础知识。

Shapes


Shape描述actor的空间范围(spatial extent)和碰撞属性(collision properties)。它们在PhysX 中用于三个目的:确定rigid objects的接触特征的相交性测试(intersection tests)、场景查询测试(scene query tests)(如raycasts)以及定义触发体积(defining trigger volumes)(当其他Shape与它们相交时生成通知)。

每个Shape都包含一个PxGeometry 对象和一个对 PxMaterial 的引用,这两个对象都必须在创建时指定。下面的代码创建一个具有球体几何图形和特定材质的Shape

PxShape* shape = physics.createShape(PxSphereGeometry(1.0f), myMaterial, true);
myActor.attachShape(*shape);
shape->release();

方法 PxRigidActorExt::createExclusiveShape() 等效于上面的三行。

用于 createShape() 的参数 “true” 通知 SDK 该Shape不会与其他Actor共享。当有许多具有相同几何图形的 Actor 时,可以使用Shape共享来降低simulate的内存成本,但共享Shape具有非常严格的限制:在共享Shape附加到 Actor 时,您无法更新共享Shape的属性。

(可选)您可以通过指定类型为 PxShapeFlagsShape flags来配置Shape。默认情况下,Shape配置为:

  • simulate Shape(在simulate期间启用接触生成( contact generation ))
  • 场景查询Shape(为场景查询启用)
  • 如果启用了调试渲染,则可视化

Shape指定几何对象时,该几何对象将复制到该Shape中。对于可以为Shape指定几何图形有一些限制,具体取决于Shape flags和父角色的类型。

  • 附加到dynamic actorssimulate``Shape不支持``TriangleMeshHeightFieldPlane geometries,除非dynamic actors配置为kinematic`。
  • 触发器Shape不支持TriangleMeshHeightField几何图形。

有关更多详细信息,请参阅以下部分。

如下所示将ShapeActor分离:

myActor.detachShape(*shape);

Simulation Shapes and Scene Query Shapes


Shape可以独立配置为参与场景查询(scene queries)和接触测试(contact tests)中的一个或两个。默认情况下,Shape将同时参与这两项操作。以下伪代码配置 PxShape 实例,使其不再参与Shape对相交测试(shape pair intersection tests):

void disableShapeInContactTests(PxShape* shape)
{shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE,false);
}

可以将 PxShape 实例配置为参与Shape对相交测试(shape pair intersection tests),如下所示:

void enableShapeInContactTests(PxShape* shape)
{shape->setFlag(PxShapeFlag::eSIMULATION_SHAPE,true);
}

要从场景查询测试中禁用PxShape 实例,请执行以下操作:

void disableShapeInSceneQueryTests(PxShape* shape)
{shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE,false);
}

最后,可以在场景查询测试中重新启用 PxShape 实例:

void enableShapeInSceneQueryTests(PxShape* shape)
{shape->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE,true);
}

注意:如果ShapeActor的运动根本不需要由simulate控制,那么可以通过在Actor上额外禁用simulate来节省内存。例如Shape仅用于场景查询,并在必要时手动移动

Kinematic Triangle Meshes (Planes, Heighfields)


可以创建一个kinematic PxRigidDynamic,它可以具有三角形网格(planeheighfield)Shape。如果此Shape具有simulate Shape标志,则此Actor必须保持kinematic。如果将标志更改为"not simulated",你甚至可以切换kinematic flag。要设置kinematic triangle mesh,请参阅以下代码:

PxRigidDynamic* meshActor = getPhysics().createRigidDynamic(PxTransform(1.0f));
PxShape* meshShape;
if(meshActor)
{meshActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);PxTriangleMeshGeometry triGeom;triGeom.triangleMesh = triangleMesh;meshShape = PxRigidActorExt::createExclusiveShape(*meshActor,triGeom,defaultMaterial);getScene().addActor(*meshActor);
}

要将kinematic triangle mesh切换为dynamic actor

PxRigidDynamic* meshActor = getPhysics().createRigidDynamic(PxTransform(1.0f));
PxShape* meshShape;
if(meshActor)
{meshActor->setRigidDynamicFlag(PxRigidDynamicFlag::eKINEMATIC, true);PxTriangleMeshGeometry triGeom;triGeom.triangleMesh = triangleMesh;meshShape = PxRigidActorExt::createExclusiveShape(*meshActor, triGeom,defaultMaterial);getScene().addActor(*meshActor);PxConvexMeshGeometry convexGeom = PxConvexMeshGeometry(convexBox);convexShape = PxRigidActorExt::createExclusiveShape(*meshActor, convexGeom,defaultMaterial);

Broad-phase Algorithms


PhysX 支持多种粗检测算法(broad-phase algorithms):

  • sweep-and-prune (SAP)
  • multi box pruning (MBP)

PxBroadPhaseTyp::eSAPPhysX 3.2 之前使用的默认算法。这是一个很好的通用选择,当许多物体处于睡眠状态时,它具有出色的性能。但是,当所有对象都在移动时,或者当在粗检测(broad-phase)中添加或删除大量对象时,性能可能会显著下降。此算法不需要定义世界边界(world bounds)即可工作。PxBroadPhaseType::eMBPPhysX 3.3中引入的一种新算法。它是一种替代的粗检测(broad-phase)算法,当所有对象都在移动或插入大量对象时,它不会遇到与eSAP相同的性能问题。但是,当许多对象处于休眠状态时,其通用性能可能不如 eSAP,并且它要求用户定义世界边界(world bounds)才能工作。所需的粗检测(broad-phase)算法由PxSceneDesc结构中的PxBroadPhaseType枚举控制。

Regions of Interest


感兴趣的区域(Regions of Interest)是围绕粗检测(broad-phase)控制的体积空间中的世界空间AABB包围盒。这些区域中包含的对象由粗检测(broad-phase)正确处理。落在这些区域之外的对象将丢失所有碰撞检测。理想情况下,这些区域应覆盖整个游戏空间,同时限制覆盖的空白空间的数量。区域可以重叠,但为了获得最大效率,建议尽可能减少区域之间的重叠量。请注意,AABB 仅接触的两个区域不被视为重叠。例如,PxBroadPhaseExt::createRegionsFromWorldBounds helper function通过将给定的世界 AABB 细分为常规 2D 网格来创建许多非重叠区域边界。区域可以由PxBroadPhaseRegion 结构定义,也可以由分配给它们的用户数据定义。它们可以在场景创建时或在运行时使用 PxScene::addBroadPhaseRegion 函数进行定义。SDK 返回分配给新创建区域的句柄,稍后可以使用 PxScene::removeBroadPhaseRegion 函数删除区域。新添加的区域可能会重叠已存在的对象。如果设置了 PxScene::addBroadPhaseRegion 调用中的 populateRegion 参数,SDK 可以自动将这些对象添加到新区域。但是,此操作not cheap,并且可能会对性能产生很大影响,尤其是在同一帧中添加多个区域时。因此,建议尽可能禁用它。该区域将被创建为空,并且只会在创建区域后添加到场景中的对象填充,或者在updated时(即当它们移动时)使用先前存在的对象填充该区域。请注意,只有PxBroadPhaseType::eMBP需要定义区域。PxBroadPhaseType::eSAP 算法则不然。此信息在PxBroadPhaseCaps结构中捕获,该结构列出了每个粗检测(broad-phase)算法的信息和功能。此结构可以通过 PxScene::getBroadPhaseCaps 函数检索。有关当前区域的运行时信息可以使用 PxScene::getNbBroadPhaseRegionsPxScene::getBroadPhaseRegions 函数进行检索。区域的最大数量目前限制为 256 个。

Broad-phase Callback


可以在 PxSceneDesc 结构体中定义与粗检测相关(broad-phase-related)的事件的回调。当在超出指定的感兴趣区域(即"out of bounds")中发现对象时,将调用此PxBroadPhaseCallback对象。SDK 会禁用这些对象的碰撞检测。一旦对象重新进入有效区域,它就会自动重新启用。由用户决定如何处理越界对象。典型选项包括:

  • 删除对象
  • 让他们继续运动而不会发生碰撞,直到他们重新进入有效区域
  • 手动将他们传送回有效位置

Collision Filtering


在几乎所有应用程序中,除了"trivial"的应用程序之外,都需要免除某些对象对(pairs of objects)的相交性(interacting),或者以特定方式为交互对(interacting pair)配置 SDK 碰撞检测行为。在submarine sample中,如上所述,当潜艇接触水雷或水雷链条时,我们需要得到通知,以便我们可以将它们炸毁。crab中的AI还需要知道crab何时接触到高度场。在了解示例如何实现此目的之前,我们需要了解SDK filtering系统。由于过率潜在的交互对(interacting pair)发生在仿真引擎的最深处,并且需要应用于彼此靠近的所有对象对,因此它对性能特别敏感。实现它的最简单方法是始终为每个可能交互的对(interacting pair)调用回调函数,其中应用程序基于两个对象指针可以使用一些自定义逻辑(例如咨询其游戏数据库)确定该对是否应该进行交互。不幸的是,如果对于一个非常大的游戏世界来说,这会变得太慢,特别是如果碰撞检测处理发生在远程处理器(如GPU)或具有本地内存的其他类型的矢量处理器上,这些处理器必须暂停其并行计算,中断运行游戏代码的主处理器,并让它在继续之前执行回调。即使它要在CPU上执行,它也可能会在多个内核或超线程上同时执行,并且必须放置线程安全代码以确保对共享数据的并发访问是安全的。更好的做法是使用某种可以在远程处理器上执行的固定函数逻辑。这就是我们在 PhysX 2.x 中所做的 - 不幸的是,我们提供的基于组的简单过滤规则(simple group based filtering rules)不够灵活,无法涵盖所有应用程序。在3.0中,我们引入了一个着色器系统(shader system),它允许开发人员使用在矢量处理器上运行的代码实现任意规则系统(因此无法访问主内存中的任何最终游戏数据库(eventual game data base )),这比2.x固定函数过滤更灵活,但同样高效,还有一个完全灵活的回调机制,其中过滤器着色器调用能够访问任何应用程序数据的CPU回调函数, 以性能为代价 – 有关详细信息,请参阅 PxSimulationFilterCallback。最好的部分是,应用程序可以基于每对(per-pair)进行决策,以进行速度与灵活性的权衡。

让我们先看一下着色器系统:下面是由 SampleSubmarine 实现的filter shader

PxFilterFlags SampleSubmarineFilterShader(PxFilterObjectAttributes attributes0, PxFilterData filterData0,PxFilterObjectAttributes attributes1, PxFilterData filterData1,PxPairFlags& pairFlags, const void* constantBlock, PxU32 constantBlockSize)
{// let triggers throughif(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1)){pairFlags = PxPairFlag::eTRIGGER_DEFAULT;return PxFilterFlag::eDEFAULT;}// generate contacts for all that were not filtered abovepairFlags = PxPairFlag::eCONTACT_DEFAULT;// trigger the contact callback for pairs (A,B) where// the filtermask of A contains the ID of B and vice versa.if((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND;return PxFilterFlag::eDEFAULT;
}

SampleSubmarineFilterShader是一个简单的着色器函数,它是PxFiltering.h中声明的PxSimulationFilterShader原型的实现。shader filter function(如上称为 SampleSubmarineFilterShader)可能不引用函数的参数及其自己的局部堆栈变量以外的任何内存,因为该函数可以在远程处理器上编译和执行。SampleSubmarineFilterShader() 将用于所有彼此靠近的Shape对(pairs of shapes) - 更准确地说:对于在世界空间中发现AABB首次相交的所有Shape对。除此之外的所有行为都由 SampleSubmarineFilterShader() 返回的内容决定。SampleSubmarineFilterShader() 的参数包括两个对象的 PxFilterObjectAttributesPxFilterData,以及一个常量内存块。请注意,指向这两个对象的指针不会传递,因为这些指针引用计算机的主内存,并且正如我们所说,这可能不适用于着色器,因此指针不是很有用,因为取消引用它们可能会导致崩溃。PxFilterObjectAttributesPxFilterData旨在包含可以从指针中快速收集的所有有用信息。PxFilterObjectAttributes是32位数据,用于编码对象的类型:例如PxFilterObjectType::eRIGID_STATICPxFilterObjectType::eRIGID_DYNAMIC,甚至PxFilterObjectType::ePARTICLE_SYSTEM。此外,它还可以让您了解对象是kinematic的还是触发器。PhysX中的每个PxShapePxParticleBase对象都有一个类型为PxFilterData的成员变量。这是 128 位用户定义的数据,可用于存储与碰撞过滤(collision filtering)相关的应用程序特定信息。这是传递给每个对象的SampleSubmarineFilterShader() 的另一个变量。对于常量块。这是应用程序可以提供给着色器进行操作的每个场景的全局信息块。您将需要使用它来编码有关要过滤的内容和不过滤的内容的规则。最后,SampleSubmarineFilterShader() 还有一个 PxPairFlags 参数。这是一个输出,类似于返回值 PxFilterFlags,尽管用法略有不同。PxFilterFlags 告诉 SDK 它是否应该永久忽略该对 (eKILL),在重叠时忽略该对,但在过滤其中一个对象的相关数据更改时再次询问 (eSUPPRESS),或者在着色器无法决定时调用性能较低但更灵活的 CPU 回调(eCALLBACK)。PxPairFlags 指定了其他标志,这些标志代表simulate将来应针对此对执行的操作。例如,eNOTIFY_TOUCH_FOUND意味着当配对真正开始接触时通知用户,而不仅仅是潜在的。

让我们看看上面的着色器是做什么的:

// let triggers through
if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
{pairFlags = PxPairFlag::eTRIGGER_DEFAULT;return PxFilterFlag::eDEFAULT;
}

这意味着,如果任一对象是触发器,则执行默认触发器行为(通知应用程序有关触摸的开始和结束),否则在它们之间执行"默认"碰撞检测。

// generate contacts for all that were not filtered above
pairFlags = PxPairFlag::eCONTACT_DEFAULT;// trigger the contact callback for pairs (A,B) where
// the filtermask of A contains the ID of B and vice versa.
if((filterData0.word0 & filterData1.word1) && (filterData1.word0 & filterData0.word1))pairFlags |= PxPairFlag::eNOTIFY_TOUCH_FOUND;return PxFilterFlag::eDEFAULT;

这表示对于所有其他对象,请执行"默认"碰撞处理。此外,还有一个基于 filterDatas 的规则,用于确定我们要求触摸通知(touch notifications)的特定对。要理解这意味着什么,我们需要知道样本赋予 filterDatas 的特殊含义。

示例的需求非常基础,因此我们将使用非常简单的方案来处理它。该示例首先使用自定义枚举为不同的对象类型提供命名代码:

struct FilterGroup
{enum Enum{eSUBMARINE     = (1 << 0),eMINE_HEAD     = (1 << 1),eMINE_LINK     = (1 << 2),eCRAB          = (1 << 3),eHEIGHTFIELD   = (1 << 4),};
};

该示例通过将每个ShapePxFilterData::word0 分配给此筛选器组类型来标识每个Shape的类型。然后,它放置一个位掩码,指定每种类型的对象,当被 word0 类型的对象触摸到 word1 中时,这些对象应生成报告。每当创建Shape时,都可以在示例中执行此操作,但由于Shape创建封装在 SampleBase 中,因此在事后使用以下函数完成:

void setupFiltering(PxRigidActor* actor, PxU32 filterGroup, PxU32 filterMask)
{PxFilterData filterData;filterData.word0 = filterGroup; // word0 = own IDfilterData.word1 = filterMask;  // word1 = ID mask to filter pairs that trigger a// contact callback;const PxU32 numShapes = actor->getNbShapes();PxShape** shapes = (PxShape**)SAMPLE_ALLOC(sizeof(PxShape*)*numShapes);actor->getShapes(shapes, numShapes);for(PxU32 i = 0; i < numShapes; i++){PxShape* shape = shapes[i];shape->setSimulationFilterData(filterData);}SAMPLE_FREE(shapes);
}

这将设置属于传递的 actor 的每个ShapePxFilterDatas。以下是如何在 SampleSubmarine 中使用它的一些示例:

setupFiltering(mSubmarineActor, FilterGroup::eSUBMARINE, FilterGroup::eMINE_HEAD |FilterGroup::eMINE_LINK);
setupFiltering(link, FilterGroup::eMINE_LINK, FilterGroup::eSUBMARINE);
setupFiltering(mineHead, FilterGroup::eMINE_HEAD, FilterGroup::eSUBMARINE);setupFiltering(heightField, FilterGroup::eHEIGHTFIELD, FilterGroup::eCRAB);
setupFiltering(mCrabBody, FilterGroup::eCRAB, FilterGroup::eHEIGHTFIELD);

这个方案可能过于简单,无法在实际游戏中使用,但它显示了filter shader的基本用法,并且它将确保为所有有用的对(interesting pairs)调用SampleSubmarine::onContact()。在扩展函数 PxDefaultSimulationFilterShader 中提供了另一种基于组的过滤机制和源。而且,同样,如果这个基于着色器的系统太不灵活,请考虑使用PxSimulationFilterCallback提供的回调方法。

Aggregates


聚合(Aggregates)是actor的集合。聚合不提供额外的simulate或查询功能,但允许您告诉 SDK 一组actor将聚类在一起,这反过来又允许 SDK 优化其空间数据操作。一个典型的用例是布娃娃,由多个不同的actor组成。如果没有聚集体,这会产生与布娃娃中的Shape一样多的粗检测实体(broad-phase entries)。通常,将布娃娃在粗检测阶段表示为单个实体,并在必要时在第二个pass中执行内部重叠测试(internal overlap tests)会更有效。另一个潜在的用例是具有大量附加Shape的单个Actor

Creating an Aggregate


PxPhysics 对象创建聚合:

PxPhysics* physics; // The physics SDK objectPxU32 nbActors;     // Max number of actors expected in the aggregate
bool selfCollisions = true;PxAggregate* aggregate = physics->createAggregate(nbActors, selfCollisions);

目前,actor的最大数量限制为128个,为了提高效率,数量应尽可能少。如果永远不需要聚合的actor之间的碰撞检测,请在创建时禁用它们。这比使用场景过滤机制(scene filtering mechanism)更有效,因为它绕过了所有内部过滤逻辑。典型的用例是statickinematic actor的聚合。请注意,最大actor个数和自碰撞属性(self-collision attribute)都是不可变的。

Populating an Aggregate


actor添加到聚合中,如下所示:

PxActor& actor;    // Some actor, previously created
aggregate->addActor(actor);

请注意,如果 Actor 已属于某个场景,则调用将被忽略。将 Actor 添加到聚合,然后将聚合添加到场景中,或者将聚合添加到场景中,然后将 Actor 添加到聚合中。

要将聚合添加到场景中(在填充之前或之后):

scene->addAggregate(*aggregate);

同样,要从场景中移除聚合,请执行以下操作:

scene->removeAggregate(*aggregate);

Releasing an Aggregate


要释放聚合:

PxAggregate* aggregate;    // The aggregate we previously created
aggregate->release();

释放 PxAggregate 不会释放聚合的actors。如果 PxAggregate 属于某个场景,则 Actor 会自动重新插入到该场景中。如果您打算同时删除 PxAggregate 及其actors,则最有效的方法是先释放actor,然后在 PxAggregate 为空时释放它。

Amortizing Insertion


在一帧中向场景中添加多个对象可能是一项代价高昂的操作。布娃娃就是这种情况,如前所述,这是 PxAggregate 的良好候选者。另一种情况是局部碎片,其自碰撞(self-collisions)经常被禁用。要将对象插入粗检测结构(broad-phase structure)的成本摊销到多个阶段结构中,请在 PxAggregate 中生成碎片,然后从聚合中删除每个 Actor ,然后通过这些帧将其重新插入到场景中。

Trigger Shapes


Trigger Shapes在场景simulate中不起作用(尽管它们可以配置为参与场景查询)。相反,它们的作用是报告与另一种shape重叠。不会为相交性测试生成触点,因此触点报告不适用于Trigger Shapes。此外,由于触发器在simulate中不起作用,SDK 将不允许同时引发eSIMULATION_SHAPEeTRIGGER_SHAPE标志;也就是说,如果引发一个标志,则引发另一个标志的尝试将被拒绝,并且错误将传递到错误流。

SampleSubmarine中使用了Trigger Shapes来确定潜艇是否已经到达宝藏。在下面的代码中,表示宝藏的 PxActor 将其单独Shape配置为Trigger Shapes:

PxShape* treasureShape;
gTreasureActor->getShapes(&treasureShape, 1);
treasureShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
treasureShape->setFlag(PxShapeFlag::eTRIGGER_SHAPE, true);

与Trigger Shapes的相交性测试通过 PxSampleSubmarine 类(PxSimulationEventCallback 的子类)中的PxSimulationEventCallback::onTrigger 的实现在 SampleSubmarine 中报告:

void SampleSubmarine::onTrigger(PxTriggerPair* pairs, PxU32 count)
{for(PxU32 i=0; i < count; i++){// ignore pairs when shapes have been deletedif (pairs[i].flags & (PxTriggerPairFlag::eREMOVED_SHAPE_TRIGGER |PxTriggerPairFlag::eREMOVED_SHAPE_OTHER))continue;if ((&pairs[i].otherShape->getActor() == mSubmarineActor) &&(&pairs[i].triggerShape->getActor() == gTreasureActor)){gTreasureFound = true;}}
}

上面的代码循环访问涉及Trigger Shapes的所有重叠Shape对(all pairs of overlapping shapes)。如果发现宝藏已被潜艇触摸,则旗帜gTreasureFound为真。

Interactions


SDK 在内部为粗检测(broad-phase)报告的每个重叠对创建一个交互对象。这些对象不仅为成对碰撞的刚体创建,而且还为重叠的触发器对创建。一般来说,用户应该假设无论涉及对象的类型(刚体,触发器,布料等)以及所涉及的PxFilterFlag标志如何,都创建了此类对象。目前,每个Actor的此类交互对象限制为 65535 个。如果超过 65535 个交互涉及同一个Actor,则 SDK 会输出一条错误消息,并忽略额外的交互。

PhysX3.4文档(5) --Rigid Body Collision相关推荐

  1. PhysX3.4文档(6) --Rigid Body Dynamics

    Rigid Body Dynamics 在本章中,我们将介绍一些主题,一旦您熟悉了设置基本的刚体模拟世界,这些主题也很重要. Velocity 刚体的运动分为线性和角速度(linear and ang ...

  2. PhysX3.4文档(1) -- startup and shutdown

    PhysX3.4文档(1) --startup shutdown startup shutdown introduction 使用physx sdk的第一步是初始化一个全局对象.这些对象会在physx ...

  3. PhysX3.4文档(8) -- Advanced Collision Detection

    Advanced Collision Detection Tuning Shape Collision Behavior 用于产生接触的Shape会影响它们通过contacts(Contact poi ...

  4. PhysX3.4文档(15) -- Vehicles

    Vehicles Introduction PhysX对车辆的支持在3.x中得到了显着的重新设计.为了取代 NxWheelShape 类 2.8.x,已经开发出核心 PhysX SDK 和车辆仿真代码 ...

  5. PhysX3.4文档(7) -- Simulation

    Simulation Callback Sequence 最简单的模拟回调(simulation callbacks)类型是事件.使用回调,应用程序可以简单地侦听事件并根据需要做出反应,前提是回调遵守 ...

  6. PhysX3.4文档(2) --Threading

    Threading Introduction 本章介绍了在多线程应用程序中如何使用PhysX.主要有三个方面使用多线程: 如何在不产生竞争的情况下调用PhysX API进行读写 如何使用多线程加速模拟 ...

  7. PhysX3.4文档(11) -- GPU Rigid Bodies

    GPU Rigid Bodies Introduction GPU 刚体是 PhysX 3.4 中引入的一项新功能.它支持整个刚体管线特征集,但目前不支持铰接.GPU 加速刚体的状态可以使用与修改和查 ...

  8. PhysX3.4文档(9) -- Joints

    Joints Joint Basics 关节(Joints)限制了两个Actor相对于彼此移动的方式.关节的典型用途是模拟门铰链或character的肩膀.关节在 PhysX extensions l ...

  9. PhysX3.4文档(3) --Geometry

    Geometry introduction 这部分主要讨论Physx的几何类.geometry主要用来构建刚体的形状,刚体的形状主要用来作碰撞的触发和physx中的屏幕查询系统的量.Physx也提供独 ...

最新文章

  1. 2022-2028年中国抗菌玻璃行业市场研究及前瞻分析报告
  2. oracle驱动程序包的安装失败,Maven 、oracle的jdbc的jar包下载失败
  3. linux 下ab压力测试
  4. 《重新认识你自己》八:与真实的自我相处
  5. 《Neural network and deep learning》学习笔记(一)
  6. QT的QRegularExpressionValidator类的使用
  7. 在一个tomcat 里面 两个相同的项目不能同时运行??
  8. Apache Mahout:入门
  9. Python绘制直方图案例一则
  10. 参数过滤mongodb过滤查询键值
  11. 当我们在讨论机器学习时我们在说些什么?
  12. mysql排列组合实现_排列组合的实现
  13. 基于mysql+php的英语四六级过级成绩管理
  14. Scala入门小纸条(4)
  15. 企业中流砥柱:别让企业中层缺位
  16. linux的服务器查看流量,查看linux服务器流量的方法总结
  17. 网站下拉菜单,选择下拉后自动填充(图)
  18. .net Core 2.1 在 CentOS7下,运行含图片处理时发生异常,报The type initializer for ‘Gdip‘ threw an exception.异常
  19. 关于新工作展望及辞职的烦恼
  20. Subsonic 介绍

热门文章

  1. 【问题】RIDE 执行输出日志中文乱码(RIDE 1.7.4 running on Python 3.7.3)
  2. (转)windows 7 下cuda 9.0 卸载、cuda8.0 安装
  3. 影楼招php吗,影楼老是招收学徒 你知道为什么吗
  4. 生成图片验证码CodeUtils
  5. 百度Deep Voice 1 2 3阅读笔记
  6. 2d和3d cnn 解决医疗影像分析问题
  7. Linux WEB服务器集群在电子商务中的应用
  8. 【论文】2019年各大顶会神经关系抽取(NRE)优质论文整理分享
  9. Linux服务器被攻击了怎么办
  10. Android 开发架构-MVC MVP MVVM详解