/*==LICENSE==* CyanWorlds.com Engine - MMOG client, server and tools Copyright (C) 2011 Cyan Worlds, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . You can contact Cyan Worlds, Inc. by email legal@cyan.com or by snail mail at: Cyan Worlds, Inc. 14617 N Newport Hwy Mead, WA 99021 *==LICENSE==*/ #ifndef plVolumeIsect_inc #define plVolumeIsect_inc #include "hsGeometry3.h" #include "hsMatrix44.h" #include "hsTemplates.h" #include "hsBounds.h" #include "pnFactory/plCreatable.h" class hsBounds3Ext; enum plVolumeCullResult { kVolumeClear = 0x0, kVolumeCulled = 0x1, kVolumeSplit = 0x2 }; class plVolumeIsect : public plCreatable { public: CLASSNAME_REGISTER( plVolumeIsect ); GETINTERFACE_ANY( plVolumeIsect, plCreatable ); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) = 0; virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const = 0; virtual hsScalar Test(const hsPoint3& pos) const = 0; virtual void Read(hsStream* s, hsResMgr* mgr) = 0; virtual void Write(hsStream* s, hsResMgr* mgr) = 0; }; class plSphereIsect : public plVolumeIsect { protected: hsPoint3 fCenter; hsPoint3 fWorldCenter; hsScalar fRadius; hsPoint3 fMins; hsPoint3 fMaxs; public: plSphereIsect(); virtual ~plSphereIsect(); CLASSNAME_REGISTER( plSphereIsect ); GETINTERFACE_ANY( plSphereIsect, plVolumeIsect ); void SetCenter(const hsPoint3& c); void SetRadius(hsScalar r); hsScalar GetRadius() const { return fRadius; } virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; // return 0 if point inside, else "distance" from pos to volume virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plConeIsect : public plVolumeIsect { protected: hsBool fCapped; hsScalar fRadAngle; hsScalar fLength; hsPoint3 fWorldTip; hsVector3 fWorldNorm; hsMatrix44 fWorldToNDC; hsMatrix44 fLightToNDC; hsVector3 fNorms[5]; hsScalar fDists[5]; void ISetup(); public: plConeIsect(); virtual ~plConeIsect(); CLASSNAME_REGISTER( plConeIsect ); GETINTERFACE_ANY( plConeIsect, plVolumeIsect ); void SetAngle(hsScalar rads); void SetLength(hsScalar d); hsScalar GetLength() const { return fCapped ? fLength : 0; } hsScalar GetAngle() const { return fRadAngle; } virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plCylinderIsect : public plVolumeIsect { protected: hsPoint3 fTop; hsPoint3 fBot; hsScalar fRadius; hsPoint3 fWorldBot; hsVector3 fWorldNorm; hsScalar fLength; hsScalar fMin; hsScalar fMax; void ISetupCyl(const hsPoint3& wTop, const hsPoint3& wBot, hsScalar radius); public: plCylinderIsect(); virtual ~plCylinderIsect(); CLASSNAME_REGISTER( plCylinderIsect ); GETINTERFACE_ANY( plCylinderIsect, plVolumeIsect ); void SetCylinder(const hsPoint3& lTop, const hsPoint3& lBot, hsScalar radius); void SetCylinder(const hsPoint3& lBot, const hsVector3& axis, hsScalar radius); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plParallelIsect : public plVolumeIsect { protected: class ParPlane { public: hsVector3 fNorm; hsScalar fMin; hsScalar fMax; hsPoint3 fPosOne; hsPoint3 fPosTwo; }; hsTArray fPlanes; public: plParallelIsect(); virtual ~plParallelIsect(); CLASSNAME_REGISTER( plParallelIsect ); GETINTERFACE_ANY( plParallelIsect, plVolumeIsect ); void SetNumPlanes(int n); // each plane is really two parallel planes UInt16 GetNumPlanes() const { return fPlanes.GetCount(); } void SetPlane(int which, const hsPoint3& locPosOne, const hsPoint3& locPosTwo); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plConvexIsect : public plVolumeIsect { protected: class SinglePlane { public: hsVector3 fNorm; hsScalar fDist; hsPoint3 fPos; hsVector3 fWorldNorm; hsScalar fWorldDist; }; hsTArray fPlanes; public: plConvexIsect(); virtual ~plConvexIsect(); CLASSNAME_REGISTER( plConvexIsect ); GETINTERFACE_ANY( plConvexIsect, plVolumeIsect ); void ClearPlanes() { fPlanes.SetCount(0); } void AddPlaneUnchecked(const hsVector3& n, hsScalar dist); // no validation here void AddPlane(const hsVector3& n, const hsPoint3& p); UInt16 GetNumPlanes() const { return fPlanes.GetCount(); } virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plBoundsIsect : public plVolumeIsect { protected: hsBounds3Ext fLocalBounds; hsBounds3Ext fWorldBounds; public: plBoundsIsect(); virtual ~plBoundsIsect(); CLASSNAME_REGISTER( plBoundsIsect ); GETINTERFACE_ANY( plBoundsIsect, plVolumeIsect ); void SetBounds(const hsBounds3Ext& bnd); virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plComplexIsect : public plVolumeIsect { protected: hsTArray fVolumes; public: plComplexIsect(); virtual ~plComplexIsect(); CLASSNAME_REGISTER( plComplexIsect ); GETINTERFACE_ANY( plComplexIsect, plVolumeIsect ); void AddVolume(plVolumeIsect* v); // Will capture pointer UInt16 GetNumVolumes() const { return fVolumes.GetCount(); } virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l); virtual void Read(hsStream* s, hsResMgr* mgr); virtual void Write(hsStream* s, hsResMgr* mgr); }; class plUnionIsect : public plComplexIsect { public: plUnionIsect(); ~plUnionIsect(); CLASSNAME_REGISTER( plUnionIsect ); GETINTERFACE_ANY( plUnionIsect, plComplexIsect ); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; }; class plIntersectionIsect : public plComplexIsect { public: plIntersectionIsect(); ~plIntersectionIsect(); CLASSNAME_REGISTER( plIntersectionIsect ); GETINTERFACE_ANY( plIntersectionIsect, plComplexIsect ); virtual plVolumeCullResult Test(const hsBounds3Ext& bnd) const; virtual hsScalar Test(const hsPoint3& pos) const; }; #endif // plVolumeIsect_inc