您的位置:首页 > 其它

ode在大型mmo场景中的应用

2012-08-30 07:05 330 查看
http://blog.csdn.net/fuzb/article/details/2306693





1)ode概念

刚体Rigidbodies

<!--[if!supportLists]-->l<!--[endif]-->属性properties

一个刚体从模拟的角度说具有各种属性,

有些属性随时间而变化://随时间而变化的属性

●物体参照点的坐标顶点(x,y,z),该点必须是此物体的重心。//Positionvector(x,y,z)

●参照点的线性速度,一个矢量(vx,vy,vz)//Linearvelocity(vx,vy,vz).

●物体的方向,代表物体的quaternion(qs,qx,qy,qz)或者一个3X3的旋转矩阵


//aquaternion(qs,qx,qy,qz)ora3x3rotationmatrix.

●用来描述随时间变化的方向的变化量的角速度矢量(wx,wy,wz)

//Angularvelocityvector(wx,wy,wz)

其他物体属性常常是固定的://固定的属性

●物体的质量//Mass

●参照点物体的质心的位置,在现在的方案中质心必须与参照点物体的位置一致,即与物体的position坐标一致.//thecenterofmass

●Inertiamatrix描述物体的质量是如何分存于重心的

注意:物体的形状Shape不是动态属性(insofar除外),只有在碰撞检验的时候才关心物体的形状这一细节



<!--[if!supportLists]-->l<!--[endif]-->坐标系统

每个物体都内含一个(x,y,z)坐标系统,物体(Body)随它而移动和旋转。

这个坐标系统以物体的重心为原点,在ode中,部分值是相对于物体坐标系统的,其它的相对于全局坐标系统。

3。2。1岛和物体失效

物体(Bodies)”通过“关节(joints)”而联系在一起,一个物体“岛(island)”是一组不能分开的物体-换种说法就是每个物体在模拟时岛内的物体是连接在一起的

在“世界”的模拟步中每个“岛”是作为独立物体对待的,认识到这点非常重要,如果在模拟时有N个相似的“岛”,那么它的时间复杂度为O(N)。

每个物体可以被设置为“有效”enabled和“无效”disabled,无效的物体被有效地“关掉”,在每个模拟步中无须更新状态。当发现物体不运动或与模拟无关时,将物体设置为无效是一个非常有效的提高计算速度的方法。

如果在一个岛内有若干个物体被设为有效时,则岛内所有物体在下一个模拟步中将变为有效。要使一个岛无效必须先让岛内的物体均无效才行。如果一个无效的岛接触到另一个有效的物体,则整个岛将有效,就象一个关节将一个有效物体连接到岛上一样。



3。3综合Integration

按时间模拟刚体系统的过程被称为整合,每个整合步按当前时间和步进时间agivenstepsize进行,从而调节每一个新时间的物体状态。



3。4力的聚集Forceaccumulators

在每个整合步之间用户可以调用函数来给刚体施加力forces,这些力将合起来成为“力聚集”作用于刚体对象之上。当下一个整合步发生时,所作用与物体上的力合在一起推动物体。每一个整合步后力聚集将变为零。Theseforcesareaddedto"forceaccumulators"intherigidbodyobject.When
thenextintegratorstephappens,thesumofalltheappliedforceswillbeusedtopushthebodyaround.Theforcesaccumulatorsaresettozeroaftereachintegratorstep.



3。5联结和约束Jointsandconstraints

常见的有ballandsocket,hinge,slider约束.

Joints是用来连接body的,constraints用来描述这种关系

Eachtimetheintegratortakesastepallthejointsareallowedtoapply
constraintforcestothebodiestheyaffect.Theseforcesarecalculatedsuchthatthebodiesmoveinsuchawaytopreserveallthejointrelationships.任何时候整合系统将根据力聚集计算所有关节的步进,它同时保持所有的节点关联。///翻译得真烂

3。6联结组Jointgroups

3。7联结错误和错误消减参数(ERP)Jointerrorandtheerrorreductionparameter(ERP)

当一个联结关联两个物体时,物体需要处在合理的位置和方向上。然而有可能物体所处位置是联结不能匹配。这种联结错误在两中情况下发生:

1、如用户给一个物体设置了错误的位置/方向,而另一个物体的不匹配。

2、在模拟是,物体从他们的位置移位了。(见图)

以下是减小联结错误的机制:在每模拟步中对物体施加特殊的力以使之回到正确的位置。这个力有erroreductionparameter来控制,值在(0-1)间。

