PhysX3学习笔记 UserGuider——shapes&geometries简译

来源:互联网 发布:斯文禽兽59818 淘宝店 编辑:程序博客网 时间:2024/06/05 14:31

API原文请戳我

Shapes

Shapes描述了 Actor空间范围和碰撞性能。

他们在物理运算引擎用于三个地方:

1交叉测试,确定刚性物体的接触特性,

2例如光线投影Raycasts的场景查询测试,

3定义碰撞器体积——用于在其他形体与其相交时生成通知

Shapes属于引用计数,参见应用计数

每个形状包含PxGeometry的对象和一个PxMaterial的引用,在创建的时候必须被同时声明。

下面的代码创建了一个形状包含了球面几何和一个特定的材料:

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

PxRigidActor:CreateShape()方法和上面三行代码等效。

createShape的false参数通知SDK工具这个shape不会被其他的Actor所共享。当你有许多完全一样几何的Actor时,你可以使用共享来减少模拟所需要的内存。但是共享shapes有一个十分严重的限制,当一个被共享的shape被添加到Actor中之后,你不能够更新他的属性。


你能够通过制定shape的标记来随意的配置shape。一个Shape被缺省设置为:

  一个模拟形状(支持模拟期间迭代的联系)

  场景查询形状(支持场景查询)

  调试渲染下的可视化


当一个几何物体被规定为一个Shape之后,这个几何对象就被复制到shape之中。几何体被制定为一个shape时有一些限制,决定于shape的标识和Actor父对象的种类。

  三角网,高度地面和平板 集合体不支持附着在动态Actor上的模拟形状,除非动态actor被定义为运动学的。

  三角网和高度领域几何体不支持碰撞器shape


看下面的片段。

像下面一样吧shape从actor中分离出来。

myActor。detachShape(*shape)
note

之前Px的版本中release()被用于从actor中分离shape,并且摧毁它。这种release的用噶在Px3.3版本中被禁止并且不再会在以后版本中支持

模拟形状和场景查询形状

shapes会被单独设置去在场景测试和查询两者中同时或者单独合作。在默认情况下,一个形状会被两者分享。

下面的未完成的代码设置了一个PxShape的实例,因此他不再参与形状的交叉测试:

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

一个PxShape的实例能够被设置成参与两个形状之间的交叉测试

void disableShapeInContact(PxShape *shape){    shape->setFlag(PXShapeFlag::eSIMULATION_SHAPE,true);}
让PxShape的实例不能参与场景查询测试

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

最后的,一个PsShape的实例也可以被重新设置为可以参与场景测试

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

笔记

如果形状的actor的移动中名不能够被模拟器控制,例如,这个shape已经被仅仅用作场景查询,并且被手动移动,之后内存能够在禁用actor模拟器的时候被保存(查询PxActorFlag::eDISABLE_SIMULATION)

触发器形状

触发器器的形状在场景模拟器中毫无作用。相反的,他们的职责是汇报是否有两个形状重叠。

交叉中不会产生触体,结果是接触体并不能够被触发器器的shape获取。另外,因为触发器在模拟器中没有起作用,sdk并不会允许eSIMULATION_SHAPE eTRIGGER_SHAPE 的标识被同时标上。换言之,如果一个标识被标记了,之后要准备标记另一个的时候就会被静止,并且会输出一个错误信息。


触发器的形状被用在 SanpleSubmarine中,判断潜水艇是否触碰到了大陆。在下面的代码中代表了大陆PxActor有自己的配置为触发器shape的隐藏形状

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

