PixelLightAPI
.
|
00001 /*********************************************************\ 00002 * File: SNRagdoll.h * 00003 * 00004 * Copyright (C) 2002-2012 The PixelLight Team (http://www.pixellight.org/) 00005 * 00006 * This file is part of PixelLight. 00007 * 00008 * PixelLight is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published by 00010 * the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * PixelLight is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with PixelLight. If not, see <http://www.gnu.org/licenses/>. 00020 \*********************************************************/ 00021 00022 00023 #ifndef __PLPHYSICS_SCENENODES_RAGDOLL_H__ 00024 #define __PLPHYSICS_SCENENODES_RAGDOLL_H__ 00025 #pragma once 00026 00027 00028 //[-------------------------------------------------------] 00029 //[ Includes ] 00030 //[-------------------------------------------------------] 00031 #include <PLCore/Tools/Loadable.h> 00032 #include <PLScene/Scene/SceneNodes/SNMesh.h> 00033 #include "PLPhysics/PLPhysics.h" 00034 00035 00036 //[-------------------------------------------------------] 00037 //[ Forward declarations ] 00038 //[-------------------------------------------------------] 00039 namespace PLMesh { 00040 class Skeleton; 00041 class SkeletonHandler; 00042 } 00043 namespace PLScene { 00044 class SNMMeshUpdate; 00045 } 00046 namespace PLPhysics { 00047 class RagdollBody; 00048 class RagdollJoint; 00049 class SCPhysicsWorld; 00050 } 00051 00052 00053 //[-------------------------------------------------------] 00054 //[ Namespace ] 00055 //[-------------------------------------------------------] 00056 namespace PLPhysics { 00057 00058 00059 //[-------------------------------------------------------] 00060 //[ Structures ] 00061 //[-------------------------------------------------------] 00062 /** 00063 * @brief 00064 * Disables collision between two bodies 00065 */ 00066 struct NoCollision { 00067 PLCore::String sFirst; 00068 PLCore::String sSecond; 00069 }; 00070 00071 /** 00072 * @brief 00073 * Set of controller gains for a particular joint 00074 */ 00075 struct JointController { 00076 PLCore::String sJoint; 00077 bool bIsControllable; 00078 00079 // ks and kd parameters for each axis (ks2, kd2 not applicable to hinge joints) 00080 float ks1, kd1; 00081 float ks2, kd2; 00082 }; 00083 00084 00085 //[-------------------------------------------------------] 00086 //[ Classes ] 00087 //[-------------------------------------------------------] 00088 /** 00089 * @brief 00090 * Ragdoll scene node 00091 * 00092 * @remarks 00093 * The ragdoll (other names are 'online animation', 'articulated') scene node is an extension of 00094 * SNMesh and allows the skeleton of the mesh to be influenced by a physics simulation. 00095 */ 00096 class SNRagdoll : public PLScene::SNMesh, public PLCore::Loadable { 00097 00098 00099 //[-------------------------------------------------------] 00100 //[ Friends ] 00101 //[-------------------------------------------------------] 00102 friend class RagdollBody; 00103 friend class RagdollJoint; 00104 00105 00106 //[-------------------------------------------------------] 00107 //[ Public definitions ] 00108 //[-------------------------------------------------------] 00109 public: 00110 /** 00111 * @brief 00112 * Scene node debug flags (SceneNode debug flags extension) 00113 */ 00114 enum EDebugFlags { 00115 DebugNoPhysicsBodies = 1<<18 /**< Do not draw the physics bodies of the ragdoll */ 00116 }; 00117 pl_enum(EDebugFlags) 00118 pl_enum_base(PLScene::SNMesh::EDebugFlags) 00119 pl_enum_value(DebugNoPhysicsBodies, "Do not draw the physics bodies of the ragdoll") 00120 pl_enum_end 00121 00122 00123 //[-------------------------------------------------------] 00124 //[ RTTI interface ] 00125 //[-------------------------------------------------------] 00126 pl_class(PLPHYSICS_RTTI_EXPORT, SNRagdoll, "PLPhysics", PLScene::SNMesh, "Ragdoll scene node") 00127 // Attributes 00128 pl_attribute(RagdollFilename, PLCore::String, "", ReadWrite, GetSet, "Ragdoll filename, if no provided a default ragdoll is created", "Type='Ragdoll'") 00129 pl_attribute(ControllerEnabled, bool, false, ReadWrite, DirectValue, "Is the PD-controller enabled?", "") 00130 pl_attribute(AttachToWorldEnabled, bool, false, ReadWrite, GetSet, "Are joints allowed to be attached to the world? (fixed joints)", "") 00131 pl_attribute(MaxTorque, float, 60.0f, ReadWrite, DirectValue, "Cap the torque generated by the controller to a reasonable value", "") 00132 pl_attribute(AutoFreeze, bool, true, ReadWrite, GetSet, "Freeze the ragdoll automatically?", "") 00133 pl_attribute(UseGravity, bool, true, ReadWrite, GetSet, "Does the gravity influence this ragdoll?", "") 00134 pl_attribute(InitFrozen, bool, true, ReadWrite, DirectValue, "Is this ragdoll frozen on initialization?", "") 00135 // Overwritten PLScene::SceneNode attributes 00136 pl_attribute(Flags, pl_flag_type(EFlags), DynamicMesh, ReadWrite, GetSet, "Flags", "") 00137 pl_attribute(DebugFlags, pl_flag_type(EDebugFlags), 0, ReadWrite, GetSet, "Debug flags", "") 00138 // Constructors 00139 pl_constructor_0(DefaultConstructor, "Default constructor", "") 00140 pl_class_end 00141 00142 00143 //[-------------------------------------------------------] 00144 //[ Public RTTI get/set functions ] 00145 //[-------------------------------------------------------] 00146 public: 00147 PLPHYSICS_API PLCore::String GetRagdollFilename() const; 00148 PLPHYSICS_API void SetRagdollFilename(const PLCore::String &sValue); 00149 PLPHYSICS_API bool GetAttachToWorldEnabled() const; 00150 PLPHYSICS_API void SetAttachToWorldEnabled(bool bValue); 00151 PLPHYSICS_API bool GetAutoFreeze() const; 00152 PLPHYSICS_API void SetAutoFreeze(bool bValue); 00153 PLPHYSICS_API bool GetUseGravity() const; 00154 PLPHYSICS_API void SetUseGravity(bool bValue); 00155 00156 00157 //[-------------------------------------------------------] 00158 //[ Public functions ] 00159 //[-------------------------------------------------------] 00160 public: 00161 /** 00162 * @brief 00163 * Default constructor 00164 */ 00165 PLPHYSICS_API SNRagdoll(); 00166 00167 /** 00168 * @brief 00169 * Destructor 00170 */ 00171 PLPHYSICS_API virtual ~SNRagdoll(); 00172 00173 /** 00174 * @brief 00175 * Returns the PL physics world scene node container the ragdoll is in 00176 * 00177 * @return 00178 * The PL physics world scene node container the ragdoll is in, a null pointer on error 00179 * (if that's the case, something went totally wrong :) 00180 * 00181 * @note 00182 * - This PL physics world scene node container can be another as the scene node container this scene node is in 00183 */ 00184 PLPHYSICS_API SCPhysicsWorld *GetWorldContainer() const; 00185 00186 /** 00187 * @brief 00188 * Clears the radgoll 00189 */ 00190 PLPHYSICS_API void ClearRagdoll(); 00191 00192 /** 00193 * @brief 00194 * Creates the ragdoll using a skeleton handler 00195 * 00196 * @param[in] pSkeletonHandler 00197 * Skeleton handler to get the ragdoll information from, if a null pointer, a ragdoll is created automatically using 00198 * the skeleton handler of the used mesh 00199 * 00200 * @return 00201 * 'true' if all went fine, else 'false' 00202 * 00203 * @remarks 00204 * This function will create a ragdoll from a skeleton handler for you automatically. 00205 * After the ragdoll was created, you just have to tweak it if required. 00206 * 00207 * @note 00208 * - Only the main layout can be created using the skeleton handler 00209 * (bodies, joints, positions, rotations etc.) 00210 * - Default joint type: Universal 00211 * - Default body size: 0.2 'length' 0.2 00212 * - Default body mass: 1.0 00213 * - The joint limits are between -0.5 and 0.5 00214 */ 00215 PLPHYSICS_API bool CreateRagdoll(PLMesh::SkeletonHandler *pSkeletonHandler = nullptr); 00216 00217 /** 00218 * @brief 00219 * Creates the physics 00220 * 00221 * @param[in] bAllowAttachToWorld 00222 * Is it allowed to attach joints to the world? 00223 * 00224 * @note 00225 * - This function calls CreatePhysicsBodies() and CreatePhysicsJoints() 00226 * - You can use this function to reset the ragdoll to the initial pose 00227 * (after a ragdoll is loaded it's in the initial pose by default) 00228 */ 00229 PLPHYSICS_API void CreatePhysics(bool bAllowAttachToWorld = true); 00230 00231 /** 00232 * @brief 00233 * Creates the physics bodies 00234 * 00235 * @note 00236 * - After this function all physics bodies are in their initial pose 00237 * 00238 * @see 00239 * - CreatePhysicsBodies() 00240 */ 00241 PLPHYSICS_API void CreatePhysicsBodies(); 00242 00243 /** 00244 * @brief 00245 * Creates the physics joints 00246 * 00247 * @param[in] bAllowAttachToWorld 00248 * Is it allowed to attach joints to the world? 00249 * 00250 * @note 00251 * - After this function all physics joints are in their initial pose 00252 * 00253 * @see 00254 * - CreatePhysicsBodies() 00255 */ 00256 PLPHYSICS_API void CreatePhysicsJoints(bool bAllowAttachToWorld = true); 00257 00258 /** 00259 * @brief 00260 * Creates the physics ragdoll 00261 * 00262 * @param[in] bAllowAttachToWorld 00263 * Is it allowed to attach joints to the world? 00264 */ 00265 PLPHYSICS_API void CreatePhysicsRagdoll(bool bAllowAttachToWorld = true); 00266 00267 /** 00268 * @brief 00269 * Returns the ragdoll skeleton 00270 * 00271 * @return 00272 * The ragdoll skeleton, a null pointer on error 00273 */ 00274 PLPHYSICS_API PLMesh::Skeleton *GetSkeleton() const; 00275 00276 /** 00277 * @brief 00278 * Returns whether the ragdoll is enabled or not 00279 * 00280 * @return 00281 * 'true' if the ragdoll is enabled, else 'false' 00282 */ 00283 PLPHYSICS_API bool IsEnabled() const; 00284 00285 /** 00286 * @brief 00287 * Enables/disables all bodies and joints 00288 * 00289 * @param[in] bEnabled 00290 * 'true' if the ragdoll is enabled, else 'false' 00291 */ 00292 PLPHYSICS_API void SetEnabled(bool bEnabled = true); 00293 00294 /** 00295 * @brief 00296 * Returns the number of bodies 00297 * 00298 * @return 00299 * The number of bodies 00300 */ 00301 PLPHYSICS_API PLCore::uint32 GetNumOfBodies() const; 00302 00303 /** 00304 * @brief 00305 * Returns a body 00306 * 00307 * @param[in] nIndex 00308 * Index of the requested body 00309 * 00310 * @return 00311 * The requested body, a null pointer on error 00312 */ 00313 PLPHYSICS_API RagdollBody *GetBody(PLCore::uint32 nIndex) const; 00314 00315 /** 00316 * @brief 00317 * Returns a body 00318 * 00319 * @param[in] sName 00320 * Name of the requested body 00321 * 00322 * @return 00323 * The requested body, a null pointer on error 00324 */ 00325 PLPHYSICS_API RagdollBody *GetBody(const PLCore::String &sName) const; 00326 00327 /** 00328 * @brief 00329 * Adds a new body 00330 * 00331 * @param[in] sName 00332 * Desired name 00333 * @param[in] bCreatePhysics 00334 * Create the physics body after the body was added? 00335 * 00336 * @return 00337 * The new ragdoll body, a null pointer on error 00338 */ 00339 PLPHYSICS_API RagdollBody *AddBody(const PLCore::String &sName = "Joint", bool bCreatePhysics = true); 00340 00341 /** 00342 * @brief 00343 * Clones a body 00344 * 00345 * @param[in] nIndex 00346 * Index of the body to clone 00347 * @param[in] bCreatePhysics 00348 * Create the physics body after the cloned body was added? 00349 * 00350 * @return 00351 * The new cloned ragdoll body, a null pointer on error 00352 */ 00353 PLPHYSICS_API RagdollBody *CloneBody(PLCore::uint32 nIndex, bool bCreatePhysics = true); 00354 00355 /** 00356 * @brief 00357 * Removes a body 00358 * 00359 * @param[in] nIndex 00360 * Index of the body to remove 00361 * 00362 * @return 00363 * 'true' if all went fine, else 'false' 00364 */ 00365 PLPHYSICS_API bool RemoveBody(PLCore::uint32 nIndex); 00366 00367 /** 00368 * @brief 00369 * Removes a body and the joint attached to it 00370 * 00371 * @param[in] nIndex 00372 * Index of the body to remove 00373 * 00374 * @return 00375 * 'true' if all went fine, else 'false' 00376 */ 00377 PLPHYSICS_API bool RemoveBodyAndJoint(PLCore::uint32 nIndex); 00378 00379 /** 00380 * @brief 00381 * Returns the number of joints 00382 * 00383 * @return 00384 * The number of joints 00385 */ 00386 PLPHYSICS_API PLCore::uint32 GetNumOfJoints() const; 00387 00388 /** 00389 * @brief 00390 * Returns a joint 00391 * 00392 * @param[in] nIndex 00393 * Index of the requested joint 00394 * 00395 * @return 00396 * The requested joint, a null pointer on error 00397 */ 00398 PLPHYSICS_API RagdollJoint *GetJoint(PLCore::uint32 nIndex) const; 00399 00400 /** 00401 * @brief 00402 * Returns a joint 00403 * 00404 * @param[in] sName 00405 * Name of the requested joint 00406 * 00407 * @return 00408 * The requested joint, a null pointer on error 00409 */ 00410 PLPHYSICS_API RagdollJoint *GetJoint(const PLCore::String &sName) const; 00411 00412 /** 00413 * @brief 00414 * Adds a new joint 00415 * 00416 * @param[in] sName 00417 * Desired name 00418 * @param[in] bCreatePhysics 00419 * Create the physics joint after the joint was added? 00420 * 00421 * @return 00422 * The new ragdoll joint, a null pointer on error 00423 */ 00424 PLPHYSICS_API RagdollJoint *AddJoint(const PLCore::String &sName = "Joint", bool bCreatePhysics = true); 00425 00426 /** 00427 * @brief 00428 * Clones a joint 00429 * 00430 * @param[in] nIndex 00431 * Index of the joint to clone 00432 * @param[in] bCreatePhysics 00433 * Create the physics joint after the cloned joint was added? 00434 * 00435 * @return 00436 * The new cloned ragdoll joint, a null pointer on error 00437 */ 00438 PLPHYSICS_API RagdollJoint *CloneJoint(PLCore::uint32 nIndex, bool bCreatePhysics = true); 00439 00440 /** 00441 * @brief 00442 * Removes a joint 00443 * 00444 * @param[in] nIndex 00445 * Index of the joint to remove 00446 * 00447 * @return 00448 * 'true' if all went fine, else 'false' 00449 */ 00450 PLPHYSICS_API bool RemoveJoint(PLCore::uint32 nIndex); 00451 00452 /** 00453 * @brief 00454 * Returns the number of no collisions 00455 * 00456 * @return 00457 * The number of no collisions 00458 */ 00459 PLPHYSICS_API PLCore::uint32 GetNumOfNoCollisions() const; 00460 00461 /** 00462 * @brief 00463 * Adds a new no collision 00464 * 00465 * @return 00466 * The new no collision, a null pointer on error 00467 */ 00468 PLPHYSICS_API NoCollision *AddNoCollision(); 00469 00470 /** 00471 * @brief 00472 * Returns a no collision 00473 * 00474 * @param[in] nIndex 00475 * Index of the requested no collision 00476 * 00477 * @return 00478 * The requested no collision, a null pointer on error 00479 */ 00480 PLPHYSICS_API NoCollision *GetNoCollision(PLCore::uint32 nIndex) const; 00481 00482 /** 00483 * @brief 00484 * Removes a no collision 00485 * 00486 * @param[in] nIndex 00487 * Index of the no collision to remove 00488 * 00489 * @return 00490 * 'true' if all went fine, else 'false' 00491 */ 00492 PLPHYSICS_API bool RemoveNoCollision(PLCore::uint32 nIndex); 00493 00494 /** 00495 * @brief 00496 * Returns the number of controllers 00497 * 00498 * @return 00499 * The number of controllers 00500 */ 00501 PLPHYSICS_API PLCore::uint32 GetNumOfControllers() const; 00502 00503 /** 00504 * @brief 00505 * Adds a new controller 00506 * 00507 * @param[in] sJointName 00508 * Name of the joint to control 00509 * 00510 * @return 00511 * The new (if not already created) controller, a null pointer on error 00512 */ 00513 PLPHYSICS_API JointController *AddController(const PLCore::String &sJointName); 00514 00515 /** 00516 * @brief 00517 * Returns a controller 00518 * 00519 * @param[in] nIndex 00520 * Index of the requested controller 00521 * 00522 * @return 00523 * The requested controller, a null pointer on error 00524 */ 00525 PLPHYSICS_API JointController *GetController(PLCore::uint32 nIndex) const; 00526 00527 /** 00528 * @brief 00529 * Returns a controller 00530 * 00531 * @param[in] sName 00532 * Name of the requested controller 00533 * 00534 * @return 00535 * The requested controller, a null pointer on error 00536 */ 00537 PLPHYSICS_API JointController *GetController(const PLCore::String &sName) const; 00538 00539 /** 00540 * @brief 00541 * Removes a controller 00542 * 00543 * @param[in] nIndex 00544 * Index of the controller to remove 00545 * 00546 * @return 00547 * 'true' if all went fine, else 'false' 00548 */ 00549 PLPHYSICS_API bool RemoveController(PLCore::uint32 nIndex); 00550 00551 00552 //[-------------------------------------------------------] 00553 //[ Private functions ] 00554 //[-------------------------------------------------------] 00555 private: 00556 /** 00557 * @brief 00558 * Computes and applies PD-controller torques to each body part 00559 */ 00560 void ApplyControlTorques(); 00561 00562 /** 00563 * @brief 00564 * Called when the scene node needs to be updated 00565 */ 00566 void OnUpdate(); 00567 00568 /** 00569 * @brief 00570 * Returns a "PLScene::SNMMeshUpdate" instance from the owner scene node 00571 * 00572 * @return 00573 * A "PLScene::SNMMeshUpdate" instance 00574 * 00575 * @note 00576 * - If not already there, this method creates an instance of the "PLScene::SNMMeshUpdate" scene node modifier which frequently updates the mesh 00577 */ 00578 PLScene::SNMMeshUpdate *GetSNMMeshUpdate(); 00579 00580 00581 //[-------------------------------------------------------] 00582 //[ Private event handlers ] 00583 //[-------------------------------------------------------] 00584 private: 00585 PLCore::EventHandler<> EventHandlerUpdate; 00586 00587 00588 //[-------------------------------------------------------] 00589 //[ Private data ] 00590 //[-------------------------------------------------------] 00591 private: 00592 SCPhysicsWorld *m_pWorldContainer; /**< The PL physics world scene node container the physics body is in */ 00593 bool m_bEnabled; /**< Is the ragdoll enabled? */ 00594 PLMesh::SkeletonHandler *m_pRagdollSkeletonHandler; /**< Skeleton handler with the current ragdoll pose */ 00595 PLCore::String m_sRagdollFilename; /**< Ragdoll filename, if no provided a default ragdoll is created */ 00596 bool m_bAttachToWorldEnabled; /**< Are joints allowed to be attached to the world? (fixed joints) */ 00597 bool m_bAutoFreeze; /**< Freeze the ragdoll automatically? */ 00598 bool m_bUseGravity; /**< Does the gravity influence this ragdoll? */ 00599 00600 // Specifies size, position, orientation, and mass of each body part 00601 PLCore::Array<RagdollBody*> m_lstBodies; 00602 PLCore::HashMap<PLCore::String, RagdollBody*> m_mapBodies; 00603 // Specifies all the joints between each of the body parts and their properties 00604 PLCore::Array<RagdollJoint*> m_lstJoints; 00605 PLCore::HashMap<PLCore::String, RagdollJoint*> m_mapJoints; 00606 // Disables collision between bodies 00607 PLCore::Array<NoCollision*> m_lstNoCollisions; 00608 // Manually specified controller gains for near critically damped behavior 00609 PLCore::Array<JointController*> m_lstControllers; 00610 PLCore::HashMap<PLCore::String, JointController*> m_mapControllers; 00611 00612 00613 //[-------------------------------------------------------] 00614 //[ Public virtual PLScene::SceneNode functions ] 00615 //[-------------------------------------------------------] 00616 public: 00617 PLPHYSICS_API virtual void DrawDebug(PLRenderer::Renderer &cRenderer, const PLScene::VisNode *pVisNode = nullptr) override; 00618 00619 00620 //[-------------------------------------------------------] 00621 //[ Protected virtual PLScene::SceneNode functions ] 00622 //[-------------------------------------------------------] 00623 protected: 00624 PLPHYSICS_API virtual void InitFunction() override; 00625 PLPHYSICS_API virtual void DeInitFunction() override; 00626 PLPHYSICS_API virtual void OnActivate(bool bActivate) override; 00627 00628 00629 //[-------------------------------------------------------] 00630 //[ Public virtual PLCore::Loadable functions ] 00631 //[-------------------------------------------------------] 00632 public: 00633 PLPHYSICS_API virtual bool Unload() override; 00634 PLPHYSICS_API virtual PLCore::String GetLoadableTypeName() const override; 00635 00636 00637 //[-------------------------------------------------------] 00638 //[ Protected virtual PLCore::Loadable functions ] 00639 //[-------------------------------------------------------] 00640 protected: 00641 PLPHYSICS_API virtual bool CallLoadable(PLCore::File &cFile, PLCore::Loader &cLoader, const PLCore::String &sMethod, const PLCore::String &sParams) override; 00642 00643 00644 }; 00645 00646 00647 //[-------------------------------------------------------] 00648 //[ Namespace ] 00649 //[-------------------------------------------------------] 00650 } // PLPhysics 00651 00652 00653 #endif // __PLPHYSICS_SCENENODES_RAGDOLL_H__
|