ERP指出在下一个模拟步中联结错误须调整的比例。如果ERP=0则不调整,物体最终将飘离模拟过程。如果ERP=1则模拟将在下一个模拟步中尽力修正所有的错误。然而将ERP设置为1并不推荐,在很多情况下并不是每个联结错误都需要修正的,建议设置ERP为0.1-0.8,默认为0.2。

3.8柔约束和约束力混合(CFM)Softconstraintandconstraintforcemixing(CFM)

自然的大多数约束事“硬的”,这就意味着这样的约束描述条件将永远不不能违反,举个例子,球必须始终在soket种,hinge的两给部分必须始终对齐的。在实际的约束中可能被无意识的错误的介入到系统中而违反,但是ERP可以更正这些错误。

也有一些约束是软的,比如说thecontactconstraintthatpreventscollidingobjectsfrompenetratingis
hardbydefault,soitactsasthoughthecollidingsurfacesaremadeofsteel.Butitcanbemadeintoa
softconstrainttosimulatesoftermaterials,therebyallowing
somenatural
penetrationofthetwoobjectswhentheyareforcedtogether.

Therearetwoparametersthatcontrolthedistinctionbetweenhardandsoftconstraints.Thefirstistheerrorreductionparameter(ERP)thathasalreadybeenintroduced.Thesecondistheconstraintforcemixing(CFM)value,thatisdescribedbelow.

3.8.1.ConstraintForceMixing(CFM)数学理论现在不管

3.8.2.HowToUseERPandCFM

如果CFM设置成0,约束将很牢固,如果CFM设置成0,约束将很牢固,如果CFM设置为一个正值,可能将违反约束的“推动它pushingonit”(例如:对于对接连接将使两个物体连到一起)。换句话说约束将是柔的,而且软度随CFM变量的增大而更柔。

注意:将cfm设置为负值将带来不好的影响,如不稳定,请不要这样做。



通过调整ERP和CFM我们能达到各种效果。如你可以模拟弹簧约束,将两个物体用一个弹簧联系。或者你可以模拟更柔性的约束。无需震动。事实上,erp和cmf可以用来完成任何想要的弹簧和减震系数的效果。如果你的弹性系数是Kp减震系数是Kd,则相应的ODE系数为ERP=hKp/(hKp+Kd)cfm=1/(hKp+Kd)其中h是setpsize。这些值将完成弹簧减震系统模拟的一样的效果

增大DFM,特别是全局的CFM将减少模拟中的算术错误。如果系统是near-singular的,则能够显著的提高稳定性。事实上如果系统是mis-behaving的,要做的第一件事就是增大全局的CFM。

3.9.Collisionhandling

bodies之间的碰撞或bodies和静态环境之间的碰撞按以下方法处理:

1、在每个模拟步之前,用户调用碰撞检查(collsiondetection)函数去决定事什么碰上什么。这些函数将返回一个contactpoint的列表(list),每个(接触点)contactpoint指明一个空间位置,一个曲面法向量(normalvector),和一个有效深度(penetrationdepth)

2、系统将为每一个接触点创建一个特定的接触联结(contactjoint)。一些关于联结的额外信息将给contactjiont,例如当前接触面的摩擦力,以及强弱程度以及其他各种属性

3、contactjoints被放入到一个joint“group”,这样以允许非常快速的从系统里添加和移除,模拟速度随着接触数量的上升而下降,所以有不同的策略用来限制接触点的数量

4、一个simulationstep发生

5、将所用的contactjoints重系统中移除。

注意内建的碰撞检测函数并不一定要使用,其他的碰撞检测库也能使用,只要它能提供正确的接触点的信息。//
我们实际在网络游戏中用物理系统的话就必须结合具体的场景来搞




3.10.Typicalsimulationcode

Createadynamicsworld.
Createbodiesinthedynamicsworld.
Setthestate(positionetc)ofallbodies.

Createjointsinthedynamicsworld.
Attachthejointstothebodies.
Settheparametersofalljoints.
Createacollisionworldandcollisiongeometryobjects,asnecessary.

Createajointgrouptoholdthecontactjoints.

Loop:

Applyforcestothebodiesasnecessary.

Adjustthejointparametersasnecessary.

Callcollisiondetection.
Createacontactjointforeverycollisionpoint,andputitinthecontactjointgroup.

Takeasimulationstep.
Removealljointsinthecontactjointgroup.

Destroythedynamicsandcollisionworlds.

3.11.Physicsmodel

3.11.1.FrictionApproximation

ODE'sfrictionmodelsareapproximationstothefrictioncone,forreasonsofefficiency.Therearecurrentlytwoapproximationstochosefrom:

