PixelLightAPI  .
SNRagdoll.h
Go to the documentation of this file.
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__


PixelLight PixelLight 0.9.11-R1
Copyright (C) 2002-2012 by The PixelLight Team
Last modified Thu Feb 23 2012 14:09:00
The content of this PixelLight document is published under the
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported