pxMultiActor.cpp 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "T3D/physics/physX/pxMultiActor.h"
  24. #include "console/consoleTypes.h"
  25. #include "core/stream/fileStream.h"
  26. #include "core/stream/bitStream.h"
  27. #include "core/resourceManager.h"
  28. #include "core/strings/stringUnit.h"
  29. #include "sim/netConnection.h"
  30. #include "math/mathIO.h"
  31. #include "math/mathUtils.h"
  32. #include "gfx/gfxTransformSaver.h"
  33. #include "gfx/gfxDrawUtil.h"
  34. #include "gfx/primBuilder.h"
  35. #include "collision/collision.h"
  36. #include "collision/abstractPolyList.h"
  37. #include "ts/tsShapeInstance.h"
  38. #include "ts/tsPartInstance.h"
  39. #include "lighting/lightManager.h"
  40. #include "scene/sceneManager.h"
  41. #include "scene/sceneRenderState.h"
  42. #include "scene/sceneObjectLightingPlugin.h"
  43. #include "T3D/objectTypes.h"
  44. #include "T3D/containerQuery.h"
  45. #include "T3D/fx/particleEmitter.h"
  46. #include "T3D/debris.h"
  47. #include "renderInstance/renderPassManager.h"
  48. #include "gui/worldEditor/editor.h" // For gEditingMission
  49. #include "T3D/physics/physX/px.h"
  50. #include "T3D/physics/physX/pxWorld.h"
  51. #include "T3D/physics/physX/pxMaterial.h"
  52. #include "T3D/physics/physX/pxCasts.h"
  53. #include "T3D/physics/physx/pxUtils.h"
  54. #include "sfx/sfxSystem.h"
  55. #include <NXU_helper.h>
  56. #include <nxu_schema.h>
  57. #include <NXU_customcopy.h>
  58. class PxMultiActor_Notify : public NXU_userNotify
  59. {
  60. protected:
  61. Vector<NxActor*> mActors;
  62. Vector<NxShape*> mShapes;
  63. Vector<NxJoint*> mJoints;
  64. const NxMat34 mTransform;
  65. const Point3F mScale;
  66. F32 mMassScale;
  67. NxCompartment *mCompartment;
  68. PxMaterial *mMaterial;
  69. Vector<String> *mActorUserProperties;
  70. Vector<String> *mJointUserProperties;
  71. public:
  72. void NXU_notifyJoint( NxJoint *joint, const char *userProperties )
  73. {
  74. if ( mJointUserProperties )
  75. mJointUserProperties->push_back( userProperties );
  76. mJoints.push_back( joint );
  77. }
  78. bool NXU_preNotifyJoint( NxJointDesc &joint, const char *userProperties )
  79. {
  80. joint.localAnchor[0].x *= mScale.x;
  81. joint.localAnchor[0].y *= mScale.y;
  82. joint.localAnchor[0].z *= mScale.z;
  83. joint.localAnchor[1].x *= mScale.x;
  84. joint.localAnchor[1].y *= mScale.y;
  85. joint.localAnchor[1].z *= mScale.z;
  86. // The PhysX exporter from 3dsMax doesn't allow creation
  87. // of fixed joints. It also doesn't seem to export the
  88. // joint names! So look for joints which all all the
  89. // motion axes are locked... make those fixed joints.
  90. if ( joint.getType() == NX_JOINT_D6 )
  91. {
  92. NxD6JointDesc *d6Joint = static_cast<NxD6JointDesc*>( &joint );
  93. if ( d6Joint->xMotion == NX_D6JOINT_MOTION_LOCKED &&
  94. d6Joint->yMotion == NX_D6JOINT_MOTION_LOCKED &&
  95. d6Joint->zMotion == NX_D6JOINT_MOTION_LOCKED &&
  96. d6Joint->swing1Motion == NX_D6JOINT_MOTION_LOCKED &&
  97. d6Joint->swing2Motion == NX_D6JOINT_MOTION_LOCKED &&
  98. d6Joint->twistMotion == NX_D6JOINT_MOTION_LOCKED )
  99. {
  100. // Ok... build a new fixed joint.
  101. NxFixedJointDesc fixed;
  102. fixed.actor[0] = joint.actor[0];
  103. fixed.actor[1] = joint.actor[1];
  104. fixed.localNormal[0] = joint.localNormal[0];
  105. fixed.localNormal[1] = joint.localNormal[1];
  106. fixed.localAxis[0] = joint.localAxis[0];
  107. fixed.localAxis[1] = joint.localAxis[1];
  108. fixed.localAnchor[0] = joint.localAnchor[0];
  109. fixed.localAnchor[1] = joint.localAnchor[1];
  110. fixed.maxForce = joint.maxForce;
  111. fixed.maxTorque = joint.maxTorque;
  112. fixed.name = joint.name;
  113. fixed.userData = joint.userData;
  114. fixed.jointFlags = joint.jointFlags;
  115. // What scene are we adding this to?
  116. NxActor *actor = fixed.actor[0] ? fixed.actor[0] : fixed.actor[1];
  117. NxScene &scene = actor->getScene();
  118. NxJoint* theJoint = scene.createJoint( fixed );
  119. mJoints.push_back( theJoint );
  120. if ( mJointUserProperties )
  121. mJointUserProperties->push_back( userProperties );
  122. // Don't generate this joint.
  123. return false;
  124. }
  125. }
  126. return true;
  127. }
  128. void NXU_notifyActor( NxActor *actor, const char *userProperties )
  129. {
  130. mActors.push_back( actor );
  131. // Save the shapes.
  132. for ( U32 i=0; i < actor->getNbShapes(); i++ )
  133. mShapes.push_back( actor->getShapes()[i] );
  134. mActorUserProperties->push_back( userProperties );
  135. };
  136. bool NXU_preNotifyMaterial( NxMaterialDesc &t, const char *userProperties )
  137. {
  138. // Don't generate materials if we have one defined!
  139. return !mMaterial;
  140. }
  141. bool NXU_preNotifyActor( NxActorDesc &actor, const char *userProperties )
  142. {
  143. // Set the right compartment.
  144. actor.compartment = mCompartment;
  145. if ( actor.shapes.size() == 0 )
  146. Con::warnf( "PxMultiActor_Notify::NXU_preNotifyActor, got an actor (%s) with no shapes, was this intentional?", actor.name );
  147. // For every shape, cast to its particular type
  148. // and apply the scale to size, mass and localPosition.
  149. for( S32 i = 0; i < actor.shapes.size(); i++ )
  150. {
  151. // If we have material then set it.
  152. if ( mMaterial )
  153. actor.shapes[i]->materialIndex = mMaterial->getMaterialId();
  154. switch( actor.shapes[i]->getType() )
  155. {
  156. case NX_SHAPE_BOX:
  157. {
  158. NxBoxShapeDesc *boxDesc = (NxBoxShapeDesc*)actor.shapes[i];
  159. boxDesc->mass *= mMassScale;
  160. boxDesc->dimensions.x *= mScale.x;
  161. boxDesc->dimensions.y *= mScale.y;
  162. boxDesc->dimensions.z *= mScale.z;
  163. boxDesc->localPose.t.x *= mScale.x;
  164. boxDesc->localPose.t.y *= mScale.y;
  165. boxDesc->localPose.t.z *= mScale.z;
  166. break;
  167. }
  168. case NX_SHAPE_SPHERE:
  169. {
  170. NxSphereShapeDesc *sphereDesc = (NxSphereShapeDesc*)actor.shapes[i];
  171. sphereDesc->mass *= mMassScale;
  172. // TODO: Spheres do not work with non-uniform
  173. // scales very well... how do we fix this?
  174. sphereDesc->radius *= mScale.x;
  175. sphereDesc->localPose.t.x *= mScale.x;
  176. sphereDesc->localPose.t.y *= mScale.y;
  177. sphereDesc->localPose.t.z *= mScale.z;
  178. break;
  179. }
  180. case NX_SHAPE_CAPSULE:
  181. {
  182. NxCapsuleShapeDesc *capsuleDesc = (NxCapsuleShapeDesc*)actor.shapes[i];
  183. capsuleDesc->mass *= mMassScale;
  184. // TODO: Capsules do not work with non-uniform
  185. // scales very well... how do we fix this?
  186. capsuleDesc->radius *= mScale.x;
  187. capsuleDesc->height *= mScale.y;
  188. capsuleDesc->localPose.t.x *= mScale.x;
  189. capsuleDesc->localPose.t.y *= mScale.y;
  190. capsuleDesc->localPose.t.z *= mScale.z;
  191. break;
  192. }
  193. default:
  194. {
  195. static String lookup[] =
  196. {
  197. "PLANE",
  198. "SPHERE",
  199. "BOX",
  200. "CAPSULE",
  201. "WHEEL",
  202. "CONVEX",
  203. "MESH",
  204. "HEIGHTFIELD"
  205. };
  206. Con::warnf( "PxMultiActor_Notify::NXU_preNotifyActor, unsupported shape type (%s), on Actor (%s)", lookup[actor.shapes[i]->getType()].c_str(), actor.name );
  207. delete actor.shapes[i];
  208. actor.shapes.erase( actor.shapes.begin() + i );
  209. --i;
  210. break;
  211. }
  212. }
  213. }
  214. NxBodyDesc *body = const_cast<NxBodyDesc*>( actor.body );
  215. if ( body )
  216. {
  217. // Must scale all of these parameters, else there will be odd results!
  218. body->mass *= mMassScale;
  219. body->massLocalPose.t.multiply( mMassScale, body->massLocalPose.t );
  220. body->massSpaceInertia.multiply( mMassScale, body->massSpaceInertia );
  221. // Ragdoll damping!
  222. //body->sleepDamping = 1.7f;
  223. //body->linearDamping = 0.4f;
  224. //body->angularDamping = 0.08f;
  225. //body->wakeUpCounter = 0.3f;
  226. }
  227. return true;
  228. };
  229. public:
  230. PxMultiActor_Notify( NxCompartment *compartment,
  231. PxMaterial *material,
  232. const NxMat34& mat,
  233. const Point3F& scale,
  234. Vector<String> *actorProps = NULL,
  235. Vector<String> *jointProps = NULL )
  236. : mCompartment( compartment ),
  237. mMaterial( material ),
  238. mScale( scale ),
  239. mTransform( mat ),
  240. mActorUserProperties( actorProps ),
  241. mJointUserProperties( jointProps )
  242. {
  243. const F32 unit = VectorF( 1.0f, 1.0f, 1.0f ).len();
  244. mMassScale = mScale.len() / unit;
  245. }
  246. virtual ~PxMultiActor_Notify()
  247. {
  248. }
  249. const Vector<NxActor*>& getActors() { return mActors; }
  250. const Vector<NxShape*>& getShapes() { return mShapes; }
  251. const Vector<NxJoint*>& getJoints() { return mJoints; }
  252. };
  253. ConsoleDocClass( PxMultiActorData,
  254. "@brief Defines the properties of a type of PxMultiActor.\n\n"
  255. "Usually it is prefered to use PhysicsShape rather than PxMultiActor because "
  256. "a PhysicsShape is not PhysX specific and can be much easier to setup.\n\n"
  257. "For more information, refer to Nvidia's PhysX docs.\n\n"
  258. "@ingroup Physics"
  259. );
  260. IMPLEMENT_CO_DATABLOCK_V1(PxMultiActorData);
  261. PxMultiActorData::PxMultiActorData()
  262. : material( NULL ),
  263. collection( NULL ),
  264. waterDragScale( 1.0f ),
  265. buoyancyDensity( 1.0f ),
  266. angularDrag( 0.0f ),
  267. linearDrag( 0.0f ),
  268. clientOnly( false ),
  269. singlePlayerOnly( false ),
  270. shapeName( StringTable->insert( "" ) ),
  271. physXStream( StringTable->insert( "" ) ),
  272. breakForce( 0.0f )
  273. {
  274. for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
  275. correctionNodeNames[i] = StringTable->insert( "" );
  276. for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
  277. correctionNodes[i] = -1;
  278. for ( S32 i = 0; i < NumMountPoints; i++ )
  279. {
  280. mountNodeNames[i] = StringTable->insert( "" );
  281. mountPointNode[i] = -1;
  282. }
  283. }
  284. PxMultiActorData::~PxMultiActorData()
  285. {
  286. if ( collection )
  287. NXU::releaseCollection( collection );
  288. }
  289. void PxMultiActorData::initPersistFields()
  290. {
  291. Parent::initPersistFields();
  292. addGroup("Media");
  293. addField( "shapeName", TypeFilename, Offset( shapeName, PxMultiActorData ),
  294. "@brief Path to the .DAE or .DTS file to render.\n\n");
  295. endGroup("Media");
  296. // PhysX collision properties.
  297. addGroup( "Physics" );
  298. addField( "physXStream", TypeFilename, Offset( physXStream, PxMultiActorData ),
  299. "@brief .XML file containing data such as actors, shapes, and joints.\n\n"
  300. "These files can be created using a free PhysX plugin for 3DS Max.\n\n");
  301. addField( "material", TYPEID< PxMaterial >(), Offset( material, PxMultiActorData ),
  302. "@brief An optional PxMaterial to be used for the PxMultiActor.\n\n"
  303. "Defines properties such as friction and restitution. "
  304. "Unrelated to the material used for rendering. The physXStream will contain "
  305. "defined materials that can be customized in 3DS Max. "
  306. "To override the material for all physics shapes in the physXStream, specify a material here.\n\n");
  307. addField( "noCorrection", TypeBool, Offset( noCorrection, PxMultiActorData ),
  308. "@hide" );
  309. UTF8 buff[256];
  310. for ( S32 i=0; i < MaxCorrectionNodes; i++ )
  311. {
  312. //dSprintf( buff, sizeof(buff), "correctionNode%d", i );
  313. addField( buff, TypeString, Offset( correctionNodeNames[i], PxMultiActorData ), "@hide" );
  314. }
  315. for ( S32 i=0; i < NumMountPoints; i++ )
  316. {
  317. //dSprintf( buff, sizeof(buff), "mountNode%d", i );
  318. addField( buff, TypeString, Offset( mountNodeNames[i], PxMultiActorData ), "@hide" );
  319. }
  320. addField( "angularDrag", TypeF32, Offset( angularDrag, PxMultiActorData ),
  321. "@brief Value used to help calculate rotational drag force while submerged in water.\n\n");
  322. addField( "linearDrag", TypeF32, Offset( linearDrag, PxMultiActorData ),
  323. "@brief Value used to help calculate linear drag force while submerged in water.\n\n");
  324. addField( "waterDragScale", TypeF32, Offset( waterDragScale, PxMultiActorData ),
  325. "@brief Scale to apply to linear and angular dampening while submerged in water.\n\n ");
  326. addField( "buoyancyDensity", TypeF32, Offset( buoyancyDensity, PxMultiActorData ),
  327. "@brief The density used to calculate buoyant forces.\n\n"
  328. "The result of the calculated buoyancy is relative to the density of the WaterObject the PxMultiActor is within.\n\n"
  329. "@note This value is necessary because Torque 3D does its own buoyancy simulation. It is not handled by PhysX."
  330. "@see WaterObject::density");
  331. endGroup( "Physics" );
  332. addField( "clientOnly", TypeBool, Offset( clientOnly, PxMultiActorData ),
  333. "@hide");
  334. addField( "singlePlayerOnly", TypeBool, Offset( singlePlayerOnly, PxMultiActorData ),
  335. "@hide");
  336. addField( "breakForce", TypeF32, Offset( breakForce, PxMultiActorData ),
  337. "@brief Force required to break an actor.\n\n"
  338. "This value does not apply to joints. "
  339. "If an actor is associated with a joint it will break whenever the joint does. "
  340. "This allows an actor \"not\" associated with a joint to also be breakable.\n\n");
  341. }
  342. void PxMultiActorData::packData(BitStream* stream)
  343. {
  344. Parent::packData(stream);
  345. stream->writeString( shapeName );
  346. stream->writeString( physXStream );
  347. if( stream->writeFlag( material ) )
  348. stream->writeRangedU32( packed ? SimObjectId( material ) : material->getId(),
  349. DataBlockObjectIdFirst, DataBlockObjectIdLast );
  350. if ( !stream->writeFlag( noCorrection ) )
  351. {
  352. // Write the correction node indices for the client.
  353. for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
  354. stream->write( correctionNodes[i] );
  355. }
  356. for ( S32 i = 0; i < NumMountPoints; i++ )
  357. stream->write( mountPointNode[i] );
  358. stream->write( waterDragScale );
  359. stream->write( buoyancyDensity );
  360. stream->write( angularDrag );
  361. stream->write( linearDrag );
  362. stream->writeFlag( clientOnly );
  363. stream->writeFlag( singlePlayerOnly );
  364. stream->write( breakForce );
  365. }
  366. void PxMultiActorData::unpackData(BitStream* stream)
  367. {
  368. Parent::unpackData(stream);
  369. shapeName = stream->readSTString();
  370. physXStream = stream->readSTString();
  371. if( stream->readFlag() )
  372. material = (PxMaterial*)stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
  373. noCorrection = stream->readFlag();
  374. if ( !noCorrection )
  375. {
  376. for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
  377. stream->read( &correctionNodes[i] );
  378. }
  379. for ( S32 i = 0; i < NumMountPoints; i++ )
  380. stream->read( &mountPointNode[i] );
  381. stream->read( &waterDragScale );
  382. stream->read( &buoyancyDensity );
  383. stream->read( &angularDrag );
  384. stream->read( &linearDrag );
  385. clientOnly = stream->readFlag();
  386. singlePlayerOnly = stream->readFlag();
  387. stream->read( &breakForce );
  388. }
  389. bool PxMultiActorData::preload( bool server, String &errorBuffer )
  390. {
  391. if ( !Parent::preload( server, errorBuffer ) )
  392. return false;
  393. // If the stream is null, exit.
  394. if ( !physXStream || !physXStream[0] )
  395. {
  396. errorBuffer = "PxMultiActorData::preload: physXStream is unset!";
  397. return false;
  398. }
  399. // Set up our buffer for the binary stream filename path.
  400. UTF8 binPhysXStream[260] = { 0 };
  401. const UTF8* ext = dStrrchr( physXStream, '.' );
  402. // Copy the xml stream path except for the extension.
  403. if ( ext )
  404. dStrncpy( binPhysXStream, physXStream, getMin( 260, ext - physXStream ) );
  405. else
  406. dStrncpy( binPhysXStream, physXStream, 260 );
  407. // Concatenate the binary extension.
  408. dStrcat( binPhysXStream, ".nxb" );
  409. // Get the modified times of the two files.
  410. FileTime xmlTime = {0}, binTime = {0};
  411. Platform::getFileTimes( physXStream, NULL, &xmlTime );
  412. Platform::getFileTimes( binPhysXStream, NULL, &binTime );
  413. // If the binary is newer... load that.
  414. if ( Platform::compareFileTimes( binTime, xmlTime ) >= 0 )
  415. _loadCollection( binPhysXStream, true );
  416. // If the binary failed... then load the xml.
  417. if ( !collection )
  418. {
  419. _loadCollection( physXStream, false );
  420. // If loaded... resave the xml in binary format
  421. // for quicker subsequent loads.
  422. if ( collection )
  423. NXU::saveCollection( collection, binPhysXStream, NXU::FT_BINARY );
  424. }
  425. // If it still isn't loaded then we've failed!
  426. if ( !collection )
  427. {
  428. errorBuffer = String::ToString( "PxMultiActorDatas::preload: could not load '%s'!", physXStream );
  429. return false;
  430. }
  431. if (!shapeName || shapeName[0] == '\0')
  432. {
  433. errorBuffer = "PxMultiActorDatas::preload: no shape name!";
  434. return false;
  435. }
  436. shape = ResourceManager::get().load( shapeName );
  437. if (bool(shape) == false)
  438. {
  439. errorBuffer = String::ToString( "PxMultiActorData::preload: unable to load shape: %s", shapeName );
  440. return false;
  441. }
  442. // Find the client side material.
  443. if ( !server && material )
  444. Sim::findObject( SimObjectId(material), material );
  445. // Get the ignore node indexes from the names.
  446. for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
  447. {
  448. if( !correctionNodeNames[i] || !correctionNodeNames[i][0] )
  449. continue;
  450. correctionNodes[i] = shape->findNode( correctionNodeNames[i] );
  451. }
  452. // Resolve mount point node indexes
  453. for ( S32 i = 0; i < NumMountPoints; i++)
  454. {
  455. char fullName[256];
  456. if ( !mountNodeNames[i] || !mountNodeNames[i][0] )
  457. {
  458. dSprintf(fullName,sizeof(fullName),"mount%d",i);
  459. mountPointNode[i] = shape->findNode(fullName);
  460. }
  461. else
  462. mountPointNode[i] = shape->findNode(mountNodeNames[i]);
  463. }
  464. // Register for file change notification to reload the collection
  465. if ( server )
  466. Torque::FS::AddChangeNotification( physXStream, this, &PxMultiActorData::_onFileChanged );
  467. return true;
  468. }
  469. void PxMultiActorData::_onFileChanged( const Torque::Path &path )
  470. {
  471. reload();
  472. }
  473. void PxMultiActorData::reload()
  474. {
  475. bool result = _loadCollection( physXStream, false );
  476. if ( !result )
  477. Con::errorf( "PxMultiActorData::reload(), _loadCollection failed..." );
  478. // Inform MultiActors who use this datablock to reload.
  479. mReloadSignal.trigger();
  480. }
  481. bool PxMultiActorData::_loadCollection( const UTF8 *path, bool isBinary )
  482. {
  483. if ( collection )
  484. {
  485. NXU::releaseCollection( collection );
  486. collection = NULL;
  487. }
  488. FileStream fs;
  489. if ( !fs.open( path, Torque::FS::File::Read ) )
  490. return false;
  491. // Load the data into memory.
  492. U32 size = fs.getStreamSize();
  493. FrameTemp<U8> buff( size );
  494. fs.read( size, buff );
  495. // If the stream didn't read anything, there's a problem.
  496. if ( size <= 0 )
  497. return false;
  498. // Ok... try to load it.
  499. collection = NXU::loadCollection( path,
  500. isBinary ? NXU::FT_BINARY : NXU::FT_XML,
  501. buff,
  502. size );
  503. return collection != NULL;
  504. }
  505. bool PxMultiActorData::createActors( NxScene *scene,
  506. NxCompartment *compartment,
  507. const NxMat34 *nxMat,
  508. const Point3F& scale,
  509. Vector<NxActor*> *outActors,
  510. Vector<NxShape*> *outShapes,
  511. Vector<NxJoint*> *outJoints,
  512. Vector<String> *outActorUserProperties,
  513. Vector<String> *outJointUserProperties )
  514. {
  515. if ( !scene )
  516. {
  517. Con::errorf( "PxMultiActorData::createActor() - returned null NxScene" );
  518. return NULL;
  519. }
  520. PxMultiActor_Notify pxNotify( compartment, material, *nxMat, scale, outActorUserProperties, outJointUserProperties );
  521. NXU::instantiateCollection( collection, *gPhysicsSDK, scene, nxMat, &pxNotify );
  522. *outActors = pxNotify.getActors();
  523. *outJoints = pxNotify.getJoints();
  524. if ( outShapes )
  525. *outShapes = pxNotify.getShapes();
  526. if ( outActors->empty() )
  527. {
  528. Con::errorf( "PxMultiActorData::createActors() - NXUStream notifier returned empty actors or joints!" );
  529. return false;
  530. }
  531. return true;
  532. }
  533. ConsoleDocClass( PxMultiActor,
  534. "@brief Represents a destructible physical object simulated using PhysX.\n\n"
  535. "Usually it is prefered to use PhysicsShape and not PxMultiActor because "
  536. "it is not PhysX specific and much easier to setup.\n"
  537. "@see PxMultiActorData.\n"
  538. "@ingroup Physics"
  539. );
  540. IMPLEMENT_CO_NETOBJECT_V1(PxMultiActor);
  541. PxMultiActor::PxMultiActor()
  542. : mShapeInstance( NULL ),
  543. mRootActor( NULL ),
  544. mWorld( NULL ),
  545. mStartImpulse( 0, 0, 0 ),
  546. mResetXfm( true ),
  547. mActorScale( 0, 0, 0 ),
  548. mDebugRender( false ),
  549. mIsDummy( false ),
  550. mBroken( false ),
  551. mDataBlock( NULL )
  552. {
  553. mNetFlags.set( Ghostable | ScopeAlways );
  554. mTypeMask |= StaticObjectType | StaticShapeObjectType;
  555. //mUserData.setObject( this );
  556. }
  557. void PxMultiActor::initPersistFields()
  558. {
  559. Parent::initPersistFields();
  560. /*
  561. // We're overloading these fields from SceneObject
  562. // in order to force it to go thru setTransform!
  563. removeField( "position" );
  564. removeField( "rotation" );
  565. removeField( "scale" );
  566. addGroup( "Transform" );
  567. addProtectedField( "position", TypeMatrixPosition, 0,
  568. &PxMultiActor::_setPositionField,
  569. &PxMultiActor::_getPositionField,
  570. "" );
  571. addProtectedField( "rotation", TypeMatrixRotation, 0,
  572. &PxMultiActor::_setRotationField,
  573. &PxMultiActor::_getRotationField,
  574. "" );
  575. addField( "scale", TypePoint3F, Offset( mObjScale, PxMultiActor ) );
  576. endGroup( "Transform" );
  577. */
  578. //addGroup("Physics");
  579. // addField( "AngularDrag", TypeF32, )
  580. //endGroup("Physics");
  581. addGroup( "Debug" );
  582. addField( "debugRender", TypeBool, Offset( mDebugRender, PxMultiActor ), "@hide");
  583. addField( "broken", TypeBool, Offset( mBroken, PxMultiActor ), "@hide");
  584. endGroup( "Debug" );
  585. //addGroup("Collision");
  586. //endGroup("Collision");
  587. }
  588. bool PxMultiActor::onAdd()
  589. {
  590. PROFILE_SCOPE( PxMultiActor_OnAdd );
  591. if (!Parent::onAdd() || !mDataBlock )
  592. return false;
  593. mIsDummy = isClientObject() && PHYSICSMGR->isSinglePlayer(); //&& mDataBlock->singlePlayerOnly;
  594. mShapeInstance = new TSShapeInstance( mDataBlock->shape, isClientObject() );
  595. mObjBox = mDataBlock->shape->bounds;
  596. resetWorldBox();
  597. addToScene();
  598. String worldName = isServerObject() ? "server" : "client";
  599. // SinglePlayer objects only have server-side physics representations.
  600. if ( mIsDummy )
  601. worldName = "server";
  602. mWorld = dynamic_cast<PxWorld*>( PHYSICSMGR->getWorld( worldName ) );
  603. if ( !mWorld || !mWorld->getScene() )
  604. {
  605. Con::errorf( "PxMultiActor::onAdd() - PhysXWorld not initialized!" );
  606. return false;
  607. }
  608. applyWarp( getTransform(), true, false );
  609. mResetXfm = getTransform();
  610. if ( !_createActors( getTransform() ) )
  611. {
  612. Con::errorf( "PxMultiActor::onAdd(), _createActors failed" );
  613. return false;
  614. }
  615. if ( !mIsDummy )
  616. mDataBlock->mReloadSignal.notify( this, &PxMultiActor::onFileNotify );
  617. // If the editor is on... let it know!
  618. //if ( gEditingMission )
  619. //onEditorEnable(); // TODO: Fix this up.
  620. PhysicsPlugin::getPhysicsResetSignal().notify( this, &PxMultiActor::onPhysicsReset, 1050.0f );
  621. setAllBroken( false );
  622. if ( isServerObject() )
  623. scriptOnAdd();
  624. return true;
  625. }
  626. void PxMultiActor::onRemove()
  627. {
  628. removeFromScene();
  629. _destroyActors();
  630. mWorld = NULL;
  631. SAFE_DELETE( mShapeInstance );
  632. PhysicsPlugin::getPhysicsResetSignal().remove( this, &PxMultiActor::onPhysicsReset );
  633. if ( !mIsDummy && mDataBlock )
  634. mDataBlock->mReloadSignal.remove( this, &PxMultiActor::onFileNotify );
  635. Parent::onRemove();
  636. }
  637. void PxMultiActor::_destroyActors()
  638. {
  639. // Dummies don't have physics objects.
  640. if ( mIsDummy || !mWorld )
  641. return;
  642. mWorld->releaseWriteLock();
  643. // Clear the root actor.
  644. mRootActor = NULL;
  645. // Clear the relative transforms.
  646. //mRelXfms.clear();
  647. // The shapes are owned by the actors, so
  648. // we just need to clear them.
  649. mShapes.clear();
  650. // Release the joints first.
  651. for( S32 i = 0; i < mJoints.size(); i++ )
  652. {
  653. NxJoint *joint = mJoints[i];
  654. if ( !joint )
  655. continue;
  656. // We allocate per joint userData and we must free it.
  657. PxUserData *jointData = PxUserData::getData( *joint );
  658. if ( jointData )
  659. delete jointData;
  660. mWorld->releaseJoint( *joint );
  661. }
  662. mJoints.clear();
  663. // Now release the actors.
  664. for( S32 i = 0; i < mActors.size(); i++ )
  665. {
  666. NxActor *actor = mActors[i];
  667. PxUserData *actorData = PxUserData::getData( *actor );
  668. if ( actorData )
  669. delete actorData;
  670. if ( actor )
  671. mWorld->releaseActor( *actor );
  672. }
  673. mActors.clear();
  674. }
  675. bool PxMultiActor::_createActors( const MatrixF &xfm )
  676. {
  677. if ( mIsDummy )
  678. {
  679. // Dummies don't have physics objects, but
  680. // they do handle actor deltas.
  681. PxMultiActor *serverObj = static_cast<PxMultiActor*>( mServerObject.getObject() );
  682. mActorDeltas.setSize( serverObj->mActors.size() );
  683. dMemset( mActorDeltas.address(), 0, mActorDeltas.memSize() );
  684. return true;
  685. }
  686. NxMat34 nxMat;
  687. nxMat.setRowMajor44( xfm );
  688. // Store the scale for comparison in setScale().
  689. mActorScale = getScale();
  690. // Release the write lock so we can create actors.
  691. mWorld->releaseWriteLock();
  692. Vector<String> actorUserProperties;
  693. Vector<String> jointUserProperties;
  694. bool created = mDataBlock->createActors( mWorld->getScene(),
  695. NULL,
  696. &nxMat,
  697. mActorScale,
  698. &mActors,
  699. &mShapes,
  700. &mJoints,
  701. &actorUserProperties,
  702. &jointUserProperties );
  703. // Debug output...
  704. //for ( U32 i = 0; i < mJoints.size(); i++ )
  705. // Con::printf( "Joint0 name: '%s'", mJoints[i]->getName() );
  706. //for ( U32 i = 0; i < actorUserProperties.size(); i++ )
  707. //Con::printf( "actor%i UserProperties: '%s'", i, actorUserProperties[i].c_str() );
  708. //for ( U32 i = 0; i < jointUserProperties.size(); i++ )
  709. // Con::printf( "joint%i UserProperties: '%s'", i, jointUserProperties[i].c_str() );
  710. if ( !created )
  711. {
  712. Con::errorf( "PxMultiActor::_createActors() - failed!" );
  713. return false;
  714. }
  715. // Make the first actor the root actor by default, but
  716. // if we have a kinematic actor then use that.
  717. mRootActor = mActors[0];
  718. for ( S32 i = 0; i < mActors.size(); i++ )
  719. {
  720. if ( mActors[i]->readBodyFlag( NX_BF_KINEMATIC ) )
  721. {
  722. mRootActor = mActors[i];
  723. break;
  724. }
  725. }
  726. mDelta.pos = mDelta.lastPos = getPosition();
  727. mDelta.rot = mDelta.lastRot = getTransform();
  728. bool *usedActors = new bool[mActors.size()];
  729. dMemset( usedActors, 0, sizeof(bool) * mActors.size() );
  730. TSShape *shape = mShapeInstance->getShape();
  731. // Should already be done when actors are destroyed.
  732. mMappedActors.clear();
  733. Vector<String> mappedActorProperties;
  734. // Remap the actors to the shape instance's bone indices.
  735. for( S32 i = 0; i < mShapeInstance->mNodeTransforms.size(); i++ )
  736. {
  737. if ( !shape )
  738. break;
  739. UTF8 comparisonName[260] = { 0 };
  740. NxActor *actor = NULL;
  741. NxActor *pushActor = NULL;
  742. String actorProperties;
  743. S32 nodeNameIdx = shape->nodes[i].nameIndex;
  744. const UTF8 *nodeName = shape->getName( nodeNameIdx );
  745. S32 dl = -1;
  746. dStrcpy( comparisonName, String::GetTrailingNumber( nodeName, dl ) ); //, ext - nodeName );
  747. dSprintf( comparisonName, sizeof( comparisonName ), "%s_pxactor", comparisonName );
  748. //String test( nodeName );
  749. //AssertFatal( test.find("gableone",0,String::NoCase) == String::NPos, "found it" );
  750. // If we find an actor that corresponds to this node we will
  751. // push it back into the remappedActors vector, otherwise
  752. // we will push back NULL.
  753. for ( S32 j = 0; j < mActors.size(); j++ )
  754. {
  755. actor = mActors[j];
  756. const UTF8 *actorName = actor->getName();
  757. if ( dStricmp( comparisonName, actorName ) == 0 )
  758. {
  759. pushActor = actor;
  760. actorProperties = actorUserProperties[j];
  761. usedActors[j] = true;
  762. break;
  763. }
  764. }
  765. mMappedActors.push_back( pushActor );
  766. mappedActorProperties.push_back( actorProperties );
  767. if ( !pushActor )
  768. dl = -1;
  769. mMappedActorDL.push_back( dl );
  770. // Increase the sleep tolerance.
  771. if ( pushActor )
  772. {
  773. //pushActor->raiseBodyFlag( NX_BF_ENERGY_SLEEP_TEST );
  774. //pushActor->setSleepEnergyThreshold( 2 );
  775. //pushActor->userData = NULL;
  776. }
  777. }
  778. // Delete any unused/orphaned actors.
  779. for ( S32 i = 0; i < mActors.size(); i++ )
  780. {
  781. if ( usedActors[i] )
  782. continue;
  783. NxActor *actor = mActors[i];
  784. Con::errorf( "PxMultiActor::_createActors() - Orphan NxActor - '%s'!", actor->getName() );
  785. if ( actor == mRootActor )
  786. {
  787. Con::errorf( "PxMultiActor::_createActors() - root actor (%s) was orphan, cannot continue.", actor->getName() );
  788. return false;
  789. }
  790. // Remove references to shapes of the deleted actor.
  791. for ( S32 i = 0; i < mShapes.size(); i++ )
  792. {
  793. if ( &(mShapes[i]->getActor()) == actor )
  794. {
  795. mShapes.erase_fast(i);
  796. i--;
  797. }
  798. }
  799. mWorld->releaseActor( *actor );
  800. }
  801. // Done with this helper.
  802. delete [] usedActors;
  803. // Repopulate mActors with one entry per real actor we own.
  804. mActors.clear();
  805. mMappedToActorIndex.clear();
  806. actorUserProperties.clear();
  807. for ( S32 i = 0; i < mMappedActors.size(); i++ )
  808. {
  809. S32 index = -1;
  810. if ( mMappedActors[i] )
  811. {
  812. index = mActors.push_back_unique( mMappedActors[i] );
  813. while ( index >= actorUserProperties.size() )
  814. actorUserProperties.push_back( String::EmptyString );
  815. actorUserProperties[index] = mappedActorProperties[i];
  816. }
  817. mMappedToActorIndex.push_back( index );
  818. }
  819. if ( mActors.size() == 0 )
  820. {
  821. Con::errorf( "PxMultiActor::_createActors, got zero actors! Were all actors orphans?" );
  822. return false;
  823. }
  824. // Initialize the actor deltas.
  825. mActorDeltas.setSize( mActors.size() );
  826. dMemset( mActorDeltas.address(), 0, mActorDeltas.memSize() );
  827. // Assign user data for actors.
  828. for ( U32 i = 0; i < mActors.size(); i++ )
  829. {
  830. NxActor *actor = mActors[i];
  831. if ( !actor )
  832. continue;
  833. actor->userData = _createActorUserData( actor, actorUserProperties[i] );
  834. }
  835. //NxActor *actor1;
  836. //NxActor *actor2;
  837. //PxUserData *pUserData;
  838. // Allocate user data for joints.
  839. for ( U32 i = 0; i < mJoints.size(); i++ )
  840. {
  841. NxJoint *joint = mJoints[i];
  842. if ( !joint )
  843. continue;
  844. joint->userData = _createJointUserData( joint, jointUserProperties[i] );
  845. /*
  846. // Set actors attached to joints as not-pushable (by the player).
  847. joint->getActors( &actor1, &actor2 );
  848. if ( actor1 )
  849. {
  850. pUserData = PxUserData::getData( *actor1 );
  851. if ( pUserData )
  852. pUserData->mCanPush = false;
  853. }
  854. if ( actor2 )
  855. {
  856. pUserData = PxUserData::getData( *actor2 );
  857. if ( pUserData )
  858. pUserData->mCanPush = false;
  859. }
  860. */
  861. }
  862. // Set actors and meshes to the unbroken state.
  863. setAllBroken( false );
  864. return true;
  865. }
  866. PxUserData* PxMultiActor::_createActorUserData( NxActor *actor, String &userProperties )
  867. {
  868. PxUserData *actorData = new PxUserData();
  869. actorData->setObject( this );
  870. // We use this for saving relative xfms for 'broken' actors.
  871. NxMat34 actorPose = actor->getGlobalPose();
  872. NxMat34 actorSpaceXfm;
  873. actorPose.getInverse( actorSpaceXfm );
  874. const String actorName( actor->getName() );
  875. static const String showStr( "PxBrokenShow" );
  876. static const String hideStr( "PxBrokenHide" );
  877. // 3DSMax saves out double newlines, replace them with one.
  878. userProperties.replace( "\r\n", "\n" );
  879. U32 propertyCount = StringUnit::getUnitCount( userProperties, "\n" );
  880. for ( U32 i = 0; i < propertyCount; i++ )
  881. {
  882. String propertyStr = StringUnit::getUnit( userProperties, i, "\n" );
  883. U32 wordCount = StringUnit::getUnitCount( propertyStr, "=" );
  884. if ( wordCount == 0 )
  885. {
  886. // We sometimes get empty lines between properties,
  887. // which doesn't break anything.
  888. continue;
  889. }
  890. if ( wordCount != 2 )
  891. {
  892. Con::warnf( "PxMultiActor::_createActorUserData, malformed UserProperty string (%s) for actor (%s)", propertyStr.c_str(), actorName.c_str() );
  893. continue;
  894. }
  895. String propertyName = StringUnit::getUnit( propertyStr, 0, "=" );
  896. String propertyValue = StringUnit::getUnit( propertyStr, 1, "=" );
  897. Vector<NxActor*> *dstVector = NULL;
  898. if ( propertyName.equal( showStr, String::NoCase ) )
  899. dstVector = &actorData->mBrokenActors;
  900. else if ( propertyName.equal( hideStr, String::NoCase ) )
  901. dstVector = &actorData->mUnbrokenActors;
  902. if ( !dstVector )
  903. continue;
  904. U32 valueCount = StringUnit::getUnitCount( propertyValue, "," );
  905. for ( U32 j = 0; j < valueCount; j++ )
  906. {
  907. String val = StringUnit::getUnit( propertyValue, j, "," );
  908. NxActor *pActor = _findActor( val );
  909. if ( !pActor )
  910. Con::warnf( "PxMultiActor::_createActorUserData, actor (%s) was not found when parsing UserProperties for actor (%s)", val.c_str(), actorName.c_str() );
  911. else
  912. {
  913. dstVector->push_back( pActor );
  914. if ( dstVector == &actorData->mBrokenActors )
  915. {
  916. NxMat34 relXfm = pActor->getGlobalPose();
  917. relXfm.multiply( relXfm, actorSpaceXfm );
  918. actorData->mRelXfm.push_back( relXfm );
  919. }
  920. }
  921. }
  922. }
  923. // Only add a contact signal to this actor if
  924. // we have objects we can break.
  925. if ( actorData->mBrokenActors.size() > 0 &&
  926. mDataBlock->breakForce > 0.0f )
  927. {
  928. actor->setContactReportFlags( NX_NOTIFY_ON_START_TOUCH_FORCE_THRESHOLD | NX_NOTIFY_FORCES );
  929. actor->setContactReportThreshold( mDataBlock->breakForce );
  930. actorData->getContactSignal().notify( this, &PxMultiActor::_onContact );
  931. }
  932. return actorData;
  933. }
  934. PxUserData* PxMultiActor::_createJointUserData( NxJoint *joint, String &userProperties )
  935. {
  936. PxUserData *jointData = new PxUserData();
  937. jointData->setObject( this );
  938. // We use this for saving relative xfms for 'broken' actors.
  939. NxActor *actor0;
  940. NxActor *actor1;
  941. joint->getActors( &actor0, &actor1 );
  942. NxMat34 actorPose = actor0->getGlobalPose();
  943. NxMat34 actorSpaceXfm;
  944. actorPose.getInverse( actorSpaceXfm );
  945. // The PxMultiActor will live longer than the joint
  946. // so this notify shouldn't ever need to be removed. Although if someone
  947. // other than this multiactor were to register for this notify and their
  948. // lifetime could be shorter, then 'they' might have to.
  949. jointData->getOnJointBreakSignal().notify( this, &PxMultiActor::_onJointBreak );
  950. // JCFHACK: put this in userProperties too.
  951. Sim::findObject( "JointBreakEmitter", jointData->mParticleEmitterData );
  952. String showStr( "PxBrokenShow" );
  953. String hideStr( "PxBrokenHide" );
  954. // Max saves out double newlines, replace them with one.
  955. userProperties.replace( "\r\n", "\n" );
  956. U32 propertyCount = StringUnit::getUnitCount( userProperties, "\n" );
  957. for ( U32 i = 0; i < propertyCount; i++ )
  958. {
  959. String propertyStr = StringUnit::getUnit( userProperties, i, "\n" );
  960. U32 wordCount = StringUnit::getUnitCount( propertyStr, "=" );
  961. if ( wordCount == 0 )
  962. {
  963. // We sometimes get empty lines between properties,
  964. // which doesn't break anything.
  965. continue;
  966. }
  967. if ( wordCount != 2 )
  968. {
  969. Con::warnf( "PxMultiActor::_createJointUserData, malformed UserProperty string (%s) for joint (%s)", propertyStr.c_str(), joint->getName() );
  970. continue;
  971. }
  972. String propertyName = StringUnit::getUnit( propertyStr, 0, "=" );
  973. String propertyValue = StringUnit::getUnit( propertyStr, 1, "=" );
  974. Vector<NxActor*> *dstVector = NULL;
  975. if ( propertyName.equal( showStr, String::NoCase ) )
  976. dstVector = &jointData->mBrokenActors;
  977. else if ( propertyName.equal( hideStr, String::NoCase ) )
  978. dstVector = &jointData->mUnbrokenActors;
  979. if ( !dstVector )
  980. continue;
  981. U32 valueCount = StringUnit::getUnitCount( propertyValue, "," );
  982. for ( U32 j = 0; j < valueCount; j++ )
  983. {
  984. String val = StringUnit::getUnit( propertyValue, j, "," );
  985. NxActor *pActor = _findActor( val );
  986. if ( !pActor )
  987. Con::warnf( "PxMultiActor::_createJointUserData, actor (%s) was not found when parsing UserProperties for joint (%s)", val.c_str(), joint->getName() );
  988. else
  989. {
  990. dstVector->push_back( pActor );
  991. if ( dstVector == &jointData->mBrokenActors )
  992. {
  993. NxMat34 relXfm = pActor->getGlobalPose();
  994. relXfm.multiply( relXfm, actorSpaceXfm );
  995. jointData->mRelXfm.push_back( relXfm );
  996. }
  997. }
  998. }
  999. }
  1000. return jointData;
  1001. }
  1002. NxActor* PxMultiActor::_findActor( const String &actorName ) const
  1003. {
  1004. for ( U32 i = 0; i < mActors.size(); i++ )
  1005. {
  1006. NxActor *actor = mActors[i];
  1007. if ( !actor )
  1008. continue;
  1009. if ( dStricmp( actor->getName(), actorName ) == 0 )
  1010. return actor;
  1011. }
  1012. return NULL;
  1013. }
  1014. String PxMultiActor::_getMeshName( const NxActor *actor ) const
  1015. {
  1016. String meshName = actor->getName();
  1017. meshName.replace( "_pxactor", "" );
  1018. //meshName = StringUnit::getUnit( meshName, 0, "_" );
  1019. return meshName;
  1020. }
  1021. bool PxMultiActor::onNewDataBlock( GameBaseData *dptr, bool reload )
  1022. {
  1023. mDataBlock = dynamic_cast<PxMultiActorData*>(dptr);
  1024. if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
  1025. return false;
  1026. // JCF: if we supported it, we would recalculate the value of mIsDummy now,
  1027. // but that would really hose everything since an object that was a dummy
  1028. // wouldn't have any actors and would need to create them, etc...
  1029. scriptOnNewDataBlock();
  1030. return true;
  1031. }
  1032. void PxMultiActor::inspectPostApply()
  1033. {
  1034. // Make sure we call the parent... else
  1035. // we won't get transform and scale updates!
  1036. Parent::inspectPostApply();
  1037. //setMaskBits( LightMask );
  1038. setMaskBits( UpdateMask );
  1039. }
  1040. void PxMultiActor::onStaticModified( const char *slotName, const char *newValue )
  1041. {
  1042. if ( isProperlyAdded() && dStricmp( slotName, "broken" ) == 0 )
  1043. setAllBroken( dAtob(newValue) );
  1044. }
  1045. void PxMultiActor::onDeleteNotify( SimObject *obj )
  1046. {
  1047. Parent::onDeleteNotify(obj);
  1048. if ( obj == mMount.object )
  1049. unmount();
  1050. }
  1051. void PxMultiActor::onFileNotify()
  1052. {
  1053. // Destroy the existing actors and recreate them...
  1054. mWorld->getPhysicsResults();
  1055. _destroyActors();
  1056. _createActors( mResetXfm );
  1057. }
  1058. void PxMultiActor::onPhysicsReset( PhysicsResetEvent reset )
  1059. {
  1060. // Dummies don't create or destroy actors, they just reuse the
  1061. // server object's ones.
  1062. if ( mIsDummy )
  1063. return;
  1064. // Store the reset transform for later use.
  1065. if ( reset == PhysicsResetEvent_Store )
  1066. {
  1067. mRootActor->getGlobalPose().getRowMajor44( mResetXfm );
  1068. }
  1069. else if ( reset == PhysicsResetEvent_Restore )
  1070. {
  1071. // Destroy the existing actors and recreate them to
  1072. // ensure they are in the proper mission startup state.
  1073. mWorld->getPhysicsResults();
  1074. _destroyActors();
  1075. _createActors( mResetXfm );
  1076. }
  1077. for ( U32 i = 0; i < mActors.size(); i++ )
  1078. {
  1079. if ( !mActors[i] )
  1080. continue;
  1081. mActors[i]->wakeUp();
  1082. }
  1083. }
  1084. void PxMultiActor::prepRenderImage( SceneRenderState *state )
  1085. {
  1086. PROFILE_SCOPE( PxMultiActor_PrepRenderImage );
  1087. if ( !mShapeInstance )
  1088. return;
  1089. Point3F cameraOffset;
  1090. getTransform().getColumn(3,&cameraOffset);
  1091. cameraOffset -= state->getDiffuseCameraPosition();
  1092. F32 dist = cameraOffset.len();
  1093. if ( dist < 0.01f )
  1094. dist = 0.01f;
  1095. F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z));
  1096. S32 dl = mShapeInstance->setDetailFromDistance( state, dist * invScale );
  1097. if ( dl < 0 )
  1098. return;
  1099. GFXTransformSaver saver;
  1100. // Set up our TS render state here.
  1101. TSRenderState rdata;
  1102. rdata.setSceneState( state );
  1103. // We might have some forward lit materials
  1104. // so pass down a query to gather lights.
  1105. LightQuery query;
  1106. query.init( getWorldSphere() );
  1107. rdata.setLightQuery( &query );
  1108. MatrixF mat = getRenderTransform();
  1109. mat.scale( getScale() );
  1110. GFX->setWorldMatrix( mat );
  1111. if ( mDebugRender || Con::getBoolVariable( "$PxDebug::render", false ) )
  1112. {
  1113. ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
  1114. ri->renderDelegate.bind( this, &PxMultiActor::_debugRender );
  1115. ri->type = RenderPassManager::RIT_Object;
  1116. state->getRenderPass()->addInst( ri );
  1117. }
  1118. else
  1119. mShapeInstance->render( rdata );
  1120. }
  1121. void PxMultiActor::_debugRender( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
  1122. {
  1123. if ( mShapeInstance )
  1124. {
  1125. GFXTransformSaver saver;
  1126. MatrixF mat = getRenderTransform();
  1127. mat.scale( mObjScale );
  1128. GFX->multWorld( mat );
  1129. //mShapeInstance->renderDebugNodes();
  1130. }
  1131. Vector<NxActor*> *actors = &mActors;
  1132. if ( mIsDummy )
  1133. {
  1134. PxMultiActor *serverObj = static_cast<PxMultiActor*>( mServerObject.getObject() );
  1135. if ( serverObj )
  1136. actors = &serverObj->mActors;
  1137. }
  1138. if ( !actors )
  1139. return;
  1140. for ( U32 i = 0; i < actors->size(); i++ )
  1141. {
  1142. NxActor *pActor = (*actors)[i];
  1143. if ( !pActor )
  1144. continue;
  1145. PxUtils::drawActor( pActor );
  1146. }
  1147. }
  1148. void PxMultiActor::_onJointBreak( NxReal breakForce, NxJoint &brokenJoint )
  1149. {
  1150. // Dummies do not have physics objects
  1151. // and shouldn't receive this callback.
  1152. if ( mIsDummy )
  1153. return;
  1154. NxActor *actor0 = NULL;
  1155. NxActor *actor1 = NULL;
  1156. brokenJoint.getActors( &actor0, &actor1 );
  1157. NxMat34 parentPose = actor0->getGlobalPose();
  1158. Point3F jointPos = pxCast<Point3F>( brokenJoint.getGlobalAnchor() );
  1159. PxUserData *jointData = PxUserData::getData( brokenJoint );
  1160. setBroken( parentPose, NxVec3( 0.0f ), jointData, true );
  1161. // NOTE: We do not NULL the joint in the list,
  1162. // or release it here, as we allow it to be released
  1163. // by the _destroyActors function on a reset or destruction
  1164. // of the PxMultiActor.
  1165. }
  1166. void PxMultiActor::_onContact( PhysicsUserData *us,
  1167. PhysicsUserData *them,
  1168. const Point3F &hitPoint,
  1169. const Point3F &hitForce )
  1170. {
  1171. PxUserData *data = (PxUserData*)us;
  1172. if ( data &&
  1173. !data->mIsBroken &&
  1174. hitForce.len() > mDataBlock->breakForce )
  1175. setAllBroken( true );
  1176. }
  1177. U32 PxMultiActor::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
  1178. {
  1179. U32 retMask = Parent::packUpdate(con, mask, stream);
  1180. stream->writeFlag( mDebugRender );
  1181. stream->writeFlag( mask & SleepMask );
  1182. if ( stream->writeFlag( mask & WarpMask ) )
  1183. {
  1184. stream->writeAffineTransform( getTransform() );
  1185. }
  1186. else if ( stream->writeFlag( mask & MoveMask ) )
  1187. {
  1188. /*
  1189. stream->writeAffineTransform( getTransform() );
  1190. NxActor *actor = mActors[ mDataBlock->correctionNodes[0] ];
  1191. const NxVec3& linVel = actor->getLinearVelocity();
  1192. stream->write( linVel.x );
  1193. stream->write( linVel.y );
  1194. stream->write( linVel.z );
  1195. */
  1196. }
  1197. // This internally uses the mask passed to it.
  1198. if ( mLightPlugin )
  1199. retMask |= mLightPlugin->packUpdate( this, LightMask, con, mask, stream );
  1200. return retMask;
  1201. }
  1202. void PxMultiActor::unpackUpdate(NetConnection *con, BitStream *stream)
  1203. {
  1204. Parent::unpackUpdate(con, stream);
  1205. mDebugRender = stream->readFlag();
  1206. if ( stream->readFlag() ) // SleepMask
  1207. {
  1208. for ( S32 i = 0; i < mActors.size(); i++ )
  1209. {
  1210. NxActor *actor = mActors[i];
  1211. if ( !actor )
  1212. continue;
  1213. if ( actor )
  1214. actor->putToSleep();
  1215. }
  1216. }
  1217. if ( stream->readFlag() ) // WarpMask
  1218. {
  1219. // If we set a warp mask,
  1220. // we need to instantly move
  1221. // the actor to the new position
  1222. // without applying any corrections.
  1223. MatrixF mat;
  1224. stream->readAffineTransform( &mat );
  1225. applyWarp( mat, true, false );
  1226. }
  1227. else if ( stream->readFlag() ) // MoveMask
  1228. {
  1229. /*
  1230. MatrixF mat;
  1231. stream->readAffineTransform( &mat );
  1232. NxVec3 linVel, angVel;
  1233. stream->read( &linVel.x );
  1234. stream->read( &linVel.y );
  1235. stream->read( &linVel.z );
  1236. applyCorrection( mat, linVel, angVel );
  1237. */
  1238. }
  1239. /*
  1240. if ( stream->readFlag() ) // ImpulseMask
  1241. {
  1242. // TODO : Set up correction nodes.
  1243. NxVec3 linVel;
  1244. stream->read( &linVel.x );
  1245. stream->read( &linVel.y );
  1246. stream->read( &linVel.z );
  1247. NxActor *actor = mActors[ mDataBlock->correctionNodes[0] ];
  1248. if ( actor )
  1249. {
  1250. mWorld->releaseWriteLock();
  1251. actor->setLinearVelocity( linVel );
  1252. mStartImpulse.zero();
  1253. }
  1254. else
  1255. mStartImpulse.set( linVel.x, linVel.y, linVel.z );
  1256. }
  1257. */
  1258. if ( mLightPlugin )
  1259. mLightPlugin->unpackUpdate( this, con, stream );
  1260. }
  1261. void PxMultiActor::setScale( const VectorF& scale )
  1262. {
  1263. if ( scale == getScale() )
  1264. return;
  1265. // This is so that the level
  1266. // designer can change the scale
  1267. // of a PhysXSingleActor in the editor
  1268. // and have the PhysX representation updated properly.
  1269. // First we call the parent's setScale
  1270. // so that the ScaleMask can be set.
  1271. Parent::setScale( scale );
  1272. // Check to see if the scale has really changed.
  1273. if ( !isProperlyAdded() || mActorScale.equal( scale ) )
  1274. return;
  1275. // Recreate the physics actors.
  1276. _destroyActors();
  1277. _createActors( getTransform() );
  1278. }
  1279. void PxMultiActor::applyWarp( const MatrixF& newMat, bool interpRender, bool sweep )
  1280. {
  1281. // Do we have actors to move?
  1282. if ( mRootActor )
  1283. {
  1284. // Get ready to change the physics state.
  1285. mWorld->releaseWriteLock();
  1286. /// Convert the new transform to nx.
  1287. NxMat34 destXfm;
  1288. destXfm.setRowMajor44( newMat );
  1289. // Get the inverse of the root actor transform
  1290. // so we can move all the actors relative to it.
  1291. NxMat34 rootInverseXfm;
  1292. mRootActor->getGlobalPose().getInverse( rootInverseXfm );
  1293. // Offset all the actors.
  1294. MatrixF tMat;
  1295. NxMat34 newXfm, relXfm;
  1296. for ( S32 i = 0; i < mActors.size(); i++ )
  1297. {
  1298. NxActor *actor = mActors[i];
  1299. if ( !actor )
  1300. continue;
  1301. const bool isKinematic = actor->readBodyFlag( NX_BF_KINEMATIC );
  1302. // Stop any velocity on it.
  1303. if ( !isKinematic )
  1304. {
  1305. actor->setAngularVelocity( NxVec3( 0.0f ) );
  1306. actor->setLinearVelocity( NxVec3( 0.0f ) );
  1307. }
  1308. // Get the transform relative to the current root.
  1309. relXfm.multiply( actor->getGlobalPose(), rootInverseXfm );
  1310. /*
  1311. if ( sweep )
  1312. {
  1313. actor->getGl obalPose().getRowMajor44( mResetPos[i] );
  1314. sweepTest( &newMat );
  1315. }
  1316. */
  1317. //
  1318. newXfm.multiply( relXfm, destXfm );
  1319. //if ( isKinematic )
  1320. //actor->moveGlobalPose( newXfm );
  1321. //else
  1322. actor->setGlobalPose( newXfm );
  1323. // Reset the delta.
  1324. Delta &delta = mActorDeltas[i];
  1325. delta.pos = pxCast<Point3F>( newXfm.t );
  1326. newXfm.getRowMajor44( tMat );
  1327. delta.rot.set( tMat );
  1328. if ( !interpRender )
  1329. {
  1330. mActorDeltas[i].lastPos = mActorDeltas[i].pos;
  1331. mActorDeltas[i].lastRot = mActorDeltas[i].rot;
  1332. }
  1333. }
  1334. }
  1335. Parent::setTransform( newMat );
  1336. mDelta.pos = newMat.getPosition();
  1337. mDelta.rot = newMat;
  1338. if ( !interpRender )
  1339. {
  1340. mDelta.lastPos = mDelta.pos;
  1341. mDelta.lastRot = mDelta.rot;
  1342. }
  1343. }
  1344. /*
  1345. bool PxMultiActor::_setPositionField( void *obj, const char *data )
  1346. {
  1347. PxMultiActor *object = reinterpret_cast<PxMultiActor*>( obj );
  1348. MatrixF transform( object->getTransform() );
  1349. Con::setData( TypeMatrixPosition, &transform, 0, 1, &data );
  1350. object->setTransform( transform );
  1351. return false;
  1352. }
  1353. const char* PxMultiActor::_getPositionField( void *obj, const char *data )
  1354. {
  1355. PxMultiActor *object = reinterpret_cast<PxMultiActor*>( obj );
  1356. return Con::getData( TypeMatrixPosition,
  1357. &object->mObjToWorld,
  1358. 0 );
  1359. }
  1360. bool PxMultiActor::_setRotationField( void *obj, const char *data )
  1361. {
  1362. PxMultiActor *object = reinterpret_cast<PxMultiActor*>( obj );
  1363. MatrixF transform( object->getTransform() );
  1364. Con::setData( TypeMatrixRotation, &transform, 0, 1, &data );
  1365. object->setTransform( transform );
  1366. return false;
  1367. }
  1368. const char* PxMultiActor::_getRotationField( void *obj, const char *data )
  1369. {
  1370. PxMultiActor *object = reinterpret_cast<PxMultiActor*>( obj );
  1371. return Con::getData( TypeMatrixRotation,
  1372. &object->mObjToWorld,
  1373. 0 );
  1374. }
  1375. */
  1376. void PxMultiActor::setTransform( const MatrixF& mat )
  1377. {
  1378. applyWarp( mat, false, true );
  1379. setMaskBits( WarpMask );
  1380. }
  1381. void PxMultiActor::mountObject( SceneObject *obj, U32 node )
  1382. {
  1383. if (obj->getObjectMount())
  1384. obj->unmount();
  1385. obj->mountObject( this, (node >= 0 && node < PxMultiActorData::NumMountPoints) ? node: 0 );
  1386. }
  1387. void PxMultiActor::unmountObject( SceneObject *obj )
  1388. {
  1389. obj->unmountObject( this );
  1390. }
  1391. bool PxMultiActor::_getNodeTransform( U32 nodeIdx, MatrixF *outXfm )
  1392. {
  1393. if ( !mShapeInstance )
  1394. return false;
  1395. PxMultiActor *actorOwner = this;
  1396. if ( mIsDummy )
  1397. {
  1398. actorOwner = static_cast<PxMultiActor*>( mServerObject.getObject() );
  1399. if ( !actorOwner )
  1400. return false;
  1401. }
  1402. TSShape *shape = mShapeInstance->getShape();
  1403. String nodeName = shape->getNodeName( nodeIdx );
  1404. NxActor *pActor = NULL;
  1405. UTF8 comparisonName[260] = { 0 };
  1406. S32 dummy = -1;
  1407. // Convert the passed node name to a valid actor name.
  1408. dStrcpy( comparisonName, String::GetTrailingNumber( nodeName, dummy ) );
  1409. dSprintf( comparisonName, sizeof( comparisonName ), "%s_pxactor", comparisonName );
  1410. // If we have an actor with that name, we are done.
  1411. pActor = actorOwner->_findActor( comparisonName );
  1412. if ( pActor )
  1413. {
  1414. pActor->getGlobalPose().getRowMajor44( *outXfm );
  1415. return true;
  1416. }
  1417. // Check if the parent node has an actor...
  1418. S32 parentIdx = shape->nodes[nodeIdx].parentIndex;
  1419. if ( parentIdx == -1 )
  1420. return false;
  1421. const String &parentName = shape->getNodeName( parentIdx );
  1422. dStrcpy( comparisonName, String::GetTrailingNumber( parentName, dummy ) );
  1423. dSprintf( comparisonName, sizeof( comparisonName ), "%s_pxactor", comparisonName );
  1424. pActor = actorOwner->_findActor( comparisonName );
  1425. if ( !pActor )
  1426. return false;
  1427. MatrixF actorMat;
  1428. pActor->getGlobalPose().getRowMajor44( actorMat );
  1429. MatrixF nmat;
  1430. QuatF q;
  1431. TSTransform::setMatrix( shape->defaultRotations[nodeIdx].getQuatF(&q),shape->defaultTranslations[nodeIdx],&nmat);
  1432. *outXfm->mul( actorMat, nmat );
  1433. return true;
  1434. }
  1435. void PxMultiActor::getMountTransform(U32 mountPoint,MatrixF* mat)
  1436. {
  1437. // Returns mount point to world space transform
  1438. if (mountPoint < PxMultiActorData::NumMountPoints) {
  1439. S32 ni = mDataBlock->mountPointNode[mountPoint];
  1440. if (ni != -1) {
  1441. if ( _getNodeTransform( ni, mat ) )
  1442. return;
  1443. }
  1444. }
  1445. *mat = mObjToWorld;
  1446. }
  1447. void PxMultiActor::getRenderMountTransform(U32 mountPoint,MatrixF* mat)
  1448. {
  1449. // Returns mount point to world space transform
  1450. if (mountPoint < PxMultiActorData::NumMountPoints) {
  1451. S32 ni = mDataBlock->mountPointNode[mountPoint];
  1452. if (ni != -1) {
  1453. if ( _getNodeTransform( ni, mat ) )
  1454. return;
  1455. }
  1456. }
  1457. *mat = getRenderTransform();
  1458. }
  1459. void PxMultiActor::processTick( const Move *move )
  1460. {
  1461. PROFILE_SCOPE( PxMultiActor_ProcessTick );
  1462. // Set the last pos/rot to the
  1463. // values of the previous tick for interpolateTick.
  1464. mDelta.lastPos = mDelta.pos;
  1465. mDelta.lastRot = mDelta.rot;
  1466. /*
  1467. NxActor *corrActor = mActors[ mDataBlock->correctionNodes[0] ];
  1468. if ( corrActor->isSleeping() || corrActor->readBodyFlag( NX_BF_FROZEN ) )
  1469. {
  1470. if ( !mSleepingLastTick )
  1471. setMaskBits( WarpMask | SleepMask );
  1472. mSleepingLastTick = true;
  1473. // HACK! Refactor sleeping so that we don't
  1474. // sleep when only one correction actor does.
  1475. _updateBounds();
  1476. return;
  1477. }
  1478. mSleepingLastTick = false;
  1479. */
  1480. MatrixF mat;
  1481. Vector<NxActor*> *actors;
  1482. if ( mIsDummy )
  1483. {
  1484. PxMultiActor *serverObj = static_cast<PxMultiActor*>( mServerObject.getObject() );
  1485. if ( !serverObj )
  1486. return;
  1487. mat = serverObj->getTransform();
  1488. actors = &serverObj->mActors;
  1489. }
  1490. else
  1491. {
  1492. // Container buoyancy & drag
  1493. _updateContainerForces();
  1494. // Save the transform from the root actor.
  1495. mRootActor->getGlobalPose().getRowMajor44( mat );
  1496. actors = &mActors;
  1497. }
  1498. // Update the transform and the root delta.
  1499. Parent::setTransform( mat );
  1500. mDelta.pos = mat.getPosition();
  1501. mDelta.rot.set( mat );
  1502. // On the client we update the individual
  1503. // actor deltas as well for interpolation.
  1504. if ( isClientObject() )
  1505. {
  1506. PROFILE_SCOPE( PxMultiActor_ProcessTick_UpdateDeltas );
  1507. for ( U32 i = 0; i < mActorDeltas.size(); i++ )
  1508. {
  1509. if ( !(*actors)[i] )
  1510. continue;
  1511. Delta &delta = mActorDeltas[i];
  1512. // Store the last position.
  1513. delta.lastPos = delta.pos;
  1514. delta.lastRot = delta.rot;
  1515. // Get the new position.
  1516. (*actors)[i]->getGlobalPose().getRowMajor44( (NxF32*)mat );
  1517. // Calculate the delta between the current
  1518. // global pose and the last global pose.
  1519. delta.pos = mat.getPosition();
  1520. delta.rot.set( mat );
  1521. }
  1522. }
  1523. // Update the bounding box to match the physics.
  1524. _updateBounds();
  1525. // Set the MoveMask so this will be updated to the client.
  1526. //setMaskBits( MoveMask );
  1527. }
  1528. void PxMultiActor::interpolateTick( F32 delta )
  1529. {
  1530. PROFILE_SCOPE( PxMultiActor_InterpolateTick );
  1531. Point3F interpPos;
  1532. QuatF interpRot;
  1533. {
  1534. // Interpolate the position based on the delta.
  1535. interpPos.interpolate( mDelta.pos, mDelta.lastPos, delta );
  1536. // Interpolate the rotation based on the delta.
  1537. interpRot.interpolate( mDelta.rot, mDelta.lastRot, delta );
  1538. // Set up the interpolated transform.
  1539. MatrixF interpMat;
  1540. interpRot.setMatrix( &interpMat );
  1541. interpMat.setPosition( interpPos );
  1542. Parent::setRenderTransform( interpMat );
  1543. }
  1544. PxMultiActor *srcObj = NULL;
  1545. if ( mIsDummy )
  1546. srcObj = static_cast<PxMultiActor*>( mServerObject.getObject() );
  1547. else
  1548. srcObj = this;
  1549. // JCF: to disable applying NxActor positions to the renderable mesh
  1550. // you can uncomment this line.
  1551. //srcObj = NULL;
  1552. if ( mShapeInstance && srcObj != NULL )
  1553. {
  1554. mShapeInstance->animate();
  1555. getDynamicXfms( srcObj, delta );
  1556. }
  1557. }
  1558. /*
  1559. void PxMultiActor::sweepTest( MatrixF *mat )
  1560. {
  1561. NxVec3 nxCurrPos = getPosition();
  1562. // If the position is zero,
  1563. // the parent hasn't been updated yet
  1564. // and we don't even need to do the sweep test.
  1565. // This is a fix for a problem that was happening
  1566. // where on the add of the PhysXSingleActor, it would
  1567. // set the position to a very small value because it would be getting a hit
  1568. // even though the current position was 0.
  1569. if ( nxCurrPos.isZero() )
  1570. return;
  1571. // Set up the flags and the query structure.
  1572. NxU32 flags = NX_SF_STATICS | NX_SF_DYNAMICS;
  1573. NxSweepQueryHit sweepResult;
  1574. dMemset( &sweepResult, 0, sizeof( sweepResult ) );
  1575. NxVec3 nxNewPos = mat->getPosition();
  1576. // Get the velocity which will be our sweep direction and distance.
  1577. NxVec3 nxDir = nxNewPos - nxCurrPos;
  1578. if ( nxDir.isZero() )
  1579. return;
  1580. NxActor *corrActor = mActors[ mDataBlock->correctionNodes[0] ];
  1581. // Get the scene and do the sweep.
  1582. corrActor->wakeUp();
  1583. corrActor->linearSweep( nxDir, flags, NULL, 1, &sweepResult, NULL );
  1584. if ( sweepResult.hitShape && sweepResult.t < nxDir.magnitude() )
  1585. {
  1586. nxDir.normalize();
  1587. nxDir *= sweepResult.t;
  1588. nxCurrPos += nxDir;
  1589. mat->setPosition( Point3F( nxCurrPos.x, nxCurrPos.y, nxCurrPos.z ) );
  1590. }
  1591. }
  1592. */
  1593. /*
  1594. void PxMultiActor::applyCorrection( const MatrixF& mat, const NxVec3& linVel, const NxVec3& angVel )
  1595. {
  1596. // Sometimes the actor hasn't been
  1597. // created yet during the call from unpackUpdate.
  1598. NxActor *corrActor = mActors[ mDataBlock->correctionNodes[0] ];
  1599. if ( !corrActor || mForceSleep )
  1600. return;
  1601. NxVec3 newPos = mat.getPosition();
  1602. NxVec3 currPos = getPosition();
  1603. NxVec3 offset = newPos - currPos;
  1604. // If the difference isn't large enough,
  1605. // just set the new transform, no correction.
  1606. if ( offset.magnitude() > 0.3f )
  1607. {
  1608. // If we're going to set the linear or angular velocity,
  1609. // we do it before we add a corrective force, since it would be overwritten otherwise.
  1610. NxVec3 currLinVel, currAngVel;
  1611. currLinVel = corrActor->getLinearVelocity();
  1612. currAngVel = corrActor->getAngularVelocity();
  1613. // Scale the corrective force by half,
  1614. // otherwise it will over correct and oscillate.
  1615. NxVec3 massCent = corrActor->getCMassGlobalPosition();
  1616. corrActor->addForceAtPos( offset, massCent, NX_SMOOTH_VELOCITY_CHANGE );
  1617. // If the linear velocity is divergent enough, change to server linear velocity.
  1618. if ( (linVel - currLinVel).magnitude() > 0.3f )
  1619. corrActor->setLinearVelocity( linVel );
  1620. // Same for angular.
  1621. if ( (angVel - currAngVel).magnitude() > 0.3f )
  1622. corrActor->setAngularVelocity( angVel );
  1623. }
  1624. Parent::setTransform( mat );
  1625. }
  1626. */
  1627. void PxMultiActor::_updateBounds()
  1628. {
  1629. PROFILE_SCOPE( PxMultiActor_UpdateBounds );
  1630. if ( mIsDummy )
  1631. {
  1632. PxMultiActor *serverObj = static_cast<PxMultiActor*>( mServerObject.getObject() );
  1633. if ( !serverObj )
  1634. return;
  1635. mWorldBox = serverObj->getWorldBox();
  1636. mWorldSphere = serverObj->getWorldSphere();
  1637. mObjBox = serverObj->getObjBox();
  1638. mRenderWorldBox = serverObj->getRenderWorldBox();
  1639. mRenderWorldSphere = mWorldSphere;
  1640. return;
  1641. }
  1642. NxBounds3 bounds;
  1643. bounds.setEmpty();
  1644. NxBounds3 shapeBounds;
  1645. for ( U32 i = 0; i < mActors.size(); i++ )
  1646. {
  1647. NxActor *pActor = mActors[i];
  1648. if ( !pActor || pActor->readActorFlag( NX_AF_DISABLE_COLLISION ) )
  1649. continue;
  1650. NxShape *const* pShapeArray = pActor->getShapes();
  1651. U32 shapeCount = pActor->getNbShapes();
  1652. for ( U32 i = 0; i < shapeCount; i++ )
  1653. {
  1654. // Get the shape's bounds.
  1655. pShapeArray[i]->getWorldBounds( shapeBounds );
  1656. // Combine them into the total bounds.
  1657. bounds.combine( shapeBounds );
  1658. }
  1659. }
  1660. mWorldBox = pxCast<Box3F>( bounds );
  1661. mWorldBox.getCenter(&mWorldSphere.center);
  1662. mWorldSphere.radius = (mWorldBox.maxExtents - mWorldSphere.center).len();
  1663. mObjBox = mWorldBox;
  1664. mWorldToObj.mul(mObjBox);
  1665. mRenderWorldBox = mWorldBox;
  1666. mRenderWorldSphere = mWorldSphere;
  1667. }
  1668. void PxMultiActor::getDynamicXfms( PxMultiActor *srcObj, F32 dt )
  1669. {
  1670. PROFILE_SCOPE( PxMultiActor_getDynamicXfms );
  1671. Vector<MatrixF> *torqueXfms = &mShapeInstance->mNodeTransforms;
  1672. const MatrixF &objectXfm = getRenderWorldTransform();
  1673. AssertFatal( torqueXfms->size() == srcObj->mMappedActors.size(), "The two skeletons are different!" );
  1674. TSShape *shape = mShapeInstance->getShape();
  1675. // TODO: We're currently preparing deltas and getting
  1676. // dynamic xforms even if the object isn't visible.
  1677. // we should probably try to delay all this until
  1678. // we're about to render.
  1679. //
  1680. /*
  1681. // TODO: Set up deltas!
  1682. if ( mCurrPos.empty() || mCurrRot.empty() )
  1683. _prepareDeltas();
  1684. */
  1685. MatrixF globalXfm;
  1686. MatrixF mat, tmp;
  1687. QuatF newRot;
  1688. Point3F newPos;
  1689. S32 dl = mShapeInstance->getCurrentDetail();
  1690. if ( dl < 0 )
  1691. return;
  1692. const String &detailName = shape->getName( shape->details[dl].nameIndex );
  1693. S32 detailSize = -1;
  1694. String::GetTrailingNumber( detailName, detailSize );
  1695. for( S32 i = 0; i < srcObj->mMappedActors.size(); i++ )
  1696. {
  1697. NxActor *actor = srcObj->mMappedActors[i];
  1698. if ( !actor || actor->readBodyFlag( NX_BF_KINEMATIC ) )
  1699. continue;
  1700. // see if the node at this index is part of the
  1701. // currently visible detail level.
  1702. if ( srcObj->mMappedActorDL[i] != detailSize )
  1703. continue;
  1704. // Get the right actor delta structure.
  1705. U32 index = srcObj->mMappedToActorIndex[i];
  1706. const Delta &delta = mActorDeltas[index];
  1707. // Do the interpolation.
  1708. newRot.interpolate( delta.rot, delta.lastRot, dt );
  1709. newRot.setMatrix( &globalXfm );
  1710. newPos.interpolate( delta.pos, delta.lastPos, dt );
  1711. globalXfm.setPosition( newPos );
  1712. (*torqueXfms)[i].mul( objectXfm, globalXfm );
  1713. }
  1714. }
  1715. void PxMultiActor::applyImpulse( const Point3F &pos, const VectorF &vec )
  1716. {
  1717. // TODO : Implement this based on correction nodes.
  1718. /*
  1719. if ( !mWorld || !mActor )
  1720. return;
  1721. mWorld->releaseWriteLock();
  1722. NxVec3 linVel = mActor->getLinearVelocity();
  1723. NxVec3 nxVel( vel.x, vel.y, vel.z );
  1724. mActor->setLinearVelocity(linVel + nxVel);
  1725. */
  1726. // JCF: something more complex is required to apply forces / breakage
  1727. // on only individual actors, and we don't have enough data to do that
  1728. // within this method.
  1729. if ( vec.len() > mDataBlock->breakForce )
  1730. setAllBroken( true );
  1731. NxVec3 nxvec = pxCast<NxVec3>( vec );
  1732. NxVec3 nxpos = pxCast<NxVec3>( pos );
  1733. for ( U32 i = 0; i < mActors.size(); i++ )
  1734. {
  1735. NxActor *actor = mActors[i];
  1736. if ( actor->isDynamic() &&
  1737. !actor->readBodyFlag( NX_BF_KINEMATIC ) &&
  1738. !actor->readActorFlag( NX_AF_DISABLE_COLLISION ) )
  1739. {
  1740. actor->addForceAtPos( nxvec, nxpos, NX_IMPULSE );
  1741. }
  1742. }
  1743. //setMaskBits( ImpulseMask );
  1744. }
  1745. void PxMultiActor::applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude )
  1746. {
  1747. mWorld->releaseWriteLock();
  1748. // Find all currently enabled actors hit by the impulse radius...
  1749. Vector<NxActor*> hitActors;
  1750. NxVec3 nxorigin = pxCast<NxVec3>(origin);
  1751. NxSphere impulseSphere( nxorigin, radius );
  1752. for ( U32 i = 0; i < mActors.size(); i++ )
  1753. {
  1754. NxActor *pActor = mActors[i];
  1755. if ( pActor->readActorFlag( NX_AF_DISABLE_COLLISION ) ||
  1756. !pActor->isDynamic() ||
  1757. pActor->readBodyFlag( NX_BF_KINEMATIC ) )
  1758. continue;
  1759. U32 numShapes = pActor->getNbShapes();
  1760. NxShape *const* pShapeArray = pActor->getShapes();
  1761. for ( U32 j = 0; j < numShapes; j++ )
  1762. {
  1763. const NxShape *pShape = pShapeArray[j];
  1764. if ( pShape->checkOverlapSphere( impulseSphere ) )
  1765. {
  1766. hitActors.push_back( pActor );
  1767. break;
  1768. }
  1769. }
  1770. }
  1771. // Apply forces to hit actors, but swap out for broken
  1772. // actors first if appropriate...
  1773. for ( U32 i = 0; i < hitActors.size(); i++ )
  1774. {
  1775. NxActor *pActor = hitActors[i];
  1776. PxUserData *pUserData = PxUserData::getData( *pActor );
  1777. // TODO: We should calculate the real force accounting
  1778. // for falloff before we break things with it.
  1779. // If we have enough force, and this is an actor that
  1780. // can be 'broken' by impacts, break it now.
  1781. if ( pUserData &&
  1782. //pUserData->mCanPush &&
  1783. pUserData->mBrokenActors.size() > 0 &&
  1784. magnitude > mDataBlock->breakForce )
  1785. {
  1786. setBroken( pActor->getGlobalPose(),
  1787. pActor->getLinearVelocity(),
  1788. pUserData,
  1789. true );
  1790. // apply force that would have been applied to this actor
  1791. // to the broken actors we just enabled.
  1792. for ( U32 j = 0; j < pUserData->mBrokenActors.size(); j++ )
  1793. {
  1794. NxActor *pBrokenActor = pUserData->mBrokenActors[j];
  1795. _applyActorRadialForce( pBrokenActor, nxorigin, radius, magnitude );
  1796. }
  1797. }
  1798. else
  1799. {
  1800. // Apply force to the actor.
  1801. _applyActorRadialForce( pActor, nxorigin, radius, magnitude );
  1802. }
  1803. }
  1804. }
  1805. void PxMultiActor::_applyActorRadialForce( NxActor *inActor, const NxVec3 &origin, F32 radius, F32 magnitude )
  1806. {
  1807. // TODO: We're not getting a good torque force
  1808. // out of explosions because we're not picking
  1809. // the nearest point on the actor to the origin
  1810. // of the radial force.
  1811. NxVec3 force = inActor->getCMassGlobalPosition() - origin;
  1812. NxF32 dist = force.magnitude();
  1813. force.normalize();
  1814. if ( dist == 0.0f )
  1815. force *= magnitude;
  1816. else
  1817. force *= mClampF( radius / dist, 0.0f, 1.0f ) * magnitude;
  1818. // HACK: Make the position we push the force thru between the
  1819. // actor pos and its center of mass. This gives us some
  1820. // rotational force as well as make the covered structure
  1821. // explode better.
  1822. NxVec3 forcePos = ( inActor->getGlobalPosition() + inActor->getCMassGlobalPosition() ) / 2.0f;
  1823. inActor->addForceAtPos( force, forcePos, NX_VELOCITY_CHANGE );
  1824. }
  1825. void PxMultiActor::_updateContainerForces()
  1826. {
  1827. if ( !mWorld->getEnabled() )
  1828. return;
  1829. PROFILE_SCOPE( PxMultiActor_updateContainerForces );
  1830. // Update container drag and buoyancy properties ( for each Actor )
  1831. for ( U32 i = 0; i < mActors.size(); i++ )
  1832. {
  1833. NxActor *pActor = mActors[i];
  1834. if ( !pActor ||
  1835. pActor->readBodyFlag(NX_BF_KINEMATIC) ||
  1836. pActor->readActorFlag(NX_AF_DISABLE_COLLISION) )
  1837. continue;
  1838. // Get world bounds of this actor ( the combination of all shape bounds )
  1839. NxShape *const* shapes = pActor->getShapes();
  1840. NxBounds3 bounds;
  1841. bounds.setEmpty();
  1842. NxBounds3 shapeBounds;
  1843. for ( U32 i = 0; i < pActor->getNbShapes(); i++ )
  1844. {
  1845. NxShape *pShape = shapes[i];
  1846. pShape->getWorldBounds(shapeBounds);
  1847. bounds.combine( shapeBounds );
  1848. }
  1849. Box3F boundsBox = pxCast<Box3F>(bounds);
  1850. ContainerQueryInfo info;
  1851. info.box = boundsBox;
  1852. info.mass = pActor->getMass();
  1853. // Find and retreive physics info from intersecting WaterObject(s)
  1854. mContainer->findObjects( boundsBox, WaterObjectType|PhysicalZoneObjectType, findRouter, &info );
  1855. // Calculate buoyancy and drag
  1856. F32 angDrag = mDataBlock->angularDrag;
  1857. F32 linDrag = mDataBlock->linearDrag;
  1858. F32 buoyancy = 0.0f;
  1859. if ( true ) //info.waterCoverage >= 0.1f)
  1860. {
  1861. F32 waterDragScale = info.waterViscosity * mDataBlock->waterDragScale;
  1862. F32 powCoverage = mPow( info.waterCoverage, 0.25f );
  1863. if ( info.waterCoverage > 0.0f )
  1864. {
  1865. //angDrag = mBuildAngDrag * waterDragScale;
  1866. //linDrag = mBuildLinDrag * waterDragScale;
  1867. angDrag = mLerp( angDrag, angDrag * waterDragScale, powCoverage );
  1868. linDrag = mLerp( linDrag, linDrag * waterDragScale, powCoverage );
  1869. }
  1870. buoyancy = ( info.waterDensity / mDataBlock->buoyancyDensity ) * mPow( info.waterCoverage, 2.0f );
  1871. }
  1872. // Apply drag (dampening)
  1873. pActor->setLinearDamping( linDrag );
  1874. pActor->setAngularDamping( angDrag );
  1875. // Apply buoyancy force
  1876. if ( buoyancy != 0 )
  1877. {
  1878. // A little hackery to prevent oscillation
  1879. // Based on this blog post:
  1880. // (http://reinot.blogspot.com/2005/11/oh-yes-they-float-georgie-they-all.html)
  1881. // JCF: disabled!
  1882. NxVec3 gravity;
  1883. mWorld->getScene()->getGravity(gravity);
  1884. //NxVec3 velocity = pActor->getLinearVelocity();
  1885. NxVec3 buoyancyForce = buoyancy * -gravity * TickSec * pActor->getMass();
  1886. //F32 currHeight = getPosition().z;
  1887. //const F32 C = 2.0f;
  1888. //const F32 M = 0.1f;
  1889. //if ( currHeight + velocity.z * TickSec * C > info.waterHeight )
  1890. // buoyancyForce *= M;
  1891. pActor->addForceAtPos( buoyancyForce, pActor->getCMassGlobalPosition(), NX_IMPULSE );
  1892. }
  1893. // Apply physical zone forces
  1894. if ( info.appliedForce.len() > 0.001f )
  1895. pActor->addForceAtPos( pxCast<NxVec3>(info.appliedForce), pActor->getCMassGlobalPosition(), NX_IMPULSE );
  1896. }
  1897. }
  1898. /*
  1899. ConsoleMethod( PxMultiActor, applyImpulse, void, 3, 3, "applyImpulse - takes a velocity vector to apply")
  1900. {
  1901. VectorF vec;
  1902. dSscanf( argv[2],"%g %g %g",
  1903. &vec.x,&vec.y,&vec.z );
  1904. object->applyImpulse( vec );
  1905. }
  1906. */
  1907. void PxMultiActor::setAllBroken( bool isBroken )
  1908. {
  1909. PROFILE_SCOPE( PxMultiActor_SetAllBroken );
  1910. if ( mIsDummy )
  1911. {
  1912. PxMultiActor *serverObj = static_cast<PxMultiActor*>( mServerObject.getObject() );
  1913. serverObj->setAllBroken( isBroken );
  1914. return;
  1915. }
  1916. mWorld->releaseWriteLock();
  1917. NxActor *actor0 = NULL;
  1918. NxActor *actor1 = NULL;
  1919. NxMat34 parentPose;
  1920. for ( U32 i = 0; i < mJoints.size(); i++ )
  1921. {
  1922. NxJoint *joint = mJoints[i];
  1923. if ( !joint )
  1924. continue;
  1925. PxUserData *jointData = PxUserData::getData( *joint );
  1926. if ( !jointData )
  1927. continue;
  1928. joint->getActors( &actor0, &actor1 );
  1929. parentPose = actor0->getGlobalPose();
  1930. setBroken( parentPose, NxVec3(0.0f), jointData, isBroken );
  1931. }
  1932. for ( U32 i = 0; i < mActors.size(); i++ )
  1933. {
  1934. NxActor *actor = mActors[i];
  1935. if ( !actor )
  1936. continue;
  1937. PxUserData *actorData = PxUserData::getData( *actor );
  1938. if ( !actorData )
  1939. continue;
  1940. setBroken( actor->getGlobalPose(),
  1941. actor->getLinearVelocity(),
  1942. actorData,
  1943. isBroken );
  1944. }
  1945. }
  1946. void PxMultiActor::setBroken( const NxMat34 &parentPose,
  1947. const NxVec3 &parentVel,
  1948. PxUserData *userData,
  1949. bool isBroken )
  1950. {
  1951. PROFILE_SCOPE( PxMultiActor_SetBroken );
  1952. // TODO: This function is highly inefficent and
  1953. // way too complex to follow... the hacked single
  1954. // player mode doesn't help.
  1955. // Be careful not to set something broken twice.
  1956. if ( isBroken &&
  1957. userData->mIsBroken == isBroken )
  1958. return;
  1959. userData->mIsBroken = isBroken;
  1960. Vector<NxActor*> *hideActors = NULL;
  1961. Vector<NxActor*> *showActors = NULL;
  1962. if ( isBroken )
  1963. {
  1964. hideActors = &userData->mUnbrokenActors;
  1965. showActors = &userData->mBrokenActors;
  1966. }
  1967. else
  1968. {
  1969. hideActors = &userData->mBrokenActors;
  1970. showActors = &userData->mUnbrokenActors;
  1971. }
  1972. NxActor *pActor = NULL;
  1973. MatrixF tMat;
  1974. for ( U32 i = 0; i < hideActors->size(); i++ )
  1975. {
  1976. pActor = (*hideActors)[i];
  1977. pActor->raiseActorFlag( NX_AF_DISABLE_COLLISION );
  1978. pActor->raiseBodyFlag( NX_BF_KINEMATIC );
  1979. pActor->putToSleep();
  1980. NxShape *const* pShapeArray = pActor->getShapes();
  1981. U32 shapeCount = pActor->getNbShapes();
  1982. for ( U32 i = 0; i < shapeCount; i++ )
  1983. pShapeArray[i]->setFlag( NX_SF_DISABLE_RAYCASTING, true );
  1984. setMeshHidden( _getMeshName( pActor ), true );
  1985. }
  1986. // Get the client side delta array.
  1987. Vector<Delta> *actorDeltas = NULL;
  1988. if ( isClientObject() )
  1989. actorDeltas = &mActorDeltas;
  1990. else if ( isServerObject() && PHYSICSMGR->isSinglePlayer() )
  1991. {
  1992. PxMultiActor *clientObj = static_cast<PxMultiActor*>( getClientObject() );
  1993. if ( clientObj )
  1994. actorDeltas = &clientObj->mActorDeltas;
  1995. }
  1996. U32 index;
  1997. for ( U32 i = 0; i < showActors->size(); i++ )
  1998. {
  1999. pActor = (*showActors)[i];
  2000. if ( showActors == &userData->mBrokenActors )
  2001. {
  2002. NxMat34 pose;
  2003. pose.multiply( parentPose, userData->mRelXfm[i] );
  2004. pActor->setGlobalPose( pose );
  2005. if ( actorDeltas )
  2006. {
  2007. for ( U32 j=0; j < mMappedActors.size(); j++ )
  2008. {
  2009. if ( mMappedActors[j] == pActor )
  2010. {
  2011. index = mMappedToActorIndex[j];
  2012. // Reset the delta.
  2013. Delta &delta = (*actorDeltas)[index];
  2014. delta.pos = pxCast<Point3F>( pose.t );
  2015. pose.getRowMajor44( tMat );
  2016. delta.rot.set( tMat );
  2017. delta.lastPos = delta.pos;
  2018. delta.lastRot = delta.rot;
  2019. break;
  2020. }
  2021. }
  2022. }
  2023. }
  2024. pActor->clearActorFlag( NX_AF_DISABLE_COLLISION );
  2025. pActor->clearBodyFlag( NX_BF_KINEMATIC );
  2026. pActor->setLinearVelocity( parentVel );
  2027. pActor->wakeUp();
  2028. NxShape *const* pShapeArray = pActor->getShapes();
  2029. U32 shapeCount = pActor->getNbShapes();
  2030. for ( U32 i = 0; i < shapeCount; i++ )
  2031. pShapeArray[i]->setFlag( NX_SF_DISABLE_RAYCASTING, false );
  2032. setMeshHidden( _getMeshName(pActor), false );
  2033. }
  2034. }
  2035. void PxMultiActor::setAllHidden( bool hide )
  2036. {
  2037. for ( U32 i = 0; i < mShapeInstance->mMeshObjects.size(); i++ )
  2038. mShapeInstance->setMeshForceHidden( i, hide );
  2039. }
  2040. ConsoleMethod( PxMultiActor, setAllHidden, void, 3, 3, "( bool )"
  2041. "@brief Hides or unhides all meshes contained in the PxMultiActor.\n\n"
  2042. "Hidden meshes will not be rendered.")
  2043. {
  2044. object->setAllHidden( dAtob(argv[2]) );
  2045. }
  2046. void PxMultiActor::setMeshHidden( String namePrefix, bool hidden )
  2047. {
  2048. if ( isServerObject() && PHYSICSMGR->isSinglePlayer() )
  2049. {
  2050. PxMultiActor *clientObj = static_cast<PxMultiActor*>( getClientObject() );
  2051. if ( clientObj )
  2052. clientObj->setMeshHidden( namePrefix, hidden );
  2053. }
  2054. for ( U32 i = 0; i < mShapeInstance->mMeshObjects.size(); i++ )
  2055. {
  2056. String meshName = mShapeInstance->getShape()->getMeshName( i );
  2057. if ( meshName.find( namePrefix ) != String::NPos )
  2058. {
  2059. mShapeInstance->setMeshForceHidden( i, hidden );
  2060. return;
  2061. }
  2062. }
  2063. Con::warnf( "PxMultiActor::setMeshHidden - could not find mesh containing substring (%s)", namePrefix.c_str() );
  2064. }
  2065. ConsoleMethod( PxMultiActor, setBroken, void, 3, 3, "( bool )"
  2066. "@brief Sets the PxMultiActor to a broken or unbroken state.\n\n")
  2067. {
  2068. object->setAllBroken( dAtob( argv[2] ) );
  2069. }
  2070. void PxMultiActorData::dumpModel()
  2071. {
  2072. TSShapeInstance *inst = new TSShapeInstance( shape, true );
  2073. String path = Platform::getMainDotCsDir();
  2074. path += "/model.dump";
  2075. FileStream *st;
  2076. if((st = FileStream::createAndOpen( path, Torque::FS::File::Write )) != NULL)
  2077. {
  2078. if ( inst )
  2079. inst->dump( *st );
  2080. else
  2081. Con::errorf( "PxMultiActor::dumpModel, no ShapeInstance." );
  2082. delete st;
  2083. }
  2084. else
  2085. Con::errorf( "PxMultiActor::dumpModel, error opening dump file." );
  2086. }
  2087. ConsoleMethod( PxMultiActorData, dumpModel, void, 2, 2,
  2088. "@brief Dumps model hierarchy and details to a file.\n\n"
  2089. "The file will be created as \'model.dump\' in the game folder. "
  2090. "If model.dump already exists, it will be overwritten.\n\n")
  2091. {
  2092. object->dumpModel();
  2093. }
  2094. ConsoleMethod( PxMultiActor, setMeshHidden, void, 4, 4, "(string meshName, bool isHidden)"
  2095. "@brief Prevents the provided mesh from being rendered.\n\n")
  2096. {
  2097. object->setMeshHidden( argv[2], dAtob( argv[3] ) );
  2098. }
  2099. void PxMultiActor::listMeshes( const String &state ) const
  2100. {
  2101. if ( mShapeInstance )
  2102. mShapeInstance->listMeshes( state );
  2103. }
  2104. ConsoleMethod( PxMultiActor, listMeshes, void, 3, 3, "(enum Hidden/Shown/All)"
  2105. "@brief Lists all meshes of the provided type in the console window.\n\n"
  2106. "@param All Lists all of the %PxMultiActor's meshes.\n"
  2107. "@param Hidden Lists all of the %PxMultiActor's hidden meshes.\n"
  2108. "@param Shown Lists all of the %PxMultiActor's visible meshes.\n")
  2109. {
  2110. object->listMeshes( argv[2] );
  2111. };
  2112. ConsoleMethod( PxMultiActorData, reload, void, 2, 2, ""
  2113. "@brief Reloads all data used for the PxMultiActorData.\n\n"
  2114. "If the reload sucessfully completes, all PxMultiActor's will be notified.\n\n")
  2115. {
  2116. object->reload();
  2117. }