Themeaningofmuischangedsothatitspecifiesthemaximumfriction(tangential)forcethatcanbepresentatacontact,ineitherofthetangentialfrictiondirections.Thisisrathernonphysicalbecauseitisindependentofthenormalforce,
butitcanbeusefulanditisthecomputationallycheapestoption.Notethatinthiscase
muisaforcelimitanmustbechosenappropriatetothesimulation.
Thefrictionconeisapproximatedbyafrictionpyramidalignedwiththefirstandsecondfrictiondirections[Ireallyneedapicturehere].Afurtherapproximationismade:firstODEcomputesthenormalforcesassumingthatallthecontactsarefrictionless.
Thenitcomputesthemaximumlimitsfmforthefriction(tangential)forcesfrom

4.DataTypesandConventions

4.1.Thebasicdatatypes

dReal.dVector3,dVector4,dMatrix3,dMatrix4,dQuaternion.

4.2.ObjectsandIDs

Therearevariouskindsofobjectthatcanbecreated:

dWorld-adynamicsworld.一个仿真世界
dSpace-acollisionspace.一个碰撞世界
dBody-arigidbody.一个刚体
dGeom-geometry(forcollision).几何体(为了碰撞)
dJoint-ajoint节点
dJointGroup-agroupofjoints.节点组

FunctionsthatdealwiththeseobjectstakeandreturnobjectIDs.TheobjectIDtypesaredWorldID,dBodyID,etc.

4.3.Argumentconventions

4.4.CversusC++

4.5.Debugging

5.World

Theworldobjectisacontainerforrigidbodiesandjoints.Objectsindifferentworldscannotinteract,forexamplerigidbodiesfromtwodifferentworldscannotcollide.
Mostapplicationswillonlyneedoneworld.
dWorldIDdWorldCreate();
Createanew,emptyworldandreturnitsIDnumber.

voiddWorldDestroy(dWorldID);
Destroyaworldandeverythinginit.Thisincludesallbodies,andalljointsthatarenotpartofajointgroup.Jointsthatarepartofajointgroupwillbedeactivated,andcanbedestroyedbycalling,forexample,
dJointGroupEmpty.

voiddWorldSetGravity(dWorldID,dRealx,dRealy,dRealz);
voiddWorldGetGravity(dWorldID,dVector3gravity);
Setandgettheworld'sglobalgravityvector.Theunitsarem/s/s,soEarth'sgravityvectorwouldbe(0,0,-9.81),assumingthat+zisup.Thedefaultisnogravity,i.e.(0,0,0).

voiddWorldSetERP(dWorldID,dRealerp);
dRealdWorldGetERP(dWorldID);
SetandgettheglobalERPvalue,thatcontrolshowmucherrorcorrectionisperformedineachtimestep.Typicalvaluesareintherange0.1--0.8.Thedefaultis0.2.

voiddWorldSetCFM(dWorldID,dRealcfm);
dRealdWorldGetCFM(dWorldID);
SetandgettheglobalCFM(constraintforcemixing)value.Typicalvaluesareintherange10-9--1.Thedefaultis10-5ifsingleprecisionisbeingused,or10-10ifdoubleprecisionisbeingused.

void
dWorldSetAutoDisableFlag(dWorldID,intdo_auto_disable);
intdWorldGetAutoDisableFlag(dWorldID);
voiddWorldSetAutoDisableLinearThreshold(dWorldID,dReallinear_threshold);
dRealdWorldGetAutoDisableLinearThreshold(dWorldID);
voiddWorldSetAutoDisableAngularThreshold(dWorldID,dRealangular_threshold);
dRealdWorldGetAutoDisableAngularThreshold(dWorldID);
voiddWorldSetAutoDisableSteps(dWorldID,intsteps);
intdWorldGetAutoDisableSteps(dWorldID);
voiddWorldSetAutoDisableTime(dWorldID,dRealtime);
dRealdWorldGetAutoDisableTime(dWorldID);
Setandgetthedefaultauto-disableparametersfornewlycreatedbodies.See
section6.5foradescriptionoftheauto-disablefeature.Thedefaultparametersare:

AutoDisableFlag=disabled
AutoDisableLinearThreshold=0.01
AutoDisableAngularThreshold=0.01
AutoDisableSteps=10
AutoDisableTime=0