触发器之间的重叠在本例中通过启用PxSimulationEventCallback::onTrigger被获取到。(这是PxSmpleSubmarine中的类,PxSimulationEventCallback的子类

void SampleSubmarine::onTrigger(PxTriggerPair* pairs, PxU32 count){    for(PxU32 i=0; i < count; i++)    {        // ignore pairs when shapes have been deleted        if (pairs[i].flags & (PxTriggerPairFlag::eDELETED_SHAPE_TRIGGER | PxTriggerPairFlag::eDELETED_SHAPE_OTHER))            continue;        if((&pairs[i].otherShape->getActor() == mSubmarineActor) && (&pairs[i].triggerShape->getActor() == gTreasureActor))        {            gTreasureFound = true;        }    }}
上面的代码在涉及触发器形状的重叠的两者间遍历。如果发现大陆碰到了潜水艇,标识就会被设置为真。


动力学 三角网格(平板,高度地面)

我们能够创建一个动力学的 PxRigidDynamic(他拥有一个三角网格)。如果这个模型拥有一个模拟器模型标识,这个actor一定是动力学的。如果你改变了标识使得不在模拟状态,你甚至可以选择动态学的标识。

为了建立动力学三角网格

PxRigidDynamic *meshActor =getPhysics().createRigidDynamic(PxTransform(1.0f));PxShape *meshShape;if(meshActor){    meshActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC,true);    PxTriangleMeshGeomtry triGeom;    triGeom.triangleMesh = triangleMesh;        meshShape = meshActor->createShape(triGeom, defaultMaterial);        getScene().addActor(*meshActor);        PxConvexMeshGeometry convexGeom = PxConvexMeshGeometry(convexBox);        convexShape = meshActor->createShape(convexGeom,defaultMaterial);        convexShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);}// 改变为动力学meshShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);convexShape->setFlag(PxShapeFlag::eSIMULATION_SHAPE, true);meshActor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, false);


几何体

PxGeometry类定义了一个拥有固定位置和方向的立体或者表面。典型的,当在模型或者场景查询中被使用是,一个变幻解释了几何帧。

对于主要对象,例如凸起网格,三角网格或者是高度地面,Px允许多重几何体引用单网格,并支持单实例缩放。

note

每一个网格都是引用技术(巴拉巴拉...


球体

PxSphereGeometry有一个属性指定,半径,并且中心在原点。

盒子

(这部分太繁杂,稍后补全..)

高度地形

如名字,地心可以用网格采样的高度值来描述

PxHeightFieldSample *samples = (PxHeightFieldSampel*)alloc(sizeof(PxHeightFieldSample)*(numRows*numCols));
每个样本(方格子)都有一个16位的整数值和2个材质(一个方格划分成2个三角面)以及一个镶嵌的标识。

../_images/heightFieldFormat_S16_TM.png

标识和材质涉及到下方的单元,顶点,沿对角线分割的三角形和三角形的材质。

这是一种特殊的已经定义了的材质,PxHeightFieldMaterial::eHOLE. 说明了高度地形的山洞?如果你用float型描述高度(也木有关系?)



棋盘标识结果
0,0,0
0,0,0
0,0,0
../_images/heightfieldTess1.png
1,1,1
1,1,1
1,1,1
../_images/heightfieldTess2.png
0,1,0
1,0,1
0,1,0
../_images/heightfieldTess3.png

为了告诉系统各个方向的高度取样,使用一个描述者来实例化PxHeighField对象:

PxHeightFieldDesc hfDesc;hfDesc.format             = PxHeightFieldFormat::eS16_TM;hfDesc.nbColumns          = numCols;hfDesc.nbRows             = numRows;hfDesc.thickness          = -10.0f;hfDesc.samples.data       = samples;hfDesc.samples.stride     = sizeof(PxHeightFieldSample);PxHeightField* aHeightField = theCooking->createHeightField(hfDesc, thePhysics->getPhysicsInsertionCallback());

为了避免使用高昂的持续碰撞检测,需要制定一个厚度。厚度在y轴扩展了碰撞体积,使得渗入地下的物体(不出现在表面)不会穿透。考虑到每一个与地形碰撞的物体,为了避免穿透,厚度必须包含那个最大物体的尺寸。

高度地形对象需要创建几何体和模型:

pxHeightFieldGeometry hfGeom(aHeightField,pxMeshGeometryFlags(),heightScale,rowScale,colScale);PxShape *aHeightFieldShape = aHeightFiledActor->createShape(hGeom,aMaterialArray,nbMaterials);

排列大小告诉系统相关方向的采样点之间距离有多远,高度值也可以使用float型描述。

c这里使用reateShape()的一个变体,制定了材料高度的组数,将索引材料的每一个单元都用来解决和单元件的碰撞。也可以用他的单一变体实例取代,但是高度地形的材质目录都必须是一个单值或者是特殊值eHole。

生成接触

HeightFiled的碰撞产生于另一个模型包含在在他的垂直体积重(体积涵盖了表面和厚度)例如,如果一个物体相交于高度地形的一条边而不是表面,那么只会产生指向表面的接触信息。考虑这个有洞的高度地形例子。

../_images/heightfieldContactGen.png

在地形边界上三角形边的碰撞信息能够使用PxHeightFieldFlag::eNo_BOUNDARY_EDGES标识来禁用,使得多个heightfeild模型边缘碰撞更加有效。



三角网格   我已经脑死亡,这个部分明天补全


0 0
原创粉丝点击