123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /*
- * OPCODE - Optimized Collision Detection
- * Copyright (C) 2001 Pierre Terdiman
- * Homepage: http://www.codercorner.com/Opcode.htm
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Contains code for a ray collider.
- * \file OPC_RayCollider.h
- * \author Pierre Terdiman
- * \date June, 2, 2001
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Include Guard
- #ifndef __OPC_RAYCOLLIDER_H__
- #define __OPC_RAYCOLLIDER_H__
- class OPCODE_API CollisionFace
- {
- public:
- //! Constructor
- inline_ CollisionFace() {}
- //! Destructor
- inline_ ~CollisionFace() {}
- udword mFaceID; //!< Index of touched face
- float mDistance; //!< Distance from collider to hitpoint
- float mU, mV; //!< Impact barycentric coordinates
- };
- class OPCODE_API CollisionFaces : private OPC_Container
- {
- public:
- //! Constructor
- CollisionFaces() {}
- //! Destructor
- ~CollisionFaces() {}
- inline_ udword GetNbFaces() const { return GetNbEntries()>>2; }
- inline_ const CollisionFace* GetFaces() const { return (const CollisionFace*)GetEntries(); }
- inline_ void Reset() { OPC_Container::Reset(); }
- inline_ void AddFace(const CollisionFace& face) { Add(face.mFaceID).Add(face.mDistance).Add(face.mU).Add(face.mV); }
- };
- #ifdef OPC_RAYHIT_CALLBACK
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * User-callback, called by OPCODE to record a hit.
- * \param hit [in] current hit
- * \param user_data [in] user-defined data from SetCallback()
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- typedef void (*HitCallback) (const CollisionFace& hit, void* user_data);
- #endif
- class OPCODE_API RayCollider : public Collider
- {
- public:
- // Constructor / Destructor
- RayCollider();
- virtual ~RayCollider();
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Generic stabbing query for generic OPCODE models. After the call, access the results:
- * - with GetContactStatus()
- * - in the user-provided destination array
- *
- * \param world_ray [in] stabbing ray in world space
- * \param model [in] Opcode model to collide with
- * \param world [in] model's world matrix, or null
- * \param cache [in] a possibly cached face index, or null
- * \return true if success
- * \warning SCALE NOT SUPPORTED. The matrices must contain rotation & translation parts only.
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- bool Collide(const Ray& world_ray, const Model& model, const Matrix4x4* world=null, udword* cache=null);
- //
- bool Collide(const Ray& world_ray, const AABBTree* tree, OPC_Container& box_indices);
- // Settings
- #ifndef OPC_RAYHIT_CALLBACK
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Settings: enable or disable "closest hit" mode.
- * \param flag [in] true to report closest hit only
- * \see SetCulling(bool flag)
- * \see SetMaxDist(float max_dist)
- * \see SetDestination(StabbedFaces* sf)
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ void SetClosestHit(bool flag) { mClosestHit = flag; }
- #endif
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Settings: enable or disable backface culling.
- * \param flag [in] true to enable backface culling
- * \see SetClosestHit(bool flag)
- * \see SetMaxDist(float max_dist)
- * \see SetDestination(StabbedFaces* sf)
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ void SetCulling(bool flag) { mCulling = flag; }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Settings: sets the higher distance bound.
- * \param max_dist [in] higher distance bound. Default = maximal value, for ray queries (else segment)
- * \see SetClosestHit(bool flag)
- * \see SetCulling(bool flag)
- * \see SetDestination(StabbedFaces* sf)
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ void SetMaxDist(float max_dist=MAX_FLOAT) { mMaxDist = max_dist; }
- #ifdef OPC_RAYHIT_CALLBACK
- inline_ void SetHitCallback(HitCallback cb) { mHitCallback = cb; }
- inline_ void SetUserData(void* user_data) { mUserData = user_data; }
- #else
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Settings: sets the destination array for stabbed faces.
- * \param cf [in] destination array, filled during queries
- * \see SetClosestHit(bool flag)
- * \see SetCulling(bool flag)
- * \see SetMaxDist(float max_dist)
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ void SetDestination(CollisionFaces* cf) { mStabbedFaces = cf; }
- #endif
- // Stats
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Stats: gets the number of Ray-BV overlap tests after a collision query.
- * \see GetNbRayPrimTests()
- * \see GetNbIntersections()
- * \return the number of Ray-BV tests performed during last query
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ udword GetNbRayBVTests() const { return mNbRayBVTests; }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Stats: gets the number of Ray-Triangle overlap tests after a collision query.
- * \see GetNbRayBVTests()
- * \see GetNbIntersections()
- * \return the number of Ray-Triangle tests performed during last query
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ udword GetNbRayPrimTests() const { return mNbRayPrimTests; }
- // In-out test
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Stats: gets the number of intersection found after a collision query. Can be used for in/out tests.
- * \see GetNbRayBVTests()
- * \see GetNbRayPrimTests()
- * \return the number of valid intersections during last query
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- inline_ udword GetNbIntersections() const { return mNbIntersections; }
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * Validates current settings. You should call this method after all the settings and callbacks have been defined for a collider.
- * \return null if everything is ok, else a string describing the problem
- */
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- override(Collider) const char* ValidateSettings();
- protected:
- // Ray in local space
- Point mOrigin; //!< Ray origin
- Point mDir; //!< Ray direction (normalized)
- Point mFDir; //!< fabsf(mDir)
- Point mData, mData2;
- // Stabbed faces
- CollisionFace mStabbedFace; //!< Current stabbed face
- #ifdef OPC_RAYHIT_CALLBACK
- HitCallback mHitCallback; //!< Callback used to record a hit
- void* mUserData; //!< User-defined data
- #else
- CollisionFaces* mStabbedFaces; //!< List of stabbed faces
- #endif
- // Stats
- udword mNbRayBVTests; //!< Number of Ray-BV tests
- udword mNbRayPrimTests; //!< Number of Ray-Primitive tests
- // In-out test
- udword mNbIntersections; //!< Number of valid intersections
- // Dequantization coeffs
- Point mCenterCoeff;
- Point mExtentsCoeff;
- // Settings
- float mMaxDist; //!< Valid segment on the ray
- #ifndef OPC_RAYHIT_CALLBACK
- bool mClosestHit; //!< Report closest hit only
- #endif
- bool mCulling; //!< Stab culled faces or not
- // Internal methods
- void _SegmentStab(const AABBCollisionNode* node);
- void _SegmentStab(const AABBNoLeafNode* node);
- void _SegmentStab(const AABBQuantizedNode* node);
- void _SegmentStab(const AABBQuantizedNoLeafNode* node);
- void _SegmentStab(const AABBTreeNode* node, OPC_Container& box_indices);
- void _RayStab(const AABBCollisionNode* node);
- void _RayStab(const AABBNoLeafNode* node);
- void _RayStab(const AABBQuantizedNode* node);
- void _RayStab(const AABBQuantizedNoLeafNode* node);
- void _RayStab(const AABBTreeNode* node, OPC_Container& box_indices);
- // Overlap tests
- inline_ BOOL RayAABBOverlap(const Point& center, const Point& extents);
- inline_ BOOL SegmentAABBOverlap(const Point& center, const Point& extents);
- inline_ BOOL RayTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2);
- // Init methods
- BOOL InitQuery(const Ray& world_ray, const Matrix4x4* world=null, udword* face_id=null);
- };
- #endif // __OPC_RAYCOLLIDER_H__
|