voiddWorldImpulseToForce(dWorldID,dRealstepsize,
dRealix,dRealiy,dRealiz,dVector3force);
Ifyouwanttoapplyalinearorangularimpulsetoarigidbody,insteadofaforceoratorque,thenyoucanusethisfunctiontoconvertthedesiredimpulseintoaforce/torquevectorbeforecallingthedBodyAdd...function.
Thisfunctionisgiventhedesiredimpulseas(ix,iy,iz)andputstheforcevectorinforce.Thecurrentalgorithmsimplyscalestheimpulseby1/stepsize,wherestepsizeisthestepsizeforthe
nextstepthatwillbetaken.
ThisfunctionisgivenadWorldIDbecause,inthefuture,theforcecomputationmaydependonintegratorparametersthataresetaspropertiesoftheworld.

voiddCloseODE();
ThisdeallocatessomeextramemoryusedbyODEthatcannotbedeallocatedusingthenormaldestroyfunctions,e.g.
dWorldDestroy.YoucanusethisfunctionattheendofyourapplicationtopreventmemoryleakcheckersfromcomplainingaboutODE.

5.1.SteppingFunctions

voiddWorldStep(dWorldID,dRealstepsize);

voiddWorldQuickStep(dWorldID,dRealstepsize);


QuickStep非常适合与对象堆栈特别是当在使用auto-disable属性。无论如何,它对near-singular系统而言具有非常差的精度。near-singular系统会在使用高摩擦contact,motors,或确定精度near-singular系统是发生。举例:一个多腿的机器人站在地上是可能就是near-singular。

这里有些方法来克服QuickStep不精确问题:

增大CFM。

减小你系统种contacts的数量(如:为机器人或生物使用最小数量的脚)。

不要过多的为contacts使用摩擦friction。

适当的使用contactslip。

避免运动学上的循环(尽管kinematicloops对有腿生物是不可避免的)。

不要对motor使用过大的力strength。

用基于力的motor来代替基于速度的motor。Useforce-basedmotorsinsteadofvelocity-basedmotors.

增加QuickStepiterations的数量也有一点点帮助,但是但你的系统是一个真正的nearsingular时没多大帮助。


5.2.ContactParameters

voiddWorldSetContactMaxCorrectingVel(dWorldID,dRealvel);

dRealdWorldGetContactMaxCorrectingVel(dWorldID);


设置得到contacts允许产生的最大的正确速度。缺省时无穷大,即没限制。减小这个数值可以帮助防止"popping"ofdeeplyembeddedobjects。

voiddWorldSetContactSurfaceLayer(dWorldID,dRealdepth);

dRealdWorldGetContactSurfaceLayer(dWorldID);

设置得到所有几何物体的表面深度。contact按给定的允许沉入物体表面。缺省的值为0,可以增大一点点如0.001来帮助防止物体接触时不停跳动的问题(jitteringproblems)。


6.RigidBodyFunctions

6.1.CreatingandDestroyingBodies


dBodyIDdBodyCreate(dWorldID);
Createabodyinthegivenworldwithdefaultmassparametersatposition(0,0,0).ReturnitsID.

voiddBodyDestroy(dBodyID);
Destroyabody.Alljointsthatareattachedtothisbodywillbeputintolimbo(i.e.unattachedandnotaffectingthesimulation,buttheywillNOTbedeleted).

6.2.Positionandorientation

voiddBodySetPosition(dBodyID,dRealx,dRealy,dRealz);

voiddBodySetRotation(dBodyID,constdMatrix3R);

voiddBodySetQuaternion(dBodyID,constdQuaternionq);

voiddBodySetLinearVel(dBodyID,dRealx,dRealy,dRealz);

voiddBodySetAngularVel(dBodyID,dRealx,dRealy,dRealz);

constdReal*dBodyGetPosition(dBodyID);

constdReal*dBodyGetRotation(dBodyID);

constdReal*dBodyGetQuaternion(dBodyID);

constdReal*dBodyGetLinearVel(dBodyID);

constdReal*dBodyGetAngularVel(dBodyID);


这些函数设置或返回物体的位置,旋转,线速度和角速度。在设置了一组物体后,如果在新的设置中与当前的连接/约束不一致的话,摹拟的结果将变的不明确。当返回时,返回的是指向内部数据结构的一个指针,所以当做任何改变时这些改变会影响到物体.

dBodyGetRotation返回一个4x3旋转矩阵



6.3.Massandforce质量和力

voiddBodySetMass(dBodyID,constdMass*mass);

voiddBodyGetMass(dBodyID,dMass*mass);



voiddBodyAddForce(dBodyID,dRealfx,dRealfy,dRealfz);

voiddBodyAddTorque(dBodyID,dRealfx,dRealfy,dRealfz);

voiddBodyAddRelForce(dBodyID,dRealfx,dRealfy,dRealfz);

