// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_MOVE_PRIMITIVE_H #define NL_MOVE_PRIMITIVE_H #include "nel/misc/types_nl.h" #include "nel/misc/vector.h" #include "nel/pacs/u_move_primitive.h" #include "move_container.h" #include "primitive_world_image.h" #include "global_retriever.h" #define NELPACS_DIST_BACK 0.01 namespace NLPACS { /** * Description of movables primitives. * * This primitive can be a 2d oriented box or a 2d oriented cylinder. * * \author Cyril 'Hulud' Corvazier * \author Nevrax France * \date 2001 */ class CMovePrimitive: public UMovePrimitive { private: friend class CMoveContainer; // Some flags enum TStaticFlags { // Mask for the primitive type PrimitiveMask =0x000f, // Mask for the primitive type ReactionMask =0x00f0, // Mask for the trigger type TriggerMask =0x0f00, // Obstacle flag. This flag tells that this object is an obstacle for others objects. ObstacleFlag =0x1000, // Ghost flag. This flag tells that this object is a ghost object or not. NonCollisionableFlag =0x2000, /// The primitive shoudln't be snapped to ground DontSnapToGroundFlag = 0x4000, // Force the size to uint16. ForceSize =0xffff }; public: /// Constructor CMovePrimitive (CMoveContainer* container, uint8 firstWorldImage, uint8 numWorldImage); /// Destructor virtual ~CMovePrimitive (); // virtual void setDontSnapToGround(bool dont) { if (dont) _StaticFlags |= DontSnapToGroundFlag; else _StaticFlags &= ~DontSnapToGroundFlag; } // bool getDontSnapToGround() const { return (_StaticFlags & DontSnapToGroundFlag) != 0; } // Return true if this primitive is noncollisionable bool isNonCollisionable () const { return (_StaticFlags&NonCollisionableFlag)!=0; } // Set noncollisionable void setNonCollisionable (bool nonCollisionable) { if (nonCollisionable) _StaticFlags|=NonCollisionableFlag; else _StaticFlags&=~NonCollisionableFlag; } // Get the nieme world image CPrimitiveWorldImage *getWorldImage (uint i) const { // Checks this primitive belong of the requested world image. nlassert ((i>=(uint)_FirstWorldImage)&&(i<(uint)_FirstWorldImage+(uint)_NumWorldImage)); // Return the good one return _WorldImages[i-_FirstWorldImage]; } // is the primitive inserted in the world image bool isInserted (uint i) const { // Checks if ((i>=(uint)_FirstWorldImage)&&(i<(uint)_FirstWorldImage+(uint)_NumWorldImage)) { // Get world image return getWorldImage (i)->isInWorldImageFlag (); } else return false; } virtual uint8 getFirstWorldImageV () const; virtual uint8 getNumWorldImageV () const; // Get first world image used uint8 getFirstWorldImage () const { return _FirstWorldImage; } // Get count of world image used uint8 getNumWorldImage () const { return _NumWorldImage; } // Dirt positions of the primitive in all the world images void dirtAllPos () { for (uint i=0; i<_NumWorldImage; i++) { // Get world image and check if it exist CPrimitiveWorldImage *worldImage=_WorldImages[i]; // Dirt its pos worldImage->dirtPos (_Container, this, uint8(i+_FirstWorldImage)); } } /** * Set the primitive type. * * \param type is the new primitive type. */ void setPrimitiveType (TType type) { // New position _StaticFlags&=~(uint32)PrimitiveMask; _StaticFlags|=type; } /** * Set the reaction type. * * \param type is the new reaction type. */ void setReactionType (TReaction type) { // New position _StaticFlags&=~(uint32)ReactionMask; _StaticFlags|=type; } /** * Set the trigger type. Default type is NotATrigger. * * \param type is the new trigger type. */ void setTriggerType (TTrigger type) { // New position _StaticFlags&=~(uint32)TriggerMask; _StaticFlags|=type; } /** * Set the collision mask for this primitive. Default mask is 0xffffffff. * * \param mask is the new collision mask. */ void setCollisionMask (TCollisionMask mask) { _CollisionMask=mask; } /** * Set the occlusion mask for this primitive. Default mask is 0xffffffff. * * \param mask is the new occlusion mask. */ void setOcclusionMask (TCollisionMask mask) { _OcclusionMask=mask; } /** * Set the obstacle flag. * * \param obstacle is true if this primitive is an obstacle, else false. */ void setObstacle (bool obstacle) { // New flag if (obstacle) _StaticFlags|=ObstacleFlag; else _StaticFlags&=~(uint32)ObstacleFlag; } /** * Set the box size. Only for boxes. * * \param width is the new width size of the box. It the size of the sides aligned on OX. * \param depth is the new depth size of the box. It the size of the sides aligned on OY. */ void setSize (float width, float depth) { // Checks nlassert ((((uint32)_StaticFlags)&PrimitiveMask)==_2DOrientedBox); // New position _Length[0]=width; _Length[1]=depth; } /** * Set the height. For boxes or cylinder. * * \param height is the new height size of the box. It the size of the sides aligned on OZ. */ void setHeight (float height) { // New size _Height=height; } /** * Set the cylinder size. Only for cylinder. * * \param radius is the new radius size of the cylinder. */ void setRadius (float radius) { // Checks nlassert ((((uint32)_StaticFlags)&PrimitiveMask)==_2DOrientedCylinder); // New position _Length[0]=radius; } /// Get primitive type TType getPrimitiveTypeInternal () const { // New position return (TType)(_StaticFlags&(uint32)PrimitiveMask); } /// Get reaction type TReaction getReactionTypeInternal () const { // New position return (TReaction)(_StaticFlags&(uint32)ReactionMask); } /// Get reaction type TTrigger getTriggerTypeInternal () const { // New position return (TTrigger)(_StaticFlags&(uint32)TriggerMask); } /// Get collision mask TCollisionMask getCollisionMaskInternal () const { // New position return _CollisionMask; } /// Get occlusion mask TCollisionMask getOcclusionMaskInternal () const { // New position return _OcclusionMask; } /// Get attenuation float getAttenuation() const { return _Attenuation; } /// Get length float getLength (uint where) const { return _Length[where]; } /// Get height float getHeightInternal () const { return _Height; } /// Get length float getRadiusInternal () const { return _Length[0]; } /// Is an obstacle ? bool isObstacle () const { return (_StaticFlags&ObstacleFlag)!=0; } /// Is collisionable bool isCollisionable() const { return !isNonCollisionable(); } /// Add a collision time ordered table element void addCollisionOTInfo (CCollisionOTInfo *info) { // Link to the list info->primitiveLink (this, _RootOTInfo); _RootOTInfo=info; } /// Remove one collision time ordered table element. void removeCollisionOTInfo (CCollisionOTInfo *toRemove); /// Remove all collision time ordered table element. void removeCollisionOTInfo (); /// Check sorted lists void checkSortedList (); /// Check trigger flag bool isTriggered (CMovePrimitive& second, bool enter, bool exit); /// \name From UMovePrimitive void setAbsorbtion (float attenuation); void setOrientation (double rot, uint8 worldImage); void setGlobalPosition (const NLMISC::CVectorD& pos, uint8 worldImage, UGlobalPosition::TType type = UGlobalPosition::Unspecified); void setGlobalPosition (const UGlobalPosition& pos, uint8 worldImage); void move (const NLMISC::CVectorD& speed, uint8 worldImage); NLMISC::CVectorD getFinalPosition (uint8 worldImage) const; const NLMISC::CVectorD& getSpeed (uint8 worldImage) const; void insertInWorldImage (uint8 worldImage); void removeFromWorldImage (uint8 worldImage); TType getPrimitiveType () const; TReaction getReactionType () const; TTrigger getTriggerType () const; TCollisionMask getCollisionMask () const; TCollisionMask getOcclusionMask () const; bool getObstacle () const; float getAbsorbtion () const; void getSize (float& width, float& depth) const; float getHeight () const; float getRadius () const; double getOrientation (uint8 worldImage) const; void getGlobalPosition (UGlobalPosition& pos, uint8 worldImage) const; // Test time. Return true if tetst can be perform, false if too many test have been computed for this primitive bool checkTestTime (uint32 testTime, uint32 maxTestIteration) { // Already checked for this test time ? if (testTime!=_LastTestTime) { // First time this primitive is visited at this test _LastTestTime=testTime; // Test counter _IterationCount=maxTestIteration; } else { // Too many test this primitive ? if (_IterationCount<=0) { // nlwarning("in checkTestTime(): Get to the max iteration count"); return false; } else _IterationCount--; } // Ok, test can be performed return true; } // *** Get mass float getMass () const { // Box ? if ( (_StaticFlags&PrimitiveMask) == _2DOrientedBox ) return _Length[0]*_Length[1]*_Height; // Cylinder ? else { nlassert ( (_StaticFlags&PrimitiveMask) == _2DOrientedCylinder ); return _Length[0]*(float)NLMISC::Pi*_Height; } } // *** Primitive over primitive bool isInCollision (CMovePrimitive *primitive); private: // The length of the 4 edges. The first is the width, the second is the depth // For cylinder, the first is the radius float _Length[2]; // This is the height of the box or of the cylinder. float _Height; // Attenuation float _Attenuation; // Flags uint16 _StaticFlags; // Num world images uint8 _NumWorldImage; // First world images uint8 _FirstWorldImage; // Occlusion mask TCollisionMask _OcclusionMask; // Collision mask TCollisionMask _CollisionMask; // Container of this primitive CMoveContainer *_Container; // List of time ordered table element using this primitive CCollisionOTInfo *_RootOTInfo; // Pointer table of world images for this primitive CPrimitiveWorldImage **_WorldImages; // Last primitive test time uint32 _LastTestTime; // Iteration count sint32 _IterationCount; }; } // NLPACS #include "move_container_inline.h" #endif // NL_MOVE_PRIMITIVE_H /* End of move_primitive.h */