/*! * @file p_node.h * @brief Definition of THE Parenting Node * * parenting is how coordinates are handled in orxonox, meaning, that all coordinates * are representet relative to another parent node. this nodes build a parenting * tree of one-sided references (from up to down referenced). * Every node manages itself a list of childrens (of whos it is parent - easy...). * * absCoordinate, absDirection have to be recalculated as soon as there was a change in * place or ortientation. this is only the case if * o bRelCoorChanged is true (so moved) * o bRelDirChanged is true (so changed) * this conditions make it cheaper to recalculate the tree (reduces redundant work). */ #ifndef _P_NODE_H #define _P_NODE_H #include "base_object.h" #include "synchronizeable.h" #include "vector.h" #include "quaternion.h" #include // FORWARD DECLARATION class TiXmlElement; #define PNODE_ITERATION_DELTA .001 //! Parental linkage modes typedef enum { // PARENTAL FOLLOWING PNODE_LOCAL_ROTATE = 0x0001, //!< Rotates all the children around their centers. PNODE_ROTATE_MOVEMENT = 0x0002, //!< Moves all the children around the center of their parent, without the rotation around their own centers. PNODE_MOVEMENT = 0x0004, //!< Moves all children along with the parent. // special linkage modes PNODE_ALL = 0x0003, //!< Moves all children around the center of their parent, and also rotates their centers PNODE_ROTATE_AND_MOVE = 0x0005, //!< Rotates all children around their axis, and moves them as the Parent Moves, but does not rotate around the center of their parent. // REPARENTING PNODE_REPARENT_TO_NULL = 0x0010, //!< Reparents to the Null, if the Parent is Removed. Meaning the Node wont have a parent anymore. PNODE_REPARENT_TO_PARENTS_PARENT = 0x0020, //!< Reparents the Node to the parents (old) parent it the parent gets removed. ///////////////////////////////////////////// // ELSE: Reparents to the NullParent. PNODE_REPARENT_DELETE_CHILDREN = 0x0040, //!< Deletes the Children of the node when This Node is Removed. (Use with care). /// FIXME PNODE_REPARENT_KEEP_POSITION = 0x0080, //!< Tries to keep the Position if the Node is reparented. // DELETION PNODE_PROHIBIT_CHILD_DELETE = 0x0100, //!< Prohibits the Children from being deleted if this Node gets deleted. PNODE_PROHIBIT_DELETE_WITH_PARENT = 0x0200, //!< Prohibits the Node to be deleted if the Parent is. Child will be reparented according to the Repaenting-Rules PNODE_REPARENT_CHILDREN_ON_REMOVE = 0x0400, //!< Reparents the Children of the Node if the Node gets Removed. PNODE_REPARENT_ON_PARENTS_REMOVE = 0x0800, //!< The Node gets Reparented if its Parent gets removed. Child will be reparented according to the Reparenting-Rules. // VISIBILITY/ACTIVITY PNODE_HIDE_CHILDREN_IF_HIDDEN = 0x1000, //!< Prohibits the Children from being drawn if this node isn't visible. (used for Draw)) PNODE_HIDE_IF_PARENT_HIDDEN = 0x2000, //!< Prohibits the node from being drawn if the Parent is invisible. PNODE_UPDATE_CHILDREN_IF_INACTIVE = 0x4000, //!< Updates the Children of this Node even if the Parent is Inactive (note if this's parent is inactive children won't be updated.) PNODE_STATIC_NODE = 0x8000, //!< Used for nodes that do not have any moving children, and that do not move. } PARENT_MODE; //! The default mode of the translation-binding. #define PNODE_PARENT_MODE_DEFAULT PNODE_ALL | \ PNODE_REPARENT_KEEP_POSITION //! Patent Node is a Engine to calculate the position of an Object in respect to the position of its parent. class PNode : virtual public BaseObject, virtual public Synchronizeable { ObjectListDeclaration(PNode); public: PNode (PNode* parent = PNode::getNullParent(), long nodeFlags = PNODE_PARENT_MODE_DEFAULT); virtual ~PNode (); virtual void loadParams(const TiXmlElement* root); void init(); // ACTIVATION // inline void activateNode() { this->bActive = this->bRelCoorChanged = this->bRelDirChanged = true; }; inline void deactivateNode() { this->bActive = false; }; inline bool getNodeActiveState() { return this->bActive; }; // POSITION // void setRelCoor (const Vector& relCoord); void setRelCoor (float x, float y, float z); void setRelCoorSoft(const Vector& relCoordSoft, float bias = 1.0); void setRelCoorSoft(float x, float y, float z, float bias = 1.0); /** @returns the relative position */ inline const Vector& getRelCoor () const { return this->prevRelCoordinate; }; /** @returns the Relative Coordinate Destination */ inline const Vector& getRelCoorSoft2D() const { return (this->toCoordinate)? *this->toCoordinate : this->relCoordinate; }; void setAbsCoor (const Vector& absCoord); void setAbsCoor (float x, float y, float z); void setAbsCoorSoft(const Vector& absCoordSoft, float bias = 1.0); void setAbsCoorSoft(float x, float y, float z, float bias = 1.0); /** @returns the absolute position */ inline const Vector& getAbsCoor () const { return this->absCoordinate; }; /** @returns the absolute X coordinate. */ inline float getAbsCoorX() { return this->absCoordinate.x; }; /** @returns the absolute Y Coordinate */ inline float getAbsCoorY() { return this->absCoordinate.y; }; /** @returns the absolute Z Coordinate */ inline float getAbsCoorZ() { return this->absCoordinate.z; }; /** @returns the absolute position */ inline const Vector& getLastAbsCoor () const { return this->lastAbsCoordinate; }; void shiftCoor (const Vector& shift); void shiftCoor (float x, float y, float z) { this->shiftCoor(Vector(x, y, z)); }; // SPEED // /** @returns the Speed of the Node */ inline float getSpeed() const { return this->velocity.len(); }; /** @returns the Velocity of the Node */ inline const Vector& getVelocity() const { return this->velocity; }; // ROTATION // void setRelDir (const Quaternion& relDir); void setRelDir (float angle, float x, float y, float z); void setRelDirSoft(const Quaternion& relDirSoft, float bias = 1.0); void setRelDirSoft(float angle, float x, float y, float z, float bias = 1.0); /** @returns the relative Direction */ inline const Quaternion& getRelDir () const { return this->prevRelDirection; }; /** @returns the Relative Directional Destination */ inline const Quaternion& getRelDirSoft2D() const { return (this->toDirection)? *this->toDirection : this->relDirection; }; /** @returns a Vector pointing into the relative Direction */ inline Vector getRelDirV() const { return this->prevRelDirection.apply(Vector(0,1,0)); }; void setAbsDir (const Quaternion& absDir); void setAbsDir (float angle, float x, float y, float z); void setAbsDirSoft(const Quaternion& absDirSoft, float bias = 1.0); void setAbsDirSoft(float angle, float x, float y, float z, float bias = 1.0); void shiftDir (const Quaternion& shift); /** @returns the absolute Direction */ inline const Quaternion& getAbsDir () const { return this->absDirection; }; /** @returns a Vector pointing into the absolute Direction */ inline Vector getAbsDirV() const { return this->absDirection.apply(Vector(0,1,0)); }; /** @returns A Vector pointing into the forward direction (X) of the Node */ inline Vector getAbsDirX() const { return this->absDirection.apply(Vector(1,0,0)); }; /** @returns A Vector pointing into the upward direction (Y) of the Node */ inline Vector getAbsDirY() const { return this->absDirection.apply(Vector(0,1,0)); }; /** @returns A Vector pointing into the right direction (Z) of the Node */ inline Vector getAbsDirZ() const { return this->absDirection.apply(Vector(0,0,1)); }; // PARENTING // void addChild (PNode* child); void addChild (const std::string& childName); void removeChild (PNode* child); void removeNode(); PNode* seekNextAssignedPNode(PNode* node) const; /** @param parent the new parent of this node */ inline void setParent (PNode* parent) { parent->addChild(this); }; void setParent (const std::string& parentName); /** @returns the parent of this PNode */ inline PNode* getParent () const { return this->parent; }; /** @returns the List of Children of this PNode */ const std::list& getNodesChildren() const { return this->children; }; void setParentSoft(PNode* parentNode, float bias = 1.0); void setParentSoft(const std::string& parentName, float bias = 1.0); // PARENTING_MODE AND OTHER FLAGS // void setParentMode (PARENT_MODE parentMode); void setParentMode (const std::string& parentingMode); /** @returns the Parenting mode of this node */ int getParentMode() const { return 0x000f & this->parentMode; }; void addNodeFlags(unsigned short nodeFlags); void removeNodeFlags(unsigned short nodeFlags); /** @returns the NullParent, the (main) ROOT of the PNode Tree. If it does not yet exist, it will be created. */ static PNode* getNullParent() { return (PNode::nullParent != NULL) ? PNode::nullParent : PNode::createNullParent(); }; // UPDATING // void updateNode (float dt); // DEBUG // void countChildNodes(int& nodes) const; void debugNode (unsigned int depth = 1, unsigned int level = 0) const; void debugDraw(unsigned int depth = 1, float size = 1.0, const Vector& color = Vector(1, 0, 0), unsigned int level = 0) const; // HELPER_FUNCTIONS // static const char* parentingModeToString(int parentingMode); static PARENT_MODE stringToParentingMode(const std::string& parentingMode); float distance(const PNode* node) const { return (this->getAbsCoor() - node->getAbsCoor()).len(); }; private: /** tells the child that the parent's Coordinate has changed */ inline void parentCoorChanged () { this->bRelCoorChanged = true; } /** tells the child that the parent's Direction has changed */ inline void parentDirChanged () { this->bRelDirChanged = true; } public: /** @returns the last calculated coordinate */ inline Vector getLastAbsCoor() { return this->lastAbsCoordinate; } private: static PNode* createNullParent(); void reparent(); bool checkIntegrity(const PNode* checkParent) const; void eraseChild(PNode* child); private: bool bRelCoorChanged; //!< If Relative Coordinate has changed since last time we checked bool bRelDirChanged; //!< If Relative Direction has changed since last time we checked Vector relCoordinate; //!< coordinates relative to the parent Vector absCoordinate; //!< absolute coordinates in the world ( from (0,0,0) ) Quaternion relDirection; //!< direction relative to the parent Quaternion absDirection; //!< absolute direvtion in the world ( from (0,0,1) ) Vector prevRelCoordinate; //!< The last Relative Coordinate from the last update-Cycle. Vector lastAbsCoordinate; //!< this is used for speedcalculation, it stores the last coordinate Quaternion prevRelDirection; //!< The last Relative Direciton from the last update-Cycle. // Quaternion lastAbsDirection; Vector velocity; //!< Saves the velocity. Vector* toCoordinate; //!< a position to which to iterate. (This is used in conjunction with setParentSoft.and set*CoorSoft) Quaternion* toDirection; //!< a direction to which to iterate. (This is used in conjunction with setParentSoft and set*DirSoft) float bias; //!< how fast to iterate to the given position (default is 1) PNode* parent; //!< a pointer to the parent node. std::list children; //!< list of the children of this PNode. bool bActive; //!< If the Node is Active (for cutting off the rest of the tree in update). unsigned short parentMode; //!< the mode of the binding static PNode* nullParent; //!< The ROOT of the main PNode Tree. private: float coorx; float coory; float coorz; float rotw; float rotx; float roty; float rotz; private: int relCoordinate_handle; int relDirection_handle; Vector relCoordinate_write; Quaternion relDirection_write; public: virtual void varChangeHandler( std::list & id ); }; // NULL_PARENT // class NullParent : public PNode { ObjectListDeclaration(NullParent); friend class PNode; NullParent(); }; #endif /* _P_NODE_H */