voiddBodyAddRelTorque(dBodyID,dRealfx,dRealfy,dRealfz);

voiddBodyAddForceAtPos(dBodyID,dRealfx,dRealfy,dRealfz,

dRealpx,dRealpy,dRealpz);

voiddBodyAddForceAtRelPos(dBodyID,dRealfx,dRealfy,dRealfz,

dRealpx,dRealpy,dRealpz);

voiddBodyAddRelForceAtPos(dBodyID,dRealfx,dRealfy,dRealfz,

dRealpx,dRealpy,dRealpz);

voiddBodyAddRelForceAtRelPos(dBodyID,dRealfx,dRealfy,dRealfz,

dRealpx,dRealpy,dRealpz);


Addforcestobodies(absoluteorrelativecoordinates).Theforcesareaccumulatedontoeachbody,andtheaccumulatorsarezeroedaftereachtimestep.
The...RelForceand...RelTorquefunctionstakeforcevectorsthatarerelativetothebody'sownframeofreference.
The...ForceAtPosand...ForceAtRelPosfunctionstakeanextrapositionvector(inglobalorbody-relativecoordinatesrespectively)thatspecifiesthepointatwhichtheforceisapplied.Allotherfunctionsapplytheforceatthecenterof
mass.
给物体加力(绝对/相对坐标)。力被聚集到每一个物体上,当经过一个时间步长时力集聚将变为0.

...RelForceand...RelTorquefunctions力向量将相对于物体自已的坐标系统。

...ForceAtPosand...ForceAtRelPos在一个外部点施加一个力(在全局或物体相对坐标系),其它函数都是作用于物体的质心的。

constdReal*dBodyGetForce(dBodyID);

constdReal*dBodyGetTorque(dBodyID);

返回力聚集和扭矩向量,返是一个指向3个dReal的数组指针,它是指向内部结构的,所以对它的改变会影响到刚体。

voiddBodySetForce;(dBodyIDb,dRealx
,dRealy,dRealz)

voiddBodySetTorque;(dBodyIDb,dRealx,dRealy,dRealz)

设置物体的力和扭矩向量,它可以在物体有效前将其力和扭矩向量置为0,

设定本文力和转矩聚积矢量。在他们被使恢复现役之前,这大概是有用为移除的本文对准零位力和转矩,在增加力的功能被拜访他们的外壳中当他们被移除的时候。



6.4.Utility

6.5.AutomaticEnablingandDisabling

每个body可以被启用和禁用。启用的body参与模拟,而禁用的body被关闭,而且在一个simulationstep种不会更新状态。新的body创建时始终时启用状态。一个禁用的body通过joint联结到一个启用物体上后在下一个simulationstep时自动被重启用

被禁用body不消耗CPU时间,因此要提高速度就要当物体处于rest时disabled掉。这个事情可以交给auto-disabled特性自动处理。

如果一个body将auto-disable标志打开,当它空闲了一个给定的模拟步时时它将自动的被disabled。

它也可以通过给定一个模拟时间来时状态处于idle空闲。

当一个body的线速度和角速度低于一个给定极限值时将被认为时空闲的。因而没个body有5个auto-disabled参数:一个enabled标志,一个空闲步数,一个空闲时间,一个线/角速度的阈值。新创建的body的这些参数从world上得到。

一下时设置和得到body的enable/disable参数的函数。

voiddBodyEnable(dBodyID);

voiddBodyDisable(dBodyID);

手动的启用禁用body。注意一个禁用的body通过joint联结到一个启用物体上后在下一个simulationstep时自动被重启用。

intdBodyIsEnabled(dBodyID);如果一个body被enabled返回1时否则返回0。

voiddBodySetAutoDisableFlag(dBodyID,intdo_auto_disable);

intdBodyGetAutoDisableFlag(dBodyID);

设置和得到body的auto-disable标志。如果一个auto-disable非零则body将在idle了足够长的时间后自动disabled。

voiddBodySetAutoDisableLinearThreshold(dBodyID,dReallinear_threshold);

dRealdBodyGetAutoDisableLinearThreshold(dBodyID);

linear_threshold设为无穷大dInfinity时将不考虑线速度因素。

voiddBodySetAutoDisableAngularThreshold(dBodyID,dRealangular_threshold);

dRealdBodyGetAutoDisableAngularThreshold(dBodyID);

angular_threshold设为无穷大dInfinity时将不考虑角速度因素。

voiddBodySetAutoDisableSteps(dBodyID,intsteps);

intdBodyGetAutoDisableSteps(dBodyID);

设steps为零时不考虑该因素

voiddBodySetAutoDisableTime(dBodyID,dRealtime);

dRealdBodyGetAutoDisableTime(dBodyID);

设time为零时不考虑该因素

voiddBodySetAutoDisableDefaults(dBodyID);

从world那里得到缺省的auto-disable参数

6.6.MiscellaneousBodyFunctions

voiddBodySetData(dBodyID,void*data);

void*dBodyGetData(dBodyID);

设置和得到body的用户数据指针user-datapointer.



voiddBodySetFiniteRotationMode(dBodyID,intmode);

这个函数时用来控制每step中更新body的orientation的方式。mode可以是:

0:“infinitesimal”无穷小。这是计算速度最快的方式,但是当body高速转动是会偶尔导致不精确,特别是这些bodiesjoinedto其他bodies。这是body创建时的缺省值。

Thisfunctioncontrolsthewayabody'sorientationisupdatedateachtimestep.Themodeargumentcanbe:

1:“finite”,这是一个比较昂贵的计算方式,但在高速转动时会更加精确。注意高速转动可以导致很多种类型的计算错误,它只是可以解决其中的一个错误。

intdBodyGetFiniteRotationMode(dBodyID);返回当前的mode(0or1).

voiddBodySetFiniteRotationAxis(dBodyID,dRealx,dRealy,dRealz);

设置body的有限旋转轴,只有当用了finiterotationmode1时才有效,如果轴是(0,0,0)fullfiniterotationsareperformedonthebody。如果这个轴不是零,body

Ifthisaxisisnonzero,thebodyisrotatedbyperformingapartialfiniterotationalongtheaxisdirectionfollowedbyaninfinitesimalrotationalonganorthogonaldirection.

××××××

这能减轻body快速旋转导致的确定错误源的错误。例如,一个车的轮子转的很快时,你可以调用这个函数,用车轮hingeaxis作为参数来提高其性能。Thiscanbeusefultoalleviatecertainsourcesoferrorcausedbyquicklyspinningbodies.

voiddBodyGetFiniteRotationAxis(dBodyID,dVector3result);返回这个轴

intdBodyGetNumJoints(dBodyIDb);返回与这个bodyjoint的body数

Returnthenumberofjointsthatareattachedtothisbody.

dJointIDdBodyGetJoint(dBodyID,intindex);通过索引返回与这个body相关的joints,索引从0ton-1,n是通过dBodyGetNumJoints得到的。

voiddBodySetGravityMode(dBodyIDb,intmode);

intdBodyGetGravityMode(dBodyIDb);

设置和得到body是不是受world的重力加速度的影响。如果mode为非零,受影响,为零不受。新建的body总是受影响的。



7.JointTypesandJointFunctions

7.1.CreatingandDestroyingJoints

7.2.MiscellaneousJointFunctions

7.3.Jointparametersettingfunctions

7.3.1.BallandSocket

<!--[if!vml]--><!--[endif]-->

voiddJointSetBallAnchor(dJointID,dRealx,dRealy,dRealz);

voiddJointGetBallAnchor(dJointID,dVector3result);

voiddJointGetBallAnchor2(dJointID,dVector3result);

7.3.2.Hinge

<!--[if!vml]--><!--[endif]-->
voiddJointSetHingeAnchor(dJointID,dRealx,dRealy,dRealz);

voiddJointSetHingeAxis(dJointID,dRealx,dRealy,dRealz);

……

7.3.3.Slider

<!--[if!vml]--><!--[endif]-->

voiddJointSetSliderAxis(dJointID,dRealx,dRealy,dRealz);

voiddJointGetSliderAxis(dJointID,dVector3result);

dRealdJointGetSliderPosition(dJointID);

dRealdJointGetSliderPositionRate(dJointID);

7.3.4.Universal


<!--[if!vml]--><!--[endif]-->

voiddJointSetUniversalAnchor(dJointID,dRealx,dRealy,dRealz);

voiddJointSetUniversalAxis1(dJointID,dRealx,dRealy,dRealz);

voiddJointSetUniversalAxis2(dJointID,dRealx,dRealy,dRealz);

……

7.3.5.Hinge-2

<!--[if!vml]--><!--[endif]-->

7.3.6.Fixed

voiddJointSetFixed(dJointID);

7.3.7.Contact

<!--[if!vml]--><!--[endif]-->

7.3.8.AngularMotor

<!--[if!vml]--><!--[endif]-->

7.4.General

7.5.Stopandmotorparameters

7.5.1.ParameterFunctions

7.6.SettingJointTorques/ForcesDirectly

8.StepFast

8.1.WhentouseStepFast1

8.2.WhenNOTtouseStepFast1

8.3.Howitworks

8.4.ExperimentalUtilitiesincludedwithStepFast1

8.5.API

9.SupportFunctions

9.1.Rotationfunctions

9.2.Massfunctions

9.3.Mathfunctions

9.4.Errorandmemoryfunctions

10.CollisionDetection

ODE有两个主要的组件:一个动态的仿真引擎和一个碰撞检测引擎。各个body的形状信息shape给到的碰撞引擎。每一个模拟步它将给出那些物体相接触,并将这些信息用接触点contactpoint的形式传递给用户。用户就可以按照这些点的信息在body间创建contactjoints。使用ODE的碰撞检测是可选项--如果可以通过其他的碰撞检测系统来得到正确的contact信息的话。

10.1.Contactpoints


structdContactGeom{

dVector3pos;//contactposition

dVector3normal;//normalvector

dRealdepth;//penetrationdepth

dGeomIDg1,g2;//thecollidinggeoms

};

协定是,如果body1是沿着法向量移动一段深度(或者同样的body2沿着法向量的反方向移动一段深度)则contactdepth减为零。这就意味着法向量指入body1。

在现实生活中,两个body间的接触是个复杂的问题。用接触点来表示只是个近似的方法。接触“片”或接触“面”可能更确切些,但是用这样的东西来表现对于快速仿真来说是个挑战。

每一个接触点模拟中都将降低速度,因此有时因为速度的原因我们被迫的忽略接触点。例如,当两个盒子相碰为了正常表现这种状态有许多接触点需要表示出来,但是我们可能只选择关键的3个。

10.2.Geoms

几何体对象(或geoms)是碰撞系统中的基本对象。

在刚体仿真中使用碰撞引擎,可置位的geoms与刚性body对象联系在一起。这就允许碰撞引擎可以从bodies上得到geoms的位置和方向。注意geoms和bodies的区别是geoms具有几何属性(尺寸,形状,位置和方向)但是没有动态属性(如速度和质量),一个body和一个geom联系再一起表示出了仿真对象的全部属性。

10.3.Spaces

Aspaceisanon-placeablegeomthatcancontainothergeoms.Itissimilartotherigidbodyconceptofthe``world'',exceptthatitappliestocollisioninsteadofdynamics.

space对象的存在使得碰撞检测加快,没有spaces,你可能在你的仿真中要通过调用dCollide来从每对geoms中获得接触点来创建contacts。N个geoms的复杂度是o(N^2),这是非常昂贵的计算。

spaces能够容纳其他的spaces。这是对划分一个碰撞环境到几个层次来进一步优化碰撞检测速度是非常有效。下面将有更细节的描述。

10.4.Generalgeomfunctions

10.5.Collisiondetection

一个碰撞检测world是被一个创建的space以及向里面添加的geom后创建的。在每个模拟步我们都想产生一个所有的geom相互接触的contacts的列表。有三个函数用来做这件事情:

a、dCollide让两个geom交叉并产生接触点contactpoints;

b、dSpaceCollide决定在一个space中的那些geom对有潜在相交,并为候选的“对”调用回调函数。它步直接产生接触点,因为也许用户想对一些对进行特殊处理——如忽略他们或不同的接触产生策略。这些决定在回调函数中作出,可以选择是否为这些对调用dCollide。

c、dSpaceCollide2决定在一个space中的那些geoms与另一个space中的geoms有潜在相交,并为候选的“对”调用回调函数。它也能对一个单独的不隶属与space的geom进行测试。这个函数对存在一个碰撞层次时时很有用的,即当一个space中包括有另一个space时。

碰撞系统设计得可以给用户具有最大得灵活性来决定在那些对象间进行检测。这就是为什么有3个碰撞函数得原因,例如,一个函数产生所有接触点。

space中可以包含space。这些下级space将代表

一个space可以包含其它space,

Thesesub-spaceswilltypicallyrepresentacollectionofgeoms(orotherspaces)thatarelocatedneareachother.Thisisusefulforgainingextracollisionperformancebydividingthecollisionworldintohierarchies.Hereisanexampleofwherethisis
useful:

假如在一些地形上有两辆行驶的汽车,每个汽车都是有很多个几何体组成,如果所有的几何体都被插入到相同的space,则碰撞检测时间将与这引起车的几何体总数成正比,或是这些数目的平方,这依赖于采用哪种space类型。

一个加速的方法是为每个汽车创建一个space,将每个汽车的几何体都加入进来,然后将这个space加入到最外层space,在最外层space每个时间步中调用dSpaceCollide进行车之间的碰撞测试,(实际是在它们的绑定盒上进行的),然后再在汽车的space中调用dSpaceCollide2进行进行几何体之间的碰撞测试。这有利于加减少浪费的时间。

Ifspacehierarchiesarebeingusedthenthecallbackfunctionmaybecalledrecursively(递归),e.g.ifdSpaceCollidecallsthecallbackwhichinturncallsdSpaceCollidewiththesamecallbackfunction.Inthiscasetheusermustmakesurethatthecallback
functionisproperlyreentrant(重入).

Hereisasamplecallbackfunctionthattraversesthroughallspacesandsub-spaces,generatingallpossiblecontactpointsforallintersectinggeoms:

voidnearCallback(void*data,dGeomIDo1,dGeomIDo2)

{

if(dGeomIsSpace(o1)||dGeomIsSpace(o2)){

//collidingaspacewithsomething

dSpaceCollide2(o1,o2,data,&nearCallback);

//collideallgeomsinternaltothespace(s)

if(dGeomIsSpace(o1))dSpaceCollide(o1,data,&nearCallback);

if(dGeomIsSpace(o2))dSpaceCollide(o2,data,&nearCallback);

}

else{

//collidingtwonon-spacegeoms,sogeneratecontact

//pointsbetweeno1ando2

intnum_contact=dCollide(o1,o2,max_contacts,contact_array,skip);

//addthesecontactpointstothesimulation

...

}

}

...

//collideallobjectstogether

dSpaceCollide(top_level_space,0,&nearCallback);

AspacecallbackfunctionisnotallowedtomodifyaspacewhilethatspaceisbeingprocessedwithdSpaceCollideordSpaceCollide2.Forexample,youcannotaddorremovegeomsfromaspace,andyoucannotrepositionthegeomswithinaspace.Doingso
willtriggeraruntimeerrorinthedebugbuildofODE.

10.5.1.CategoryandCollideBitfields

//testifgeomo1andgeomo2cancollide

cat1=dGeomGetCategoryBits(o1);

cat2=dGeomGetCategoryBits(o2);

col1=dGeomGetCollideBits(o1);

col2=dGeomGetCollideBits(o2);

if((cat1&col2)||(cat2&col1)){

//callthecallbackwitho1ando2

}

else{

//donothing,o1ando2donotcollide

}



10.5.2.CollisionDetectionFunctions

10.6.Spacefunctions

10.7.GeometryClasses

10.7.1.SphereClass

10.7.2.BoxClass

10.7.3.PlaneClass

10.7.4.CappedCylinderClass

10.7.5.RayClass

10.7.6.TriangleMeshClass

10.7.7.GeometryTransformClass

10.8.Userdefinedclasses

10.9.Compositeobjects

10.10.Utilityfunctions

10.11.Implementationnotes

10.11.1.LargeEnvironments

Oftenthecollisionworldwillcontainmanyobjectsthatarepartofthestaticenvironment,thatarenotassociatedwithrigidbodies.ODE'scollisiondetectionisoptimizedtodetectgeomsthatdonotmoveandtoprecomputeasmuchinformationaspossible
abouttheseobjectstosavetime.Forexample,boundingboxesandinternalcollisiondatastructuresareprecomputed.

10.11.2.UsingaDifferentCollisionLibrary



2)mmo应用

由于地形数据庞大,直接拿一般的trimesh来做地形geom,生成的时候会比较慢,一种更好的办法是自己用

dCreateGeom创建一种新的几何体,作为我们的地形几何体,然后自己实现各种其他集合体跟他的碰撞。

//registerourcustomcolliderclass

dGeomClasscustomColliderClass;

customColliderClass.bytes:=0;//Idon'tneedanymemory

customColliderClass.collider:=CustomGetColliderFnFn;

customColliderClass.aabb:=dInfiniteAABB;

customColliderClass.aabb_test:=nil;

customColliderClass.dtor:=nil;

newClassNum:=dCreateGeomClass(customColliderClass);

//createageomofthatclassandaddittothespace

newCollider:=dCreateGeom(newClassNum);

dSpaceAdd(space,newCollider);

dColliderFn*CustomGetColliderFnFn(intnum)

{

if(num=dSphereClass)

Result:=CustomColliderFnSphere

elseif(num=dBoxClassthen)

Result:=CustomColliderFnBox

else

Result:=nil;

end;



intCustomColliderFnBox(dGeomIDo1,dGeomIDo2,intflags,dContactGeom*contact,intskip)

{

//根据地形高度得出碰撞点就可以了

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: